blob: fe6d1b264e5038e3381e4e21ef4d55f9fd610983 [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;
24
Neels Hofmeyr4f118412020-06-04 15:25:10 +020025import from Misc_Helpers all;
Harald Welte4003d112017-12-09 22:35:39 +010026import from General_Types all;
Harald Welte28d943e2017-11-25 15:00:50 +010027import from Osmocom_Types all;
Harald Welteae026692017-12-09 01:03:01 +010028import from GSM_Types all;
Harald Welte28d943e2017-11-25 15:00:50 +010029import from IPL4asp_Types all;
30
Harald Welte6f521d82017-12-11 19:52:02 +010031import from BSSAP_Types all;
Harald Welte6811d102019-04-14 22:23:14 +020032import from RAN_Adapter all;
Harald Welte47cd0e32020-08-21 12:39:11 +020033import from BSSAP_LE_Adapter all;
34import from BSSAP_LE_CodecPort all;
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020035import from BSSAP_LE_Types all;
36import from BSSLAP_Types all;
Harald Welteae026692017-12-09 01:03:01 +010037import from BSSAP_CodecPort all;
38import from BSSMAP_Templates all;
Harald Welte28d943e2017-11-25 15:00:50 +010039import from IPA_Emulation all;
Stefan Sperling830dc9d2018-02-12 21:08:28 +010040import from IPA_CodecPort all;
Harald Welteae026692017-12-09 01:03:01 +010041import from IPA_Types all;
Stefan Sperling0796a822018-10-05 13:01:39 +020042import from IPA_Testing all;
Harald Welteae026692017-12-09 01:03:01 +010043import from RSL_Types all;
Harald Welte624f9632017-12-16 19:26:04 +010044import from RSL_Emulation all;
Daniel Willmann191e0d92018-01-17 12:44:35 +010045import from MGCP_Emulation all;
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +010046import from MGCP_Templates all;
47import from MGCP_Types all;
Pau Espin Pedrolfd02ad42019-06-18 17:45:20 +020048import from MGCP_CodecPort all;
Harald Welte28d943e2017-11-25 15:00:50 +010049
Harald Welte96c94412017-12-09 03:12:45 +010050import from Osmocom_CTRL_Functions all;
Harald Weltea5d2ab22017-12-09 14:21:42 +010051import from Osmocom_CTRL_Types all;
Harald Welteffe55fc2018-01-17 22:39:54 +010052import from Osmocom_CTRL_Adapter all;
Harald Welte96c94412017-12-09 03:12:45 +010053
Daniel Willmannebdecc02020-08-12 15:30:17 +020054import from StatsD_Types all;
55import from StatsD_CodecPort all;
56import from StatsD_CodecPort_CtrlFunct all;
57import from StatsD_Checker all;
58
Harald Weltebc03c762018-02-12 18:09:38 +010059import from Osmocom_VTY_Functions all;
60import from TELNETasp_PortType all;
61
Harald Welte6f521d82017-12-11 19:52:02 +010062import from MobileL3_CommonIE_Types all;
Harald Weltee3bd6582018-01-31 22:51:25 +010063import from MobileL3_Types all;
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +010064import from MobileL3_RRM_Types all;
Harald Welte6f521d82017-12-11 19:52:02 +010065import from L3_Templates all;
66import from GSM_RR_Types all;
67
Stefan Sperlingc307e682018-06-14 15:15:46 +020068import from SCCP_Templates all;
Neels Hofmeyr4ff93282018-03-12 04:25:35 +010069import from BSSMAP_Templates all;
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020070import from BSSMAP_LE_Templates all;
Neels Hofmeyr4ff93282018-03-12 04:25:35 +010071
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +010072import from SCCPasp_Types all;
73
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +020074import from GSM_SystemInformation all;
75import from GSM_RestOctets all;
Neels Hofmeyrad132f22020-07-08 02:20:16 +020076import from TCCConversion_Functions all;
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +020077
Neels Hofmeyrbf720202021-10-02 12:58:24 +020078type record of integer integer_list;
79
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 */
Neels Hofmeyrf246a922020-05-13 02:27:10 +020082const integer NUM_MSC := 3;
Harald Welteae026692017-12-09 01:03:01 +010083const float T3101_MAX := 12.0;
Harald Welte28d943e2017-11-25 15:00:50 +010084
Harald Welte799c97b2017-12-14 17:50:30 +010085/* make sure to sync this with the osmo-bts.cfg you're using */
Philipp Maiercb6cc482018-03-26 13:08:00 +020086const integer NUM_TCHH_PER_BTS := 2;
87const integer NUM_TCHF_PER_BTS := 4;
Neels Hofmeyr74083c22020-07-29 00:43:01 +020088const integer NUM_SDCCH_PER_BTS := 3;
Harald Welte799c97b2017-12-14 17:50:30 +010089
Neels Hofmeyrbf720202021-10-02 12:58:24 +020090/* Default Training Sequence Code expected for bts[i]:
91 * BTS 0 has BSIC 10 (and no explicit timeslot training_sequence_code config), so expecting TSC = (BSIC & 7) = 2.
92 * BTS 1 has BSIC 11, TSC = (BSIC & 7) = 3.
93 * BTS 2 has BSIC 12, TSC = (BSIC & 7) = 4.
94 * BTS 2 has BSIC 12, TSC = (BSIC & 7) = 4.
95 */
96const integer_list BTS_TSC := {
97 2,
98 3,
99 4,
100 4
101}
Harald Welte4003d112017-12-09 22:35:39 +0100102
Harald Welte21b46bd2017-12-17 19:46:32 +0100103/* per-BTS state which we keep */
Harald Welte96c94412017-12-09 03:12:45 +0100104type record BTS_State {
Harald Welte21b46bd2017-12-17 19:46:32 +0100105 /* component reference to the IPA_Client component used for RSL */
Harald Weltea5d2ab22017-12-09 14:21:42 +0100106 IPA_Client rsl
Harald Welte96c94412017-12-09 03:12:45 +0100107}
108
Neels Hofmeyr22c3f792020-06-17 02:49:28 +0200109/* Default list of counters for an 'msc' entity. */
110const CounterNameVals counternames_msc_mscpool := {
111 { "mscpool:subscr:new", 0 },
112 { "mscpool:subscr:known", 0 },
113 { "mscpool:subscr:reattach", 0 },
114 { "mscpool:subscr:attach_lost", 0 },
115 { "mscpool:subscr:paged", 0 }
116};
117
Neels Hofmeyrbf037052020-10-28 22:52:02 +0000118/* List of global mscpool counters, not related to a specific 'msc' entity. */
119const CounterNameVals counternames_bsc_mscpool := {
120 { "mscpool:subscr:no_msc", 0 }
121};
122
Neels Hofmeyr12941bd2020-08-29 03:21:26 +0000123/* Default list of counters for 'bsc' and 'bts' entities. */
124const CounterNameVals counternames_bsc_bts_handover := {
125 { "assignment:attempted", 0 },
126 { "assignment:completed", 0 },
127 { "assignment:stopped", 0 },
128 { "assignment:no_channel", 0 },
129 { "assignment:timeout", 0 },
130 { "assignment:failed", 0 },
131 { "assignment:error", 0 },
132
133 { "handover:attempted", 0 },
134 { "handover:completed", 0 },
135 { "handover:stopped", 0 },
136 { "handover:no_channel", 0 },
137 { "handover:timeout", 0 },
138 { "handover:failed", 0 },
139 { "handover:error", 0 },
140
141 { "intra_cell_ho:attempted", 0 },
142 { "intra_cell_ho:completed", 0 },
143 { "intra_cell_ho:stopped", 0 },
144 { "intra_cell_ho:no_channel", 0 },
145 { "intra_cell_ho:timeout", 0 },
146 { "intra_cell_ho:failed", 0 },
147 { "intra_cell_ho:error", 0 },
148
149 { "intra_bsc_ho:attempted", 0 },
150 { "intra_bsc_ho:completed", 0 },
151 { "intra_bsc_ho:stopped", 0 },
152 { "intra_bsc_ho:no_channel", 0 },
153 { "intra_bsc_ho:timeout", 0 },
154 { "intra_bsc_ho:failed", 0 },
155 { "intra_bsc_ho:error", 0 },
156
157 { "interbsc_ho_out:attempted", 0 },
158 { "interbsc_ho_out:completed", 0 },
159 { "interbsc_ho_out:stopped", 0 },
160 { "interbsc_ho_out:timeout", 0 },
161 { "interbsc_ho_out:failed", 0 },
162 { "interbsc_ho_out:error", 0 },
163
164 { "interbsc_ho_in:attempted", 0 },
165 { "interbsc_ho_in:completed", 0 },
166 { "interbsc_ho_in:stopped", 0 },
167 { "interbsc_ho_in:no_channel", 0 },
168 { "interbsc_ho_in:timeout", 0 },
169 { "interbsc_ho_in:failed", 0 },
170 { "interbsc_ho_in:error", 0 }
171};
172
Neels Hofmeyrac432fa2021-11-02 16:45:56 +0100173const CounterNameVals counternames_bts_handover := {
174 { "incoming_intra_bsc_ho:attempted", 0 },
175 { "incoming_intra_bsc_ho:completed", 0 },
176 { "incoming_intra_bsc_ho:stopped", 0 },
177 { "incoming_intra_bsc_ho:no_channel", 0 },
178 { "incoming_intra_bsc_ho:timeout", 0 },
179 { "incoming_intra_bsc_ho:failed", 0 },
180 { "incoming_intra_bsc_ho:error", 0 }
181};
182
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +0200183/* Set of all System Information received during one RSL port's startup.
184 * Note that some System Information may be sent on RSL, but lacking actual SI data, to indicate that the BTS should not
185 * broadcast that SI type. That will be reflected as 'omit' here.
186 */
187type record SystemInformationConfig {
188 SystemInformationType1 si1 optional,
189 SystemInformationType2 si2 optional,
190 SystemInformationType2bis si2bis optional,
191 SystemInformationType2ter si2ter optional,
Neels Hofmeyrad132f22020-07-08 02:20:16 +0200192 SI2quaterRestOctetsList si2quater optional,
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +0200193 SystemInformationType3 si3 optional,
194 SystemInformationType4 si4 optional,
Pau Espin Pedrol28652d82021-02-09 20:20:17 +0100195 SystemInformationType13 si13 optional,
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +0200196 SystemInformationType5 si5 optional,
197 SystemInformationType5bis si5bis optional,
198 SystemInformationType5ter si5ter optional,
199 SystemInformationType6 si6 optional
200};
201
202const SystemInformationConfig SystemInformationConfig_omit := {
203 si1 := omit,
204 si2 := omit,
205 si2bis := omit,
206 si2ter := omit,
207 si2quater := omit,
208 si3 := omit,
209 si4 := omit,
210 si13 := omit,
211 si5 := omit,
212 si5bis := omit,
213 si5ter := omit,
214 si6 := omit
215};
216
217/* tr_EUTRAN_CellDesc with defaults used in BSC_Tests.ttcn */
218template EUTRAN_CellDesc tr_EUTRAN_CellDesc_default(template (present) uint16_t e_arfcn := ?,
219 template uint3_t meas_bw := 3)
220:= tr_EUTRAN_CellDesc(e_arfcn := e_arfcn,
221 meas_bw_presence := '1'B,
222 meas_bw := meas_bw);
223
224/* tr_EUTRAN_NeighbourCells with defaults used in BSC_Tests.ttcn */
Harald Welte65e419a2020-08-21 12:38:33 +0200225template EUTRAN_NeighbourCells tr_EUTRAN_NeighbourCells_default(template (present) EUTRAN_CellDescs cell_desc_list := { tr_EUTRAN_CellDesc_default },
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +0200226 template uint3_t prio := 3,
227 template (present) uint5_t thresh_high := 20,
228 template uint5_t thresh_low := 10,
229 template uint5_t qrxlevmin := 22)
230:= tr_EUTRAN_NeighbourCells(
231 cell_desc_list := cell_desc_list,
232 prio_presence := '1'B,
233 prio := prio,
234 thresh_high := thresh_high,
235 thresh_low_presence := '1'B,
236 thresh_low := thresh_low,
237 qrxlevmin_presence := '1'B,
238 qrxlevmin := qrxlevmin);
239
240template SystemInformationConfig SystemInformationConfig_default := {
241 si1 := {
242 cell_chan_desc := '8FB38000000000000000000000000000'O,
243 rach_control := {
244 max_retrans := RACH_MAX_RETRANS_7,
245 tx_integer := '1001'B,
246 cell_barr_access := false,
247 re_not_allowed := true,
248 acc := '0000010000000000'B
249 },
250 rest_octets := ?
251 },
252 si2 := {
253 bcch_freq_list := '00000000000000000000000000000000'O,
254 ncc_permitted := '11111111'B,
255 rach_control := {
256 max_retrans := RACH_MAX_RETRANS_7,
257 tx_integer := '1001'B,
258 cell_barr_access := false,
259 re_not_allowed := true,
260 acc := '0000010000000000'B
261 }
262 },
263 si2bis := omit,
264 si2ter := {
265 extd_bcch_freq_list := '8E320000000000000000000000000800'O,
266 rest_octets := ?
267 },
268 si2quater := {
269 tr_SI2quaterRestOctets_EUTRAN( repeated_neigh_cells := { tr_EUTRAN_NeighbourCells_default } )
270 },
271 si3 := {
272 cell_id := 0,
273 lai := {
274 mcc_mnc := '001F01'H,
275 lac := 1
276 },
277 ctrl_chan_desc := {
278 msc_r99 := true,
279 att := true,
280 bs_ag_blks_res := 1,
281 ccch_conf := CCHAN_DESC_1CCCH_COMBINED,
282 si22ind := false,
283 cbq3 := CBQ3_IU_MODE_NOT_SUPPORTED,
284 spare := '00'B,
285 bs_pa_mfrms := 3,
286 t3212 := 30
287 },
288 cell_options := {
289 dn_ind := false,
290 pwrc := false,
291 dtx := MS_SHALL_USE_UL_DTX,
292 radio_link_tout_div4 := 7
293 },
294 cell_sel_par := {
295 cell_resel_hyst_2dB := 2,
296 ms_txpwr_max_cch := 7,
297 acs := '0'B,
298 neci := true,
299 rxlev_access_min := 0
300 },
301 rach_control := {
302 max_retrans := RACH_MAX_RETRANS_7,
303 tx_integer := '1001'B,
304 cell_barr_access := false,
305 re_not_allowed := true,
306 acc := '0000010000000000'B
307 },
308 rest_octets := {
309 sel_params := {
310 presence := '0'B,
311 params := omit
312 },
313 pwr_offset := {
314 presence := '0'B,
315 offset := omit
316 },
317 si_2ter_ind := '1'B,
318 early_cm_ind := '0'B,
319 sched_where := {
320 presence := '0'B,
321 where := omit
322 },
323 gprs_ind := {
324 presence := '1'B,
325 ind := {
326 ra_colour := 0,
327 si13_pos := '0'B
328 }
329 },
330 umts_early_cm_ind := '1'B,
331 si2_quater_ind := {
332 presence := '1'B,
333 ind := '0'B
334 },
335 iu_mode_ind := omit,
336 si21_ind := {
337 presence := '0'B,
338 pos := omit
339 }
340 }
341 },
342 si4 := {
343 lai := {
344 mcc_mnc := '001F01'H,
345 lac := 1
346 },
347 cell_sel_par := {
348 cell_resel_hyst_2dB := 2,
349 ms_txpwr_max_cch := 7,
350 acs := '0'B,
351 neci := true,
352 rxlev_access_min := 0
353 },
354 rach_control := {
355 max_retrans := RACH_MAX_RETRANS_7,
356 tx_integer := '1001'B,
357 cell_barr_access := false,
358 re_not_allowed := true,
359 acc := '0000010000000000'B
360 },
Neels Hofmeyr74083c22020-07-29 00:43:01 +0200361 cbch_chan_desc := {
362 iei := '64'O,
363 v := {
364 chan_nr := {
365 u := {
366 sdcch4 := {
367 tag := '001'B,
368 sub_chan := 2
369 }
370 },
371 tn := 0
372 },
373 tsc := 2,
374 h := false,
375 arfcn := 871,
376 maio_hsn := omit
377 }
378 },
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +0200379 cbch_mobile_alloc := omit,
380 rest_octets := {
381 sel_params := {
382 presence := '0'B,
383 params := omit
384 },
385 pwr_offset := {
386 presence := '0'B,
387 offset := omit
388 },
389 gprs_ind := {
390 presence := '1'B,
391 ind := {
392 ra_colour := 0,
393 si13_pos := '0'B
394 }
395 },
396 s_presence := '0'B,
397 s := omit
398 }
399 },
Pau Espin Pedrol28652d82021-02-09 20:20:17 +0100400 si13 := {
401 rest_octets := {
402 presence := '1'B,
403 bcch_change_mark := ?,
404 si_change_field := '0000'B,
405 presence2 := '0'B,
406 si13_change_mark := omit,
407 gprs_ma := omit,
408 zero := '0'B, /* PBCCH not present in cell */
409 rac := 0,
410 spgc_ccch_sup := '0'B,
411 priority_access_thr := '110'B,
412 network_control_order := '00'B,
413 gprs_cell_opts := {
414 nmo := '01'B,
415 t3168 := '011'B,
416 t3192 := '010'B,
417 drx_timer_max := '011'B,
418 access_burst_type := '0'B,
419 control_ack_type := '1'B,
420 bs_cv_max := 15,
421 pan_presence := '1'B,
422 pan_dec := 1,
423 pan_inc := 1,
424 pan_max := '111'B,
425 ext_info_presence := ?,
426 ext_info_length := *,
427 ext_info := *
428 },
429 gprs_pwr_ctrl_params := {
430 alpha := 0,
431 t_avg_w := '10000'B,
432 t_avg_t := '10000'B,
433 pc_meas_chan := '0'B,
434 n_avg_i := '1000'B
435 }
436 }
437 },
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +0200438 si5 := {
439 bcch_freq_list := '10000000000000000000000000000000'O
440 },
441 si5bis := omit,
442 si5ter := {
443 extd_bcch_freq_list := '9E050020000000000000000000000000'O
444 },
445 si6 := {
446 cell_id := 0,
447 lai := {
448 mcc_mnc := '001F01'H,
449 lac := 1
450 },
451 cell_options := {
452 dtx_ext := '1'B,
453 pwrc := false,
454 dtx := '01'B,
455 radio_link_timeout := '0111'B
456 },
457 ncc_permitted := '11111111'B,
458 rest_octets := ?
459 }
460 };
461
462
463/* List of all the System Information received on all RSL ports */
464type record of SystemInformationConfig SystemInformationConfig_list;
465
466function f_sysinfo_dec_raw(inout SystemInformationConfig si, RSL_Message rsl)
467{
468 var RSL_IE_Body sysinfo_type_ie;
469 var RSL_IE_SysinfoType si_type;
470 var octetstring data;
471
472 if (f_rsl_find_ie(rsl, RSL_IE_SYSINFO_TYPE, sysinfo_type_ie) == false) {
473 setverdict(fail, "Cannot find RSL_IE_SYSINFO_TYPE");
474 mtc.stop;
475 }
476 si_type := sysinfo_type_ie.sysinfo_type;
477
478 if (rsl.msg_type == RSL_MT_BCCH_INFO) {
479 var RSL_IE_Body bcch_ie;
480 if (f_rsl_find_ie(rsl, RSL_IE_FULL_BCCH_INFO, bcch_ie)) {
481 data := bcch_ie.other.payload;
482 }
483 } else if (rsl.msg_type == RSL_MT_SACCH_FILL) {
484 var RSL_IE_Body l3_ie;
485 if (f_rsl_find_ie(rsl, RSL_IE_L3_INFO, l3_ie)) {
486 data := l3_ie.l3_info.payload;
487 }
488 } else {
489 setverdict(fail, "Don't understand this System Information message");
490 mtc.stop;
491 }
492
493 var boolean handled := false;
494
495 if (rsl.msg_type == RSL_MT_BCCH_INFO) {
496 handled := true;
497
498 if (si_type == RSL_SYSTEM_INFO_1) {
499 if (not isbound(data)) {
500 si.si1 := omit;
501 } else {
502 si.si1 := dec_SystemInformation(data).payload.si1;
503 }
504 } else if (si_type == RSL_SYSTEM_INFO_2) {
505 if (not isbound(data)) {
506 si.si2 := omit;
507 } else {
508 si.si2 := dec_SystemInformation(data).payload.si2;
509 }
510 } else if (si_type == RSL_SYSTEM_INFO_2bis) {
511 if (not isbound(data)) {
512 si.si2bis := omit;
513 } else {
514 si.si2bis := dec_SystemInformation(data).payload.si2bis;
515 }
516 } else if (si_type == RSL_SYSTEM_INFO_2ter) {
517 if (not isbound(data)) {
518 si.si2ter := omit;
519 } else {
520 si.si2ter := dec_SystemInformation(data).payload.si2ter;
521 }
522 } else if (si_type == RSL_SYSTEM_INFO_2quater) {
523 if (not isbound(data)) {
524 si.si2quater := {};
525 } else {
526 var SystemInformationType2quater decoded := dec_SystemInformation(data).payload.si2quater;
527 /* this is a *record* of SI2quaterRestOctets! (multiplexed) */
528 si.si2quater[decoded.rest_octets.si2quater_index] := decoded.rest_octets;
529 }
530 } else if (si_type == RSL_SYSTEM_INFO_3) {
531 if (not isbound(data)) {
532 si.si3 := omit;
533 } else {
534 si.si3 := dec_SystemInformation(data).payload.si3;
535 }
536 } else if (si_type == RSL_SYSTEM_INFO_4) {
537 if (not isbound(data)) {
538 si.si4 := omit;
539 } else {
540 si.si4 := dec_SystemInformation(data).payload.si4;
541 }
542 } else if (si_type == RSL_SYSTEM_INFO_13) {
543 if (not isbound(data)) {
544 si.si13 := omit;
545 } else {
Pau Espin Pedrol28652d82021-02-09 20:20:17 +0100546 si.si13 := dec_SystemInformation(data).payload.si13;
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +0200547 }
548 } else {
549 handled := false;
550 }
551 } else if (rsl.msg_type == RSL_MT_SACCH_FILL) {
552 handled := true;
553
554 if (si_type == RSL_SYSTEM_INFO_5) {
555 if (not isbound(data)) {
556 si.si5 := omit;
557 } else {
558 si.si5 := dec_SystemInformation(data).payload.si5;
559 }
560 } else if (si_type == RSL_SYSTEM_INFO_5bis) {
561 if (not isbound(data)) {
562 si.si5bis := omit;
563 } else {
564 si.si5bis := dec_SystemInformation(data).payload.si5bis;
565 }
566 } else if (si_type == RSL_SYSTEM_INFO_5ter) {
567 if (not isbound(data)) {
568 si.si5ter := omit;
569 } else {
570 si.si5ter := dec_SystemInformation(data).payload.si5ter;
571 }
572 } else if (si_type == RSL_SYSTEM_INFO_6) {
573 if (not isbound(data)) {
574 si.si6 := omit;
575 } else {
576 si.si6 := dec_SystemInformation(data).payload.si6;
577 }
578 } else {
579 handled := false;
580 }
581 }
582
583 if (not handled) {
584 setverdict(fail, "Unexpected SI type in ", rsl.msg_type, " message: ", si_type);
585 }
586}
587
Harald Weltea4ca4462018-02-09 00:17:14 +0100588type component test_CT extends CTRL_Adapter_CT {
Harald Welte21b46bd2017-12-17 19:46:32 +0100589 /* Array of per-BTS state */
Harald Welte96c94412017-12-09 03:12:45 +0100590 var BTS_State bts[NUM_BTS];
Harald Welte89ab1912018-02-23 18:56:29 +0100591 /* RSL common Channel Port (for RSL_Emulation) */
592 port RSL_CCHAN_PT RSL_CCHAN[NUM_BTS];
Harald Welte21b46bd2017-12-17 19:46:32 +0100593 /* array of per-BTS RSL test ports */
Harald Welteae026692017-12-09 01:03:01 +0100594 port IPA_RSL_PT IPA_RSL[NUM_BTS];
Stefan Sperling830dc9d2018-02-12 21:08:28 +0100595 port IPA_CODEC_PT IPA; /* Required for compilation of TC_rsl_unknown_unit_id() */
Pau Espin Pedrol5a2d7432019-06-07 19:43:45 +0200596 /* CTRL muxed over IPA in SCCPlite conn BSC<->MSC (or BSC-NAT) */
597 port IPA_CTRL_PT SCCPLITE_IPA_CTRL;
Pau Espin Pedrolaf0c61e2022-01-11 12:48:34 +0100598 /* Configure/manage IPA_Emulation: */
599 port IPA_CFG_PT IPA_CFG_PORT;
Harald Weltea5d2ab22017-12-09 14:21:42 +0100600
Daniel Willmann191e0d92018-01-17 12:44:35 +0100601 var MGCP_Emulation_CT vc_MGCP;
Harald Weltebc03c762018-02-12 18:09:38 +0100602 port TELNETasp_PT BSCVTY;
Daniel Willmann191e0d92018-01-17 12:44:35 +0100603
Daniel Willmannebdecc02020-08-12 15:30:17 +0200604 /* StatsD */
605 var StatsD_Checker_CT vc_STATSD;
606
Neels Hofmeyrf246a922020-05-13 02:27:10 +0200607 var RAN_Adapter g_bssap[NUM_MSC];
Harald Welte47cd0e32020-08-21 12:39:11 +0200608 var BSSAP_LE_Adapter g_bssap_le;
Harald Weltea4ca4462018-02-09 00:17:14 +0100609 /* for old legacy-tests only */
610 port BSSAP_CODEC_PT BSSAP;
Harald Welte47cd0e32020-08-21 12:39:11 +0200611 port BSSAP_LE_CODEC_PT BSSAP_LE;
Harald Weltea4ca4462018-02-09 00:17:14 +0100612
Harald Welte21b46bd2017-12-17 19:46:32 +0100613 /* are we initialized yet */
Harald Welte28d943e2017-11-25 15:00:50 +0100614 var boolean g_initialized := false;
Harald Welte21b46bd2017-12-17 19:46:32 +0100615
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +0200616 /* Osmux is enabled through VTY */
617 var boolean g_osmux_enabled := false;
618
Pau Espin Pedrolc675b612020-01-09 19:55:40 +0100619 /*Configure T(tias) over VTY, seconds */
620 var integer g_bsc_sccp_timer_ias := 7 * 60;
621 /*Configure T(tiar) over VTY, seconds */
622 var integer g_bsc_sccp_timer_iar := 15 * 60;
623
Neels Hofmeyr4fbad7f2020-06-16 00:30:47 +0200624 /* global test case guard timer (actual timeout value is set in f_init()) */
Harald Welteae026692017-12-09 01:03:01 +0100625 timer T_guard := 30.0;
626
Neels Hofmeyr22c3f792020-06-17 02:49:28 +0200627 var CounterNameValsList g_ctr_msc;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +0000628 var CounterNameValsList g_ctr_bsc;
629 var CounterNameValsList g_ctr_bts;
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +0200630
631 /* System Information bytes as received during RSL startup, for each RSL[idx]. */
632 var SystemInformationConfig_list g_system_information := {};
Harald Welte28d943e2017-11-25 15:00:50 +0100633}
634
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +0200635type record of charstring phys_chan_configs;
Harald Welte28d943e2017-11-25 15:00:50 +0100636modulepar {
Harald Welte21b46bd2017-12-17 19:46:32 +0100637 /* IP address at which the BSC can be reached */
Harald Welte696ddb62017-12-08 14:01:43 +0100638 charstring mp_bsc_ip := "127.0.0.1";
Stefan Sperling830dc9d2018-02-12 21:08:28 +0100639 /* port number to which to establish the IPA OML connections */
640 integer mp_bsc_oml_port := 3002;
Harald Welte21b46bd2017-12-17 19:46:32 +0100641 /* port number to which to establish the IPA RSL connections */
Harald Welte696ddb62017-12-08 14:01:43 +0100642 integer mp_bsc_rsl_port := 3003;
Harald Welte21b46bd2017-12-17 19:46:32 +0100643 /* port number to which to establish the IPA CTRL connection */
Harald Welte96c94412017-12-09 03:12:45 +0100644 integer mp_bsc_ctrl_port := 4249;
Daniel Willmannebdecc02020-08-12 15:30:17 +0200645 /* port number to which to listen for STATSD metrics */
646 integer mp_bsc_statsd_port := 8125;
Daniel Willmann191e0d92018-01-17 12:44:35 +0100647 /* IP address at which the test binds */
648 charstring mp_test_ip := "127.0.0.1";
Harald Weltea4ca4462018-02-09 00:17:14 +0100649
Neels Hofmeyrf246a922020-05-13 02:27:10 +0200650 RAN_Configurations mp_bssap_cfg := {
651 {
652 transport := BSSAP_TRANSPORT_AoIP,
653 sccp_service_type := "mtp3_itu",
654 sctp_addr := { 23905, "127.0.0.1", 2905, "127.0.0.1" },
655 own_pc := 185, /* 0.23.1 first MSC emulation */
656 own_ssn := 254,
657 peer_pc := 187, /* 0.23.3 osmo-bsc */
658 peer_ssn := 254,
659 sio := '83'O,
Harald Weltecb0cc432020-06-21 19:42:31 +0200660 rctx := 1
Neels Hofmeyrf246a922020-05-13 02:27:10 +0200661 },
662 {
663 transport := BSSAP_TRANSPORT_AoIP,
664 sccp_service_type := "mtp3_itu",
665 sctp_addr := { 23906, "127.0.0.1", 2905, "127.0.0.1" },
666 own_pc := 2, /* 0.0.2 second MSC emulation */
667 own_ssn := 254,
668 peer_pc := 187, /* 0.23.3 osmo-bsc */
669 peer_ssn := 254,
670 sio := '83'O,
671 rctx := 2
672 },
673 {
674 transport := BSSAP_TRANSPORT_AoIP,
675 sccp_service_type := "mtp3_itu",
676 sctp_addr := { 23907, "127.0.0.1", 2905, "127.0.0.1" },
677 own_pc := 3, /* 0.0.3 third MSC emulation */
678 own_ssn := 254,
679 peer_pc := 187, /* 0.23.3 osmo-bsc */
680 peer_ssn := 254,
681 sio := '83'O,
682 rctx := 3
683 }
Harald Weltea4ca4462018-02-09 00:17:14 +0100684 };
Pau Espin Pedrol58cf6822019-05-28 18:11:33 +0200685
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +0200686 /* Must match per BTS config in osmo-bsc.cfg */
687 phys_chan_configs phys_chan_config := {
688 "CCCH+SDCCH4+CBCH",
689 "TCH/F",
690 "TCH/F",
691 "TCH/F",
692 "TCH/F",
Vadim Yanitskiy343c9eb2021-07-16 18:36:01 +0600693 "TCH/H",
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +0200694 "PDCH",
695 "PDCH"
696 };
697
Harald Welte47cd0e32020-08-21 12:39:11 +0200698 BSSAP_LE_Configuration mp_bssap_le_cfg := {
699 sccp_service_type := "mtp3_itu",
700 sctp_addr := { 23908, "127.0.0.1", 2905, "127.0.0.1" },
Neels Hofmeyrac086c12020-09-18 23:46:42 +0200701 own_pc := 190, /* 0.23.6 SMLC emulation */
Harald Welte47cd0e32020-08-21 12:39:11 +0200702 own_ssn := 252, /* SMLC side SSN */
703 peer_pc := 187, /* 0.23.3 osmo-bsc */
704 peer_ssn := 250, /* BSC side SSN */
705 sio := '83'O,
706 rctx := 6
707 };
Neels Hofmeyrcfe44062020-10-15 02:28:08 +0200708 boolean mp_enable_lcs_tests := true;
Harald Welte47cd0e32020-08-21 12:39:11 +0200709
Pau Espin Pedrol8f30ccd2019-11-01 17:30:57 +0100710 /* Value set in osmo-bsc.cfg "ms max power" */
711 uint8_t mp_exp_ms_power_level := 7;
Harald Weltea4ca4462018-02-09 00:17:14 +0100712}
713
Neels Hofmeyr9f3e6ac2021-04-08 23:09:24 +0200714friend function f_gen_test_hdlr_pars(integer bssap_idx := 0) return TestHdlrParams {
Philipp Maier48604732018-10-09 15:00:37 +0200715
716 var TestHdlrParams pars := valueof(t_def_TestHdlrPars);
Neels Hofmeyrf246a922020-05-13 02:27:10 +0200717 if (mp_bssap_cfg[bssap_idx].transport == BSSAP_TRANSPORT_AoIP) {
Philipp Maier48604732018-10-09 15:00:37 +0200718 pars.aoip := true;
719 } else {
720 pars.aoip := false;
721 }
Pau Espin Pedrol8f30ccd2019-11-01 17:30:57 +0100722 pars.exp_ms_power_level := mp_exp_ms_power_level;
Neels Hofmeyrf246a922020-05-13 02:27:10 +0200723 pars.mscpool.bssap_idx := bssap_idx;
Neels Hofmeyrbf720202021-10-02 12:58:24 +0200724 pars.expect_tsc := BTS_TSC[0];
Vadim Yanitskiy96bb9cb2021-12-10 21:14:15 +0300725 pars.imsi := f_rnd_imsi('00101'H);
726
727 log(testcasename(), ": using IMSI ", pars.imsi);
Neels Hofmeyrb5b7a6e2021-06-04 19:03:45 +0200728
Philipp Maier48604732018-10-09 15:00:37 +0200729 return pars;
730}
731
Neels Hofmeyr22c3f792020-06-17 02:49:28 +0200732/* Convenience functions for rate counters using g_ctr_msc. */
733
734private function f_ctrs_msc_init(integer mscs_count := NUM_MSC, CounterNameVals counternames := counternames_msc_mscpool) runs on test_CT {
735 g_ctr_msc := f_counter_name_vals_get_n(IPA_CTRL, "msc", mscs_count, counternames);
736 log("initial msc rate counters: ", g_ctr_msc);
737}
738
739private function f_ctrs_msc_add(integer msc_nr, charstring countername, integer val := 1) runs on test_CT {
Neels Hofmeyr9656e922020-06-30 01:27:01 +0200740 f_counter_name_vals_list_add(g_ctr_msc, msc_nr, countername, val);
Neels Hofmeyr22c3f792020-06-17 02:49:28 +0200741}
742
743/* f_ctrs_msc_init();
744 * f_do_thing(on_msc := 0);
745 * f_do_thing(on_msc := 0);
746 * f_do_other(on_msc := 1);
747 * f_ctrs_msc_add(0, "thing", 2);
748 * f_ctrs_msc_add(1, "other");
749 * f_ctrs_msc_verify();
750 */
751private function f_ctrs_msc_verify() runs on test_CT {
752 log("verifying msc rate counters: ", g_ctr_msc);
753 f_counter_name_vals_expect_n(IPA_CTRL, "msc", g_ctr_msc);
754}
755
756/* convenience: f_ctrs_msc_add() and f_ctrs_msc_verify() in one call.
757 * f_ctrs_msc_init();
758 * f_do_thing(on_msc := 0);
759 * f_do_thing(on_msc := 0);
760 * f_do_thing(on_msc := 0);
761 * f_ctrs_msc_expect(0, "thing", 3);
762 */
763private function f_ctrs_msc_expect(integer msc_nr, charstring countername, integer val := 1) runs on test_CT {
764 f_ctrs_msc_add(msc_nr, countername, val);
765 f_ctrs_msc_verify();
766}
767
Neels Hofmeyr12941bd2020-08-29 03:21:26 +0000768/* Convenience functions for rate counters using g_ctr_bts, always also including g_ctr_bsc. */
769
Neels Hofmeyrb7581872021-11-07 14:02:49 +0100770private 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 +0000771 g_ctr_bts := f_counter_name_vals_get_n(IPA_CTRL, "bts", bts_count, counternames);
Neels Hofmeyr4dec8cc2021-11-29 15:59:44 +0100772 log("initial bts rate counters: ", g_ctr_bts);
Neels Hofmeyrb7581872021-11-07 14:02:49 +0100773}
774
775function f_ctrs_bsc_and_bts_init(integer bts_count := NUM_BTS, CounterNameVals counternames := counternames_bsc_bts_handover) runs on test_CT {
776 f_ctrs_bts_init(bts_count, counternames);
Neels Hofmeyr12941bd2020-08-29 03:21:26 +0000777 f_ctrs_bsc_init(counternames);
778}
779
Neels Hofmeyrac432fa2021-11-02 16:45:56 +0100780private function f_ctrs_bsc_and_bts_handover_init(integer bts_count := NUM_BTS) runs on test_CT {
781 var CounterNameVals bts_names := counternames_bsc_bts_handover & counternames_bts_handover;
Neels Hofmeyr4dec8cc2021-11-29 15:59:44 +0100782 f_ctrs_bts_init(bts_count, bts_names);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +0100783 f_ctrs_bsc_init(counternames_bsc_bts_handover);
784}
785
786private function f_ctrs_bts_add(integer bts_nr, charstring countername, integer val := 1) runs on test_CT {
Neels Hofmeyr12941bd2020-08-29 03:21:26 +0000787 f_counter_name_vals_list_add(g_ctr_bts, bts_nr, countername, val);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +0100788}
789
790private function f_ctrs_bsc_and_bts_add(integer bts_nr, charstring countername, integer val := 1) runs on test_CT {
791 f_ctrs_bts_add(bts_nr, countername, val);
Neels Hofmeyr12941bd2020-08-29 03:21:26 +0000792 f_ctrs_bsc_add(countername, val);
793}
794
Neels Hofmeyrb7581872021-11-07 14:02:49 +0100795function f_ctrs_bts_verify() runs on test_CT {
796 f_counter_name_vals_expect_n(IPA_CTRL, "bts", g_ctr_bts);
797}
798
Neels Hofmeyr12941bd2020-08-29 03:21:26 +0000799/* f_ctrs_bsc_and_bts_init();
800 * f_do_thing(on_bts := 0);
801 * f_do_thing(on_bts := 0);
802 * f_do_other(on_bts := 1);
803 * f_ctrs_bsc_and_bts_add(0, "thing", 2);
804 * f_ctrs_bsc_and_bts_add(1, "other");
805 * f_ctrs_bsc_and_bts_verify();
806 */
807private function f_ctrs_bsc_and_bts_verify() runs on test_CT {
Neels Hofmeyrb7581872021-11-07 14:02:49 +0100808 f_ctrs_bts_verify();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +0000809 f_ctrs_bsc_verify();
810}
811
812/* convenience: f_ctrs_bsc_and_bts_add() and f_ctrs_bsc_and_bts_verify() in one call.
813 * f_ctrs_bsc_and_bts_init();
814 * f_do_thing(on_bts := 0);
815 * f_do_thing(on_bts := 0);
816 * f_do_thing(on_bts := 0);
817 * f_ctrs_bsc_and_bts_expect(0, "thing", 3);
818 */
819private function f_ctrs_bsc_and_bts_expect(integer bts_nr, charstring countername, integer val := 1) runs on test_CT {
820 f_ctrs_bsc_and_bts_add(bts_nr, countername, val);
821 f_ctrs_bsc_and_bts_verify();
822}
823
824
825/* Convenience functions for rate counters using g_ctr_bsc. */
826
827private function f_ctrs_bsc_init(CounterNameVals counternames := counternames_bsc_bts_handover) runs on test_CT {
828 g_ctr_bsc := f_counter_name_vals_get_n(IPA_CTRL, "bsc", 1, counternames);
829 log("initial bsc rate counters: ", g_ctr_bsc);
830}
831
832private function f_ctrs_bsc_add(charstring countername, integer val := 1) runs on test_CT {
833 f_counter_name_vals_list_add(g_ctr_bsc, 0, countername, val);
834}
835
836/* f_ctrs_bsc_init();
837 * f_do_thing();
838 * f_do_thing();
839 * f_do_other();
840 * f_ctrs_bsc_add("thing", 2);
841 * f_ctrs_bsc_add("other");
842 * f_ctrs_bsc_verify();
843 */
844private function f_ctrs_bsc_verify() runs on test_CT {
845 f_counter_name_vals_expect_n(IPA_CTRL, "bsc", g_ctr_bsc);
846}
847
848/* convenience: f_ctrs_bsc_add() and f_ctrs_bsc_verify() in one call.
849 * f_ctrs_bsc_init();
850 * f_do_thing();
851 * f_ctrs_bsc_expect("thing", 1);
852 */
853private function f_ctrs_bsc_expect(charstring countername, integer val := 1) runs on test_CT {
854 f_ctrs_bsc_add(countername, val);
855 f_ctrs_bsc_verify();
856}
857
Neels Hofmeyr22c3f792020-06-17 02:49:28 +0200858
Neels Hofmeyr9f3e6ac2021-04-08 23:09:24 +0200859friend function f_shutdown_helper() runs on test_CT {
Neels Hofmeyr18997492021-12-13 17:30:35 +0100860 /* Run the subscr and conn leak test only when the VTY is initialized */
861 if (BSCVTY.checkstate("Mapped")) {
862 f_verify_talloc_count(BSCVTY, {"struct bsc_subscr", "struct gsm_subscriber_connection"});
863 }
864
Daniel Willmann637ef6c2018-07-25 10:49:09 +0200865 all component.stop;
Philipp Maier282ca4b2018-02-27 17:17:00 +0100866 setverdict(pass);
Daniel Willmannafce8662018-07-06 23:11:32 +0200867 mtc.stop;
Philipp Maier282ca4b2018-02-27 17:17:00 +0100868}
869
Neels Hofmeyrf246a922020-05-13 02:27:10 +0200870private function f_legacy_bssap_reset(integer bssap_idx := 0) runs on test_CT {
Harald Weltea4ca4462018-02-09 00:17:14 +0100871 var BSSAP_N_UNITDATA_ind ud_ind;
Pau Espin Pedrol24c05992020-09-01 12:54:12 +0200872 var boolean reset_received := false;
Harald Weltea4ca4462018-02-09 00:17:14 +0100873 timer T := 5.0;
Neels Hofmeyrf246a922020-05-13 02:27:10 +0200874 BSSAP.send(ts_BSSAP_UNITDATA_req(g_bssap[bssap_idx].sccp_addr_peer, g_bssap[bssap_idx].sccp_addr_own,
875 ts_BSSMAP_Reset(0, g_osmux_enabled)));
Harald Weltea4ca4462018-02-09 00:17:14 +0100876 T.start;
877 alt {
Neels Hofmeyrf246a922020-05-13 02:27:10 +0200878 [] BSSAP.receive(tr_BSSAP_UNITDATA_ind(g_bssap[bssap_idx].sccp_addr_own, g_bssap[bssap_idx].sccp_addr_peer,
879 tr_BSSMAP_ResetAck(g_osmux_enabled))) {
Neels Hofmeyr4f5d7be2020-10-16 16:28:16 +0200880 log("BSSMAP: Received RESET-ACK in response to RESET, we're ready to go!");
Harald Weltea4ca4462018-02-09 00:17:14 +0100881 }
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +0200882 [] BSSAP.receive(tr_BSSAP_UNITDATA_ind(?, ?, tr_BSSMAP_Reset(g_osmux_enabled))) -> value ud_ind {
Neels Hofmeyr4f5d7be2020-10-16 16:28:16 +0200883 log("BSSMAP: Respoding to inbound RESET with RESET-ACK");
Harald Weltea4ca4462018-02-09 00:17:14 +0100884 BSSAP.send(ts_BSSAP_UNITDATA_req(ud_ind.callingAddress, ud_ind.calledAddress,
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +0200885 ts_BSSMAP_ResetAck(g_osmux_enabled)));
Pau Espin Pedrol24c05992020-09-01 12:54:12 +0200886 reset_received := true;
Harald Weltea4ca4462018-02-09 00:17:14 +0100887 repeat;
888 }
889 [] BSSAP.receive { repeat; }
Pau Espin Pedrol24c05992020-09-01 12:54:12 +0200890 [] T.timeout {
Neels Hofmeyr4f5d7be2020-10-16 16:28:16 +0200891 log("BSSMAP: Timeout waiting for RESET-ACK after sending RESET");
Pau Espin Pedrol24c05992020-09-01 12:54:12 +0200892 /* If we received a RESET after ours was sent, it
893 may be a race condition where the other peer beacame
894 available after we sent it, but we are in a desired
895 state anyway, so go forward. */
896 if (not reset_received) {
897 setverdict(fail);
898 }
899 }
Harald Weltea4ca4462018-02-09 00:17:14 +0100900 }
Harald Welte28d943e2017-11-25 15:00:50 +0100901}
902
Harald Welteae026692017-12-09 01:03:01 +0100903type record IPA_Client {
Harald Welte21b46bd2017-12-17 19:46:32 +0100904 /* IPA Emulation component reference */
Harald Welteae026692017-12-09 01:03:01 +0100905 IPA_Emulation_CT vc_IPA,
Harald Welte21b46bd2017-12-17 19:46:32 +0100906 /* Unit-ID and other CCM parameters to use for IPA client emulation */
Harald Welteae026692017-12-09 01:03:01 +0100907 IPA_CCM_Parameters ccm_pars,
Harald Welte21b46bd2017-12-17 19:46:32 +0100908 /* String identifier for this IPA Client */
Harald Welte624f9632017-12-16 19:26:04 +0100909 charstring id,
Harald Welte21b46bd2017-12-17 19:46:32 +0100910 /* Associated RSL Emulation Component (if any). Only used in "Handler mode" */
Harald Welte624f9632017-12-16 19:26:04 +0100911 RSL_Emulation_CT vc_RSL optional
Harald Welte28d943e2017-11-25 15:00:50 +0100912}
913
Harald Welte21b46bd2017-12-17 19:46:32 +0100914/*! Start the IPA/RSL related bits for one IPA_Client.
915 * \param clnt IPA_Client for which to establish
916 * \param bsc_host IP address / hostname of the BSC
917 * \param bsc_port TCP port number of the BSC
918 * \param i number identifying this BTS
919 * \param handler_mode Start an RSL_Emulation_CT component (true) or not (false) */
Harald Welte624f9632017-12-16 19:26:04 +0100920function f_ipa_rsl_start(inout IPA_Client clnt, charstring bsc_host, PortNumber bsc_port, integer i,
921 boolean handler_mode := false)
Harald Welte28d943e2017-11-25 15:00:50 +0100922runs on test_CT {
Harald Welteae026692017-12-09 01:03:01 +0100923 timer T := 10.0;
924
Harald Welte96c94412017-12-09 03:12:45 +0100925 clnt.id := "IPA" & int2str(i) & "-RSL";
Harald Welte71389132021-12-09 21:58:18 +0100926 clnt.vc_IPA := IPA_Emulation_CT.create(clnt.id & "-IPA") alive;
Harald Welteae026692017-12-09 01:03:01 +0100927 clnt.ccm_pars := c_IPA_default_ccm_pars;
928 clnt.ccm_pars.name := "Osmocom TTCN-3 BTS Simulator";
929 clnt.ccm_pars.unit_id := int2str(1234+i) & "/0/0";
Harald Welte624f9632017-12-16 19:26:04 +0100930 if (handler_mode) {
Harald Welte71389132021-12-09 21:58:18 +0100931 clnt.vc_RSL := RSL_Emulation_CT.create(clnt.id & "-RSL") alive;
Harald Welte89ab1912018-02-23 18:56:29 +0100932 connect(clnt.vc_RSL:CCHAN_PT, self:RSL_CCHAN[i]);
Harald Welte624f9632017-12-16 19:26:04 +0100933 }
Harald Welteae026692017-12-09 01:03:01 +0100934
935 map(clnt.vc_IPA:IPA_PORT, system:IPA_CODEC_PT);
Pau Espin Pedrolaf0c61e2022-01-11 12:48:34 +0100936 connect(clnt.vc_IPA:CFG_PORT, self:IPA_CFG_PORT);
Harald Welte624f9632017-12-16 19:26:04 +0100937 if (handler_mode) {
938 connect(clnt.vc_IPA:IPA_RSL_PORT, clnt.vc_RSL:IPA_PT);
939 } else {
940 connect(clnt.vc_IPA:IPA_RSL_PORT, self:IPA_RSL[i]);
941 }
Harald Welteae026692017-12-09 01:03:01 +0100942
Harald Welte5d1a2202017-12-13 19:51:29 +0100943 clnt.vc_IPA.start(IPA_Emulation.main_client(bsc_host, bsc_port, "", 10000+i, clnt.ccm_pars));
Harald Welte624f9632017-12-16 19:26:04 +0100944 if (handler_mode) {
945 clnt.vc_RSL.start(RSL_Emulation.main());
946 return;
947 }
Harald Welteae026692017-12-09 01:03:01 +0100948
949 /* wait for IPA RSL link to connect and send ID ACK */
950 T.start;
951 alt {
Vadim Yanitskiya2afacc2020-05-18 21:16:19 +0700952 [] IPA_RSL[i].receive(tr_ASP_IPA_EV(ASP_IPA_EVENT_ID_ACK)) {
Harald Welteae026692017-12-09 01:03:01 +0100953 T.stop;
Vadim Yanitskiy9b4e3562020-05-25 21:40:52 +0700954 IPA_RSL[i].send(ts_ASP_RSL_UD(ts_RSL_PAGING_LOAD_IND(23)));
Harald Welteae026692017-12-09 01:03:01 +0100955 }
Harald Welte60e823a2017-12-10 14:10:59 +0100956 [] IPA_RSL[i].receive(ASP_IPA_Event:?) { repeat }
Harald Welteae026692017-12-09 01:03:01 +0100957 [] IPA_RSL[i].receive { repeat }
958 [] T.timeout {
Harald Welte96c94412017-12-09 03:12:45 +0100959 setverdict(fail, "Timeout RSL waiting for ASP_IPA_EVENT_ID_ACK");
Daniel Willmannafce8662018-07-06 23:11:32 +0200960 mtc.stop;
Harald Welteae026692017-12-09 01:03:01 +0100961 }
962 }
963}
964
Harald Welte12055472018-03-17 20:10:08 +0100965function f_ipa_rsl_stop(inout IPA_Client clnt) runs on test_CT {
Pau Espin Pedrolaf0c61e2022-01-11 12:48:34 +0100966 var IPL4asp_Types.Result res := {
967 errorCode := omit,
968 connId := omit,
969 os_error_code := omit,
970 os_error_text := omit
971 };
972
Harald Welte12055472018-03-17 20:10:08 +0100973 if (not isbound(clnt) or not isbound(clnt.vc_IPA)) {
974 return;
975 }
Pau Espin Pedrolaf0c61e2022-01-11 12:48:34 +0100976
977 /* Alive components don't finish sockets (TCP FIN) when they are
978 * stopped. Hence, we need to manually call close() on them to make sure
979 * the IUT knows about it. */
980 f_ipa_cfg_disconnect(IPA_CFG_PORT, res);
981
Harald Welte12055472018-03-17 20:10:08 +0100982 clnt.vc_IPA.stop;
983 if (isbound(clnt.vc_RSL)) {
984 clnt.vc_RSL.stop;
985 }
986}
987
Harald Welte21b46bd2017-12-17 19:46:32 +0100988/* Wait for the OML connection to be brought up by the external osmo-bts-omldummy */
Harald Weltea5d2ab22017-12-09 14:21:42 +0100989function f_wait_oml(integer bts_nr, charstring status, float secs_max) runs on test_CT {
990 timer T := secs_max;
991 T.start;
992 while (true) {
993 if (f_ctrl_get_bts(IPA_CTRL, bts_nr, "oml-connection-state") == status) {
994 T.stop;
Harald Weltebd868bd2017-12-10 18:28:40 +0100995 /* the 'degraded' state exists from OML connection time, and we have to wait
996 * until all MO's are initialized */
997 T.start(1.0);
998 T.timeout;
Harald Weltea5d2ab22017-12-09 14:21:42 +0100999 return;
1000 }
Harald Weltef0d6ac62017-12-17 17:02:21 +01001001 f_sleep(0.1);
Harald Weltea5d2ab22017-12-09 14:21:42 +01001002 if (not T.running) {
Max99253902018-11-16 17:57:39 +01001003 setverdict(fail, "Timeout waiting for BTS" & int2str(bts_nr) & " oml-connection-state ", status);
Daniel Willmannafce8662018-07-06 23:11:32 +02001004 mtc.stop;
Harald Weltea5d2ab22017-12-09 14:21:42 +01001005 }
1006 }
1007}
1008
Harald Welte21b46bd2017-12-17 19:46:32 +01001009/* global altstep for global guard timer; also takes care of responding RESET witH RESET-ACK */
Harald Welteae026692017-12-09 01:03:01 +01001010altstep as_Tguard() runs on test_CT {
Harald Welte60e823a2017-12-10 14:10:59 +01001011 var BSSAP_N_UNITDATA_ind ud_ind;
Neels Hofmeyrcc3f76a2018-03-12 01:43:25 +01001012 [] T_guard.timeout {
1013 setverdict(fail, "Timeout of T_guard");
Daniel Willmannafce8662018-07-06 23:11:32 +02001014 mtc.stop;
Neels Hofmeyrcc3f76a2018-03-12 01:43:25 +01001015 }
Harald Welte60e823a2017-12-10 14:10:59 +01001016 /* always respond with RESET ACK to RESET */
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02001017 [] BSSAP.receive(tr_BSSAP_UNITDATA_ind(?, ?, tr_BSSMAP_Reset(g_osmux_enabled))) -> value ud_ind {
Harald Welte60e823a2017-12-10 14:10:59 +01001018 BSSAP.send(ts_BSSAP_UNITDATA_req(ud_ind.callingAddress, ud_ind.calledAddress,
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02001019 ts_BSSMAP_ResetAck(g_osmux_enabled)));
Harald Welte69c1c262017-12-13 21:02:08 +01001020 repeat;
Harald Welte60e823a2017-12-10 14:10:59 +01001021 }
Harald Welte28d943e2017-11-25 15:00:50 +01001022}
1023
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +01001024altstep no_bssmap_reset() runs on test_CT {
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02001025 [] BSSAP.receive(tr_BSSAP_UNITDATA_ind(?, ?, tr_BSSMAP_Reset(g_osmux_enabled))) {
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +01001026 setverdict(fail, "unexpected BSSMAP Reset");
Daniel Willmannafce8662018-07-06 23:11:32 +02001027 mtc.stop;
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +01001028 }
1029}
1030
Daniel Willmann191e0d92018-01-17 12:44:35 +01001031function f_init_mgcp(charstring id) runs on test_CT {
1032 id := id & "-MGCP";
1033
1034 var MGCPOps ops := {
1035 create_cb := refers(MGCP_Emulation.ExpectedCreateCallback),
1036 unitdata_cb := refers(MGCP_Emulation.DummyUnitdataCallback)
1037 };
1038 var MGCP_conn_parameters mgcp_pars := {
1039 callagent_ip := mp_bsc_ip,
Harald Welte9e4273e2018-01-29 22:01:22 +01001040 callagent_udp_port := -1,
Daniel Willmann191e0d92018-01-17 12:44:35 +01001041 mgw_ip := mp_test_ip,
Pau Espin Pedrol1a026a52019-06-18 17:21:52 +02001042 mgw_udp_port := 2427,
Pau Espin Pedrolfd02ad42019-06-18 17:45:20 +02001043 /* Enable it for SCCPlite, since we have 2 MGCP sockets towards MGW (UDP one +
1044 the on with MGCP over IPA forwarded from MSC one) */
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001045 multi_conn_mode := (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_SCCPlite_SERVER)
Daniel Willmann191e0d92018-01-17 12:44:35 +01001046 };
1047
Harald Welte71389132021-12-09 21:58:18 +01001048 vc_MGCP := MGCP_Emulation_CT.create(id) alive;
Daniel Willmann191e0d92018-01-17 12:44:35 +01001049 vc_MGCP.start(MGCP_Emulation.main(ops, mgcp_pars, id));
1050}
1051
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02001052/* Enable or disable (current default) Osmux. When enabling, BSSMAP Reset
1053 * contains extra IE (OsmuxSupport) and osmo-bsc will handle AssignReq with
1054 * OsmuxCID IE.
1055 */
1056private function f_vty_allow_osmux(boolean allow) runs on test_CT {
1057 f_vty_enter_cfg_msc(BSCVTY, 0);
1058 if (allow) {
1059 f_vty_transceive(BSCVTY, "osmux on");
1060 } else {
1061 f_vty_transceive(BSCVTY, "osmux off");
1062 }
1063 f_vty_transceive(BSCVTY, "exit");
1064 f_vty_transceive(BSCVTY, "exit");
1065 g_osmux_enabled := allow;
1066}
1067
Max2253c0b2018-11-06 19:28:05 +01001068function f_init_vty(charstring id := "foo") runs on test_CT {
Harald Welte94e0c342018-04-07 11:33:23 +02001069 if (BSCVTY.checkstate("Mapped")) {
1070 /* skip initialization if already executed once */
1071 return;
1072 }
Harald Weltebc03c762018-02-12 18:09:38 +01001073 map(self:BSCVTY, system:BSCVTY);
1074 f_vty_set_prompts(BSCVTY);
1075 f_vty_transceive(BSCVTY, "enable");
Pau Espin Pedrolc675b612020-01-09 19:55:40 +01001076 f_cs7_inst_0_cfg(BSCVTY, {"sccp-timer ias " & int2str(g_bsc_sccp_timer_ias),
1077 "sccp-timer iar " & int2str(g_bsc_sccp_timer_iar)});
Harald Weltebc03c762018-02-12 18:09:38 +01001078}
1079
Neels Hofmeyr9f3e6ac2021-04-08 23:09:24 +02001080friend function f_logp(TELNETasp_PT pt, charstring log_msg)
Neels Hofmeyr4f118412020-06-04 15:25:10 +02001081{
1082 // log on TTCN3 log output
1083 log(log_msg);
1084 // log in stderr log
Neels Hofmeyr8bdafe52021-12-14 17:25:48 +01001085 if (pt.checkstate("Mapped")) {
1086 f_vty_transceive(pt, "logp lglobal notice TTCN3 f_logp(): " & log_msg);
1087 }
Neels Hofmeyr4f118412020-06-04 15:25:10 +02001088}
1089
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +02001090private function f_sysinfo_seen(integer rsl_idx, RSL_Message rsl) runs on test_CT
1091{
1092 if (rsl_idx >= lengthof(g_system_information)) {
1093 g_system_information[rsl_idx] := SystemInformationConfig_omit
1094 }
1095 f_sysinfo_dec_raw(g_system_information[rsl_idx], rsl);
1096}
1097
1098altstep as_catch_RSL_sysinfo(integer rsl_idx) runs on test_CT {
1099 var ASP_RSL_Unitdata rx_rsl_ud;
1100
1101 /* For handler_mode := false, receiving the RSL bootstrap messages directly on IPA_RSL */
1102 [] IPA_RSL[rsl_idx].receive(tr_ASP_RSL_UD(tr_RSL_NO_BCCH_INFO)) -> value rx_rsl_ud {
1103 f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
1104 repeat;
1105 }
1106 [] IPA_RSL[rsl_idx].receive(tr_ASP_RSL_UD(tr_RSL_BCCH_INFO)) -> value rx_rsl_ud {
1107 f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
1108 repeat;
1109 }
1110 [] IPA_RSL[rsl_idx].receive(tr_ASP_RSL_UD(tr_RSL_NO_SACCH_FILL)) -> value rx_rsl_ud {
1111 f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
1112 repeat;
1113 }
1114 [] IPA_RSL[rsl_idx].receive(tr_ASP_RSL_UD(tr_RSL_SACCH_FILL)) -> value rx_rsl_ud {
1115 f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
1116 repeat;
1117 }
1118
1119 /* For handler_mode := true, receiving the RSL bootstrap messages via RSL_Emulation */
1120 [] RSL_CCHAN[rsl_idx].receive(tr_ASP_RSL_UD(tr_RSL_NO_BCCH_INFO)) -> value rx_rsl_ud {
1121 f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
1122 repeat;
1123 }
1124 [] RSL_CCHAN[rsl_idx].receive(tr_ASP_RSL_UD(tr_RSL_BCCH_INFO)) -> value rx_rsl_ud {
1125 f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
1126 repeat;
1127 }
1128 [] RSL_CCHAN[rsl_idx].receive(tr_ASP_RSL_UD(tr_RSL_NO_SACCH_FILL)) -> value rx_rsl_ud {
1129 f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
1130 repeat;
1131 }
1132 [] RSL_CCHAN[rsl_idx].receive(tr_ASP_RSL_UD(tr_RSL_SACCH_FILL)) -> value rx_rsl_ud {
1133 f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
1134 repeat;
1135 }
1136}
1137
Neels Hofmeyra460f1f2020-08-09 20:17:03 +00001138/* TODO: use BooleanList from COMMON/src/General_Types.ttcn */
1139private type record of boolean my_BooleanList;
1140
1141private function f_vty_msc_allow_attach(TELNETasp_PT pt, my_BooleanList allow_attach_list)
1142{
Neels Hofmeyr8f576712020-08-12 22:49:53 +00001143 var charstring config := f_vty_transceive_ret(pt, "show running-config");
1144
Neels Hofmeyra460f1f2020-08-09 20:17:03 +00001145 for (var integer msc_nr := 0; msc_nr < sizeof(allow_attach_list); msc_nr := msc_nr+1) {
Neels Hofmeyr8f576712020-08-12 22:49:53 +00001146 if (f_strstr(config, "\nmsc " & int2str(msc_nr) & "\n") < 0) {
1147 /* There is no 'msc N' for this msc_nr in the running config, so don't create an empty msc by
1148 * stepping into that config node. */
1149 log("msc ", msc_nr, " is not configured, skipping");
1150 continue;
1151 }
Neels Hofmeyra460f1f2020-08-09 20:17:03 +00001152 f_vty_enter_cfg_msc(pt, msc_nr);
1153 if (allow_attach_list[msc_nr]) {
1154 /* strict := false: ignore if osmo-bsc does not support this config option (latest build) */
1155 f_vty_transceive(pt, "allow-attach", strict := false);
1156 } else {
1157 f_vty_transceive(pt, "no allow-attach", strict := false);
1158 }
1159 f_vty_transceive(pt, "exit");
1160 f_vty_transceive(pt, "exit");
1161 }
1162}
1163
Harald Welte21b46bd2017-12-17 19:46:32 +01001164/* global initialization function
1165 * \param nr_bts Number of BTSs we should start/bring up
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001166 * \param handler_mode Start an RSL_Emulation_CT component (true) or not (false).
1167 * \param nr_msc Number of virtual MSCs to bring up to connect to osmo-bsc.
1168 */
1169function f_init(integer nr_bts := NUM_BTS, boolean handler_mode := false, boolean allow_osmux := false,
Neels Hofmeyr4fbad7f2020-06-16 00:30:47 +02001170 integer nr_msc := 1, float guard_timeout := 30.0) runs on test_CT {
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001171 var integer bssap_idx;
Harald Welte28d943e2017-11-25 15:00:50 +01001172
Harald Welteae026692017-12-09 01:03:01 +01001173 if (g_initialized) {
1174 return;
Harald Welte28d943e2017-11-25 15:00:50 +01001175 }
Harald Welteae026692017-12-09 01:03:01 +01001176 g_initialized := true;
1177
Neels Hofmeyr4fbad7f2020-06-16 00:30:47 +02001178 T_guard.start(guard_timeout);
Daniel Willmanne68f9272018-11-27 15:15:28 +01001179 activate(as_Tguard());
1180
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02001181 f_init_vty("VirtMSC");
Pau Espin Pedrol23510fb2021-07-20 17:00:38 +02001182 f_vty_allow_osmux(allow_osmux);
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02001183
Neels Hofmeyra460f1f2020-08-09 20:17:03 +00001184 var my_BooleanList allow_attach := { false, false, false };
Daniel Willmannebdecc02020-08-12 15:30:17 +02001185 f_init_statsd("VirtMSC", vc_STATSD, mp_test_ip, mp_bsc_statsd_port);
1186
Neels Hofmeyr9db8e0e2021-08-23 20:45:58 +02001187 /* Make sure each MSC's internal state is "DISCONNECTED" at first */
1188 for (bssap_idx := 0; bssap_idx < NUM_MSC; bssap_idx := bssap_idx+1) {
1189 f_vty_transceive(BSCVTY, "msc " & int2str(bssap_idx) & " bssmap reset", strict := false);
1190 }
1191
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001192 for (bssap_idx := 0; bssap_idx < nr_msc; bssap_idx := bssap_idx+1) {
Neels Hofmeyra460f1f2020-08-09 20:17:03 +00001193 allow_attach[bssap_idx] := true;
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001194 /* Call a function of our 'parent component' RAN_Adapter_CT to start the
1195 * MSC-side BSSAP emulation */
1196 if (handler_mode) {
1197 var RanOps ranops := MSC_RanOps;
1198 ranops.use_osmux := g_osmux_enabled;
1199 f_ran_adapter_init(g_bssap[bssap_idx], mp_bssap_cfg[bssap_idx], "VirtMSC", ranops);
1200 connect(self:SCCPLITE_IPA_CTRL, g_bssap[bssap_idx].vc_RAN:CTRL_CLIENT);
1201 f_ran_adapter_start(g_bssap[bssap_idx]);
1202 } else {
1203 f_ran_adapter_init(g_bssap[bssap_idx], mp_bssap_cfg[bssap_idx], "VirtMSC", omit);
1204 connect(self:BSSAP, g_bssap[bssap_idx].vc_SCCP:SCCP_SP_PORT);
1205 f_ran_adapter_start(g_bssap[bssap_idx]);
1206 f_legacy_bssap_reset();
1207 }
Harald Welte67089ee2018-01-17 22:19:03 +01001208 }
Harald Welted5833a82018-05-27 16:52:56 +02001209
Neels Hofmeyrcfe44062020-10-15 02:28:08 +02001210 if (mp_enable_lcs_tests) {
1211 if (handler_mode) {
1212 f_bssap_le_adapter_init(g_bssap_le, mp_bssap_le_cfg, "VirtSMLC", SMLC_BssapLeOps);
1213 } else {
1214 f_bssap_le_adapter_init(g_bssap_le, mp_bssap_le_cfg, "VirtSMLC", omit);
1215 connect(self:BSSAP_LE, g_bssap_le.vc_SCCP:SCCP_SP_PORT);
1216 }
1217 f_bssap_le_adapter_start(g_bssap_le);
Harald Welte47cd0e32020-08-21 12:39:11 +02001218 }
Harald Welte47cd0e32020-08-21 12:39:11 +02001219
Neels Hofmeyra460f1f2020-08-09 20:17:03 +00001220 /* start the test with exactly all enabled MSCs allowed to attach */
1221 f_vty_msc_allow_attach(BSCVTY, allow_attach);
1222
Pau Espin Pedrol9a5b8ff2021-01-04 19:01:31 +01001223 f_ipa_ctrl_start_client(mp_bsc_ip, mp_bsc_ctrl_port);
Harald Welte28d943e2017-11-25 15:00:50 +01001224
Daniel Willmann191e0d92018-01-17 12:44:35 +01001225 f_init_mgcp("VirtMSC");
1226
Neels Hofmeyr0b7365b2020-07-04 00:52:34 +02001227 for (var integer i := 0; i < nr_bts; i := i+1) {
1228 f_init_bts(i, handler_mode);
Harald Welte696ddb62017-12-08 14:01:43 +01001229 }
Neels Hofmeyr0b7365b2020-07-04 00:52:34 +02001230}
Harald Welte696ddb62017-12-08 14:01:43 +01001231
Neels Hofmeyr0b7365b2020-07-04 00:52:34 +02001232function f_init_bts(integer bts_idx := 0, boolean handler_mode := false)
1233runs on test_CT {
1234 /* wait until osmo-bts-omldummy has respawned */
1235 f_wait_oml(bts_idx, "degraded", 5.0);
1236
1237 /* start RSL connection */
1238 f_ipa_rsl_start(bts[bts_idx].rsl, mp_bsc_ip, mp_bsc_rsl_port, bts_idx, handler_mode);
1239 /* wait until BSC tells us "connected" */
1240 f_wait_oml(bts_idx, "connected", 5.0);
Harald Welte28d943e2017-11-25 15:00:50 +01001241}
1242
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +02001243function f_init_bts_and_check_sysinfo(integer bts_idx := 0, boolean handler_mode := false,
1244 template SystemInformationConfig expect_si)
1245runs on test_CT {
1246 var default sysinfo := activate(as_catch_RSL_sysinfo(bts_idx));
1247
1248 f_init_bts(bts_idx, handler_mode);
1249
1250 /* Give some time to (hopefully/most likely) collect all system informations from RSL startup.
1251 * We could stop as soon as all expected SI are received, but then we might miss SI that we don't expect and
1252 * that might be sent afterwards. So rather give a generous timeout and be quite sure to catch all SI.
1253 */
1254 f_sleep(5.0);
1255 log("RSL ", bts_idx, " SYSTEM INFORMATION: ", g_system_information[bts_idx]);
1256
1257 deactivate(sysinfo);
1258
1259 if (match(g_system_information[bts_idx], expect_si)) {
1260 setverdict(pass);
1261 } else {
1262 log("RSL ", bts_idx, ": EXPECTED SI: ", expect_si);
1263 log("RSL ", bts_idx, ": GOT SI: ", g_system_information[bts_idx]);
1264 setverdict(fail, "received SI does not match expectations");
1265 return;
1266 }
1267}
1268
Maxd4e56962018-10-31 19:08:25 +01001269/* expect to receive a RSL message matching a specified template on a given BTS / stream */
Harald Welte65e419a2020-08-21 12:38:33 +02001270function f_exp_ipa_rx(integer bts_nr, template (present) RSL_Message t_rx, float t_secs := 2.0, IpaStreamId sid := IPAC_PROTO_RSL_TRX0)
Harald Welteae026692017-12-09 01:03:01 +01001271runs on test_CT return RSL_Message {
1272 var ASP_RSL_Unitdata rx_rsl_ud;
1273 timer T := t_secs;
1274
1275 T.start;
1276 alt {
Vadim Yanitskiy9b4e3562020-05-25 21:40:52 +07001277 [] IPA_RSL[bts_nr].receive(tr_ASP_RSL_UD(t_rx, sid)) -> value rx_rsl_ud {
Harald Welteae026692017-12-09 01:03:01 +01001278 T.stop;
1279 }
1280 [] IPA_RSL[bts_nr].receive { repeat; }
Harald Welteb2917702017-12-10 15:48:52 +01001281 [] T.timeout {
1282 setverdict(fail, "Timeout expecting ", t_rx);
Daniel Willmannafce8662018-07-06 23:11:32 +02001283 mtc.stop;
Harald Welteb2917702017-12-10 15:48:52 +01001284 }
Harald Welteae026692017-12-09 01:03:01 +01001285 }
1286 return rx_rsl_ud.rsl;
1287}
1288
Harald Welte21b46bd2017-12-17 19:46:32 +01001289/* helper function to transmit RSL on a given BTS/stream */
Harald Welte65e419a2020-08-21 12:38:33 +02001290function f_ipa_tx(integer bts_nr, template (value) RSL_Message t_tx, IpaStreamId sid := IPAC_PROTO_RSL_TRX0)
Harald Welteae026692017-12-09 01:03:01 +01001291runs on test_CT {
Vadim Yanitskiy9b4e3562020-05-25 21:40:52 +07001292 IPA_RSL[bts_nr].send(ts_ASP_RSL_UD(t_tx, sid));
Harald Welteae026692017-12-09 01:03:01 +01001293}
1294
1295
Harald Welte4003d112017-12-09 22:35:39 +01001296/* verify we get a CHAN_ACT after CHAN RQD */
Harald Welteae026692017-12-09 01:03:01 +01001297testcase TC_chan_act_noreply() runs on test_CT {
1298 var BSSAP_N_UNITDATA_ind ud_ind;
Harald Welte930d0a72018-03-22 22:08:40 +01001299 var RSL_Message rsl_unused;
Harald Welte28d943e2017-11-25 15:00:50 +01001300
Harald Welte89d42e82017-12-17 16:42:41 +01001301 f_init(1);
Harald Welte28d943e2017-11-25 15:00:50 +01001302
Vadim Yanitskiy9b4e3562020-05-25 21:40:52 +07001303 IPA_RSL[0].send(ts_ASP_RSL_UD(ts_RSL_CHAN_RQD('23'O, 23)));
Harald Welte930d0a72018-03-22 22:08:40 +01001304 rsl_unused := f_exp_ipa_rx(0, tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001305 f_shutdown_helper();
Harald Welte28d943e2017-11-25 15:00:50 +01001306}
1307
Neels Hofmeyr734b1a32021-11-29 16:00:17 +01001308const CounterNameVals counternames_bts_chreq := {
1309 { "chreq:total", 0 },
1310 { "chreq:attempted_emerg", 0 },
1311 { "chreq:attempted_call", 0 },
1312 { "chreq:attempted_location_upd", 0 },
1313 { "chreq:attempted_pag", 0 },
1314 { "chreq:attempted_pdch", 0 },
1315 { "chreq:attempted_other", 0 },
1316 { "chreq:attempted_unknown", 0 },
1317 { "chreq:successful", 0 },
1318 { "chreq:successful_emerg", 0 },
1319 { "chreq:successful_call", 0 },
1320 { "chreq:successful_location_upd", 0 },
1321 { "chreq:successful_pag", 0 },
1322 { "chreq:successful_pdch", 0 },
1323 { "chreq:successful_other", 0 },
1324 { "chreq:successful_unknown", 0 },
1325 { "chreq:no_channel", 0 },
1326 { "chreq:max_delay_exceeded", 0 }
1327};
1328
1329/* verify the "chreq:*" counters */
1330private function f_chan_act_counter(OCT1 ra, charstring chreq_ctr_suffix) runs on test_CT
1331{
1332 var GsmFrameNumber fn := 23;
1333
1334 f_logp(BSCVTY, "f_chan_act_counter(" & chreq_ctr_suffix & ")");
1335
1336 var RSL_Message rx_rsl;
1337 f_ipa_tx(0, ts_RSL_CHAN_RQD(ra, fn));
1338 rx_rsl := f_exp_ipa_rx(0, tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
1339 var RslChannelNr chan_nr := rx_rsl.ies[0].body.chan_nr;
1340
1341 f_ctrs_bts_add(0, "chreq:total");
1342 f_ctrs_bts_add(0, "chreq:attempted_" & chreq_ctr_suffix);
1343 f_ctrs_bts_verify();
1344
1345 f_ipa_tx(0, ts_RSL_CHAN_ACT_ACK(chan_nr, fn+10));
1346 rx_rsl := f_exp_ipa_rx(0, tr_RSL_IMM_ASSIGN(0));
1347
1348 f_ctrs_bts_add(0, "chreq:successful");
1349 f_ctrs_bts_add(0, "chreq:successful_" & chreq_ctr_suffix);
1350 f_ctrs_bts_verify();
1351
1352 /* test is done, release RSL Conn Fail Ind to clean up */
1353 f_ipa_tx(0, ts_RSL_CONN_FAIL_IND(chan_nr, RSL_ERR_RADIO_LINK_FAIL));
1354 rx_rsl := f_exp_ipa_rx(0, tr_RSL_MsgTypeD(RSL_MT_RF_CHAN_REL), 10.0);
1355 f_ipa_tx(0, ts_RSL_RF_CHAN_REL_ACK(chan_nr));
1356 f_sleep(1.0);
1357}
1358
Harald Welte4003d112017-12-09 22:35:39 +01001359testcase TC_chan_act_counter() runs on test_CT {
1360 var BSSAP_N_UNITDATA_ind ud_ind;
1361 var integer chreq_total;
Harald Welte930d0a72018-03-22 22:08:40 +01001362 var RSL_Message rsl_unused;
Harald Welte4003d112017-12-09 22:35:39 +01001363
Harald Welte89d42e82017-12-17 16:42:41 +01001364 f_init(1);
Harald Welte4003d112017-12-09 22:35:39 +01001365
Neels Hofmeyr734b1a32021-11-29 16:00:17 +01001366 f_vty_allow_emerg_bts(true, 0);
1367
1368 f_ctrs_bts_init(1, counternames_bts_chreq);
1369
1370 /* emergency call: RA & 0xe0 == 0xa0 --> CHREQ_T_EMERG_CALL */
1371 f_chan_act_counter('a3'O, "emerg");
1372
1373 /* voice TCH/H: RA & 0xf0 == 0x40 --> CHREQ_T_VOICE_CALL_TCH_H */
1374 f_chan_act_counter('43'O, "call");
1375
1376 /* LU: RA & 0xf0 == 0x00 --> CHREQ_T_LOCATION_UPD */
1377 f_chan_act_counter('03'O, "location_upd");
1378
1379 /* Paging: RA & 0xf0 == 0x20 --> CHREQ_T_PAG_R_TCH_F */
1380 f_chan_act_counter('23'O, "pag");
1381 /* Paging: RA & 0xf0 == 0x30 --> CHREQ_T_PAG_R_TCH_FH */
1382 f_chan_act_counter('33'O, "pag");
1383
1384 /* LU: RA & 0xfc == 0x78 --> CHREQ_T_PDCH_TWO_PHASE */
1385 /* no PCU, so PDCH not allowed. Skip this test for now. */
1386 /* f_chan_act_counter('7b'O, "pdch"); */
1387
1388 /* LU: RA & 0xf0 == 0x10 --> CHREQ_T_SDCCH */
1389 f_chan_act_counter('13'O, "other");
Harald Welte4003d112017-12-09 22:35:39 +01001390
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001391 f_shutdown_helper();
Harald Welte4003d112017-12-09 22:35:39 +01001392}
1393
Harald Welteae026692017-12-09 01:03:01 +01001394/* CHAN RQD -> CHAN ACT -> CHAN ACT ACK -> RF CHAN REL */
Philipp Maier9c60a622020-07-09 15:08:46 +02001395private function f_TC_chan_act_ack_noest(OCT1 ra := '23'O) runs on test_CT {
Harald Welteae026692017-12-09 01:03:01 +01001396 var RSL_Message rx_rsl;
1397
Harald Welteae026692017-12-09 01:03:01 +01001398 /* Send CHAN RQD and wait for allocation; acknowledge it */
Philipp Maier9c60a622020-07-09 15:08:46 +02001399 var RslChannelNr chan_nr := f_chreq_act_ack(ra);
Harald Welteae026692017-12-09 01:03:01 +01001400
1401 /* expect BSC to disable the channel again if there's no RLL EST IND */
1402 rx_rsl := f_exp_ipa_rx(0, tr_RSL_MsgTypeD(RSL_MT_RF_CHAN_REL), T3101_MAX);
1403
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001404 f_shutdown_helper();
Harald Welteae026692017-12-09 01:03:01 +01001405}
1406
Philipp Maier9c60a622020-07-09 15:08:46 +02001407/* Normal variant */
1408testcase TC_chan_act_ack_noest() runs on test_CT {
Philipp Maieraf58db22020-08-12 17:24:40 +02001409 f_init(1);
Philipp Maier9c60a622020-07-09 15:08:46 +02001410 f_TC_chan_act_ack_noest();
1411}
1412
1413/* Emergency call variant */
1414testcase TC_chan_act_ack_noest_emerg() runs on test_CT {
1415 /* See also: 3GPP TS 04.08, Table 9.9, ra=101xxxxx */
Philipp Maieraf58db22020-08-12 17:24:40 +02001416 f_init(1);
1417 f_vty_allow_emerg_bts(true, 0);
Philipp Maier9c60a622020-07-09 15:08:46 +02001418 f_TC_chan_act_ack_noest(ra := 'A5'O);
1419}
1420
Philipp Maier606f07d2020-08-12 17:21:58 +02001421/* Emergency call variant, but emergency calls are not allowed */
1422testcase TC_chan_rqd_emerg_deny() runs on test_CT {
1423 /* See also: 3GPP TS 04.08, Table 9.9, ra=101xxxxx */
1424
1425 var RSL_Message rx_rsl;
1426 var GsmRrMessage rr;
1427
1428 f_init(1);
1429 f_vty_allow_emerg_bts(false, 0);
1430
1431 IPA_RSL[0].clear;
1432 f_ipa_tx(0, ts_RSL_CHAN_RQD('A5'O, 23));
1433
1434 rx_rsl := f_exp_ipa_rx(0, tr_RSL_MsgTypeC(RSL_MT_IMMEDIATE_ASSIGN_CMD));
1435 rr := dec_GsmRrMessage(rx_rsl.ies[1].body.full_imm_ass_info.payload);
1436 if (rr.header.message_type == IMMEDIATE_ASSIGNMENT_REJECT) {
1437 setverdict(pass);
1438 } else {
1439 setverdict(fail, "immediate assignment not rejected");
1440 }
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +01001441
1442 f_shutdown_helper();
Philipp Maier606f07d2020-08-12 17:21:58 +02001443}
1444
Harald Welteae026692017-12-09 01:03:01 +01001445/* Test behavior if MSC never answers to CR */
1446testcase TC_chan_act_ack_est_ind_noreply() runs on test_CT {
Harald Weltef77aef62018-01-28 15:35:42 +01001447 var RslLinkId main_dcch := valueof(ts_RslLinkID_DCCH(0));
1448 var IpaStreamId sid := IPAC_PROTO_RSL_TRX0;
Harald Welteae026692017-12-09 01:03:01 +01001449 var RSL_Message rx_rsl;
Harald Weltef77aef62018-01-28 15:35:42 +01001450 var ASP_RSL_Unitdata rx_rsl_ud;
Harald Welteae026692017-12-09 01:03:01 +01001451
Harald Welte89d42e82017-12-17 16:42:41 +01001452 f_init(1);
Harald Welteae026692017-12-09 01:03:01 +01001453
1454 /* Send CHAN RQD and wait for allocation; acknowledge it */
Harald Welted6939652017-12-13 21:02:46 +01001455 var RslChannelNr chan_nr := f_chreq_act_ack();
Harald Welteae026692017-12-09 01:03:01 +01001456
1457 var octetstring l3 := '00010203040506'O
1458 f_ipa_tx(0, ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3));
1459
1460 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3)));
1461
1462 /* expect BSC to disable the channel again if there's no response from MSC */
Harald Weltef77aef62018-01-28 15:35:42 +01001463 /* MS waits 20s (T3210) at LU; 10s (T3230) at CM SERV REQ and 5s (T3220) AT detach */
Neels Hofmeyra5302c82018-11-04 23:09:58 +01001464 f_expect_chan_rel(0, chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001465 f_shutdown_helper();
Harald Welteae026692017-12-09 01:03:01 +01001466}
1467
1468/* Test behavior if MSC answers with CREF to CR */
1469testcase TC_chan_act_ack_est_ind_refused() runs on test_CT {
1470 var BSSAP_N_CONNECT_ind rx_c_ind;
1471 var RSL_Message rx_rsl;
1472
Harald Welte89d42e82017-12-17 16:42:41 +01001473 f_init(1);
Harald Welteae026692017-12-09 01:03:01 +01001474
1475 /* Send CHAN RQD and wait for allocation; acknowledge it */
Harald Welted6939652017-12-13 21:02:46 +01001476 var RslChannelNr chan_nr := f_chreq_act_ack();
Harald Welteae026692017-12-09 01:03:01 +01001477
1478 var octetstring l3 := '00010203040506'O
1479 f_ipa_tx(0, ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3));
1480
1481 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3))) -> value rx_c_ind;
1482 BSSAP.send(ts_BSSAP_DISC_req(rx_c_ind.connectionId, 0));
1483
1484 /* expect BSC to disable the channel */
Neels Hofmeyra5302c82018-11-04 23:09:58 +01001485 f_expect_chan_rel(0, chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001486 f_shutdown_helper();
Harald Welteae026692017-12-09 01:03:01 +01001487}
1488
Harald Welte618ef642017-12-14 14:58:20 +01001489/* CHAN RQD -> CHAN ACT -> CHAN ACT NACK -> RF CHAN REL */
1490testcase TC_chan_act_nack() runs on test_CT {
1491 var RSL_Message rx_rsl;
1492 var integer chact_nack;
1493
Harald Welte89d42e82017-12-17 16:42:41 +01001494 f_init(1);
Harald Welte618ef642017-12-14 14:58:20 +01001495
1496 chact_nack := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", 0, "chan_act:nack");
1497
1498 f_ipa_tx(0, ts_RSL_CHAN_RQD('33'O, 33));
1499 rx_rsl := f_exp_ipa_rx(0, tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
1500 var RslChannelNr chan_nr := rx_rsl.ies[0].body.chan_nr;
1501
1502 f_ipa_tx(0, ts_RSL_CHAN_ACT_NACK(chan_nr, RSL_ERR_EQUIPMENT_FAIL));
1503
1504 /* wait for some time to hope the NACK arrives before the CTRL GET below */
1505 f_sleep(0.5);
1506
1507 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", 0, "chan_act:nack", chact_nack+1);
1508
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001509 f_shutdown_helper();
Harald Welte618ef642017-12-14 14:58:20 +01001510}
1511
Harald Welte799c97b2017-12-14 17:50:30 +01001512/* Test for channel exhaustion due to RACH overload */
1513testcase TC_chan_exhaustion() runs on test_CT {
1514 var ASP_RSL_Unitdata rsl_ud;
1515 var integer i;
1516 var integer chreq_total, chreq_nochan;
1517
Harald Welte89d42e82017-12-17 16:42:41 +01001518 f_init(1);
Harald Welte799c97b2017-12-14 17:50:30 +01001519
1520 chreq_total := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:total");
1521 chreq_nochan := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:no_channel");
1522
Neels Hofmeyr85fa37f2021-10-06 13:50:38 +02001523 /* GSM 44.018 Table 9.1.8.2:
Pau Espin Pedrolfe200d72018-12-10 12:41:04 +01001524 * RA = '33'O -> Establishment cause = 0011xxxx (MS dual rate capable and asks for "TCH/H or TCH/F").
1525 * With current setup, expect 4xSDCCH + 4xTCH/F + 1xTCH/H to succeed */
Philipp Maiercb6cc482018-03-26 13:08:00 +02001526 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 +01001527 var RslChannelNr chan_nr := f_chreq_act_ack('33'O, i);
Harald Welte799c97b2017-12-14 17:50:30 +01001528 }
1529
1530 IPA_RSL[0].clear;
1531
Harald Weltedd8cbf32018-01-28 12:07:52 +01001532 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:total",
Philipp Maiercb6cc482018-03-26 13:08:00 +02001533 chreq_total + NUM_TCHF_PER_BTS + NUM_TCHH_PER_BTS + NUM_SDCCH_PER_BTS);
Harald Welte799c97b2017-12-14 17:50:30 +01001534
1535 /* now expect additional channel activations to fail */
1536 f_ipa_tx(0, ts_RSL_CHAN_RQD('42'O, 42));
1537
1538 alt {
Vadim Yanitskiy9b4e3562020-05-25 21:40:52 +07001539 [] IPA_RSL[0].receive(tr_ASP_RSL_UD(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV))) {
Harald Welte799c97b2017-12-14 17:50:30 +01001540 setverdict(fail, "Received CHAN ACT ACK without resources?!?");
1541 }
Vadim Yanitskiy9b4e3562020-05-25 21:40:52 +07001542 [] IPA_RSL[0].receive(tr_ASP_RSL_UD(tr_RSL_IMM_ASSIGN(?))) -> value rsl_ud {
Harald Welte799c97b2017-12-14 17:50:30 +01001543 var GsmRrMessage rr;
1544 /* match on IMM ASS REJ */
1545 rr := dec_GsmRrMessage(rsl_ud.rsl.ies[1].body.full_imm_ass_info.payload);
1546 if (rr.header.message_type == IMMEDIATE_ASSIGNMENT_REJECT) {
1547 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:total",
Philipp Maiercb6cc482018-03-26 13:08:00 +02001548 chreq_total + NUM_TCHF_PER_BTS + NUM_TCHH_PER_BTS + NUM_SDCCH_PER_BTS+1);
Harald Welte799c97b2017-12-14 17:50:30 +01001549 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:no_channel",
1550 chreq_nochan+1);
1551 setverdict(pass);
1552 } else {
1553 repeat;
1554 }
1555 }
1556 [] IPA_RSL[0].receive { repeat; }
1557 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001558 f_shutdown_helper();
Harald Welte799c97b2017-12-14 17:50:30 +01001559}
1560
Vadim Yanitskiy1ff1fdf2018-11-27 01:32:57 +07001561/* Test channel deactivation due to silence from MS */
1562testcase TC_chan_deact_silence() runs on test_CT {
1563 var RslChannelNr chan_nr;
1564
1565 f_init(1);
1566
1567 /* Request for a dedicated channel */
1568 chan_nr := f_chreq_act_ack('23'O);
1569
1570 /* Wait some time until the channel is released */
1571 f_sleep(2.0);
1572
1573 /* Expect CHANnel RELease */
1574 alt {
Vadim Yanitskiy9b4e3562020-05-25 21:40:52 +07001575 [] IPA_RSL[0].receive(tr_ASP_RSL_UD(tr_RSL_MsgTypeD(RSL_MT_RF_CHAN_REL))) {
Vadim Yanitskiy1ff1fdf2018-11-27 01:32:57 +07001576 log("Received CHANnel RELease");
1577 setverdict(pass);
1578 }
Vadim Yanitskiy9b4e3562020-05-25 21:40:52 +07001579 [] IPA_RSL[0].receive(tr_ASP_RSL_UD(tr_RSL_IMM_ASSIGN(?))) {
Vadim Yanitskiy1ff1fdf2018-11-27 01:32:57 +07001580 /* See OS#3709, OsmoBSC should not send Immediate
1581 * Assignment Reject since a dedicated channel was
1582 * already allocated, and Immediate Assignment was
1583 * already sent. */
1584 setverdict(fail, "Unexpected Immediate Assignment!");
1585 }
1586 [] IPA_RSL[0].receive {
1587 setverdict(fail, "Unexpected RSL message!");
1588 }
1589 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001590 f_shutdown_helper();
Vadim Yanitskiy1ff1fdf2018-11-27 01:32:57 +07001591}
1592
Harald Weltecfe2c962017-12-15 12:09:32 +01001593/***********************************************************************
1594 * Assignment Testing
1595 ***********************************************************************/
1596
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02001597/* Verify that the BSC refuses any BSSAP connection from the MSC (They are all BSC->MSC direction,
1598 * except for the inter-BSC handover, MT side) */
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001599testcase TC_outbound_connect(integer bssap_idx := 0) runs on test_CT {
Harald Welte89d42e82017-12-17 16:42:41 +01001600 f_init(1);
Harald Weltecfe2c962017-12-15 12:09:32 +01001601
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001602 BSSAP.send(ts_BSSAP_CONNECT_req(g_bssap[bssap_idx].sccp_addr_peer, g_bssap[bssap_idx].sccp_addr_own,
1603 2342, ts_BSSMAP_AssignmentReq));
Harald Weltecfe2c962017-12-15 12:09:32 +01001604 BSSAP.receive(tr_BSSAP_DISC_ind(2342, ?, ?));
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001605 f_shutdown_helper();
Harald Weltecfe2c962017-12-15 12:09:32 +01001606}
1607
Harald Welte16a4adf2017-12-14 18:54:01 +01001608/* Test behavior if MSC answers with CREF to CR */
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001609testcase TC_assignment_cic_only(integer bssap_idx := 0) runs on test_CT {
Harald Welte16a4adf2017-12-14 18:54:01 +01001610 var BSSAP_N_CONNECT_ind rx_c_ind;
1611 var RSL_Message rx_rsl;
1612 var DchanTuple dt;
1613
Harald Welte89d42e82017-12-17 16:42:41 +01001614 f_init(1);
Harald Welte16a4adf2017-12-14 18:54:01 +01001615
1616 dt := f_est_dchan('23'O, 23, '00000000'O);
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001617 if (mp_bssap_cfg[bssap_idx].transport == BSSAP_TRANSPORT_AoIP) {
Harald Welte17b27da2018-05-25 20:33:53 +02001618 /* send assignment without AoIP IEs */
1619 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_AssignmentReq(ts_BSSMAP_IE_CIC(0, 1))));
1620 } else {
1621 /* Send assignmetn without CIC in IPA case */
1622 var BSSMAP_IE_AoIP_TransportLayerAddress tla :=
1623 valueof(ts_BSSMAP_IE_AoIP_TLA4('01020304'O, 2342));
1624 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_AssignmentReq(omit, tla)));
1625 }
Harald Welte16a4adf2017-12-14 18:54:01 +01001626 alt {
1627 [] BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_AssignmentComplete)) {
1628 setverdict(fail, "AoIP BSC cannot accept ASSIGNMENT without AoIP Transport IE");
1629 }
Harald Welte235ebf12017-12-15 14:18:16 +01001630 /* TODO: Actually expect GSM0808_CAUSE_REQ_A_IF_TYPE_NOT_SUPP */
Harald Welte16a4adf2017-12-14 18:54:01 +01001631 [] BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_AssignmentFail)) {
1632 setverdict(pass);
1633 }
1634 [] BSSAP.receive { repeat; }
1635 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01001636 f_perform_clear_test_ct(dt);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001637 f_shutdown_helper();
Harald Welte16a4adf2017-12-14 18:54:01 +01001638}
1639
Harald Welteed848512018-05-24 22:27:58 +02001640/* generate an assignment request for either AoIP or SCCPlite */
Pau Espin Pedrol07866632020-09-03 19:10:55 +02001641function 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 +02001642 var PDU_BSSAP ass_cmd;
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02001643 var BSSMAP_IE_Osmo_OsmuxCID osmux_cid := valueof(ts_OsmuxCID(0));
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001644 if (mp_bssap_cfg[bssap_idx].transport == BSSAP_TRANSPORT_AoIP) {
Harald Welteed848512018-05-24 22:27:58 +02001645 var BSSMAP_IE_AoIP_TransportLayerAddress tla :=
Pau Espin Pedrol07866632020-09-03 19:10:55 +02001646 valueof(f_ts_BSSMAP_IE_AoIP_TLA(aoip_tla, 2342));
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02001647 if (osmux_enabled) {
1648 ass_cmd := valueof(ts_BSSMAP_AssignmentReq(omit, tla, osmux_cid));
1649 } else {
1650 ass_cmd := valueof(ts_BSSMAP_AssignmentReq(omit, tla));
1651 }
Harald Welteed848512018-05-24 22:27:58 +02001652 } else {
1653 var BSSMAP_IE_CircuitIdentityCode cic := valueof(ts_BSSMAP_IE_CIC(0,1));
Pau Espin Pedrol096d73d2019-06-06 12:49:17 +02001654 ass_cmd := valueof(ts_BSSMAP_AssignmentReq(cic, omit));
Harald Welteed848512018-05-24 22:27:58 +02001655 }
1656 return ass_cmd;
1657}
1658
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02001659function f_gen_handover_req(integer bssap_idx := 0, charstring aoip_tla := "1.2.3.4",
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02001660 template (omit) BSSMAP_oldToNewBSSIEs oldToNewBSSIEs := omit,
1661 template (omit) TestHdlrEncrParams enc := omit) return PDU_BSSAP {
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01001662 var PDU_BSSAP ho_req;
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02001663
1664 var BSSMAP_IE_EncryptionInformation encryptionInformation :=
1665 valueof(ts_BSSMAP_IE_EncrInfo('0000000000000000'O,'01'O));
1666 var template BSSMAP_IE_ChosenEncryptionAlgorithm chosenEncryptionAlgorithm := omit;
1667 var template BSSMAP_IE_KC128 kc128 := omit;
1668 if (ispresent(enc)) {
1669 var TestHdlrEncrParams v_enc := valueof(enc);
1670 encryptionInformation := valueof(ts_BSSMAP_IE_EncrInfo(v_enc.enc_key, v_enc.enc_alg));
1671 chosenEncryptionAlgorithm := valueof(
1672 ts_BSSMAP_IE_ChosenEncryptionAlgorithm(int2oct(enum2int(
Oliver Smith598e1ed2021-07-09 10:28:40 +02001673 f_cipher_mode_bssmap_to_rsl(v_enc.enc_alg)), 1)));
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02001674 if (ispresent(v_enc.enc_kc128)) {
1675 kc128 := ts_BSSMAP_IE_Kc128(v_enc.enc_kc128);
1676 }
1677 }
1678
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001679 if (mp_bssap_cfg[bssap_idx].transport == BSSAP_TRANSPORT_AoIP) {
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01001680 var BSSMAP_IE_AoIP_TransportLayerAddress tla :=
Pau Espin Pedrol07866632020-09-03 19:10:55 +02001681 valueof(f_ts_BSSMAP_IE_AoIP_TLA(aoip_tla, 2342));
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02001682 ho_req := valueof(ts_BSSMAP_HandoverRequest(omit, tla, oldToNewBSSIEs := oldToNewBSSIEs,
1683 encryptionInformation := encryptionInformation,
1684 chosenEncryptionAlgorithm := chosenEncryptionAlgorithm,
1685 kC128 := kc128));
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01001686 } else {
1687 var BSSMAP_IE_CircuitIdentityCode cic := valueof(ts_BSSMAP_IE_CIC(0,1));
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02001688 ho_req := valueof(ts_BSSMAP_HandoverRequest(cic, omit, oldToNewBSSIEs := oldToNewBSSIEs,
1689 encryptionInformation := encryptionInformation,
1690 chosenEncryptionAlgorithm := chosenEncryptionAlgorithm,
1691 kC128 := kc128));
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01001692 }
1693 return ho_req;
1694}
1695
Harald Welteed848512018-05-24 22:27:58 +02001696/* generate an assignment complete template for either AoIP or SCCPlite */
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001697function f_gen_exp_compl(boolean expect_osmux := false, integer bssap_idx := 0) return template PDU_BSSAP {
Harald Welteed848512018-05-24 22:27:58 +02001698 var template PDU_BSSAP exp_compl;
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02001699 var BSSMAP_IE_Osmo_OsmuxCID osmux_cid := valueof(ts_OsmuxCID(0));
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001700 if (mp_bssap_cfg[bssap_idx].transport == BSSAP_TRANSPORT_AoIP) {
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02001701 if (expect_osmux) {
1702 exp_compl := tr_BSSMAP_AssignmentComplete(omit, ?, osmux_cid);
1703 } else {
1704 exp_compl := tr_BSSMAP_AssignmentComplete(omit, ?, omit);
1705 }
Harald Welteed848512018-05-24 22:27:58 +02001706 } else {
1707 /* CIC is optional "*" as the MSC allocated it */
Pau Espin Pedrol096d73d2019-06-06 12:49:17 +02001708 exp_compl := tr_BSSMAP_AssignmentComplete(*, omit);
Harald Welteed848512018-05-24 22:27:58 +02001709 }
1710 return exp_compl;
1711}
1712
Harald Welte235ebf12017-12-15 14:18:16 +01001713/* Run everything required up to sending a caller-specified assignment command and expect response */
1714function f_assignment_exp(PDU_BSSAP ass_cmd, template PDU_BSSAP exp, charstring fail_text)
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01001715runs on test_CT return DchanTuple {
Harald Welte235ebf12017-12-15 14:18:16 +01001716 var BSSAP_N_CONNECT_ind rx_c_ind;
1717 var RSL_Message rx_rsl;
1718 var DchanTuple dt;
1719
Harald Welte89d42e82017-12-17 16:42:41 +01001720 f_init(1);
Harald Welte235ebf12017-12-15 14:18:16 +01001721
1722 dt := f_est_dchan('23'O, 23, '00000000'O);
1723 /* send assignment without AoIP IEs */
1724 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ass_cmd));
1725 alt {
1726 [] BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_AssignmentComplete)) {
1727 if (ischosen(exp.pdu.bssmap.assignmentComplete)) {
1728 setverdict(pass);
1729 } else {
1730 setverdict(fail, fail_text);
1731 }
1732 }
1733 [] BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_AssignmentFail)) {
1734 if (ischosen(exp.pdu.bssmap.assignmentFailure)) {
1735 setverdict(pass);
1736 } else {
1737 setverdict(fail, fail_text);
1738 }
1739 }
1740 [] BSSAP.receive { repeat; }
1741 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01001742 return dt;
Harald Welte235ebf12017-12-15 14:18:16 +01001743}
1744testcase TC_assignment_csd() runs on test_CT {
1745 var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
Harald Welteed848512018-05-24 22:27:58 +02001746 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Harald Welte235ebf12017-12-15 14:18:16 +01001747 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelTypeCSD);
1748 //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 +01001749 var DchanTuple dt := f_assignment_exp(ass_cmd, exp_fail, "BSC accepted Assignment for CSD");
1750 f_perform_clear_test_ct(dt);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001751 f_shutdown_helper();
Harald Welte235ebf12017-12-15 14:18:16 +01001752}
1753
1754testcase TC_assignment_ctm() runs on test_CT {
1755 var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
Harald Welteed848512018-05-24 22:27:58 +02001756 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Harald Welte235ebf12017-12-15 14:18:16 +01001757 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelTypeCTM);
1758 //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 +01001759 var DchanTuple dt := f_assignment_exp(ass_cmd, exp_fail, "BSC accepted Assignment for Speech+CTM");
1760 f_perform_clear_test_ct(dt);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001761 f_shutdown_helper();
Harald Welte235ebf12017-12-15 14:18:16 +01001762}
1763
Harald Welte4003d112017-12-09 22:35:39 +01001764type record DchanTuple {
1765 integer sccp_conn_id,
1766 RslChannelNr rsl_chan_nr
Harald Weltea5d2ab22017-12-09 14:21:42 +01001767}
1768
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +02001769type record of DchanTuple DchanTuples;
1770
Harald Welted6939652017-12-13 21:02:46 +01001771/* Send CHAN RQD and wait for allocation; acknowledge it */
1772private function f_chreq_act_ack(OCT1 ra := '23'O, GsmFrameNumber fn := 23)
1773runs on test_CT return RslChannelNr {
1774 var RSL_Message rx_rsl;
1775 f_ipa_tx(0, ts_RSL_CHAN_RQD(ra, fn));
1776 rx_rsl := f_exp_ipa_rx(0, tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
1777 var RslChannelNr chan_nr := rx_rsl.ies[0].body.chan_nr;
1778 f_ipa_tx(0, ts_RSL_CHAN_ACT_ACK(chan_nr, fn+10));
Daniel Willmannf4ac4ce2018-08-02 14:06:30 +02001779 rx_rsl := f_exp_ipa_rx(0, tr_RSL_IMM_ASSIGN(0));
Harald Welted6939652017-12-13 21:02:46 +01001780 return chan_nr;
1781}
1782
Harald Welte4003d112017-12-09 22:35:39 +01001783/* helper function to establish a dedicated channel via BTS and MSC */
1784function f_est_dchan(OCT1 ra, GsmFrameNumber fn, octetstring l3)
1785runs on test_CT return DchanTuple {
1786 var BSSAP_N_CONNECT_ind rx_c_ind;
Harald Welte4003d112017-12-09 22:35:39 +01001787 var DchanTuple dt;
Harald Weltea5d2ab22017-12-09 14:21:42 +01001788
Harald Welte4003d112017-12-09 22:35:39 +01001789 /* Send CHAN RQD and wait for allocation; acknowledge it */
Harald Welted6939652017-12-13 21:02:46 +01001790 dt.rsl_chan_nr := f_chreq_act_ack(ra, fn);
Harald Welte4003d112017-12-09 22:35:39 +01001791
1792 f_ipa_tx(0, ts_RSL_EST_IND(dt.rsl_chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3));
1793
1794 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3))) -> value rx_c_ind;
1795 dt.sccp_conn_id := rx_c_ind.connectionId;
1796 BSSAP.send(ts_BSSAP_CONNECT_res(dt.sccp_conn_id));
1797
1798 return dt;
Harald Weltea5d2ab22017-12-09 14:21:42 +01001799}
1800
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02001801/* Like f_est_dchan(), but for the first lchan of a dynamic timeslot: first ACK the deactivation of PDCH. */
1802function f_est_dchan_dyn(OCT1 ra, GsmFrameNumber fn, octetstring l3)
1803runs on test_CT return DchanTuple {
1804 var BSSAP_N_CONNECT_ind rx_c_ind;
1805 var DchanTuple dt;
1806
1807 /* Send CHAN RQD */
1808 var RSL_Message rx_rsl;
1809 f_ipa_tx(0, ts_RSL_CHAN_RQD(ra, fn));
1810
1811 /* The dyn TS first deactivates PDCH */
1812 rx_rsl := f_exp_ipa_rx(0, tr_RSL_MsgTypeD(RSL_MT_RF_CHAN_REL), T3101_MAX);
1813 dt.rsl_chan_nr := rx_rsl.ies[0].body.chan_nr;
1814 f_ipa_tx(0, ts_RSL_RF_CHAN_REL_ACK(dt.rsl_chan_nr));
1815
1816 rx_rsl := f_exp_ipa_rx(0, tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
1817 dt.rsl_chan_nr := rx_rsl.ies[0].body.chan_nr;
1818
1819 /* Now activates the signalling channel */
1820 f_ipa_tx(0, ts_RSL_CHAN_ACT_ACK(dt.rsl_chan_nr, fn+10));
1821 rx_rsl := f_exp_ipa_rx(0, tr_RSL_IMM_ASSIGN(0));
1822
1823 f_ipa_tx(0, ts_RSL_EST_IND(dt.rsl_chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3));
1824
1825 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3))) -> value rx_c_ind;
1826 dt.sccp_conn_id := rx_c_ind.connectionId;
1827 BSSAP.send(ts_BSSAP_CONNECT_res(dt.sccp_conn_id));
1828
1829 return dt;
1830}
1831
Harald Welte641fcbe2018-06-14 10:58:35 +02001832/* expect RF CAN REL from BTS, acknowledge it and clear the MSC side */
1833private function f_exp_chan_rel_and_clear(DchanTuple dt, integer bts_nr := 0) runs on test_CT {
1834 var RSL_Message rx_rsl;
1835 /* expect BSC to disable the channel */
1836 rx_rsl := f_exp_ipa_rx(0, tr_RSL_MsgTypeD(RSL_MT_RF_CHAN_REL), T3101_MAX);
1837 /* respond with CHAN REL ACK */
1838 f_ipa_tx(0, ts_RSL_RF_CHAN_REL_ACK(dt.rsl_chan_nr));
1839
1840 /* expect Clear Complete from BSC */
1841 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete));
1842
1843 /* MSC disconnects as instructed. */
1844 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
1845}
1846
Harald Welte4003d112017-12-09 22:35:39 +01001847/* Test behavior of channel release after unilateral RLL REL IND (DISC from MS) */
1848testcase TC_chan_rel_rll_rel_ind() runs on test_CT {
Neels Hofmeyr27f64362018-03-12 01:44:00 +01001849 var BSSAP_N_DATA_ind rx_di;
Harald Welte4003d112017-12-09 22:35:39 +01001850 var DchanTuple dt;
Harald Welte96c94412017-12-09 03:12:45 +01001851
Harald Welte89d42e82017-12-17 16:42:41 +01001852 f_init(1);
Harald Welte96c94412017-12-09 03:12:45 +01001853
Harald Welte4003d112017-12-09 22:35:39 +01001854 dt := f_est_dchan('23'O, 23, '00010203040506'O);
1855
1856 /* simulate RLL REL IND */
1857 f_ipa_tx(0, ts_RSL_REL_IND(dt.rsl_chan_nr, valueof(ts_RslLinkID_DCCH(0))));
1858
Neels Hofmeyr27f64362018-03-12 01:44:00 +01001859 /* expect Clear Request on MSC side */
1860 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearRequest)) -> value rx_di;
1861
1862 /* Instruct BSC to clear channel */
1863 var BssmapCause cause := bit2int(rx_di.userData.pdu.bssmap.clearRequest.cause.causeValue);
1864 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
1865
Harald Welte4003d112017-12-09 22:35:39 +01001866 /* expect BSC to disable the channel */
Harald Welte641fcbe2018-06-14 10:58:35 +02001867 f_exp_chan_rel_and_clear(dt, 0);
Neels Hofmeyr27f64362018-03-12 01:44:00 +01001868
1869 /* wait for SCCP emulation to do its job */
1870 f_sleep(1.0);
Harald Welte4003d112017-12-09 22:35:39 +01001871
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001872 f_shutdown_helper();
Harald Welte4003d112017-12-09 22:35:39 +01001873}
1874
1875/* Test behavior of channel release after CONN FAIL IND from BTS */
1876testcase TC_chan_rel_conn_fail() runs on test_CT {
1877 var BSSAP_N_DATA_ind rx_di;
Harald Welte4003d112017-12-09 22:35:39 +01001878 var DchanTuple dt;
1879
Harald Welte89d42e82017-12-17 16:42:41 +01001880 f_init(1);
Harald Welte4003d112017-12-09 22:35:39 +01001881
1882 dt := f_est_dchan('23'O, 23, '00010203040506'O);
1883
1884 /* simulate CONN FAIL IND */
Harald Weltea8ed9062017-12-14 09:46:01 +01001885 f_ipa_tx(0, ts_RSL_CONN_FAIL_IND(dt.rsl_chan_nr, RSL_ERR_RADIO_LINK_FAIL));
Harald Welte4003d112017-12-09 22:35:39 +01001886 /* TODO: different cause values? */
1887
Harald Welte4003d112017-12-09 22:35:39 +01001888 /* expect Clear Request from BSC */
1889 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearRequest)) -> value rx_di;
1890
1891 /* Instruct BSC to clear channel */
1892 var BssmapCause cause := bit2int(rx_di.userData.pdu.bssmap.clearRequest.cause.causeValue);
1893 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
1894
Harald Welte6ff76ea2018-01-28 13:08:01 +01001895 /* expect BSC to disable the channel */
Harald Welte641fcbe2018-06-14 10:58:35 +02001896 f_exp_chan_rel_and_clear(dt, 0);
Harald Welte4003d112017-12-09 22:35:39 +01001897
1898 /* wait for SCCP emulation to do its job */
1899 f_sleep(1.0);
1900
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001901 f_shutdown_helper();
Harald Welte4003d112017-12-09 22:35:39 +01001902}
1903
Harald Welte99f3ca02018-06-14 13:40:29 +02001904/* Test behavior of early CONN FAIL IND from BTS (before EST IND!) */
1905/* See also https://www.osmocom.org/issues/3182 */
1906testcase TC_early_conn_fail() runs on test_CT {
1907 var RSL_Message rx_rsl;
1908 var DchanTuple dt;
1909
1910 f_init(1);
1911
1912 /* BTS->BSC: Send CHAN RQD and wait for allocation; acknowledge it */
Harald Weltec46ea3c2020-10-10 18:46:12 +02001913 dt.rsl_chan_nr := f_chreq_act_ack(f_rnd_ra_cs(), 23);
Harald Welte99f3ca02018-06-14 13:40:29 +02001914
1915 /* BTS->BSC: simulate CONN FAIL IND */
1916 f_ipa_tx(0, ts_RSL_CONN_FAIL_IND(dt.rsl_chan_nr, RSL_ERR_RADIO_LINK_FAIL));
1917
1918 /* BTS->BSC: Expect RF channel release from BSC on Abis */
1919 rx_rsl := f_exp_ipa_rx(0, tr_RSL_MsgTypeD(RSL_MT_RF_CHAN_REL), 10.0);
1920
1921 /* BTS<-BSC: respond with CHAN REL ACK */
1922 f_ipa_tx(0, ts_RSL_RF_CHAN_REL_ACK(dt.rsl_chan_nr));
1923
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001924 f_shutdown_helper();
Harald Welte99f3ca02018-06-14 13:40:29 +02001925}
1926
1927/* Test behavior of late CONN FAIL IND from BTS (ater REL IND!) */
1928/* See also https://www.osmocom.org/issues/3182 */
1929testcase TC_late_conn_fail() runs on test_CT {
1930 var RSL_Message rx_rsl;
1931 var DchanTuple dt;
1932
1933 f_init(1);
1934
1935 dt := f_est_dchan('23'O, 23, '00010203040506'O);
1936
1937 /* BSC<-MSC: Instruct BSC to clear connection */
1938 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(0)));
1939
1940 /* BTS->BSC: expect BSC to deactivate SACCH */
1941 rx_rsl := f_exp_ipa_rx(0, tr_RSL_DEACT_SACCH(dt.rsl_chan_nr));
1942
1943 /* BTS->BSC: simulate a late CONN FAIL IND from BTS */
1944 f_ipa_tx(0, ts_RSL_CONN_FAIL_IND(dt.rsl_chan_nr, RSL_ERR_RADIO_LINK_FAIL));
1945
1946 /* BTS<-BSC: Expect RF channel release from BSC on Abis */
1947 rx_rsl := f_exp_ipa_rx(0, tr_RSL_MsgTypeD(RSL_MT_RF_CHAN_REL), 10.0);
1948 /* BTS->BSC: respond with CHAN REL ACK */
1949 f_ipa_tx(0, ts_RSL_RF_CHAN_REL_ACK(dt.rsl_chan_nr));
1950
1951 /* BSC->MSC: expect Clear Complete from BSC */
1952 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete));
1953
1954 /* BSC<-MSC: MSC disconnects as requested. */
1955 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
1956
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001957 f_shutdown_helper();
Harald Welte99f3ca02018-06-14 13:40:29 +02001958}
1959
Oliver Smithaf03bef2021-08-24 15:34:51 +02001960private function f_TC_stats_conn_fail(charstring id) runs on MSC_ConnHdlr {
1961 var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
1962 var PDU_BSSAP ass_cmd := f_gen_ass_req();
1963
1964 f_statsd_reset();
1965
1966 /* Establish SDCCH */
1967 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelTypeCSD);
1968 f_establish_fully(ass_cmd, exp_fail);
1969
1970 /* Expect stats to be 0 */
1971 var StatsDExpects expect := {
1972 {name := "TTCN3.bts.0.chan.rf_fail", mtype := "c", min := 0, max := 0},
1973 {name := "TTCN3.bts.0.chan.rf_fail_sdcch", mtype := "c", min := 0, max := 0}
1974 };
1975 f_statsd_expect(expect);
1976
1977 /* Simulate CONN FAIL IND on SDCCH */
1978 RSL.send(ts_ASP_RSL_UD(
1979 ts_RSL_CONN_FAIL_IND(g_chan_nr, RSL_ERR_RADIO_LINK_FAIL),
1980 IPAC_PROTO_RSL_TRX0));
1981
Neels Hofmeyr58be48a2021-09-07 18:39:21 +02001982 f_sleep(1.0);
1983
Oliver Smithaf03bef2021-08-24 15:34:51 +02001984 /* Expect stats to be 1 */
1985 expect := {
1986 {name := "TTCN3.bts.0.chan.rf_fail", mtype := "c", min := 1, max := 1},
1987 {name := "TTCN3.bts.0.chan.rf_fail_sdcch", mtype := "c", min := 1, max := 1}
1988 };
1989 f_statsd_expect(expect);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01001990 BSSAP.receive(tr_BSSMAP_ClearRequest);
1991 f_perform_clear();
Oliver Smithaf03bef2021-08-24 15:34:51 +02001992}
1993testcase TC_stats_conn_fail() runs on test_CT {
1994 var TestHdlrParams pars := f_gen_test_hdlr_pars();
1995 var MSC_ConnHdlr vc_conn;
1996
1997 f_init(1, true);
1998 f_sleep(1.0);
1999
2000 vc_conn := f_start_handler(refers(f_TC_stats_conn_fail), pars);
2001 vc_conn.done;
2002
2003 f_shutdown_helper();
2004}
2005
Neels Hofmeyrf44ccd12018-11-05 19:15:23 +01002006function f_expect_chan_rel(integer bts_nr, RslChannelNr rsl_chan_nr,
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002007 boolean expect_deact_sacch := true,
2008 boolean expect_rr_chan_rel := true,
2009 boolean expect_rll_rel_req := true,
Harald Welte99787102019-02-04 10:41:36 +01002010 boolean handle_rll_rel := true,
Pau Espin Pedrol36bd4fa2021-04-15 13:00:24 +02002011 template CellSelIndValue expect_cells := omit,
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002012 template RR_Cause expect_rr_cause := ?
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002013 ) runs on test_CT {
Harald Welte91d54a52018-01-28 15:35:07 +01002014
2015 var RslLinkId main_dcch := valueof(ts_RslLinkID_DCCH(0));
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002016 var boolean got_deact_sacch := false;
2017 var boolean got_rr_chan_rel := false;
2018 var boolean got_rll_rel_req := false;
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002019 var ASP_RSL_Unitdata ud;
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002020 var RSL_IE_Body l3_ie;
2021 var PDU_ML3_NW_MS l3;
2022 var RR_Cause got_cause;
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002023 log("f_expect_chan_rel() expecting: expect_deact_sacch=", expect_deact_sacch, " expect_rr_chan_rel=", expect_rr_chan_rel,
2024 " expect_rll_rel_req=", expect_rll_rel_req);
Harald Welte91d54a52018-01-28 15:35:07 +01002025 alt {
Vadim Yanitskiy9b4e3562020-05-25 21:40:52 +07002026 [] IPA_RSL[bts_nr].receive(tr_ASP_RSL_UD(tr_RSL_DEACT_SACCH(rsl_chan_nr))) {
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002027 got_deact_sacch := true;
Harald Welte91d54a52018-01-28 15:35:07 +01002028 repeat;
2029 }
Pau Espin Pedrol841b90d2021-04-15 16:42:52 +02002030 [not istemplatekind(expect_cells, "omit")] IPA_RSL[bts_nr].receive(tr_ASP_RSL_UD(tr_RSL_DATA_REQ(rsl_chan_nr, ?, decmatch tr_RRM_RR_RELEASE_CellSelectInd))) -> value ud {
Harald Welte99787102019-02-04 10:41:36 +01002031 got_rr_chan_rel := true;
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002032
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002033 if (f_rsl_find_ie(ud.rsl, RSL_IE_L3_INFO, l3_ie) == false) {
2034 setverdict(fail, "cannot find L3");
2035 mtc.stop;
2036 }
2037 l3 := dec_PDU_ML3_NW_MS(l3_ie.l3_info.payload);
2038
Pau Espin Pedrol36bd4fa2021-04-15 13:00:24 +02002039 if (not istemplatekind(expect_cells, "omit")) {
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002040 var CellSelIndValue cells := dec_CellSelIndValue(
2041 l3.msgs.rrm.channelRelease.cellSelectionIndicator.cellSelectionIndicatorValue);
2042
Pau Espin Pedrol36bd4fa2021-04-15 13:00:24 +02002043 log("GOT RR CHANNEL RELEASE WITH CELLS: ", cells);
2044 if (match(cells, expect_cells)) {
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002045 setverdict(pass);
2046 } else {
Pau Espin Pedrol36bd4fa2021-04-15 13:00:24 +02002047 log("EXPECTED CELLS: ", expect_cells);
2048 setverdict(fail, "Received cells list on RR Channel Release does not match expectations");
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002049 }
2050 }
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002051
2052 if (not istemplatekind(expect_rr_cause, "omit")) {
2053 int2enum(oct2int(l3.msgs.rrm.channelRelease.rRCause.valuePart), got_cause);
2054 log("GOT CAUSE CODE: ", l3.msgs.rrm.channelRelease.rRCause.valuePart, " = ", got_cause);
2055 if (match(got_cause, expect_rr_cause)) {
2056 setverdict(pass);
2057 } else {
2058 log("EXPECTED CAUSE CODE: ", expect_rr_cause);
2059 setverdict(fail, "Received RR Channel Release Cause code does not match expectations");
2060 }
2061 }
Harald Welte99787102019-02-04 10:41:36 +01002062 repeat;
2063 }
Pau Espin Pedrol841b90d2021-04-15 16:42:52 +02002064 [istemplatekind(expect_cells, "omit")] IPA_RSL[bts_nr].receive(tr_ASP_RSL_UD(tr_RSL_DATA_REQ(rsl_chan_nr, ?, decmatch tr_RRM_RR_RELEASE))) -> value ud {
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002065 got_rr_chan_rel := true;
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002066
2067 if (not istemplatekind(expect_rr_cause, "omit")) {
2068 if (f_rsl_find_ie(ud.rsl, RSL_IE_L3_INFO, l3_ie) == false) {
2069 setverdict(fail, "cannot find L3");
2070 mtc.stop;
2071 }
2072 l3 := dec_PDU_ML3_NW_MS(l3_ie.l3_info.payload);
2073
2074 int2enum(oct2int(l3.msgs.rrm.channelRelease.rRCause.valuePart), got_cause);
2075 log("GOT CAUSE CODE: ", l3.msgs.rrm.channelRelease.rRCause.valuePart, " = ", got_cause);
2076 if (match(got_cause, expect_rr_cause)) {
2077 setverdict(pass);
2078 } else {
2079 log("EXPECTED CAUSE CODE: ", expect_rr_cause);
2080 setverdict(fail, "Received RR Channel Release Cause code does not match expectations");
2081 }
2082 }
Neels Hofmeyr211169d2018-11-07 00:37:29 +01002083 repeat;
2084 }
Vadim Yanitskiy9b4e3562020-05-25 21:40:52 +07002085 [] IPA_RSL[bts_nr].receive(tr_ASP_RSL_UD(tr_RSL_REL_REQ(rsl_chan_nr, ?))) {
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002086 got_rll_rel_req := true;
Harald Welte91d54a52018-01-28 15:35:07 +01002087 /* FIXME: Why are we getting this for LinkID SACCH? */
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002088 if (handle_rll_rel) {
2089 f_ipa_tx(0, ts_RSL_REL_CONF(rsl_chan_nr, main_dcch));
2090 }
Harald Welte91d54a52018-01-28 15:35:07 +01002091 repeat;
2092 }
Vadim Yanitskiy9b4e3562020-05-25 21:40:52 +07002093 [] IPA_RSL[bts_nr].receive(tr_ASP_RSL_UD(tr_RSL_MsgTypeD(RSL_MT_RF_CHAN_REL))) {
Harald Welte91d54a52018-01-28 15:35:07 +01002094 /* respond with CHAN REL ACK */
2095 f_ipa_tx(0, ts_RSL_RF_CHAN_REL_ACK(rsl_chan_nr));
2096 }
2097 /* ignore any user data */
Vadim Yanitskiy9b4e3562020-05-25 21:40:52 +07002098 [] IPA_RSL[bts_nr].receive(tr_ASP_RSL_UD(tr_RSL_MsgTypeR(?))) {
Harald Welte91d54a52018-01-28 15:35:07 +01002099 repeat;
2100 }
2101 }
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002102
2103 log("f_expect_chan_rel() summary: got_deact_sacch=", got_deact_sacch, " got_rr_chan_rel=", got_rr_chan_rel,
2104 " got_rll_rel_req=", got_rll_rel_req);
2105
2106 if (expect_deact_sacch != got_deact_sacch) {
2107 setverdict(fail, "f_expect_chan_rel(): expect_deact_sacch=", expect_deact_sacch, " got_deact_sacch=", got_deact_sacch);
2108 }
2109 if (expect_rr_chan_rel != got_rr_chan_rel) {
2110 setverdict(fail, "f_expect_chan_rel(): expect_rr_chan_rel=", expect_rr_chan_rel, " got_rr_chan_rel=", got_rr_chan_rel);
2111 }
2112 if (expect_rll_rel_req != got_rll_rel_req) {
2113 setverdict(fail, "f_expect_chan_rel(): expect_rll_rel_req=", expect_rll_rel_req, " got_rll_rel_req=", got_rll_rel_req);
2114 }
Harald Welte91d54a52018-01-28 15:35:07 +01002115}
2116
Harald Welte4003d112017-12-09 22:35:39 +01002117/* Test behavior of channel release after hard Clear Command from MSC */
2118testcase TC_chan_rel_hard_clear() runs on test_CT {
2119 var BSSAP_N_DATA_ind rx_di;
Harald Welte4003d112017-12-09 22:35:39 +01002120 var DchanTuple dt;
Harald Welte4003d112017-12-09 22:35:39 +01002121
Harald Welte89d42e82017-12-17 16:42:41 +01002122 f_init(1);
Harald Welte4003d112017-12-09 22:35:39 +01002123
2124 dt := f_est_dchan('23'O, 23, '00010203040506'O);
2125
2126 /* Instruct BSC to clear channel */
2127 var BssmapCause cause := 0;
2128 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
2129
2130 /* expect Clear Complete from BSC on A */
2131 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete)) {
2132 /* release the SCCP connection */
2133 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2134 }
2135
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002136 f_expect_chan_rel(0, dt.rsl_chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002137 f_shutdown_helper();
Harald Welte4003d112017-12-09 22:35:39 +01002138}
2139
Pau Espin Pedrol841b90d2021-04-15 16:42:52 +02002140function f_TC_chan_rel_last_eutran_plmn_hard_clear(boolean tx_csfb_ind) runs on test_CT {
2141 var BSSAP_N_DATA_ind rx_di;
2142 var DchanTuple dt;
2143
2144 f_init(1);
2145
2146 dt := f_est_dchan('23'O, 23, '00010203040506'O);
2147 /* Send CommonID with some random PLMN (BSC doesn't take it into account
2148 /* yet when generating the EUTRAN neigh list in RR CHannel Release) */
2149 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_CommonId('001019876543210'H, '323454'O)));
2150
2151 /* Instruct BSC to clear channel */
2152 var BssmapCause cause := 0;
2153 if (tx_csfb_ind) {
2154 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommandCSFB(cause)));
2155 } else {
2156 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
2157 }
2158
2159 /* expect Clear Complete from BSC on A */
2160 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete)) {
2161 /* release the SCCP connection */
2162 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2163 }
2164
2165 /* 1 neighbor is added by default in osmo-bts.cfg and
2166 SystemInformationConfig_default, use that: */
2167 var template CellSelIndValue exp_cells := f_tr_rr_chan_rel_earfcns(1);
2168
2169 f_expect_chan_rel(0, dt.rsl_chan_nr, expect_rll_rel_req := false, expect_cells := exp_cells);
2170 f_shutdown_helper();
2171}
2172
2173/* Test behavior of RR Channel rRelease after Clear Command without CSFB indicator
2174 from MSC, previously receiving any CommonID containing the "Last Used E-UTRAN
2175 PLMN Id". According to spec (3GPP TS 48.008 sec 3.1.30) that's the bit requesting
2176 EUTRAN neighbor list sent later on by BSC in RR Channel, so receiving CSFB
2177 Indicator or not shouldn't matter at all. */
2178testcase TC_chan_rel_last_eutran_plmn_hard_clear_no_csfb() runs on test_CT {
2179 f_TC_chan_rel_last_eutran_plmn_hard_clear(false);
2180}
2181
2182/* Test behavior of RR Channel rRelease after Clear Command with CSFB indicator from
2183 MSC, previously receiving any CommonID containing the "Last Used E-UTRAN PLMN
2184 Id". According to spec (3GPP TS 48.008 sec 3.1.30) that's the bit requesting
2185 EUTRAN neighbor list sent later on by BSC in RR Channel. */
2186testcase TC_chan_rel_last_eutran_plmn_hard_clear_csfb() runs on test_CT {
2187 f_TC_chan_rel_last_eutran_plmn_hard_clear(true);
2188}
2189
2190/* Test behavior of RR Channel Release after Clear Command with CSFB indicator from
2191 MSC, without receiving any CommonID containing the "Last Used E-UTRAN PLMN
2192 Id". According to spec (TS 48.008 version 16.0.0 Release 16 "3.2.1.21") the
2193 CSFB Indicator should not be used anymore, and hence, there should be no
2194 EUTRAN neighbor list sent by BSC in RR Channel release since no CommonId with
2195 Last Used E-UTRAN PLMN Id" IE was sent for this conn. */
Harald Welte99787102019-02-04 10:41:36 +01002196testcase TC_chan_rel_hard_clear_csfb() 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
2204 /* Instruct BSC to clear channel */
2205 var BssmapCause cause := 0;
2206 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommandCSFB(cause)));
2207
2208 /* expect Clear Complete from BSC on A */
2209 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete)) {
2210 /* release the SCCP connection */
2211 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2212 }
2213
Pau Espin Pedrol841b90d2021-04-15 16:42:52 +02002214 f_expect_chan_rel(0, dt.rsl_chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002215 f_shutdown_helper();
Harald Welte99787102019-02-04 10:41:36 +01002216}
2217
Harald Welted8c36cd2017-12-09 23:05:31 +01002218/* Test behavior of channel release after hard RLSD from MSC */
2219testcase TC_chan_rel_hard_rlsd() runs on test_CT {
Harald Welted8c36cd2017-12-09 23:05:31 +01002220 var DchanTuple dt;
Harald Welted8c36cd2017-12-09 23:05:31 +01002221
Harald Welte89d42e82017-12-17 16:42:41 +01002222 f_init(1);
Harald Welted8c36cd2017-12-09 23:05:31 +01002223
2224 dt := f_est_dchan('23'O, 23, '00010203040506'O);
2225
2226 /* release the SCCP connection */
2227 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2228
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002229 f_expect_chan_rel(0, dt.rsl_chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002230 f_shutdown_helper();
Harald Welted8c36cd2017-12-09 23:05:31 +01002231}
2232
Harald Welte550daf92018-06-11 19:22:13 +02002233/* Test behavior of channel release after hard RLSD from MSC and MS is not responding to RLL REL REQ */
2234testcase TC_chan_rel_hard_rlsd_ms_dead() runs on test_CT {
2235 var DchanTuple dt;
2236
2237 f_init(1);
2238
2239 dt := f_est_dchan('23'O, 23, '00010203040506'O);
2240
2241 /* release the SCCP connection */
2242 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2243
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002244 f_expect_chan_rel(0, dt.rsl_chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002245 f_shutdown_helper();
Harald Welte550daf92018-06-11 19:22:13 +02002246}
2247
Harald Welte85804d42017-12-10 14:11:58 +01002248/* Test behavior of channel release after BSSMAP RESET from MSC */
2249testcase TC_chan_rel_a_reset() runs on test_CT {
Harald Welte85804d42017-12-10 14:11:58 +01002250 var DchanTuple dt;
Harald Welte85804d42017-12-10 14:11:58 +01002251
Harald Welte89d42e82017-12-17 16:42:41 +01002252 f_init(1);
Harald Welte85804d42017-12-10 14:11:58 +01002253
2254 dt := f_est_dchan('23'O, 23, '00010203040506'O);
2255
2256 /* Clear the queue, it might still contain stuff like IMMEDIATE ASSIGN */
2257 IPA_RSL[0].clear;
2258
2259 /* perform BSSAP RESET, expect RESET ACK and DISC.ind on connection */
Neels Hofmeyrf246a922020-05-13 02:27:10 +02002260 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)));
Harald Welte85804d42017-12-10 14:11:58 +01002261 interleave {
Neels Hofmeyrf246a922020-05-13 02:27:10 +02002262 [] BSSAP.receive(tr_BSSAP_UNITDATA_ind(g_bssap[0].sccp_addr_own, g_bssap[0].sccp_addr_peer, tr_BSSMAP_ResetAck(g_osmux_enabled))) { }
Harald Welte85804d42017-12-10 14:11:58 +01002263 [] BSSAP.receive(tr_BSSAP_DISC_ind(dt.sccp_conn_id, ?, ?)) { }
2264 }
2265
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002266 f_expect_chan_rel(0, dt.rsl_chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002267 f_shutdown_helper();
Harald Welte85804d42017-12-10 14:11:58 +01002268}
2269
Pau Espin Pedrolc675b612020-01-09 19:55:40 +01002270/* Verify T(iar) triggers and releases the channel */
2271testcase TC_chan_rel_sccp_tiar_timeout() runs on test_CT {
2272 var DchanTuple dt;
2273
2274 /* Set T(iar) in BSC low enough that it will trigger before other side
2275 has time to keep alive with a T(ias). Keep recommended ratio of
2276 T(iar) >= T(ias)*2 */
2277 g_bsc_sccp_timer_ias := 2;
2278 g_bsc_sccp_timer_iar := 5;
2279
2280 f_init(1);
2281
2282 dt := f_est_dchan('23'O, 23, '00010203040506'O);
2283 f_expect_chan_rel(0, dt.rsl_chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002284 f_shutdown_helper();
Pau Espin Pedrolc675b612020-01-09 19:55:40 +01002285}
2286
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002287private function f_tc_chan_rel_rr_cause(myBSSMAP_Cause clear_cmd_cause, template RR_Cause expect_rr_cause)
2288runs on test_CT
2289{
2290 var DchanTuple dt;
2291
2292 dt := f_est_dchan('23'O, 23, '00010203040506'O);
2293 var BssmapCause cause := 0;
2294 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(enum2int(clear_cmd_cause))));
2295 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete)) {
2296 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2297 }
2298
2299 f_expect_chan_rel(0, dt.rsl_chan_nr, expect_rll_rel_req := false, expect_rr_cause := expect_rr_cause);
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002300}
2301
2302/* Test that Clear Command cause codes affect the RR Channel Release cause code */
2303testcase TC_chan_rel_rr_cause() runs on test_CT {
2304 f_init(1);
2305
2306 f_tc_chan_rel_rr_cause(GSM0808_CAUSE_CALL_CONTROL, GSM48_RR_CAUSE_NORMAL);
2307 f_tc_chan_rel_rr_cause(GSM0808_CAUSE_HANDOVER_SUCCESSFUL, GSM48_RR_CAUSE_NORMAL);
2308 f_tc_chan_rel_rr_cause(GSM0808_CAUSE_PREEMPTION, GSM48_RR_CAUSE_PREMPTIVE_REL);
2309 f_tc_chan_rel_rr_cause(GSM0808_CAUSE_RADIO_INTERFACE_MESSAGE_FAILURE, GSM48_RR_CAUSE_PROT_ERROR_UNSPC);
2310 f_tc_chan_rel_rr_cause(GSM0808_CAUSE_RADIO_INTERFACE_FAILURE, GSM48_RR_CAUSE_ABNORMAL_UNSPEC);
2311 f_tc_chan_rel_rr_cause(GSM0808_CAUSE_EQUIPMENT_FAILURE, GSM48_RR_CAUSE_ABNORMAL_UNSPEC);
Vadim Yanitskiye18aebb2021-01-03 13:10:43 +01002312
2313 f_shutdown_helper();
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002314}
2315
Harald Welte5cd20ed2017-12-13 21:03:20 +01002316/* Test behavior if RSL EST IND for non-active channel */
2317testcase TC_rll_est_ind_inact_lchan() runs on test_CT {
2318 timer T := 2.0;
2319
Harald Welte89d42e82017-12-17 16:42:41 +01002320 f_init(1);
Harald Welte5cd20ed2017-12-13 21:03:20 +01002321
2322 var octetstring l3 := '00010203040506'O;
2323 var RslChannelNr chan_nr := valueof(t_RslChanNr_Bm(6));
2324 f_ipa_tx(0, ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3));
2325
2326 T.start;
2327 alt {
2328 [] BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3))) {
2329 setverdict(fail, "MSC received COMPL L3 for non-active lchan");
2330 }
2331 [] BSSAP.receive {}
2332 [] IPA_RSL[0].receive {}
2333 [] T.timeout {}
2334 }
2335
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002336 f_shutdown_helper();
Harald Welte5cd20ed2017-12-13 21:03:20 +01002337}
2338
2339/* Test behavior if RSL EST IND for invalid SAPI */
2340testcase TC_rll_est_ind_inval_sapi1() runs on test_CT {
2341 var RslChannelNr chan_nr;
2342
Harald Welte89d42e82017-12-17 16:42:41 +01002343 f_init(1);
Harald Welte5cd20ed2017-12-13 21:03:20 +01002344
2345 chan_nr := f_chreq_act_ack()
2346
2347 var octetstring l3 := '00010203040506'O;
2348 f_ipa_tx(0, ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(1)), l3));
2349
2350 timer T := 2.0;
2351 T.start;
2352 alt {
2353 [] BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3))) {
2354 setverdict(fail, "MSC received COMPL L3 for invalid SAPI 1");
2355 }
2356 [] BSSAP.receive { repeat; }
2357 [] IPA_RSL[0].receive { repeat; }
2358 [] T.timeout {}
2359 }
2360
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002361 f_shutdown_helper();
Harald Welte5cd20ed2017-12-13 21:03:20 +01002362}
2363
2364/* Test behavior if RSL EST IND for invalid SAPI */
2365testcase TC_rll_est_ind_inval_sapi3() runs on test_CT {
2366 timer T := 2.0;
2367
Harald Welte89d42e82017-12-17 16:42:41 +01002368 f_init(1);
Harald Welte5cd20ed2017-12-13 21:03:20 +01002369
2370 var RslChannelNr chan_nr := f_chreq_act_ack();
2371
2372 var octetstring l3 := '00010203040506'O;
2373 f_ipa_tx(0, ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(3)), l3));
2374
2375 T.start;
2376 alt {
2377 [] BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3))) {
2378 setverdict(fail, "MSC received COMPL L3 for invalid SAPI 3");
2379 }
2380 [] BSSAP.receive { repeat; }
2381 [] IPA_RSL[0].receive { repeat; }
2382 [] T.timeout {}
2383 }
2384
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002385 f_shutdown_helper();
Harald Welte5cd20ed2017-12-13 21:03:20 +01002386}
2387
2388/* Test behavior if RSL EST IND for invalid SACCH */
2389testcase TC_rll_est_ind_inval_sacch() runs on test_CT {
2390 timer T := 2.0;
2391
Harald Welte89d42e82017-12-17 16:42:41 +01002392 f_init(1);
Harald Welte5cd20ed2017-12-13 21:03:20 +01002393
2394 var RslChannelNr chan_nr := f_chreq_act_ack();
2395
2396 var octetstring l3 := '00010203040506'O;
2397 f_ipa_tx(0, ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_SACCH(0)), l3));
2398
2399 T.start;
2400 alt {
2401 [] BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3))) {
2402 setverdict(fail, "MSC received COMPL L3 for invalid Link SACCH");
2403 }
2404 [] BSSAP.receive { repeat; }
2405 [] IPA_RSL[0].receive { repeat; }
2406 [] T.timeout {}
2407 }
2408
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002409 f_shutdown_helper();
Harald Welte5cd20ed2017-12-13 21:03:20 +01002410}
2411
Vadim Yanitskiy61f784a2020-10-01 21:12:19 +07002412/* Verify DLCI / RSL Link ID conversion for MO/MT messages on SAPI0/SAPI3 */
2413private function f_TC_tch_dlci_link_id_sapi(charstring id) runs on MSC_ConnHdlr {
2414 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
2415 var PDU_BSSAP ass_cmd := f_gen_ass_req();
2416
2417 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
2418 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
2419
2420 f_establish_fully(ass_cmd, exp_compl);
2421
2422 /* SAPI0 has already been established by f_establish_fully(), establish SAPI3 */
2423 RSL.send(ts_RSL_EST_IND(g_chan_nr, ts_RslLinkID_SACCH(3), '0904'O));
2424 /* Expect BSSAP/DTAP on SAPI3 (DLCI IE) */
2425 BSSAP.receive(PDU_BSSAP:{
2426 discriminator := '1'B,
2427 spare := '0000000'B,
2428 dlci := 'C3'O,
2429 lengthIndicator := ?,
2430 pdu := { dtap := '0904'O }
2431 });
2432
2433 /* Send messages on DCCH/SAPI0 and ACCH/SAPI3 */
2434 for (var integer i := 0; i < 32; i := i + 1) {
2435 var octetstring l3 := '09'O & f_rnd_octstring(14);
2436 var template (value) RslLinkId link_id;
2437 var template (value) OCT1 dlci;
2438
2439 if (i mod 2 == 0) {
2440 /* SAPI0 on FACCH or SDCCH */
2441 link_id := ts_RslLinkID_DCCH(0);
2442 dlci := '80'O;
2443 } else {
2444 /* SAPI3 on SACCH */
2445 link_id := ts_RslLinkID_SACCH(3);
2446 dlci := 'C3'O;
2447 }
2448
2449 /* Send MO message: RSL -> BSSAP */
Neels Hofmeyr0aa719b2020-10-12 18:43:09 +00002450 f_mo_l3_transceive(RSL, link_id, dlci, l3);
Vadim Yanitskiy61f784a2020-10-01 21:12:19 +07002451 /* Send MT message: BSSAP -> RSL */
Neels Hofmeyr0aa719b2020-10-12 18:43:09 +00002452 f_mt_l3_transceive(RSL, link_id, dlci, l3);
Vadim Yanitskiy61f784a2020-10-01 21:12:19 +07002453 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01002454 f_perform_clear();
Vadim Yanitskiy61f784a2020-10-01 21:12:19 +07002455}
2456testcase TC_tch_dlci_link_id_sapi() runs on test_CT {
2457 var TestHdlrParams pars := f_gen_test_hdlr_pars();
2458 var MSC_ConnHdlr vc_conn;
2459
2460 f_init(1, true);
2461 f_sleep(1.0);
2462
2463 vc_conn := f_start_handler(refers(f_TC_tch_dlci_link_id_sapi), pars);
2464 vc_conn.done;
2465
2466 f_shutdown_helper();
2467}
2468
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002469private function f_exp_sapi_n_reject(template (present) GsmSapi sapi := ?,
2470 template myBSSMAP_Cause cause := ?,
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +07002471 template (present) BIT2 cc := ?,
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002472 float T_val := 2.0)
2473runs on test_CT {
2474 var BSSAP_N_DATA_ind rx_di;
2475 timer T;
2476
2477 var template BSSMAP_IE_Cause tr_cause := tr_BSSMAP_IE_Cause(cause);
2478 var template PDU_BSSAP tr_pdu := tr_BSSMAP_SAPInReject(sapi);
2479
2480 T.start(T_val);
2481 alt {
2482 [] BSSAP.receive(tr_BSSAP_DATA_ind(?, tr_pdu)) -> value rx_di {
2483 var BSSMAP_IE_Cause rx_cause := rx_di.userData.pdu.bssmap.sAPInReject.cause;
2484 if (not match(rx_cause, tr_cause)) {
2485 setverdict(fail, "Rx unexpected Cause IE: ",
2486 rx_cause, " vs expected ", tr_cause);
2487 }
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +07002488
2489 /* Who ever on the earth decided to define this field as two separate bits?!? */
2490 var BIT2 rx_cc := rx_di.userData.pdu.bssmap.sAPInReject.dLCI.c2
2491 & rx_di.userData.pdu.bssmap.sAPInReject.dLCI.c1;
2492 if (not match(rx_cc, cc)) {
2493 setverdict(fail, "Rx unexpected Control Channel type: ",
2494 rx_cc, " vs expected ", cc);
2495 }
2496
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002497 setverdict(pass);
2498 }
2499 [] BSSAP.receive(BSSAP_N_DATA_ind:?) -> value rx_di {
2500 setverdict(fail, "Rx unexpected BSSAP PDU: ", rx_di);
2501 }
2502 [] T.timeout {
2503 setverdict(fail, "Timeout waiting for BSSMAP SAPI N Reject");
2504 }
2505 }
2506}
2507
2508/* Check if we get SAPI N Reject on receipt of unexpected RLL RELease INDication */
2509testcase TC_rll_rel_ind_sapi_n_reject() runs on test_CT {
2510 var octetstring rnd_data := f_rnd_octstring(16);
2511 var RSL_Message rx_rsl;
2512 var DchanTuple dt;
2513
2514 f_init(1);
2515
2516 /* MS establishes a SAPI=0 link on DCCH */
2517 dt := f_est_dchan(f_rnd_ra_cs(), 23, rnd_data);
2518
2519 /* MSC sends some data on (not yet established) SAPI=3 link */
2520 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSAP_DTAP(rnd_data, '03'O)));
2521 /* BSC attempts to establish a SAPI=3 link on DCCH */
2522 rx_rsl := f_exp_ipa_rx(0, tr_RSL_EST_REQ(dt.rsl_chan_nr, tr_RslLinkID_DCCH(3)));
2523
2524 /* MS sends unexpected RELease INDication on SAPI=3 */
2525 f_ipa_tx(0, ts_RSL_REL_IND(dt.rsl_chan_nr, ts_RslLinkID_DCCH(3)));
2526 /* We expect to receive BSSMAP SAPI N Reject message from the BSC */
2527 f_exp_sapi_n_reject(3, GSM0808_CAUSE_MS_NOT_EQUIPPED);
2528
2529 /* Clean up the connection */
2530 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2531 f_expect_chan_rel(0, dt.rsl_chan_nr, expect_rll_rel_req := false);
2532
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002533 f_shutdown_helper();
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002534}
2535
2536/* Check if we get SAPI N Reject on receipt of unexpected RLL ERROR INDication */
2537testcase TC_rll_err_ind_sapi_n_reject() runs on test_CT {
2538 var octetstring rnd_data := f_rnd_octstring(16);
2539 var RSL_Message rx_rsl;
2540 var DchanTuple dt;
2541
2542 f_init(1);
2543
2544 /* MS establishes a SAPI=0 link on DCCH */
2545 dt := f_est_dchan(f_rnd_ra_cs(), 23, rnd_data);
2546
2547 /* MSC sends some data on (not yet established) SAPI=3 link */
2548 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSAP_DTAP(rnd_data, '03'O)));
2549 /* BSC attempts to establish a SAPI=3 link on DCCH */
2550 rx_rsl := f_exp_ipa_rx(0, tr_RSL_EST_REQ(dt.rsl_chan_nr, tr_RslLinkID_DCCH(3)));
2551
2552 /* BTS sends unexpected ERROR INDication on SAPI=3 */
2553 f_ipa_tx(0, ts_RSL_ERROR_IND(dt.rsl_chan_nr, ts_RslLinkID_DCCH(3), ''O));
2554 /* We expect to receive BSSMAP SAPI N Reject message from the BSC */
2555 f_exp_sapi_n_reject(3, GSM0808_CAUSE_BSS_NOT_EQUIPPED);
2556
2557 /* Clean up the connection */
2558 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2559 f_expect_chan_rel(0, dt.rsl_chan_nr, expect_rll_rel_req := false);
2560
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002561 f_shutdown_helper();
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002562}
2563
2564/* Check if we get SAPI N Reject due to a SAPI=3 link establishment timeout */
2565testcase TC_rll_timeout_sapi_n_reject() runs on test_CT {
2566 var octetstring rnd_data := f_rnd_octstring(16);
2567 var RSL_Message rx_rsl;
2568 var DchanTuple dt;
2569
2570 f_init(1);
2571
2572 /* MS establishes a SAPI=0 link on DCCH */
2573 dt := f_est_dchan(f_rnd_ra_cs(), 23, rnd_data);
2574
2575 /* MSC sends some data on (not yet established) SAPI=3 link */
2576 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSAP_DTAP(rnd_data, '03'O)));
2577 /* BSC attempts to establish a SAPI=3 link on DCCH */
2578 rx_rsl := f_exp_ipa_rx(0, tr_RSL_EST_REQ(dt.rsl_chan_nr, tr_RslLinkID_DCCH(3)));
2579
2580 /* MS does not respond, so the link establishment timeout triggers SAPI N Reject */
2581 f_exp_sapi_n_reject(3, GSM0808_CAUSE_BSS_NOT_EQUIPPED, T_val := 8.0);
2582
2583 /* Clean up the connection */
2584 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2585 f_expect_chan_rel(0, dt.rsl_chan_nr, expect_rll_rel_req := false);
2586
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002587 f_shutdown_helper();
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002588}
2589
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +07002590/* Check DLCI CC (Control Channel type) bits in SAPI N Reject */
2591testcase TC_rll_sapi_n_reject_dlci_cc() runs on test_CT {
2592 var octetstring rnd_data := f_rnd_octstring(16);
2593 var RSL_Message rx_rsl;
2594 var DchanTuple dt;
2595
2596 f_init(1);
2597
2598 /* MS establishes a SAPI=0 link on DCCH */
2599 dt := f_est_dchan(f_rnd_ra_cs(), 23, rnd_data);
2600
2601 /* MSC sends some data on (not yet established) SAPI=3 link */
2602 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSAP_DTAP(rnd_data, '03'O)));
2603 /* BSC attempts to establish a SAPI=3 link on DCCH */
2604 rx_rsl := f_exp_ipa_rx(0, tr_RSL_EST_REQ(dt.rsl_chan_nr, tr_RslLinkID_DCCH(3)));
2605
2606 /* MS sends unexpected ERROR INDication on DCCH/ACCH SAPI=3 */
2607 f_ipa_tx(0, ts_RSL_ERROR_IND(dt.rsl_chan_nr, ts_RslLinkID_DCCH(3), ''O));
Pau Espin Pedrol121f27f2022-01-12 12:02:10 +01002608 f_exp_sapi_n_reject(3, GSM0808_CAUSE_BSS_NOT_EQUIPPED, '10'B);
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +07002609
2610 /* Clean up the connection */
2611 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2612 f_expect_chan_rel(0, dt.rsl_chan_nr, expect_rll_rel_req := false);
2613
2614 f_shutdown_helper();
2615}
2616
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +02002617testcase TC_si_default() runs on test_CT {
2618 f_init(0);
2619 f_init_bts_and_check_sysinfo(0, expect_si := SystemInformationConfig_default);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002620 f_shutdown_helper();
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +02002621}
Harald Welte4003d112017-12-09 22:35:39 +01002622
Neels Hofmeyr56f24782020-07-09 00:50:49 +02002623/* We're testing SI2quater with lists of EARFCNs. Instead of just incrementing EARFCNs, also pick some from the edges of
2624 * the entire value range. This function provides the same EARFCN numbers for the same earfcn_index */
2625private function f_test_si2quater_earfcn_by_idx(integer earfcn_index) return uint16_t
2626{
2627 select (earfcn_index) {
2628 case (0) {
2629 /* E-ARFCN 111 is already added in the osmo-bsc.cfg */
2630 return 111;
2631 }
2632 case (1) {
2633 return 1;
2634 }
2635 case (2) {
2636 return 0;
2637 }
2638 case (3) {
2639 return 65535;
2640 }
2641 case else {
2642 return 23 * (earfcn_index - 3);
2643 }
2644 }
2645}
2646
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002647function f_test_si2quater(integer total_earfcns, template SystemInformationConfig expect_si,
2648 template CellSelIndValue expect_cells := omit) runs on test_CT {
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002649
2650 f_init(0);
2651
2652 /* E-ARFCN 111 is already added in the osmo-bsc.cfg, so only add more arfcns if total_earfcns > 1 */
2653 for (var integer i := 1; i < total_earfcns; i := i + 1) {
Neels Hofmeyr56f24782020-07-09 00:50:49 +02002654 f_bts_0_cfg(BSCVTY, {"si2quater neighbor-list add earfcn " & int2str(f_test_si2quater_earfcn_by_idx(i))
2655 & " thresh-hi 20 thresh-lo 10 prio 3 qrxlv 22 meas 3"});
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002656 }
2657
2658 f_init_bts_and_check_sysinfo(0, expect_si := expect_si);
2659
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002660 if (not istemplatekind(expect_cells, "omit")) {
2661 /* Also check that RR Channel Release contains these EARFCNs.
2662 * (copied code from TC_chan_rel_hard_clear_csfb) */
2663 var BSSAP_N_DATA_ind rx_di;
2664 var DchanTuple dt;
2665
2666 dt := f_est_dchan('23'O, 23, '00010203040506'O);
Pau Espin Pedrold0046312021-04-19 16:35:58 +02002667 /* Send CommonID with some random PLMN (BSC doesn't take it into account
2668 * yet when generating the EUTRAN neigh list in RR CHannel Release) */
2669 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_CommonId('001019876543210'H, '323454'O)));
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002670
2671 /* Instruct BSC to clear channel */
2672 var BssmapCause cause := 0;
2673 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommandCSFB(cause)));
2674
2675 /* expect Clear Complete from BSC on A */
2676 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete)) {
2677 /* release the SCCP connection */
2678 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2679 }
2680
Pau Espin Pedrol841b90d2021-04-15 16:42:52 +02002681 f_expect_chan_rel(0, dt.rsl_chan_nr, expect_rll_rel_req := false, expect_cells := expect_cells);
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002682 }
2683
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002684 for (var integer i := 1; i < total_earfcns; i := i + 1) {
Neels Hofmeyr56f24782020-07-09 00:50:49 +02002685 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 +02002686 }
2687}
2688
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002689private function f_tr_si2quater_earfcns(integer count) return template SI2quaterRestOctetsList
2690{
2691 var template SI2quaterRestOctetsList si2quater := {};
2692 var integer si2quater_count := (count + 2) / 3;
2693
2694 for (var integer i := 0; i < count; i := i + 1) {
Neels Hofmeyr56f24782020-07-09 00:50:49 +02002695 var integer earfcn := f_test_si2quater_earfcn_by_idx(i);
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002696 var integer index := i / 3;
2697 var integer earfcn_index := i mod 3;
2698 if (index >= lengthof(si2quater)) {
2699 si2quater[index] := tr_SI2quaterRestOctets_EUTRAN(index := index, count := si2quater_count - 1);
2700 }
2701 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);
2702 }
2703
2704 return si2quater;
2705}
2706
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002707private function f_tr_rr_chan_rel_earfcns(integer count) return template CellSelIndValue
2708{
2709 var template CellSelIndValue_EUTRAN_Descrs cells := {};
2710
Alexander Couzensf74b5cb2020-09-10 22:28:40 +02002711 /* the lte neighbors must match the config & vty to pass this test */
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002712 for (var integer i := 0; i < count; i := i + 1) {
2713 var integer earfcn := f_test_si2quater_earfcn_by_idx(i);
Alexander Couzensf74b5cb2020-09-10 22:28:40 +02002714 cells[i] := tr_CellSelIndValue_EUTRAN_Descr(earfcn, '1'B, 3);
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002715 }
2716
2717 return tr_CellSelIndValue_EUTRAN(cells);
2718}
2719
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002720private function f_tc_si2quater_n_earfcns(integer n) runs on test_CT
2721{
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002722 var template SystemInformationConfig sic := SystemInformationConfig_default;
Pau Espin Pedrol8ab62e42020-12-18 16:19:11 +01002723 sic.si2quater := f_tr_si2quater_earfcns(n);
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002724 var template CellSelIndValue cells := f_tr_rr_chan_rel_earfcns(n);
2725 f_test_si2quater(n, sic, cells);
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002726}
2727
2728testcase TC_si2quater_2_earfcns() runs on test_CT {
2729 f_tc_si2quater_n_earfcns(2);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002730 f_shutdown_helper();
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002731}
2732
2733testcase TC_si2quater_3_earfcns() runs on test_CT {
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002734 f_tc_si2quater_n_earfcns(3);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002735 f_shutdown_helper();
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002736}
2737
2738testcase TC_si2quater_4_earfcns() runs on test_CT {
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002739 f_tc_si2quater_n_earfcns(4);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002740 f_shutdown_helper();
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002741}
2742
2743testcase TC_si2quater_5_earfcns() runs on test_CT {
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002744 f_tc_si2quater_n_earfcns(5);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002745 f_shutdown_helper();
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002746}
2747
2748testcase TC_si2quater_6_earfcns() runs on test_CT {
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002749 f_tc_si2quater_n_earfcns(6);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002750 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002751}
2752
2753testcase TC_si2quater_12_earfcns() runs on test_CT {
2754 f_tc_si2quater_n_earfcns(12);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002755 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002756}
2757
2758testcase TC_si2quater_23_earfcns() runs on test_CT {
2759 f_tc_si2quater_n_earfcns(23);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002760 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002761}
2762
2763testcase TC_si2quater_32_earfcns() runs on test_CT {
2764 f_tc_si2quater_n_earfcns(32);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002765 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002766}
2767
2768testcase TC_si2quater_33_earfcns() runs on test_CT {
2769 f_tc_si2quater_n_earfcns(33);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002770 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002771}
2772
2773testcase TC_si2quater_42_earfcns() runs on test_CT {
2774 f_tc_si2quater_n_earfcns(42);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002775 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002776}
2777
2778testcase TC_si2quater_48_earfcns() runs on test_CT {
2779 f_tc_si2quater_n_earfcns(48);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002780 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002781}
2782
2783/* verify the VTY error response when adding too many EARFCNs, and showing that osmo-bsc still sends 16 SI2quater with
2784 * 48 EARFCNs. */
2785testcase TC_si2quater_49_earfcns() runs on test_CT {
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002786 var template SystemInformationConfig sic := SystemInformationConfig_default;
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002787 sic.si2quater := f_tr_si2quater_earfcns(48); /* 48, not 49! */
2788 f_init(0);
2789
2790 for (var integer i := 1; i < 48; i := i + 1) {
Neels Hofmeyr56f24782020-07-09 00:50:49 +02002791 f_bts_0_cfg(BSCVTY, {"si2quater neighbor-list add earfcn " & int2str(f_test_si2quater_earfcn_by_idx(i))
2792 & " thresh-hi 20 thresh-lo 10 prio 3 qrxlv 22 meas 3"});
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002793 }
2794
2795 /* The 49th EARFCN no longer fits, expect VTY error */
2796 f_vty_enter_cfg_bts(BSCVTY, 0);
2797 var charstring vty_error;
2798 vty_error := f_vty_transceive_ret(BSCVTY,
2799 "si2quater neighbor-list add earfcn 70 thresh-hi 20 thresh-lo 10 prio 3 qrxlv 22 meas 3")
2800 f_vty_transceive(BSCVTY, "end");
2801
2802 if (f_strstr(vty_error, "Unable to add ARFCN 70") >= 0) {
2803 log("Got expected VTY error: ", vty_error);
2804 setverdict(pass);
2805 } else {
2806 setverdict(fail, "Expected the 49th EUTRAN ARFCN to be rejected by vty config, got: ", vty_error);
2807 }
2808
2809 f_init_bts_and_check_sysinfo(0, expect_si := sic);
2810
2811 for (var integer i := 1; i < 48; i := i + 1) {
Neels Hofmeyr56f24782020-07-09 00:50:49 +02002812 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 +02002813 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002814 f_shutdown_helper();
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002815}
2816
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02002817private function f_acc09_count_allowed(AccessControlClass acc) return uint8_t
2818{
2819 var uint8_t count := 0;
2820 for (var integer i := 5; i < 16; i := i + 1) {
2821 if (acc[i] == '0'B) { /* the list marks barred, we count allowed */
2822 count := count + 1;
2823 }
2824 }
2825 return count;
2826}
2827
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02002828private function f_recv_next_si1(integer rsl_idx := 0) runs on test_CT return SystemInformationType1
2829{
2830 var ASP_RSL_Unitdata rx_rsl_ud;
2831 var SystemInformationType1 last_si1;
2832
2833 timer T := 30.0;
2834 T.start;
2835 alt {
2836 [] IPA_RSL[rsl_idx].receive(tr_ASP_RSL_UD((tr_RSL_NO_BCCH_INFO,
2837 tr_RSL_BCCH_INFO,
2838 tr_RSL_NO_SACCH_FILL,
2839 tr_RSL_SACCH_FILL))
2840 ) -> value rx_rsl_ud {
2841 f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
2842 if (g_system_information[rsl_idx].si1 == omit) {
2843 repeat;
2844 }
2845 last_si1 := g_system_information[rsl_idx].si1;
2846 g_system_information[rsl_idx].si1 := omit;
2847 T.stop;
2848 }
Vadim Yanitskiy79ebd5e2021-01-04 00:12:55 +01002849 [] IPA_RSL[rsl_idx].receive { repeat; }
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02002850 [] T.timeout { setverdict(fail, "Timeout receiving next SI1"); }
2851 }
2852 return last_si1;
2853}
2854
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02002855/* verify ACC rotate feature */
2856testcase TC_si_acc_rotate() runs on test_CT {
2857 var template SystemInformationConfig sic := SystemInformationConfig_default;
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02002858 var SystemInformationType1 last_si1;
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02002859 var AccessControlClass acc;
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02002860 var uint8_t count;
2861 var integer times_allowed[10] := { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
2862
2863 f_init(0, guard_timeout := 60.0);
2864
2865 f_bts_0_cfg(BSCVTY, {"rach access-control-class 5 barred",
2866 "access-control-class-rotate 3",
2867 "access-control-class-rotate-quantum 1"});
2868
2869 /* Init and get first sysinfo */
2870 f_init_bts_and_check_sysinfo(0, expect_si := ?);
2871
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02002872 for (var integer i:= 0; i < 20; i := i + 1) {
2873 last_si1 := f_recv_next_si1(0);
2874 acc := last_si1.rach_control.acc;
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02002875 count := f_acc09_count_allowed(acc);
2876 log("RSL: GOT SI1 ACC len=", count, ": ", acc);
2877
2878 if (count != 3) {
2879 log("RSL: EXPECTED SI ACC len=3");
2880 setverdict(fail, "received SI does not match expectations");
2881 break;
2882 }
2883
2884 for (var integer j := 0; j < 10; j := j + 1) {
2885 if (acc[16 - 1 - j] == '0'B) { /* the list marks barred, we count allowed */
2886 times_allowed[j] := times_allowed[j] + 1;
2887 }
2888 }
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02002889 }
2890
2891 for (var integer j := 0; j < 10; j := j + 1) {
2892 log("ACC", j, " allowed ", times_allowed[j], " times" );
2893 if (j != 5 and times_allowed[j] < 3) {
2894 setverdict(fail, "ACC", j, " ERROR: allowed ", times_allowed[j], " < 1 times");
2895 } else if (j == 5 and times_allowed[j] > 0) {
2896 setverdict(fail, "ACC", j, " ERROR: allowed ", times_allowed[j], " > 0 times");
2897 }
2898 }
2899
2900 f_bts_0_cfg(BSCVTY, {"access-control-class-rotate 10",
2901 "rach access-control-class 5 allowed"});
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002902 f_shutdown_helper();
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02002903}
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002904
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02002905/* verify ACC startup ramp+rotate feature */
2906testcase TC_si_acc_ramp_rotate() runs on test_CT {
2907 var template SystemInformationConfig sic := SystemInformationConfig_default;
2908 var SystemInformationType1 last_si1;
2909 var AccessControlClass acc;
2910 var ASP_RSL_Unitdata rx_rsl_ud;
2911 var uint8_t count;
2912 var uint8_t prev_count;
2913 var integer times_allowed[10] := { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
2914
2915 f_init(0, guard_timeout := 80.0);
2916
2917 f_bts_0_cfg(BSCVTY, {"rach access-control-class 4 barred",
2918 "access-control-class-rotate 0",
2919 "access-control-class-rotate-quantum 1",
2920 "access-control-class-ramping",
2921 "access-control-class-ramping-step-interval 5",
2922 "access-control-class-ramping-step-size 5"});
2923
2924 /* Init and get first sysinfo */
2925 f_init_bts_and_check_sysinfo(0, expect_si := ?);
2926 last_si1 := g_system_information[0].si1;
2927 acc := last_si1.rach_control.acc;
2928 count := f_acc09_count_allowed(acc);
2929 /* Adm subset size was set to 0 above, so wait until all ACC are barred */
2930 while (count > 0) {
2931 last_si1 := f_recv_next_si1(0);
2932 acc := last_si1.rach_control.acc;
2933 count := f_acc09_count_allowed(acc);
2934 log("RSL: wait len()=0: GOT SI1 ACC len=", count, ": ", acc);
2935 }
2936
2937 /* Increase adm subset size, we should see ramping start up */
2938 f_bts_0_cfg(BSCVTY, {"access-control-class-rotate 10"});
2939 prev_count := 0;
2940 while (true) {
2941 last_si1 := f_recv_next_si1(0);
2942 acc := last_si1.rach_control.acc;
2943 count := f_acc09_count_allowed(acc);
2944 log("RSL: GOT SI1 ACC len=", count, ": ", acc);
2945
2946 if (prev_count > count) {
2947 setverdict(fail, "ACC allowed count dropped while expecting grow: ", prev_count, " -> ", count);
2948 break;
2949 }
2950
2951 if (count == 9) {
2952 break; /* Maximum reached (10 - 1 perm barred), done here */
2953 }
2954
2955 prev_count := count;
2956 }
2957
2958 setverdict(pass);
2959
2960 f_bts_0_cfg(BSCVTY, {"access-control-class-rotate 10",
2961 "rach access-control-class 4 allowed",
2962 "no access-control-class-ramping"});
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002963 f_shutdown_helper();
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02002964}
2965
Harald Welte4003d112017-12-09 22:35:39 +01002966testcase TC_ctrl_msc_connection_status() runs on test_CT {
2967 var charstring ctrl_resp;
2968
Harald Welte89d42e82017-12-17 16:42:41 +01002969 f_init(1);
Harald Welte4003d112017-12-09 22:35:39 +01002970
2971 /* See https://osmocom.org/issues/2729 */
2972 f_ctrl_get_exp(IPA_CTRL, "msc_connection_status", "connected");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002973 f_shutdown_helper();
Harald Welte4003d112017-12-09 22:35:39 +01002974}
2975
Stefan Sperlingb041b3d2018-01-03 17:14:55 +01002976testcase TC_ctrl_msc0_connection_status() runs on test_CT {
2977 var charstring ctrl_resp;
2978
2979 f_init(1);
Stefan Sperlingb041b3d2018-01-03 17:14:55 +01002980
2981 f_ctrl_get_exp(IPA_CTRL, "msc.0.connection_status", "connected");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002982 f_shutdown_helper();
Stefan Sperlingb041b3d2018-01-03 17:14:55 +01002983}
2984
Neels Hofmeyr0bc470d2021-08-21 13:37:13 +02002985/* Verify correct stats on the number of configured and connected MSCs */
2986private function f_tc_stat_num_msc_connected_msc_connhdlr(integer expect_num_msc_connected) runs on MSC_ConnHdlr {
2987 g_pars := f_gen_test_hdlr_pars();
2988 var StatsDExpects expect := {
2989 { name := "TTCN3.bsc.0.num_msc.connected", mtype := "g", min := expect_num_msc_connected, max := expect_num_msc_connected },
2990 { name := "TTCN3.bsc.0.num_msc.total", mtype := "g", min := NUM_MSC, max := NUM_MSC }
2991 };
2992 f_statsd_expect(expect);
2993}
2994
2995private function f_tc_stat_num_msc_connected_test_ct(void_fn tc_fn, integer nr_msc) runs on test_CT
2996{
2997 var MSC_ConnHdlr vc_conn;
2998
2999 f_init(nr_bts := 1, handler_mode := true, nr_msc := nr_msc);
3000 f_sleep(1.0);
3001 vc_conn := f_start_handler(tc_fn);
3002 vc_conn.done;
3003
3004 /* Also verify stat exposed on CTRL interface */
3005 f_ctrl_get_exp(IPA_CTRL, "stat_item.last.bsc.0.num_msc:connected", int2str(nr_msc));
3006 f_ctrl_get_exp(IPA_CTRL, "stat_item.last.bsc.0.num_msc:total", int2str(NUM_MSC));
3007
3008 f_shutdown_helper();
3009}
3010
3011/* Verify that when 1 MSC is active, that num_msc:connected reports 1. */
3012private function f_tc_stat_num_msc_connected_1(charstring id) runs on MSC_ConnHdlr {
3013 f_tc_stat_num_msc_connected_msc_connhdlr(1);
3014}
3015testcase TC_stat_num_msc_connected_1() runs on test_CT {
3016 f_tc_stat_num_msc_connected_test_ct(refers(f_tc_stat_num_msc_connected_1), 1);
3017}
3018
3019/* Verify that when 2 MSCs are active, that num_msc:connected reports 2. */
3020private function f_tc_stat_num_msc_connected_2(charstring id) runs on MSC_ConnHdlr {
3021 f_tc_stat_num_msc_connected_msc_connhdlr(2);
3022}
3023testcase TC_stat_num_msc_connected_2() runs on test_CT {
3024 f_tc_stat_num_msc_connected_test_ct(refers(f_tc_stat_num_msc_connected_2), 2);
3025}
3026
3027/* Verify that when 3 MSCs are active, that num_msc:connected reports 3. */
3028private function f_tc_stat_num_msc_connected_3(charstring id) runs on MSC_ConnHdlr {
3029 f_tc_stat_num_msc_connected_msc_connhdlr(3);
3030}
3031testcase TC_stat_num_msc_connected_3() runs on test_CT {
3032 f_tc_stat_num_msc_connected_test_ct(refers(f_tc_stat_num_msc_connected_3), 3);
3033}
3034
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +02003035/* Verify correct stats on the number of configured and connected MSCs */
3036private function f_tc_stat_num_bts_connected_msc_connhdlr(integer expect_num_bts_connected) runs on MSC_ConnHdlr {
3037 g_pars := f_gen_test_hdlr_pars();
3038 var StatsDExpects expect := {
3039 { name := "TTCN3.bsc.0.num_bts.oml_connected", mtype := "g", min := expect_num_bts_connected, max := NUM_BTS_CFG },
3040 { name := "TTCN3.bsc.0.num_bts.all_trx_rsl_connected", mtype := "g", min := expect_num_bts_connected, max := expect_num_bts_connected },
3041 { name := "TTCN3.bsc.0.num_bts.total", mtype := "g", min := NUM_BTS_CFG, max := NUM_BTS_CFG },
3042 { name := "TTCN3.bsc.0.num_trx.rsl_connected", mtype := "g", min := expect_num_bts_connected, max := expect_num_bts_connected },
3043 { name := "TTCN3.bsc.0.num_trx.total", mtype := "g", min := NUM_BTS_CFG, max := NUM_BTS_CFG }
3044 };
3045 f_statsd_expect(expect);
3046}
3047
3048private function f_tc_stat_num_bts_connected_test_ct(void_fn tc_fn, integer nr_bts) runs on test_CT {
3049 var MSC_ConnHdlr vc_conn;
3050
3051 f_init(nr_bts := nr_bts, handler_mode := true, nr_msc := 1);
3052 f_sleep(1.0);
3053 vc_conn := f_start_handler(tc_fn);
3054 vc_conn.done;
3055
3056 /* Also verify stat exposed on CTRL interface */
3057 f_ctrl_get_exp(IPA_CTRL, "stat_item.last.bsc.0.num_bts:all_trx_rsl_connected", int2str(nr_bts));
3058 f_ctrl_get_exp(IPA_CTRL, "stat_item.last.bsc.0.num_bts:total", int2str(NUM_BTS_CFG));
3059 f_ctrl_get_exp(IPA_CTRL, "stat_item.last.bsc.0.num_trx:rsl_connected", int2str(nr_bts));
3060 f_ctrl_get_exp(IPA_CTRL, "stat_item.last.bsc.0.num_trx:total", int2str(NUM_BTS_CFG));
3061
Neels Hofmeyra41ae302021-09-06 22:06:02 +02003062 /* Verify rf_states exposed on CTRL interface */
3063 var charstring expect_net_rf_states := "";
3064 for (var integer i := 0; i < NUM_BTS_CFG; i := i + 1) {
3065 var charstring expect_bts_rf_states := int2str(i) & ",0,";
3066 if (i < NUM_BTS) {
3067 /* In these tests, OML for the first NUM_BTS are always connected via osmo-bts-omldummy */
3068 expect_bts_rf_states := expect_bts_rf_states & "operational,unlocked,";
3069 } else {
3070 /* For remaining i < NUM_BTS_CFG, OML is not connected, i.e. inoperational */
3071 expect_bts_rf_states := expect_bts_rf_states & "inoperational,locked,";
3072 }
3073 /* The RF policy is still global in osmo-bsc, i.e. always "on" */
3074 expect_bts_rf_states := expect_bts_rf_states & "on,";
3075 if (i < nr_bts) {
3076 /* For BTS where RSL is connected, the RSL state will be "up" */
3077 expect_bts_rf_states := expect_bts_rf_states & "rsl-up;";
3078 } else {
3079 expect_bts_rf_states := expect_bts_rf_states & "rsl-down;";
3080 }
3081
3082 f_ctrl_get_exp(IPA_CTRL, "bts." & int2str(i) & ".rf_states", expect_bts_rf_states);
3083 expect_net_rf_states := expect_net_rf_states & expect_bts_rf_states;
3084 }
3085 f_ctrl_get_exp(IPA_CTRL, "rf_states", expect_net_rf_states);
3086
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +02003087 f_shutdown_helper();
3088}
3089
3090/* Verify that when 1 BTS is connected, that num_{bts,trx}:*_connected reports 1. */
3091private function f_tc_stat_num_bts_connected_1(charstring id) runs on MSC_ConnHdlr {
3092 f_tc_stat_num_bts_connected_msc_connhdlr(1);
3093}
3094testcase TC_stat_num_bts_connected_1() runs on test_CT {
3095 f_tc_stat_num_bts_connected_test_ct(refers(f_tc_stat_num_bts_connected_1), 1);
3096}
3097
3098/* Verify that when 2 BTS is connected, that num_{bts,trx}:*_connected reports 2. */
3099private function f_tc_stat_num_bts_connected_2(charstring id) runs on MSC_ConnHdlr {
3100 f_tc_stat_num_bts_connected_msc_connhdlr(2);
3101}
3102testcase TC_stat_num_bts_connected_2() runs on test_CT {
3103 f_tc_stat_num_bts_connected_test_ct(refers(f_tc_stat_num_bts_connected_2), 2);
3104}
3105
3106/* Verify that when 3 BTS is connected, that num_{bts,trx}:*_connected reports 3. */
3107private function f_tc_stat_num_bts_connected_3(charstring id) runs on MSC_ConnHdlr {
3108 f_tc_stat_num_bts_connected_msc_connhdlr(3);
3109}
3110testcase TC_stat_num_bts_connected_3() runs on test_CT {
3111 f_tc_stat_num_bts_connected_test_ct(refers(f_tc_stat_num_bts_connected_3), 3);
3112}
3113
Harald Welte4003d112017-12-09 22:35:39 +01003114testcase TC_ctrl() runs on test_CT {
3115 var charstring ctrl_resp;
3116
Harald Welte89d42e82017-12-17 16:42:41 +01003117 f_init(1);
Harald Welte4003d112017-12-09 22:35:39 +01003118
3119 /* all below values must match the osmo-bsc.cfg config file used */
3120
Harald Welte6a129692018-03-17 17:30:14 +01003121 f_ctrl_get_exp(IPA_CTRL, "mcc", "001");
3122 f_ctrl_get_exp(IPA_CTRL, "mnc", "01");
Oliver Smith75aa0202019-08-19 14:17:50 +02003123 f_ctrl_get_exp(IPA_CTRL, "number-of-bts", "4");
Harald Welte4003d112017-12-09 22:35:39 +01003124
3125 var integer bts_nr := 0;
3126 f_ctrl_get_exp_bts(IPA_CTRL, bts_nr, "location-area-code", "1");
3127 f_ctrl_get_exp_bts(IPA_CTRL, bts_nr, "cell-identity", "0");
3128 f_ctrl_get_exp_bts(IPA_CTRL, bts_nr, "oml-connection-state", "connected");
3129 f_ctrl_get_exp_bts(IPA_CTRL, bts_nr, "gprs-mode", "gprs");
3130 f_ctrl_get_exp_bts(IPA_CTRL, bts_nr, "rf_state", "operational,unlocked,on");
3131 f_ctrl_get_exp_trx(IPA_CTRL, bts_nr, 0, "arfcn", "871");
3132 f_ctrl_get_exp_trx(IPA_CTRL, bts_nr, 0, "max-power-reduction", "20");
3133
3134 var integer uptime := str2int(f_ctrl_get_bts(IPA_CTRL, bts_nr, "oml-uptime"));
3135 f_sleep(2.0);
3136 if (str2int(f_ctrl_get_bts(IPA_CTRL, bts_nr, "oml-uptime")) < uptime+1) {
3137 setverdict(fail, "oml-uptime not incrementing as expected");
3138 }
3139 /* TODO: Disconnect RSL, imply that OML is disconnected and check for uptime zero? */
3140
3141 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bsc", 0, "paging:attempted", 0);
3142
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003143 f_shutdown_helper();
Harald Welte96c94412017-12-09 03:12:45 +01003144}
3145
Pau Espin Pedrol5a2d7432019-06-07 19:43:45 +02003146/* Verify that Upon receival of SET "location", BSC forwards a TRAP
3147 "location-state" over the SCCPlite IPA conn */
3148testcase TC_ctrl_location() runs on test_CT {
3149 var MSC_ConnHdlr vc_conn;
3150 var integer bts_nr := 0;
3151
3152 f_init(1, true);
3153 f_sleep(1.0);
3154
3155 f_ctrl_set_bts(IPA_CTRL, bts_nr, "location", "1234567,fix3d,0.340000,0.560000,0.780000");
3156 f_ctrl_exp_trap(SCCPLITE_IPA_CTRL, "bts." & int2str(bts_nr) & ".location-state",
3157 "1234567,fix3d,0.340000,0.560000,0.780000,operational,unlocked,on,001,01");
3158
3159 f_ctrl_set(SCCPLITE_IPA_CTRL, "rf_locked", "1");
3160 f_sleep(2.0);
3161
3162 f_ctrl_set_bts(IPA_CTRL, bts_nr, "location", "1234888,fix3d,0.350000,0.570000,0.790000");
3163 f_ctrl_exp_trap(SCCPLITE_IPA_CTRL, "bts." & int2str(bts_nr) & ".location-state",
3164 "1234888,fix3d,0.350000,0.570000,0.790000,operational,locked,off,001,01");
3165
3166 /* should match the one from config */
3167 f_ctrl_set(SCCPLITE_IPA_CTRL, "rf_locked", "0");
3168
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003169 f_shutdown_helper();
Pau Espin Pedrol5a2d7432019-06-07 19:43:45 +02003170}
3171
Harald Welte6f521d82017-12-11 19:52:02 +01003172
3173/***********************************************************************
3174 * Paging Testing
3175 ***********************************************************************/
3176
3177type record Cell_Identity {
3178 GsmMcc mcc,
3179 GsmMnc mnc,
3180 GsmLac lac,
3181 GsmCellId ci
3182};
Harald Welte24135bd2018-03-17 19:27:53 +01003183private const Cell_Identity cid := { '001'H, '01'H, 1, 0 };
Stefan Sperling049a86e2018-03-20 15:51:00 +01003184private const Cell_Identity unknown_cid := { '678'H, 'f90'H, 1, 0 };
Harald Welte6f521d82017-12-11 19:52:02 +01003185
Harald Welte5d1a2202017-12-13 19:51:29 +01003186type set of integer BtsIdList;
3187
3188private function f_bts_in_list(integer bts_id, BtsIdList bts_ids) return boolean {
3189 for (var integer j := 0; j < sizeof(bts_ids); j := j + 1) {
3190 if (bts_id == bts_ids[j]) {
3191 return true;
3192 }
3193 }
3194 return false;
3195}
Harald Welte6f521d82017-12-11 19:52:02 +01003196
3197/* core paging test helper function; used by most paging test cases */
3198private function f_pageing_helper(hexstring imsi,
3199 template BSSMAP_FIELD_CellIdentificationList cid_list,
Harald Welte5d1a2202017-12-13 19:51:29 +01003200 BtsIdList bts_ids := { 0 },
Harald Welte6f521d82017-12-11 19:52:02 +01003201 template RSL_ChanNeeded rsl_chneed := omit,
Vadim Yanitskiycc4623d2020-03-28 06:14:06 +07003202 template (omit) OCT4 tmsi := omit) runs on test_CT
Harald Welte6f521d82017-12-11 19:52:02 +01003203{
3204 var template BSSMAP_IE_ChannelNeeded bssmap_chneed;
Vadim Yanitskiycc4623d2020-03-28 06:14:06 +07003205 var template MobileIdentityV mi;
Harald Welte6f521d82017-12-11 19:52:02 +01003206 var RSL_Message rx_rsl;
3207 var integer paging_group := hex2int(imsi[lengthof(imsi)-1]);
Harald Welte5d1a2202017-12-13 19:51:29 +01003208 var integer i;
Harald Welte6f521d82017-12-11 19:52:02 +01003209
3210 f_init();
Harald Welte6f521d82017-12-11 19:52:02 +01003211
3212 /* Clear the queue, it might still contain stuff like BCCH FILLING */
Harald Weltec3068592018-03-17 19:55:31 +01003213 for (i := 0; i < NUM_BTS; i := i + 1) {
3214 IPA_RSL[i].clear;
Harald Welte5d1a2202017-12-13 19:51:29 +01003215 }
Harald Welte6f521d82017-12-11 19:52:02 +01003216
3217 if (isvalue(rsl_chneed)) {
3218 /* The values of 08.08 3.2.2.36 and 08.58 9.3.40 are luckily identical */
3219 bssmap_chneed := ts_BSSMAP_IE_ChanNeeded(int2bit(enum2int(valueof(rsl_chneed)),2));
3220 } else {
3221 bssmap_chneed := omit;
3222 }
3223
Neels Hofmeyrf246a922020-05-13 02:27:10 +02003224 BSSAP.send(ts_BSSAP_UNITDATA_req(g_bssap[0].sccp_addr_peer, g_bssap[0].sccp_addr_own,
3225 ts_BSSMAP_Paging(imsi, cid_list, tmsi, bssmap_chneed)));
Harald Welte6f521d82017-12-11 19:52:02 +01003226
Vadim Yanitskiycc4623d2020-03-28 06:14:06 +07003227 if (not istemplatekind(tmsi, "omit")) {
3228 mi := t_MI_TMSI(tmsi);
Harald Welte6f521d82017-12-11 19:52:02 +01003229 } else {
Vadim Yanitskiycc4623d2020-03-28 06:14:06 +07003230 mi := tr_MI_IMSI(imsi);
Harald Welte6f521d82017-12-11 19:52:02 +01003231 }
Vadim Yanitskiycc4623d2020-03-28 06:14:06 +07003232
Harald Welte5d1a2202017-12-13 19:51:29 +01003233 for (i := 0; i < sizeof(bts_ids); i := i + 1) {
Vadim Yanitskiycc4623d2020-03-28 06:14:06 +07003234 rx_rsl := f_exp_ipa_rx(bts_ids[i], tr_RSL_PAGING_CMD(mi));
Harald Welte5d1a2202017-12-13 19:51:29 +01003235 /* check channel type, paging group */
3236 if (rx_rsl.ies[1].body.paging_group != paging_group) {
3237 setverdict(fail, "Paging for wrong paging group");
3238 }
3239 if (ispresent(rsl_chneed) and
3240 rx_rsl.ies[3].body.chan_needed.chan_needed != valueof(rsl_chneed)) {
3241 setverdict(fail, "RSL Channel Needed != BSSMAP Channel Needed");
3242 }
Harald Welte6f521d82017-12-11 19:52:02 +01003243 }
Harald Welte2fccd982018-01-31 15:48:19 +01003244 f_sleep(2.0);
Harald Welte5d1a2202017-12-13 19:51:29 +01003245 /* do a quick check on all not-included BTSs if they received paging */
3246 for (i := 0; i < NUM_BTS; i := i + 1) {
3247 timer T := 0.1;
3248 if (f_bts_in_list(i, bts_ids)) {
3249 continue;
3250 }
3251 T.start;
3252 alt {
Vadim Yanitskiy9b4e3562020-05-25 21:40:52 +07003253 [] IPA_RSL[i].receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD(mi))) {
Harald Welte5d1a2202017-12-13 19:51:29 +01003254 setverdict(fail, "Paging on BTS ", i, " which is not part of ", bts_ids);
3255 }
3256 [] IPA_RSL[i].receive { repeat; }
3257 [] T.timeout { }
3258 }
Harald Welte6f521d82017-12-11 19:52:02 +01003259 }
3260
3261 setverdict(pass);
3262}
3263
Harald Welte5d1a2202017-12-13 19:51:29 +01003264const BtsIdList c_BtsId_all := { 0, 1, 2 };
Harald Welte751d3eb2018-01-31 15:51:06 +01003265const BtsIdList c_BtsId_none := { };
Harald Welte5d1a2202017-12-13 19:51:29 +01003266const BtsIdList c_BtsId_LAC1 := { 0, 1 };
3267const BtsIdList c_BtsId_LAC2 := { 2 };
3268
Harald Welte6f521d82017-12-11 19:52:02 +01003269/* PAGING by IMSI + TMSI */
3270testcase TC_paging_imsi_nochan() runs on test_CT {
3271 var BSSMAP_FIELD_CellIdentificationList cid_list;
3272 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Philipp Maier8c04b0a2018-02-23 13:48:48 +01003273 f_pageing_helper('001010100000001'H, cid_list, c_BtsId_all, omit, omit);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003274 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003275}
3276
3277/* PAGING by IMSI + TMSI */
3278testcase TC_paging_tmsi_nochan() runs on test_CT {
3279 var BSSMAP_FIELD_CellIdentificationList cid_list;
3280 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003281 f_pageing_helper('001010100000001'H, cid_list, c_BtsId_all, omit, 'A1B2C301'O);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003282 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003283}
3284
3285/* Paging with different "channel needed' values */
3286testcase TC_paging_tmsi_any() runs on test_CT {
3287 var BSSMAP_FIELD_CellIdentificationList cid_list;
3288 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003289 f_pageing_helper('001010100000002'H, cid_list, c_BtsId_all, RSL_CHANNEED_ANY, 'A1B2C302'O);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003290 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003291}
3292testcase TC_paging_tmsi_sdcch() runs on test_CT {
3293 var BSSMAP_FIELD_CellIdentificationList cid_list;
3294 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003295 f_pageing_helper('001010100000003'H, cid_list, c_BtsId_all, RSL_CHANNEED_SDCCH, 'A1B2C303'O);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003296 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003297}
3298testcase TC_paging_tmsi_tch_f() runs on test_CT {
3299 var BSSMAP_FIELD_CellIdentificationList cid_list;
3300 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003301 f_pageing_helper('001010000000004'H, cid_list, c_BtsId_all, RSL_CHANNEED_TCH_F, 'A1B2C304'O);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003302 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003303}
3304testcase TC_paging_tmsi_tch_hf() runs on test_CT {
3305 var BSSMAP_FIELD_CellIdentificationList cid_list;
3306 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003307 f_pageing_helper('001010000000005'H, cid_list, c_BtsId_all, RSL_CHANNEED_TCH_ForH, 'A1B2C305'O);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003308 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003309}
3310
3311/* Paging by CGI */
3312testcase TC_paging_imsi_nochan_cgi() runs on test_CT {
3313 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3314 cid_list := { cIl_CGI := { ts_BSSMAP_CI_CGI(cid.mcc, cid.mnc, cid.lac, cid.ci) } };
Harald Welte5d1a2202017-12-13 19:51:29 +01003315 f_pageing_helper('001010000000006'H, cid_list, { 0 });
Philipp Maier282ca4b2018-02-27 17:17:00 +01003316 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003317}
3318
3319/* Paging by LAC+CI */
3320testcase TC_paging_imsi_nochan_lac_ci() runs on test_CT {
3321 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3322 cid_list := { cIl_LAC_CI := { ts_BSSMAP_CI_LAC_CI(cid.lac, cid.ci) } };
Harald Welte5d1a2202017-12-13 19:51:29 +01003323 f_pageing_helper('001010000000007'H, cid_list, { 0 });
Philipp Maier282ca4b2018-02-27 17:17:00 +01003324 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003325}
3326
3327/* Paging by CI */
3328testcase TC_paging_imsi_nochan_ci() runs on test_CT {
3329 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3330 cid_list := { cIl_CI := { ts_BSSMAP_CI_CI(cid.ci) } };
Harald Welte5d1a2202017-12-13 19:51:29 +01003331 f_pageing_helper('001010000000008'H, cid_list, { 0 });
Philipp Maier282ca4b2018-02-27 17:17:00 +01003332 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003333}
3334
3335/* Paging by LAI */
3336testcase TC_paging_imsi_nochan_lai() runs on test_CT {
3337 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3338 cid_list := { cIl_LAI := { ts_BSSMAP_CI_LAI(cid.mcc, cid.mnc, cid.lac) } };
Harald Welte5d1a2202017-12-13 19:51:29 +01003339 f_pageing_helper('001010000000009'H, cid_list, c_BtsId_LAC1);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003340 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003341}
3342
3343/* Paging by LAC */
3344testcase TC_paging_imsi_nochan_lac() runs on test_CT {
3345 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3346 cid_list := { cIl_LAC := { ts_BSSMAP_CI_LAC(cid.lac) } };
Harald Welte5d1a2202017-12-13 19:51:29 +01003347 f_pageing_helper('001010000000010'H, cid_list, c_BtsId_LAC1);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003348 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003349}
3350
3351/* Paging by "all in BSS" */
3352testcase TC_paging_imsi_nochan_all() runs on test_CT {
3353 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3354 cid_list := { cIl_allInBSS := ''O };
Harald Welte5d1a2202017-12-13 19:51:29 +01003355 f_pageing_helper('001010000000011'H, cid_list, c_BtsId_all);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003356 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003357}
3358
Stefan Sperling7b5e1782018-03-20 19:32:43 +01003359/* Paging by PLMN+LAC+RNC; We do not implement this; Verify nothing is paged */
Harald Welte751d3eb2018-01-31 15:51:06 +01003360testcase TC_paging_imsi_nochan_plmn_lac_rnc() runs on test_CT {
3361 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3362 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 +01003363 f_pageing_helper('001010000000012'H, cid_list, c_BtsId_none);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003364 f_shutdown_helper();
Harald Welte751d3eb2018-01-31 15:51:06 +01003365}
Harald Welte6f521d82017-12-11 19:52:02 +01003366
Stefan Sperling7b5e1782018-03-20 19:32:43 +01003367/* Paging by RNC; We do not implement this; Verify nothing is paged */
Harald Welte751d3eb2018-01-31 15:51:06 +01003368testcase TC_paging_imsi_nochan_rnc() runs on test_CT {
3369 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3370 cid_list := { cIl_RNC := { int2oct(13, 2) } };
Stefan Sperling7b5e1782018-03-20 19:32:43 +01003371 f_pageing_helper('001010000000013'H, cid_list, c_BtsId_none);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003372 f_shutdown_helper();
Harald Welte751d3eb2018-01-31 15:51:06 +01003373}
3374
Stefan Sperling7b5e1782018-03-20 19:32:43 +01003375/* Paging by LAC+RNC; We do not implement; Verify nothing is paged */
Harald Welte751d3eb2018-01-31 15:51:06 +01003376testcase TC_paging_imsi_nochan_lac_rnc() runs on test_CT {
3377 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3378 cid_list := { cIl_LAC_RNC := { ts_BSSMAP_CI_LAC_RNC(cid.lac, 14) } };
Stefan Sperling7b5e1782018-03-20 19:32:43 +01003379 f_pageing_helper('001010000000014'H, cid_list, c_BtsId_none);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003380 f_shutdown_helper();
Harald Welte751d3eb2018-01-31 15:51:06 +01003381}
3382
Harald Welte6f521d82017-12-11 19:52:02 +01003383/* Paging on multiple cells (multiple entries in list): Verify all of them page */
Harald Welte751d3eb2018-01-31 15:51:06 +01003384testcase TC_paging_imsi_nochan_lacs() runs on test_CT {
3385 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3386 cid_list := { cIl_LAC := { ts_BSSMAP_CI_LAC(1), ts_BSSMAP_CI_LAC(2) } };
3387 f_pageing_helper('001010000000015'H, cid_list, c_BtsId_all);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003388 f_shutdown_helper();
Harald Welte751d3eb2018-01-31 15:51:06 +01003389}
3390
3391/* Paging on empty list: Verify none of them page */
3392testcase TC_paging_imsi_nochan_lacs_empty() runs on test_CT {
3393 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3394 cid_list := { cIl_LAC := { } };
3395 f_pageing_helper('001010000000016'H, cid_list, c_BtsId_none);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003396 f_shutdown_helper();
Harald Welte751d3eb2018-01-31 15:51:06 +01003397}
3398
Stefan Sperling049a86e2018-03-20 15:51:00 +01003399/* Paging by CGI with unknown MCC/MNC: Verify nothing is paged. */
3400testcase TC_paging_imsi_nochan_cgi_unknown_cid() runs on test_CT {
3401 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3402 cid_list := { cIl_CGI := { ts_BSSMAP_CI_CGI(unknown_cid.mcc, unknown_cid.mnc, unknown_cid.lac, unknown_cid.ci) } };
3403 f_pageing_helper('001010000000006'H, cid_list, c_BtsId_none);
3404 f_shutdown_helper();
3405}
3406
Harald Welte6f521d82017-12-11 19:52:02 +01003407/* Verify paging retransmission interval + count */
3408/* Verify paging stops after channel establishment */
Harald Welte6f521d82017-12-11 19:52:02 +01003409/* Test behavior under paging overload */
Harald Welteae026692017-12-09 01:03:01 +01003410
Harald Weltee65d40e2017-12-13 00:09:06 +01003411/* Verify PCH load */
3412testcase TC_paging_imsi_load() runs on test_CT {
3413 var BSSMAP_FIELD_CellIdentificationList cid_list;
3414 timer T := 4.0;
Harald Welte2caa1062018-03-17 18:19:05 +01003415 timer T_retrans := 1.0;
Harald Weltee65d40e2017-12-13 00:09:06 +01003416 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003417 f_pageing_helper('001010123456789'H, cid_list, c_BtsId_all);
Harald Weltee65d40e2017-12-13 00:09:06 +01003418
3419 /* tell BSC there is no paging space anymore */
3420 f_ipa_tx(0, ts_RSL_PAGING_LOAD_IND(0));
Harald Welte3b57ab52018-03-17 18:01:10 +01003421 f_sleep(0.2);
3422 IPA_RSL[0].clear;
Harald Weltee65d40e2017-12-13 00:09:06 +01003423
3424 /* Wait for 4 seconds if any more PAGING CMD are received on RSL. Normally,
3425 * there would be 8 retransmissions during 4 seconds */
3426 T.start;
Harald Welte2caa1062018-03-17 18:19:05 +01003427 T_retrans.start;
Harald Weltee65d40e2017-12-13 00:09:06 +01003428 alt {
Vadim Yanitskiy9b4e3562020-05-25 21:40:52 +07003429 [] IPA_RSL[0].receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD(?))) {
Harald Weltee65d40e2017-12-13 00:09:06 +01003430 setverdict(fail, "Received PAGING after LOAD_IND(0)");
Daniel Willmannafce8662018-07-06 23:11:32 +02003431 mtc.stop;
Harald Weltee65d40e2017-12-13 00:09:06 +01003432 }
Harald Welte2caa1062018-03-17 18:19:05 +01003433 [] T_retrans.timeout {
3434 /* re-trnsmit the zero-space LOAD IND to avoid BSC 'auto credit' */
3435 f_ipa_tx(0, ts_RSL_PAGING_LOAD_IND(0));
3436 T_retrans.start;
3437 repeat;
3438 }
Harald Weltee65d40e2017-12-13 00:09:06 +01003439 [] T.timeout {
3440 setverdict(pass);
3441 }
3442 }
Philipp Maier282ca4b2018-02-27 17:17:00 +01003443
3444 f_shutdown_helper();
Harald Weltee65d40e2017-12-13 00:09:06 +01003445}
3446
Harald Welte235ebf12017-12-15 14:18:16 +01003447/* Verify Paging Counter */
Harald Welte1ff69992017-12-14 12:31:17 +01003448testcase TC_paging_counter() runs on test_CT {
3449 var BSSMAP_FIELD_CellIdentificationList cid_list;
3450 timer T := 4.0;
3451 var integer i;
3452 var integer paging_attempted_bsc;
3453 var integer paging_attempted_bts[NUM_BTS];
Oliver Smith8b343d32021-11-26 13:01:42 +01003454 var integer paging_expired_bsc;
Harald Welte1ff69992017-12-14 12:31:17 +01003455 var integer paging_expired_bts[NUM_BTS];
3456 cid_list := valueof(ts_BSSMAP_CIL_noCell);
3457
3458 f_init();
3459
3460 /* read counters before paging */
3461 paging_attempted_bsc := f_ctrl_get_ratectr_abs(IPA_CTRL, "bsc", 0, "paging:attempted");
Oliver Smith8b343d32021-11-26 13:01:42 +01003462 if (Misc_Helpers.f_osmo_repo_is("nightly")) { /* osmo-bsc > 1.8.0 */
3463 paging_expired_bsc := f_ctrl_get_ratectr_abs(IPA_CTRL, "bsc", 0, "paging:expired");
3464 }
Harald Welte1ff69992017-12-14 12:31:17 +01003465 for (i := 0; i < NUM_BTS; i := i+1) {
3466 paging_attempted_bts[i] := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", i, "paging:attempted");
3467 paging_expired_bts[i] := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", i, "paging:expired");
3468 }
3469
3470 f_pageing_helper('001230000000001'H, cid_list, c_BtsId_all);
3471
3472 /* expect the attempted pages on BSC and each BTSs to have incremented by one */
3473 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bsc", 0, "paging:attempted", paging_attempted_bsc+1);
3474 for (i := 0; i < NUM_BTS; i := i+1) {
3475 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", i, "paging:attempted",
3476 paging_attempted_bts[i]+1);
3477 }
3478
3479 /* assume that 12s later the paging on all BTSs have expired and hence incremented by 1 */
3480 f_sleep(12.0);
Oliver Smith8b343d32021-11-26 13:01:42 +01003481 if (Misc_Helpers.f_osmo_repo_is("nightly")) { /* osmo-bsc > 1.8.0 */
3482 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bsc", 0, "paging:expired", paging_expired_bsc+1);
3483 }
Harald Welte1ff69992017-12-14 12:31:17 +01003484 for (i := 0; i < NUM_BTS; i := i+1) {
3485 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", i, "paging:expired",
3486 paging_expired_bts[i]+1);
3487 }
Harald Welte1ff69992017-12-14 12:31:17 +01003488
Philipp Maier282ca4b2018-02-27 17:17:00 +01003489 f_shutdown_helper();
Harald Welte1ff69992017-12-14 12:31:17 +01003490}
3491
3492
Harald Welte10985002017-12-12 09:29:15 +01003493/* Verify paging stops after A-RESET */
3494testcase TC_paging_imsi_a_reset() runs on test_CT {
3495 var BSSMAP_FIELD_CellIdentificationList cid_list;
3496 timer T := 3.0;
3497 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003498 f_pageing_helper('001010123456789'H, cid_list, c_BtsId_all);
Harald Welte10985002017-12-12 09:29:15 +01003499
3500 /* Perform a BSSMAP Reset and wait for ACK */
Neels Hofmeyrf246a922020-05-13 02:27:10 +02003501 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)));
Harald Welte10985002017-12-12 09:29:15 +01003502 alt {
Neels Hofmeyrf246a922020-05-13 02:27:10 +02003503 [] BSSAP.receive(tr_BSSAP_UNITDATA_ind(g_bssap[0].sccp_addr_own, g_bssap[0].sccp_addr_peer, tr_BSSMAP_ResetAck(g_osmux_enabled))) { }
Harald Welte10985002017-12-12 09:29:15 +01003504 [] BSSAP.receive { repeat; }
3505 }
3506
Daniel Willmanncbef3982018-07-30 09:22:40 +02003507 /* Wait to avoid a possible race condition if a paging message is
3508 * received right before the reset ACK. */
3509 f_sleep(0.2);
3510
Harald Welte10985002017-12-12 09:29:15 +01003511 /* Clear the queue, it might still contain stuff like BCCH FILLING */
Philipp Maier1e6b4422018-02-23 14:02:13 +01003512 for (var integer i := 0; i < sizeof(IPA_RSL); i := i+1) {
3513 IPA_RSL[i].clear;
3514 }
Harald Welte10985002017-12-12 09:29:15 +01003515
3516 /* Wait for 3 seconds if any more PAGING CMD are received on RSL */
3517 T.start;
3518 alt {
Vadim Yanitskiy9b4e3562020-05-25 21:40:52 +07003519 [] IPA_RSL[0].receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD(?))) {
Harald Welte10985002017-12-12 09:29:15 +01003520 setverdict(fail, "Received PAGING after A-RESET");
Daniel Willmannafce8662018-07-06 23:11:32 +02003521 mtc.stop;
Harald Welte10985002017-12-12 09:29:15 +01003522 }
Vadim Yanitskiy9b4e3562020-05-25 21:40:52 +07003523 [] IPA_RSL[1].receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD(?))) {
Harald Welte5d1a2202017-12-13 19:51:29 +01003524 setverdict(fail, "Received PAGING after A-RESET");
Daniel Willmannafce8662018-07-06 23:11:32 +02003525 mtc.stop;
Harald Welte5d1a2202017-12-13 19:51:29 +01003526 }
Vadim Yanitskiy9b4e3562020-05-25 21:40:52 +07003527 [] IPA_RSL[2].receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD(?))) {
Harald Welte5d1a2202017-12-13 19:51:29 +01003528 setverdict(fail, "Received PAGING after A-RESET");
Daniel Willmannafce8662018-07-06 23:11:32 +02003529 mtc.stop;
Harald Welte5d1a2202017-12-13 19:51:29 +01003530 }
Harald Welte10985002017-12-12 09:29:15 +01003531 [] T.timeout {
3532 setverdict(pass);
3533 }
3534 }
Philipp Maier282ca4b2018-02-27 17:17:00 +01003535
3536 f_shutdown_helper();
Harald Welte10985002017-12-12 09:29:15 +01003537}
Harald Welteae026692017-12-09 01:03:01 +01003538
Philipp Maierf45824a2019-08-14 14:44:10 +02003539/* Verify how we handle unsolicited Paging Response. In case of an unsolicit
3540 * paging response we can not know which MSC is in charge, so we will blindly
3541 * pick the first configured MSC. This behavior is required in order to make
3542 * MT-CSFB calls working because in those cases the BSC can not know that the
3543 * MSC has already paged the subscriver via SGs. So any MT-CSFB call will look
3544 * like an unsolicited Paging Response to the MSC.
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +01003545 */
3546testcase TC_paging_resp_unsol() runs on test_CT {
3547
3548 f_init(1);
Philipp Maierf45824a2019-08-14 14:44:10 +02003549 timer T := 5.0;
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +01003550
3551 var BSSAP_N_CONNECT_ind rx_c_ind;
3552 var DchanTuple dt;
3553 var PDU_ML3_MS_NW l3 := valueof(ts_PAG_RESP(valueof(ts_MI_IMSI_LV('001010008880018'H))));
Philipp Maierf45824a2019-08-14 14:44:10 +02003554 var octetstring rr_pag_resp := enc_PDU_ML3_MS_NW(l3);
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +01003555
3556 /* Send CHAN RQD and wait for allocation; acknowledge it */
3557 dt.rsl_chan_nr := f_chreq_act_ack();
3558
3559 /* Send unsolicited Paging response (no matching Paging CMD stored in BSC) */
3560 f_ipa_tx(0, ts_RSL_EST_IND(dt.rsl_chan_nr, valueof(ts_RslLinkID_DCCH(0)), enc_PDU_ML3_MS_NW(l3)));
3561
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +01003562
Philipp Maierf45824a2019-08-14 14:44:10 +02003563 /* Expevct a CR with a matching Paging response on the A-Interface */
3564 T.start;
3565 alt {
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01003566 [] BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(rr_pag_resp))) -> value rx_c_ind {
Philipp Maierf45824a2019-08-14 14:44:10 +02003567 setverdict(pass);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01003568 dt.sccp_conn_id := rx_c_ind.connectionId;
3569 BSSAP.send(ts_BSSAP_CONNECT_res(dt.sccp_conn_id));
Philipp Maierf45824a2019-08-14 14:44:10 +02003570 }
3571 [] BSSAP.receive {
3572 setverdict(fail, "Received unexpected message on A-Interface!");
3573 }
3574 [] T.timeout {
3575 setverdict(fail, "Received nothing on A-Interface!");
3576 }
3577 }
3578
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01003579 f_perform_clear_test_ct(dt);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003580 f_shutdown_helper();
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +01003581}
3582
Harald Welte4e9b9cc2017-12-14 18:31:02 +01003583/* Test RSL link drop causes counter increment */
3584testcase TC_rsl_drop_counter() runs on test_CT {
3585 var integer rsl_fail;
3586
Harald Welte89d42e82017-12-17 16:42:41 +01003587 f_init(1);
Harald Welte4e9b9cc2017-12-14 18:31:02 +01003588
3589 rsl_fail := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", 0, "rsl_fail");
3590
Pau Espin Pedrolaf0c61e2022-01-11 12:48:34 +01003591 f_ipa_rsl_stop(bts[0].rsl);
Harald Welte4e9b9cc2017-12-14 18:31:02 +01003592
3593 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", 0, "rsl_fail", rsl_fail+1);
3594
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003595 f_shutdown_helper();
Harald Welte4e9b9cc2017-12-14 18:31:02 +01003596}
3597
3598/* TODO: Test OML link drop causes counter increment */
3599
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003600/* The body of TC_rsl_unknown_unit_id() and TC_oml_unknown_unit_id() tests. */
3601function f_ipa_unknown_unit_id(integer mp_bsc_ipa_port) runs on test_CT return boolean {
3602 timer T := 10.0;
3603
3604 bts[0].rsl.id := "IPA-0-RSL";
Harald Welte71389132021-12-09 21:58:18 +01003605 bts[0].rsl.vc_IPA := IPA_Emulation_CT.create(bts[0].rsl.id & "-IPA") alive;
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003606 bts[0].rsl.ccm_pars := c_IPA_default_ccm_pars;
3607 bts[0].rsl.ccm_pars.name := "Osmocom TTCN-3 BTS Simulator";
Oliver Smith92c2bdb2019-08-20 15:11:24 +02003608 bts[0].rsl.ccm_pars.unit_id := "99/0/0"; /* value which is unknown at BTS */
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003609
Pau Espin Pedrol9a5b8ff2021-01-04 19:01:31 +01003610 f_ipa_ctrl_start_client(mp_bsc_ip, mp_bsc_ctrl_port);
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003611
3612 f_init_mgcp("VirtMSC");
3613
3614 /* start RSL/OML connection (XXX re-uses RSL port/protocol definitions for OML) */
3615 map(bts[0].rsl.vc_IPA:IPA_PORT, system:IPA);
3616 connect(bts[0].rsl.vc_IPA:IPA_RSL_PORT, self:IPA_RSL[0]);
3617 bts[0].rsl.vc_IPA.start(IPA_Emulation.main_client(mp_bsc_ip, mp_bsc_ipa_port, "", 10000, bts[0].rsl.ccm_pars));
3618
3619 /* wait for IPA OML link to connect and then disconnect */
3620 T.start;
3621 alt {
Vadim Yanitskiya2afacc2020-05-18 21:16:19 +07003622 [] IPA_RSL[0].receive(tr_ASP_IPA_EV(ASP_IPA_EVENT_DOWN)) {
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003623 T.stop;
3624 return true;
3625 }
3626 [] IPA_RSL[0].receive { repeat }
3627 [] T.timeout {
Daniel Willmannafce8662018-07-06 23:11:32 +02003628 return false;
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003629 }
3630 }
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003631 return false;
3632}
3633
3634/* BSC should close an RSL connection from a BTS with unknown unit ID (OS#2714). */
3635testcase TC_rsl_unknown_unit_id() runs on test_CT {
3636 if (f_ipa_unknown_unit_id(mp_bsc_rsl_port)) {
3637 setverdict(pass);
3638 } else {
3639 setverdict(fail, "Timeout RSL waiting for connection to close");
3640 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003641 f_shutdown_helper();
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003642}
3643
3644
3645/* BSC should close an RSL connection from a BTS with unknown unit ID (OS#2714). */
3646testcase TC_oml_unknown_unit_id() runs on test_CT {
3647 if (f_ipa_unknown_unit_id(mp_bsc_oml_port)) {
3648 setverdict(pass);
3649 } else {
3650 setverdict(fail, "Timeout OML waiting for connection to close");
3651 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003652 f_shutdown_helper();
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003653}
3654
3655
Harald Weltec1a2fff2017-12-17 11:06:19 +01003656/***********************************************************************
Harald Welte6811d102019-04-14 22:23:14 +02003657 * "New world" test cases using RSL_Emulation + RAN_Emulation
Harald Weltec1a2fff2017-12-17 11:06:19 +01003658 ***********************************************************************/
3659
Harald Welte6811d102019-04-14 22:23:14 +02003660import from RAN_Emulation all;
Harald Welte47cd0e32020-08-21 12:39:11 +02003661import from BSSAP_LE_Emulation all;
Harald Weltec1a2fff2017-12-17 11:06:19 +01003662import from RSL_Emulation all;
3663import from MSC_ConnectionHandler all;
3664
3665type function void_fn(charstring id) runs on MSC_ConnHdlr;
3666
Harald Welte336820c2018-05-31 20:34:52 +02003667/* helper function to create and connect a MSC_ConnHdlr component */
Neels Hofmeyrf246a922020-05-13 02:27:10 +02003668private function f_connect_handler(inout MSC_ConnHdlr vc_conn, integer bssap_idx := 0) runs on test_CT {
3669 connect(vc_conn:RAN, g_bssap[bssap_idx].vc_RAN:PROC);
Daniel Willmann191e0d92018-01-17 12:44:35 +01003670 connect(vc_conn:MGCP_PROC, vc_MGCP:MGCP_PROC);
Harald Weltec1a2fff2017-12-17 11:06:19 +01003671 connect(vc_conn:RSL, bts[0].rsl.vc_RSL:CLIENT_PT);
Harald Weltef70df652018-01-29 22:00:23 +01003672 connect(vc_conn:RSL_PROC, bts[0].rsl.vc_RSL:RSL_PROC);
Philipp Maier88f4ae82018-03-01 14:00:58 +01003673 if (isvalue(bts[1])) {
Philipp Maier956a92f2018-02-16 10:58:07 +01003674 connect(vc_conn:RSL1, bts[1].rsl.vc_RSL:CLIENT_PT);
3675 connect(vc_conn:RSL1_PROC, bts[1].rsl.vc_RSL:RSL_PROC);
3676 }
Neels Hofmeyr91401012019-07-11 00:42:35 +02003677 if (isvalue(bts[2])) {
3678 connect(vc_conn:RSL2, bts[2].rsl.vc_RSL:CLIENT_PT);
3679 connect(vc_conn:RSL2_PROC, bts[2].rsl.vc_RSL:RSL_PROC);
3680 }
Neels Hofmeyrf246a922020-05-13 02:27:10 +02003681 connect(vc_conn:BSSAP, g_bssap[bssap_idx].vc_RAN:CLIENT);
Neels Hofmeyrcfe44062020-10-15 02:28:08 +02003682 if (mp_enable_lcs_tests) {
3683 connect(vc_conn:BSSAP_LE, g_bssap_le.vc_BSSAP_LE:CLIENT);
3684 connect(vc_conn:BSSAP_LE_PROC, g_bssap_le.vc_BSSAP_LE:PROC);
3685 }
Daniel Willmann191e0d92018-01-17 12:44:35 +01003686 connect(vc_conn:MGCP, vc_MGCP:MGCP_CLIENT);
Pau Espin Pedrolfd02ad42019-06-18 17:45:20 +02003687 connect(vc_conn:MGCP_MULTI, vc_MGCP:MGCP_CLIENT_MULTI);
Daniel Willmannebdecc02020-08-12 15:30:17 +02003688 connect(vc_conn:STATSD_PROC, vc_STATSD:STATSD_PROC);
Harald Welte336820c2018-05-31 20:34:52 +02003689}
3690
Neels Hofmeyrda436782021-07-20 22:09:06 +02003691function f_start_handler_create(template (omit) TestHdlrParams pars := omit)
Harald Welte336820c2018-05-31 20:34:52 +02003692runs on test_CT return MSC_ConnHdlr {
3693 var charstring id := testcasename();
3694 var MSC_ConnHdlr vc_conn;
Neels Hofmeyrf246a922020-05-13 02:27:10 +02003695 var integer bssap_idx := 0;
3696 if (isvalue(pars)) {
3697 bssap_idx := valueof(pars).mscpool.bssap_idx;
3698 }
Harald Welte336820c2018-05-31 20:34:52 +02003699 vc_conn := MSC_ConnHdlr.create(id);
Neels Hofmeyrf246a922020-05-13 02:27:10 +02003700 f_connect_handler(vc_conn, bssap_idx);
Neels Hofmeyrda436782021-07-20 22:09:06 +02003701 return vc_conn;
3702}
3703
3704function f_start_handler_run(MSC_ConnHdlr vc_conn, void_fn fn, template (omit) TestHdlrParams pars := omit)
3705runs on test_CT return MSC_ConnHdlr {
3706 var charstring id := testcasename();
Neels Hofmeyr1708d1b2020-10-10 16:56:48 +02003707 /* Emit a marker to appear in the SUT's own logging output */
Neels Hofmeyrda436782021-07-20 22:09:06 +02003708 f_logp(BSCVTY, id & "() start");
Harald Weltea0630032018-03-20 21:09:55 +01003709 vc_conn.start(f_handler_init(fn, id, pars));
Harald Weltec1a2fff2017-12-17 11:06:19 +01003710 return vc_conn;
3711}
3712
Neels Hofmeyrda436782021-07-20 22:09:06 +02003713function f_start_handler(void_fn fn, template (omit) TestHdlrParams pars := omit)
3714runs on test_CT return MSC_ConnHdlr {
3715 return f_start_handler_run(f_start_handler_create(pars), fn, pars);
3716}
3717
Harald Weltea0630032018-03-20 21:09:55 +01003718/* first function inside ConnHdlr component; sets g_pars + starts function */
3719private function f_handler_init(void_fn fn, charstring id, template (omit) TestHdlrParams pars := omit)
3720runs on MSC_ConnHdlr {
3721 if (isvalue(pars)) {
3722 g_pars := valueof(pars);
3723 }
3724 fn.apply(id);
3725}
3726
Oliver Smith26a3db72021-07-09 13:51:29 +02003727private function f_vty_encryption_a5(charstring options) runs on test_CT {
3728 f_vty_transceive(BSCVTY, "configure terminal");
3729 f_vty_transceive(BSCVTY, "network");
3730 f_vty_transceive(BSCVTY, "encryption a5 " & options);
3731 f_vty_transceive(BSCVTY, "exit");
3732 f_vty_transceive(BSCVTY, "exit");
3733}
3734
3735private function f_vty_encryption_a5_reset() runs on test_CT {
3736 /* keep in sync with docker-playground.git ttcn3-bsc-test/osmo-bsc.cfg */
3737 f_vty_encryption_a5("0 1 3");
3738}
3739
Harald Welte3c86ea02018-05-10 22:28:05 +02003740/* Establish signalling channel (non-assignment case) followed by cipher mode */
3741private function f_tc_ciph_mode_a5(charstring id) runs on MSC_ConnHdlr {
Harald Welteed848512018-05-24 22:27:58 +02003742 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
3743 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Harald Welte3c86ea02018-05-10 22:28:05 +02003744 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelTypeSIGNAL);
Philipp Maier23000732018-05-18 11:25:37 +02003745 ass_cmd.pdu.bssmap.assignmentRequest.circuitIdentityCode := omit;
3746 ass_cmd.pdu.bssmap.assignmentRequest.aoIPTransportLayer := omit;
3747 exp_compl.pdu.bssmap.assignmentComplete.circuitIdentityCode := omit;
3748 exp_compl.pdu.bssmap.assignmentComplete.aoIPTransportLayer := omit;
Harald Welte3c86ea02018-05-10 22:28:05 +02003749
Philipp Maier23000732018-05-18 11:25:37 +02003750 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01003751 f_perform_clear();
Harald Welte3c86ea02018-05-10 22:28:05 +02003752}
3753testcase TC_ciph_mode_a5_0() runs on test_CT {
3754 var MSC_ConnHdlr vc_conn;
Philipp Maier48604732018-10-09 15:00:37 +02003755 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte3c86ea02018-05-10 22:28:05 +02003756 pars.encr := valueof(t_EncrParams('01'O, f_rnd_octstring(8)));
3757
3758 f_init(1, true);
3759 f_sleep(1.0);
3760 vc_conn := f_start_handler(refers(f_tc_ciph_mode_a5), pars);
3761 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003762 f_shutdown_helper();
Harald Welte3c86ea02018-05-10 22:28:05 +02003763}
3764testcase TC_ciph_mode_a5_1() runs on test_CT {
3765 var MSC_ConnHdlr vc_conn;
Philipp Maier48604732018-10-09 15:00:37 +02003766 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte3c86ea02018-05-10 22:28:05 +02003767 pars.encr := valueof(t_EncrParams('02'O, f_rnd_octstring(8)));
3768
3769 f_init(1, true);
3770 f_sleep(1.0);
3771 vc_conn := f_start_handler(refers(f_tc_ciph_mode_a5), pars);
3772 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003773 f_shutdown_helper();
Harald Welte3c86ea02018-05-10 22:28:05 +02003774}
Oliver Smith50b98122021-07-09 15:00:28 +02003775/* OS#4975: verify that A5/2 is preferred over A5/0 */
3776testcase TC_ciph_mode_a5_2_0() runs on test_CT {
3777 var MSC_ConnHdlr vc_conn;
3778 var TestHdlrParams pars := f_gen_test_hdlr_pars();
3779
3780 pars.encr := valueof(t_EncrParams('05'O, f_rnd_octstring(8))); /* A5/0 and A5/2 (0x01|0x04)*/
3781 pars.encr_exp_enc_alg := '04'O; /* A5/2 */
3782
3783 f_init(1, true);
3784 f_vty_encryption_a5("0 1 2 3");
3785 f_sleep(1.0);
3786 vc_conn := f_start_handler(refers(f_tc_ciph_mode_a5), pars);
3787 vc_conn.done;
3788 f_vty_encryption_a5_reset();
3789 f_shutdown_helper();
3790}
Oliver Smith1dff88d2021-07-09 08:45:51 +02003791/* OS#4975: verify that A5/1 is preferred over A5/2 */
3792testcase TC_ciph_mode_a5_2_1() runs on test_CT {
3793 var MSC_ConnHdlr vc_conn;
3794 var TestHdlrParams pars := f_gen_test_hdlr_pars();
3795
3796 pars.encr := valueof(t_EncrParams('06'O, f_rnd_octstring(8))); /* A5/1 and A5/2 (0x02|0x04)*/
3797 pars.encr_exp_enc_alg := '02'O; /* A5/1 */
3798
3799 f_init(1, true);
3800 f_vty_encryption_a5("1 2");
3801 f_sleep(1.0);
3802 vc_conn := f_start_handler(refers(f_tc_ciph_mode_a5), pars);
3803 vc_conn.done;
3804 f_vty_encryption_a5_reset();
3805 f_shutdown_helper();
3806}
Harald Welte3c86ea02018-05-10 22:28:05 +02003807testcase TC_ciph_mode_a5_3() runs on test_CT {
3808 var MSC_ConnHdlr vc_conn;
Philipp Maier48604732018-10-09 15:00:37 +02003809 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte3c86ea02018-05-10 22:28:05 +02003810 pars.encr := valueof(t_EncrParams('08'O, f_rnd_octstring(8)));
3811
3812 f_init(1, true);
3813 f_sleep(1.0);
3814 vc_conn := f_start_handler(refers(f_tc_ciph_mode_a5), pars);
3815 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003816 f_shutdown_helper();
Harald Welte3c86ea02018-05-10 22:28:05 +02003817}
Neels Hofmeyr81ad27f2021-06-11 00:09:40 +02003818/* Establish a Signalling channel with A5/4 encryption. */
3819testcase TC_ciph_mode_a5_4() runs on test_CT {
3820 var MSC_ConnHdlr vc_conn;
3821 var TestHdlrParams pars := f_gen_test_hdlr_pars();
3822 pars.encr := valueof(t_EncrParams('10'O, f_rnd_octstring(8), f_rnd_octstring(16)));
Harald Welte3c86ea02018-05-10 22:28:05 +02003823
Neels Hofmeyr81ad27f2021-06-11 00:09:40 +02003824 f_init(1, true);
Oliver Smith26a3db72021-07-09 13:51:29 +02003825 f_vty_encryption_a5("0 1 3 4");
Neels Hofmeyr81ad27f2021-06-11 00:09:40 +02003826 f_sleep(1.0);
3827 vc_conn := f_start_handler(refers(f_tc_ciph_mode_a5), pars);
3828 vc_conn.done;
Oliver Smith26a3db72021-07-09 13:51:29 +02003829 f_vty_encryption_a5_reset();
Neels Hofmeyr81ad27f2021-06-11 00:09:40 +02003830 f_shutdown_helper();
3831}
Pau Espin Pedrol07866632020-09-03 19:10:55 +02003832/* establish initial channel, enable ciphering followed by assignment to ciphered channel */
3833private function f_tc_assignment_aoip_tla_v6(charstring id) runs on MSC_ConnHdlr {
3834 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
3835 var PDU_BSSAP ass_cmd := f_gen_ass_req(aoip_tla := "::3");
3836 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
3837 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
3838
3839 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01003840 f_perform_clear();
Pau Espin Pedrol07866632020-09-03 19:10:55 +02003841}
3842testcase TC_assignment_aoip_tla_v6() runs on test_CT {
3843 var MSC_ConnHdlr vc_conn;
3844 var TestHdlrParams pars := f_gen_test_hdlr_pars();
3845
3846 f_init(1, true);
3847 f_sleep(1.0);
3848 vc_conn := f_start_handler(refers(f_tc_assignment_aoip_tla_v6), pars);
3849 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003850 f_shutdown_helper();
Pau Espin Pedrol07866632020-09-03 19:10:55 +02003851}
3852
Harald Welte3c86ea02018-05-10 22:28:05 +02003853
3854/* establish initial channel, enable ciphering followed by assignment to ciphered channel */
Harald Welte651fcdc2018-05-10 20:23:16 +02003855private function f_tc_assignment_fr_a5(charstring id) runs on MSC_ConnHdlr {
Harald Welteed848512018-05-24 22:27:58 +02003856 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
3857 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Harald Weltec1a2fff2017-12-17 11:06:19 +01003858
Harald Welte552620d2017-12-16 23:21:36 +01003859 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
3860 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
Harald Welte73cd2712017-12-17 00:44:52 +01003861
Harald Weltea0630032018-03-20 21:09:55 +01003862 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01003863 f_perform_clear();
Harald Welte552620d2017-12-16 23:21:36 +01003864}
Harald Welte552620d2017-12-16 23:21:36 +01003865testcase TC_assignment_fr_a5_0() runs on test_CT {
3866 var MSC_ConnHdlr vc_conn;
Philipp Maier48604732018-10-09 15:00:37 +02003867 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte651fcdc2018-05-10 20:23:16 +02003868 pars.encr := valueof(t_EncrParams('01'O, f_rnd_octstring(8)));
Harald Welte552620d2017-12-16 23:21:36 +01003869
Harald Welte89d42e82017-12-17 16:42:41 +01003870 f_init(1, true);
Harald Welte552620d2017-12-16 23:21:36 +01003871 f_sleep(1.0);
Harald Welte651fcdc2018-05-10 20:23:16 +02003872 vc_conn := f_start_handler(refers(f_tc_assignment_fr_a5), pars);
Harald Welte552620d2017-12-16 23:21:36 +01003873 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003874 f_shutdown_helper();
Harald Welte552620d2017-12-16 23:21:36 +01003875}
Harald Welte552620d2017-12-16 23:21:36 +01003876testcase TC_assignment_fr_a5_1() runs on test_CT {
Harald Weltec1a2fff2017-12-17 11:06:19 +01003877 var MSC_ConnHdlr vc_conn;
Philipp Maier48604732018-10-09 15:00:37 +02003878 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte651fcdc2018-05-10 20:23:16 +02003879 pars.encr := valueof(t_EncrParams('02'O, f_rnd_octstring(8)));
Harald Weltec1a2fff2017-12-17 11:06:19 +01003880
Harald Welte89d42e82017-12-17 16:42:41 +01003881 f_init(1, true);
Harald Weltec1a2fff2017-12-17 11:06:19 +01003882 f_sleep(1.0);
Harald Welte651fcdc2018-05-10 20:23:16 +02003883 vc_conn := f_start_handler(refers(f_tc_assignment_fr_a5), pars);
3884 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003885 f_shutdown_helper();
Harald Welte651fcdc2018-05-10 20:23:16 +02003886}
3887testcase TC_assignment_fr_a5_3() runs on test_CT {
3888 var MSC_ConnHdlr vc_conn;
Philipp Maier48604732018-10-09 15:00:37 +02003889 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte651fcdc2018-05-10 20:23:16 +02003890 pars.encr := valueof(t_EncrParams('08'O, f_rnd_octstring(8)));
Harald Weltec1a2fff2017-12-17 11:06:19 +01003891
Harald Welte651fcdc2018-05-10 20:23:16 +02003892 f_init(1, true);
3893 f_sleep(1.0);
3894 vc_conn := f_start_handler(refers(f_tc_assignment_fr_a5), pars);
Harald Weltec1a2fff2017-12-17 11:06:19 +01003895 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003896 f_shutdown_helper();
Harald Weltec1a2fff2017-12-17 11:06:19 +01003897}
Neels Hofmeyr0d8ec532021-06-11 00:09:48 +02003898/* Establish a Signalling channel and re-assign to TCH/F with A5/4 encryption. */
3899testcase TC_assignment_fr_a5_4() runs on test_CT {
3900 var MSC_ConnHdlr vc_conn;
3901 var TestHdlrParams pars := f_gen_test_hdlr_pars();
3902 pars.encr := valueof(t_EncrParams('10'O, f_rnd_octstring(8), f_rnd_octstring(16)));
3903
3904 f_init(1, true);
Oliver Smith7eabd312021-07-12 14:18:56 +02003905 f_vty_encryption_a5("0 1 3 4");
Neels Hofmeyr0d8ec532021-06-11 00:09:48 +02003906 f_sleep(1.0);
3907 vc_conn := f_start_handler(refers(f_tc_assignment_fr_a5), pars);
3908 vc_conn.done;
Oliver Smith7eabd312021-07-12 14:18:56 +02003909 f_vty_encryption_a5_reset();
Neels Hofmeyr0d8ec532021-06-11 00:09:48 +02003910 f_shutdown_helper();
3911}
Harald Weltec1a2fff2017-12-17 11:06:19 +01003912
Neels Hofmeyr0faeb7a2021-06-10 23:59:35 +02003913/* Allow only A5/4, but omit the Kc128 IE from MSC's msg. Expect Cipher Mode Reject. */
3914testcase TC_assignment_fr_a5_4_fail() runs on test_CT {
3915 var TestHdlrParams pars := f_gen_test_hdlr_pars();
3916 var MSC_ConnHdlr vc_conn;
3917
3918 f_init(1, true);
3919 f_sleep(1.0);
3920
3921 pars.encr := valueof(t_EncrParams('10'O, f_rnd_octstring(8))); // A5/4 support, but Kc128 missing!
3922 vc_conn := f_start_handler(refers(f_TC_assignment_a5_not_sup), pars);
3923 vc_conn.done;
3924 f_shutdown_helper();
3925}
3926
Harald Welte552620d2017-12-16 23:21:36 +01003927/* Expect ASSIGNMENT FAIL if mandatory IE is missing */
3928private function f_tc_assignment_fr_a5_1_codec_missing(charstring id) runs on MSC_ConnHdlr {
Philipp Maier48604732018-10-09 15:00:37 +02003929 g_pars := f_gen_test_hdlr_pars();
Harald Welte552620d2017-12-16 23:21:36 +01003930 var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
Harald Welteed848512018-05-24 22:27:58 +02003931 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Harald Welte552620d2017-12-16 23:21:36 +01003932
3933 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02003934 /* Omit: ass_cmd.pdu.bssmap.assignmentRequest.codecList */
3935
Harald Weltea0630032018-03-20 21:09:55 +01003936 f_establish_fully(ass_cmd, exp_fail);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01003937 f_perform_clear();
Harald Welte552620d2017-12-16 23:21:36 +01003938}
Harald Welte552620d2017-12-16 23:21:36 +01003939testcase TC_assignment_fr_a5_1_codec_missing() runs on test_CT {
3940 var MSC_ConnHdlr vc_conn;
3941
Harald Welte89d42e82017-12-17 16:42:41 +01003942 f_init(1, true);
Harald Welte552620d2017-12-16 23:21:36 +01003943 f_sleep(1.0);
3944
Harald Welte8863fa12018-05-10 20:15:27 +02003945 vc_conn := f_start_handler(refers(f_tc_assignment_fr_a5_1_codec_missing));
Harald Welte552620d2017-12-16 23:21:36 +01003946 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003947 f_shutdown_helper();
Harald Welte552620d2017-12-16 23:21:36 +01003948}
3949
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +02003950private function f_TC_assignment_a5_not_sup(charstring id) runs on MSC_ConnHdlr {
3951 var template PDU_BSSAP exp_ass_cpl := f_gen_exp_compl();
3952 var PDU_BSSAP exp_ass_req := f_gen_ass_req();
Harald Welte552620d2017-12-16 23:21:36 +01003953
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +02003954 exp_ass_req.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
3955 exp_ass_req.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
3956
3957 /* this is like the beginning of f_establish_fully(), but only up to ciphering reject */
3958
3959 var BSSMAP_FIELD_CodecType codecType;
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +02003960
3961 codecType := exp_ass_req.pdu.bssmap.assignmentRequest.codecList.codecElements[0].codecType;
3962 f_MscConnHdlr_init(g_pars.media_nr, host_bts, host_mgw_mgcp, codecType);
3963
3964 f_create_chan_and_exp();
3965 /* we should now have a COMPL_L3 at the MSC */
3966
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +02003967 /* Start ciphering, expect Cipher Mode Reject */
Neels Hofmeyr6c388f22021-06-11 02:36:56 +02003968 f_cipher_mode(g_pars.encr, exp_fail := true);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01003969 f_perform_clear();
Harald Welte552620d2017-12-16 23:21:36 +01003970}
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +02003971testcase TC_assignment_fr_a5_not_sup() runs on test_CT {
3972 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte552620d2017-12-16 23:21:36 +01003973 var MSC_ConnHdlr vc_conn;
3974
Harald Welte89d42e82017-12-17 16:42:41 +01003975 f_init(1, true);
Harald Welte552620d2017-12-16 23:21:36 +01003976 f_sleep(1.0);
3977
Neels Hofmeyr0588cad2021-06-11 01:38:18 +02003978 pars.encr := valueof(t_EncrParams('20'O, f_rnd_octstring(8), f_rnd_octstring(16)));
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +02003979 vc_conn := f_start_handler(refers(f_TC_assignment_a5_not_sup), pars);
Harald Welte552620d2017-12-16 23:21:36 +01003980 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003981 f_shutdown_helper();
Harald Welte552620d2017-12-16 23:21:36 +01003982}
3983
3984
Harald Welte4532e0a2017-12-23 02:05:44 +01003985private function f_tc_assignment_sign(charstring id) runs on MSC_ConnHdlr {
Philipp Maier48604732018-10-09 15:00:37 +02003986 g_pars := f_gen_test_hdlr_pars();
Harald Welte4532e0a2017-12-23 02:05:44 +01003987 var template PDU_BSSAP exp_compl := tr_BSSMAP_AssignmentComplete(omit, omit);
Philipp Maier48604732018-10-09 15:00:37 +02003988 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Harald Welte4532e0a2017-12-23 02:05:44 +01003989 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelTypeSIGNAL);
Daniel Willmannebdecc02020-08-12 15:30:17 +02003990
3991 f_statsd_reset();
Harald Weltea0630032018-03-20 21:09:55 +01003992 f_establish_fully(ass_cmd, exp_compl);
Daniel Willmannebdecc02020-08-12 15:30:17 +02003993
3994 var StatsDExpects expect := {
Daniel Willmannc5398f72020-09-21 10:41:35 +02003995 { name := "TTCN3.bts.0.chreq.total", mtype := "c", min := 1, max := 1},
3996 { name := "TTCN3.bts.0.chreq.successful", mtype := "c", min := 1, max := 1},
Daniel Willmannebdecc02020-08-12 15:30:17 +02003997 { name := "TTCN3.bsc.0.assignment.attempted", mtype := "c", min := 1, max := 1},
3998 { name := "TTCN3.bsc.0.assignment.completed", mtype := "c", min := 1, max := 1}
3999 };
4000 f_statsd_expect(expect);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004001 f_perform_clear();
Harald Welte4532e0a2017-12-23 02:05:44 +01004002}
4003
4004testcase TC_assignment_sign() runs on test_CT {
4005 var MSC_ConnHdlr vc_conn;
4006
4007 f_init(1, true);
4008 f_sleep(1.0);
4009
Harald Welte8863fa12018-05-10 20:15:27 +02004010 vc_conn := f_start_handler(refers(f_tc_assignment_sign));
Harald Welte4532e0a2017-12-23 02:05:44 +01004011 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004012 f_shutdown_helper();
Harald Welte4532e0a2017-12-23 02:05:44 +01004013}
4014
Harald Welte60aa5762018-03-21 19:33:13 +01004015/***********************************************************************
4016 * Codec (list) testing
4017 ***********************************************************************/
4018
4019/* check if the given rsl_mode is compatible with the a_elem */
4020private function f_match_codec(BSSMAP_FIELD_CodecElement a_elem, RSL_IE_ChannelMode rsl_mode)
4021return boolean {
4022 select (a_elem.codecType) {
4023 case (GSM_FR) {
4024 if (match(rsl_mode, tr_RSL_ChanMode(RSL_CHRT_TCH_F, RSL_CMOD_SP_GSM1))) {
4025 return true;
4026 }
4027 }
4028 case (GSM_HR) {
4029 if (match(rsl_mode, tr_RSL_ChanMode(RSL_CHRT_TCH_H, RSL_CMOD_SP_GSM1))) {
4030 return true;
4031 }
4032 }
4033 case (GSM_EFR) {
4034 if (match(rsl_mode, tr_RSL_ChanMode(RSL_CHRT_TCH_F, RSL_CMOD_SP_GSM2))) {
4035 return true;
4036 }
4037 }
4038 case (FR_AMR) {
4039 if (match(rsl_mode, tr_RSL_ChanMode(RSL_CHRT_TCH_F, RSL_CMOD_SP_GSM3))) {
4040 return true;
4041 }
4042 }
4043 case (HR_AMR) {
4044 if (match(rsl_mode, tr_RSL_ChanMode(RSL_CHRT_TCH_H, RSL_CMOD_SP_GSM3))) {
4045 return true;
4046 }
4047 }
4048 case else { }
4049 }
4050 return false;
4051}
4052
4053/* check if the given rsl_mode is compatible with the a_list */
4054private function f_match_codecs(BSSMAP_IE_SpeechCodecList a_list, RSL_IE_ChannelMode rsl_mode)
4055return boolean {
4056 for (var integer i := 0; i < sizeof(a_list); i := i+1) {
4057 if (f_match_codec(a_list.codecElements[i], rsl_mode)) {
4058 return true;
4059 }
4060 }
4061 return false;
4062}
4063
4064/* determine BSSMAP_IE_ChannelType from *first* element of BSSMAP_FIELD_CodecElement */
Philipp Maier61f6b572018-07-06 14:03:38 +02004065function f_BSSMAP_chtype_from_codec(BSSMAP_FIELD_CodecElement a_elem)
Harald Welte60aa5762018-03-21 19:33:13 +01004066return BSSMAP_IE_ChannelType {
4067 /* FIXME: actually look at all elements of BSSMAP_IE_SpeechCodecList */
4068 var BSSMAP_IE_ChannelType ret := valueof(ts_BSSMAP_IE_ChannelType);
4069 select (a_elem.codecType) {
4070 case (GSM_FR) {
4071 ret.channelRateAndType := ChRate_TCHF;
4072 ret.speechId_DataIndicator := Spdi_TCHF_FR;
4073 }
4074 case (GSM_HR) {
4075 ret.channelRateAndType := ChRate_TCHH;
4076 ret.speechId_DataIndicator := Spdi_TCHH_HR;
4077 }
4078 case (GSM_EFR) {
4079 ret.channelRateAndType := ChRate_TCHF;
4080 ret.speechId_DataIndicator := Spdi_TCHF_EFR;
4081 }
4082 case (FR_AMR) {
4083 ret.channelRateAndType := ChRate_TCHF;
4084 ret.speechId_DataIndicator := Spdi_TCHF_AMR;
4085 }
4086 case (HR_AMR) {
4087 ret.channelRateAndType := ChRate_TCHH;
4088 ret.speechId_DataIndicator := Spdi_TCHH_AMR;
4089 }
4090 case else {
4091 setverdict(fail, "Unsupported codec ", a_elem);
Daniel Willmannafce8662018-07-06 23:11:32 +02004092 mtc.stop;
Harald Welte60aa5762018-03-21 19:33:13 +01004093 }
4094 }
4095 return ret;
4096}
4097
Harald Weltea63b9102018-03-22 20:36:16 +01004098private function f_rsl_chmod_tmpl_from_codec(BSSMAP_FIELD_CodecElement a_elem)
4099return template RSL_IE_Body {
4100 var template RSL_IE_Body mode_ie := {
4101 chan_mode := {
4102 len := ?,
4103 reserved := ?,
4104 dtx_d := ?,
4105 dtx_u := ?,
4106 spd_ind := RSL_SPDI_SPEECH,
4107 ch_rate_type := -,
4108 coding_alg_rate := -
4109 }
4110 }
4111
4112 select (a_elem.codecType) {
4113 case (GSM_FR) {
4114 mode_ie.chan_mode.ch_rate_type := RSL_CHRT_TCH_F;
4115 mode_ie.chan_mode.coding_alg_rate := RSL_CMOD_SP_GSM1;
4116 }
4117 case (GSM_HR) {
4118 mode_ie.chan_mode.ch_rate_type := RSL_CHRT_TCH_H;
4119 mode_ie.chan_mode.coding_alg_rate := RSL_CMOD_SP_GSM1;
4120 }
4121 case (GSM_EFR) {
4122 mode_ie.chan_mode.ch_rate_type := RSL_CHRT_TCH_F;
4123 mode_ie.chan_mode.coding_alg_rate := RSL_CMOD_SP_GSM2;
4124 }
4125 case (FR_AMR) {
4126 mode_ie.chan_mode.ch_rate_type := RSL_CHRT_TCH_F;
4127 mode_ie.chan_mode.coding_alg_rate := RSL_CMOD_SP_GSM3;
4128 }
4129 case (HR_AMR) {
4130 mode_ie.chan_mode.ch_rate_type := RSL_CHRT_TCH_H;
4131 mode_ie.chan_mode.coding_alg_rate := RSL_CMOD_SP_GSM3;
4132 }
4133 }
4134 return mode_ie;
4135}
4136
Harald Welte60aa5762018-03-21 19:33:13 +01004137type record CodecListTest {
4138 BSSMAP_IE_SpeechCodecList codec_list,
4139 charstring id
4140}
4141type record of CodecListTest CodecListTests
4142
4143private function f_TC_assignment_codec(charstring id) runs on MSC_ConnHdlr {
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004144 f_assignment_codec(id);
4145}
4146
4147private function f_assignment_codec(charstring id, boolean do_perform_clear := true) runs on MSC_ConnHdlr {
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02004148 var PDU_BSSAP ass_cmd := f_gen_ass_req(g_pars.use_osmux);
4149 var template PDU_BSSAP exp_compl := f_gen_exp_compl(g_pars.use_osmux);
Harald Welte60aa5762018-03-21 19:33:13 +01004150
4151 /* puzzle together the ASSIGNMENT REQ for given codec[s] */
Neels Hofmeyrf246a922020-05-13 02:27:10 +02004152 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
Harald Welte79f3f542018-05-25 20:02:37 +02004153 ass_cmd.pdu.bssmap.assignmentRequest.codecList := g_pars.ass_codec_list;
4154 exp_compl.pdu.bssmap.assignmentComplete.speechCodec.codecElements[0] :=
4155 g_pars.ass_codec_list.codecElements[0];
Philipp Maierd0e64b02019-03-13 14:15:23 +01004156 if (isvalue(g_pars.expect_mr_s0_s7)) {
4157 exp_compl.pdu.bssmap.assignmentComplete.speechCodec.codecElements[0].s0_7 :=
4158 g_pars.expect_mr_s0_s7;
4159 }
Harald Welte79f3f542018-05-25 20:02:37 +02004160 }
Harald Welte60aa5762018-03-21 19:33:13 +01004161 ass_cmd.pdu.bssmap.assignmentRequest.channelType :=
4162 f_BSSMAP_chtype_from_codec(g_pars.ass_codec_list.codecElements[0]);
Harald Welte60aa5762018-03-21 19:33:13 +01004163 log("expecting ASS COMPL like this: ", exp_compl);
4164
4165 f_establish_fully(ass_cmd, exp_compl);
Harald Weltea63b9102018-03-22 20:36:16 +01004166
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004167 if (not g_pars.expect_channel_mode_modify) {
4168 /* Verify that the RSL-side activation actually matches our expectations */
4169 var RSL_Message rsl := f_rslem_get_last_act(RSL_PROC, 0, g_chan_nr);
Harald Weltea63b9102018-03-22 20:36:16 +01004170
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004171 var RSL_IE_Body mode_ie;
4172 if (f_rsl_find_ie(rsl, RSL_IE_CHAN_MODE, mode_ie) == false) {
4173 setverdict(fail, "Couldn't find CHAN_MODE IE");
Daniel Willmannafce8662018-07-06 23:11:32 +02004174 mtc.stop;
Neels Hofmeyrbcf62bc2018-07-04 00:24:33 +02004175 }
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004176 var template RSL_IE_Body t_mode_ie := f_rsl_chmod_tmpl_from_codec(g_pars.ass_codec_list.codecElements[0]);
4177 if (not match(mode_ie, t_mode_ie)) {
4178 log("mode_ie ", mode_ie, " != t_mode_ie ", t_mode_ie);
4179 setverdict(fail, "RSL Channel Mode IE doesn't match expectation");
Neels Hofmeyrbcf62bc2018-07-04 00:24:33 +02004180 }
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004181
4182 var RSL_IE_Body mr_conf;
4183 if (g_pars.expect_mr_conf_ie != omit) {
4184 if (f_rsl_find_ie(rsl, RSL_IE_MR_CONFIG, mr_conf) == false) {
4185 setverdict(fail, "Missing MR CONFIG IE in RSL Chan Activ");
4186 mtc.stop;
4187 }
Neels Hofmeyrbcf62bc2018-07-04 00:24:33 +02004188 log("found RSL MR CONFIG IE: ", mr_conf);
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004189
4190 if (not match(mr_conf, g_pars.expect_mr_conf_ie)) {
4191 setverdict(fail, "RSL MR CONFIG IE does not match expectation. Expected: ",
4192 g_pars.expect_mr_conf_ie);
4193 }
4194 } else {
4195 if (f_rsl_find_ie(rsl, RSL_IE_MR_CONFIG, mr_conf) == true) {
4196 log("found RSL MR CONFIG IE: ", mr_conf);
4197 setverdict(fail, "Found MR CONFIG IE in RSL Chan Activ, expecting omit");
4198 mtc.stop;
4199 }
Neels Hofmeyrbcf62bc2018-07-04 00:24:33 +02004200 }
4201 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004202
4203 if (do_perform_clear) {
4204 f_perform_clear();
4205 }
Harald Welte60aa5762018-03-21 19:33:13 +01004206}
4207
Philipp Maierd0e64b02019-03-13 14:15:23 +01004208private function f_TC_assignment_codec_fail(charstring id) runs on MSC_ConnHdlr {
4209
4210 var PDU_BSSAP ass_cmd := f_gen_ass_req();
4211 var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
4212
4213 /* puzzle together the ASSIGNMENT REQ for given codec[s] */
Neels Hofmeyrf246a922020-05-13 02:27:10 +02004214 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
Philipp Maierd0e64b02019-03-13 14:15:23 +01004215 ass_cmd.pdu.bssmap.assignmentRequest.codecList := g_pars.ass_codec_list;
4216 }
4217 ass_cmd.pdu.bssmap.assignmentRequest.channelType :=
4218 f_BSSMAP_chtype_from_codec(g_pars.ass_codec_list.codecElements[0]);
4219 log("expecting ASS FAIL like this: ", exp_fail);
4220
4221 f_establish_fully(ass_cmd, exp_fail);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004222 f_perform_clear();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004223}
4224
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004225const CounterNameVals counternames_bsc_bts_assignment := {
4226 { "assignment:attempted", 0 },
4227 { "assignment:completed", 0 },
4228 { "assignment:stopped", 0 },
4229 { "assignment:no_channel", 0 },
4230 { "assignment:timeout", 0 },
4231 { "assignment:failed", 0 },
4232 { "assignment:error", 0 }
4233};
4234
4235const CounterNameVals counternames_bts_assignment := {
4236 { "assignment:attempted_sign", 0 },
4237 { "assignment:attempted_speech", 0 },
4238 { "assignment:completed_sign", 0 },
4239 { "assignment:completed_speech", 0 },
4240 { "assignment:stopped_sign", 0 },
4241 { "assignment:stopped_speech", 0 },
4242 { "assignment:no_channel_sign", 0 },
4243 { "assignment:no_channel_speech", 0 },
4244 { "assignment:timeout_sign", 0 },
4245 { "assignment:timeout_speech", 0 },
4246 { "assignment:failed_sign", 0 },
4247 { "assignment:failed_speech", 0 },
4248 { "assignment:error_sign", 0 },
4249 { "assignment:error_speech", 0 }
4250};
4251
4252function f_ctrs_bsc_and_bts_assignment_init(integer bts_count := NUM_BTS) runs on test_CT {
4253 var CounterNameVals bts_names := counternames_bsc_bts_assignment & counternames_bts_assignment;
4254 f_ctrs_bts_init(bts_count, bts_names);
4255 f_ctrs_bsc_init(counternames_bsc_bts_assignment);
4256}
4257
Harald Welte60aa5762018-03-21 19:33:13 +01004258testcase TC_assignment_codec_fr() runs on test_CT {
Philipp Maier48604732018-10-09 15:00:37 +02004259 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte60aa5762018-03-21 19:33:13 +01004260 var MSC_ConnHdlr vc_conn;
4261
4262 f_init(1, true);
4263 f_sleep(1.0);
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004264 f_ctrs_bsc_and_bts_assignment_init(1);
Harald Welte60aa5762018-03-21 19:33:13 +01004265
4266 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
Harald Welte8863fa12018-05-10 20:15:27 +02004267 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
Harald Welte60aa5762018-03-21 19:33:13 +01004268 vc_conn.done;
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004269
4270 f_ctrs_bsc_and_bts_add(0, "assignment:attempted", 1);
4271 f_ctrs_bts_add(0, "assignment:attempted_speech", 1);
4272 f_ctrs_bsc_and_bts_add(0, "assignment:completed", 1);
4273 f_ctrs_bts_add(0, "assignment:completed_speech", 1);
4274 f_ctrs_bts_verify();
4275
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004276 f_shutdown_helper();
Harald Welte60aa5762018-03-21 19:33:13 +01004277}
4278
4279testcase TC_assignment_codec_hr() runs on test_CT {
Philipp Maier48604732018-10-09 15:00:37 +02004280 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte60aa5762018-03-21 19:33:13 +01004281 var MSC_ConnHdlr vc_conn;
4282
4283 f_init(1, true);
4284 f_sleep(1.0);
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004285 f_ctrs_bsc_and_bts_assignment_init(1);
Harald Welte60aa5762018-03-21 19:33:13 +01004286
4287 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR}));
Harald Welte8863fa12018-05-10 20:15:27 +02004288 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
Harald Welte60aa5762018-03-21 19:33:13 +01004289 vc_conn.done;
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004290
4291 f_ctrs_bsc_and_bts_add(0, "assignment:attempted", 1);
4292 f_ctrs_bts_add(0, "assignment:attempted_speech", 1);
4293 f_ctrs_bsc_and_bts_add(0, "assignment:completed", 1);
4294 f_ctrs_bts_add(0, "assignment:completed_speech", 1);
4295 f_ctrs_bts_verify();
4296
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004297 f_shutdown_helper();
Harald Welte60aa5762018-03-21 19:33:13 +01004298}
4299
4300testcase TC_assignment_codec_efr() runs on test_CT {
Philipp Maier48604732018-10-09 15:00:37 +02004301 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte60aa5762018-03-21 19:33:13 +01004302 var MSC_ConnHdlr vc_conn;
4303
4304 f_init(1, true);
4305 f_sleep(1.0);
4306
4307 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecEFR}));
Harald Welte8863fa12018-05-10 20:15:27 +02004308 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
Harald Welte60aa5762018-03-21 19:33:13 +01004309 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004310 f_shutdown_helper();
Harald Welte60aa5762018-03-21 19:33:13 +01004311}
4312
Philipp Maierd0e64b02019-03-13 14:15:23 +01004313/* Allow 5,90k only (current default config) */
4314private function f_allow_amr_rate_5_90k() runs on test_CT {
Neels Hofmeyr2a5670b2020-11-25 23:39:57 +00004315 f_vty_cfg_msc(BSCVTY, 0, {
4316 "amr-config 12_2k forbidden",
4317 "amr-config 10_2k forbidden",
4318 "amr-config 7_95k forbidden",
4319 "amr-config 7_40k forbidden",
4320 "amr-config 6_70k forbidden",
4321 "amr-config 5_90k allowed",
4322 "amr-config 5_15k forbidden",
4323 "amr-config 4_75k forbidden"
4324 });
Philipp Maierd0e64b02019-03-13 14:15:23 +01004325}
4326
4327/* Allow 4,75k, 5,90k, 4,70k and 12,2k, which are the most common rates
4328 * ("Config-NB-Code = 1") */
4329private function f_allow_amr_rate_4_75k_5_90k_7_40k_12_20k() runs on test_CT {
Neels Hofmeyr2a5670b2020-11-25 23:39:57 +00004330 f_vty_cfg_msc(BSCVTY, 0, {
4331 "amr-config 12_2k allowed",
4332 "amr-config 10_2k forbidden",
4333 "amr-config 7_95k forbidden",
4334 "amr-config 7_40k allowed",
4335 "amr-config 6_70k forbidden",
4336 "amr-config 5_90k allowed",
4337 "amr-config 5_15k forbidden",
4338 "amr-config 4_75k allowed"
4339 });
Philipp Maierd0e64b02019-03-13 14:15:23 +01004340}
4341
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004342private function f_vty_amr_start_mode_set(boolean fr, charstring startmode) runs on test_CT {
4343 var charstring tch;
4344 if (fr) {
4345 tch := "tch-f";
4346 } else {
4347 tch := "tch-h";
4348 }
4349 f_vty_cfg_bts(BSCVTY, 0, { "amr " & tch & " start-mode " & startmode });
4350}
4351
4352/* Set the AMR start-mode for this TCH back to the default configuration. */
4353private function f_vty_amr_start_mode_restore(boolean fr) runs on test_CT {
4354 f_vty_amr_start_mode_set(fr, "auto");
4355}
4356
Harald Welte60aa5762018-03-21 19:33:13 +01004357testcase TC_assignment_codec_amr_f() runs on test_CT {
Philipp Maier48604732018-10-09 15:00:37 +02004358 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte60aa5762018-03-21 19:33:13 +01004359 var MSC_ConnHdlr vc_conn;
Philipp Maier7695a0d2018-09-27 17:52:14 +02004360
4361 /* Note: This setups the codec configuration. The parameter payload in
4362 * mr_conf must be consistant with the parameter codecElements in pars
4363 * and also must match the amr-config in osmo-bsc.cfg! */
Neels Hofmeyrbcf62bc2018-07-04 00:24:33 +02004364 var RSL_IE_Body mr_conf := {
4365 other := {
4366 len := 2,
4367 payload := '2804'O
4368 }
4369 };
Harald Welte60aa5762018-03-21 19:33:13 +01004370
Philipp Maier7695a0d2018-09-27 17:52:14 +02004371 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_F}));
Philipp Maier806f8f12019-03-12 12:13:41 +01004372 pars.ass_codec_list.codecElements[0].s0_7 := '00000100'B; /* 5,90k */
Philipp Maier7695a0d2018-09-27 17:52:14 +02004373 pars.ass_codec_list.codecElements[0].s8_15 := '01010111'B;
4374 pars.expect_mr_conf_ie := mr_conf;
4375
Harald Welte60aa5762018-03-21 19:33:13 +01004376 f_init(1, true);
4377 f_sleep(1.0);
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004378 f_vty_amr_start_mode_set(true, "1");
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004379 f_ctrs_bsc_and_bts_assignment_init(1);
Harald Welte60aa5762018-03-21 19:33:13 +01004380
Harald Welte8863fa12018-05-10 20:15:27 +02004381 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
Harald Welte60aa5762018-03-21 19:33:13 +01004382 vc_conn.done;
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004383
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004384 f_ctrs_bsc_and_bts_add(0, "assignment:attempted", 1);
4385 f_ctrs_bts_add(0, "assignment:attempted_speech", 1);
4386 f_ctrs_bsc_and_bts_add(0, "assignment:completed", 1);
4387 f_ctrs_bts_add(0, "assignment:completed_speech", 1);
4388 f_ctrs_bts_verify();
4389
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004390 f_vty_amr_start_mode_restore(true);
Vadim Yanitskiy292e5962021-01-03 14:18:47 +01004391 f_shutdown_helper();
Harald Welte60aa5762018-03-21 19:33:13 +01004392}
4393
4394testcase TC_assignment_codec_amr_h() runs on test_CT {
Philipp Maier48604732018-10-09 15:00:37 +02004395 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte60aa5762018-03-21 19:33:13 +01004396 var MSC_ConnHdlr vc_conn;
Philipp Maier7695a0d2018-09-27 17:52:14 +02004397
4398 /* See note above */
Neels Hofmeyrbcf62bc2018-07-04 00:24:33 +02004399 var RSL_IE_Body mr_conf := {
4400 other := {
4401 len := 2,
4402 payload := '2804'O
4403 }
4404 };
Harald Welte60aa5762018-03-21 19:33:13 +01004405
Philipp Maier7695a0d2018-09-27 17:52:14 +02004406 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_H}));
Philipp Maier806f8f12019-03-12 12:13:41 +01004407 pars.ass_codec_list.codecElements[0].s0_7 := '00000100'B; /* 5,90k */
Philipp Maier7695a0d2018-09-27 17:52:14 +02004408 pars.ass_codec_list.codecElements[0].s8_15 := '00000111'B;
4409 pars.expect_mr_conf_ie := mr_conf;
4410
Harald Welte60aa5762018-03-21 19:33:13 +01004411 f_init(1, true);
4412 f_sleep(1.0);
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004413 f_vty_amr_start_mode_set(false, "1");
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004414 f_ctrs_bsc_and_bts_assignment_init(1);
Harald Welte60aa5762018-03-21 19:33:13 +01004415
Harald Welte8863fa12018-05-10 20:15:27 +02004416 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
Harald Welte60aa5762018-03-21 19:33:13 +01004417 vc_conn.done;
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004418
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004419 f_ctrs_bsc_and_bts_add(0, "assignment:attempted", 1);
4420 f_ctrs_bts_add(0, "assignment:attempted_speech", 1);
4421 f_ctrs_bsc_and_bts_add(0, "assignment:completed", 1);
4422 f_ctrs_bts_add(0, "assignment:completed_speech", 1);
4423 f_ctrs_bts_verify();
4424
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004425 f_vty_amr_start_mode_restore(false);
Vadim Yanitskiy292e5962021-01-03 14:18:47 +01004426 f_shutdown_helper();
Harald Welte60aa5762018-03-21 19:33:13 +01004427}
4428
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004429/* Establish signalling on a TCH/F lchan, and then switch to speech mode without a new Assignment. */
4430testcase TC_assignment_codec_fr_by_mode_modify() runs on test_CT {
4431 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4432 var MSC_ConnHdlr vc_conn;
4433
4434 f_init(1, true);
4435 f_sleep(1.0);
4436
4437 /* By disabling all SDCCH, the MS should be given a TCH/F for signalling. Then activating an FR codec should
4438 * merely do a Channel Mode Modify, and not assign to a new lchan. f_establish_fully() already accounts for
4439 * expecting a Channel Mode Modify if the channel type is compatible. */
4440 f_disable_all_sdcch();
4441 f_disable_all_tch_h();
4442
4443 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
4444 pars.expect_channel_mode_modify := true;
4445 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
4446 vc_conn.done;
4447
4448 f_enable_all_sdcch();
4449 f_enable_all_tch();
4450 f_shutdown_helper();
4451}
4452
Neels Hofmeyr454d7922020-11-26 02:24:57 +00004453/* 'amr start-mode auto' should not keep the (unused) 'smod' bits from previous configuration */
4454testcase TC_assignment_codec_amr_startmode_cruft() runs on test_CT {
4455 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4456 var MSC_ConnHdlr vc_conn;
4457
4458 var RSL_IE_Body mr_conf := {
4459 other := {
4460 len := 2,
4461 payload := '2004'O /* <- expect ICMI=0, smod=00 */
4462 }
4463 };
4464
4465 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_F}));
4466 pars.ass_codec_list.codecElements[0].s0_7 := '00000100'B; /* 5,90k */
4467 pars.ass_codec_list.codecElements[0].s8_15 := '01010111'B;
4468 pars.expect_mr_conf_ie := mr_conf;
4469
4470 f_init(1, true);
4471 f_sleep(1.0);
4472
4473 /* First set nonzero start mode bits */
4474 f_vty_amr_start_mode_set(true, "4");
4475 /* Now set to auto, and expect the startmode bits to be zero in the message, i.e. ensure that osmo-bsc does not
4476 * let the startmode bits stick around and has deterministic MultiRate config for 'start-mode auto'; that is
4477 * ensured by above '2004'O, where 'x0xx'O indicates ICMI = 0, spare = 0, smod = 00. */
4478 f_vty_amr_start_mode_set(true, "auto");
4479
4480 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
4481 vc_conn.done;
Neels Hofmeyr454d7922020-11-26 02:24:57 +00004482
4483 /* Clear the startmode bits to not affect subsequent tests, in case the bits should indeed stick around. */
4484 f_vty_amr_start_mode_set(true, "1");
4485 f_vty_amr_start_mode_restore(true);
Vadim Yanitskiy292e5962021-01-03 14:18:47 +01004486 f_shutdown_helper();
Neels Hofmeyr454d7922020-11-26 02:24:57 +00004487}
4488
Neels Hofmeyr21863562020-11-26 00:34:33 +00004489function f_TC_assignment_codec_amr(boolean fr, octetstring mrconf, bitstring s8_s0, bitstring exp_s8_s0,
4490 charstring start_mode := "1")
Philipp Maierd0e64b02019-03-13 14:15:23 +01004491runs on test_CT {
4492
4493 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4494 var MSC_ConnHdlr vc_conn;
4495
4496 /* See note above */
4497 var RSL_IE_Body mr_conf := {
4498 other := {
4499 len := lengthof(mrconf),
4500 payload := mrconf
4501 }
4502 };
4503
4504 if (fr) {
4505 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_F}));
4506 } else {
4507 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_H}));
4508 }
4509 pars.ass_codec_list.codecElements[0].s0_7 := s8_s0;
4510 pars.ass_codec_list.codecElements[0].s8_15 := '00000111'B;
4511 pars.expect_mr_conf_ie := mr_conf;
4512 pars.expect_mr_s0_s7 := exp_s8_s0;
4513
4514 f_init(1, true);
4515 f_allow_amr_rate_4_75k_5_90k_7_40k_12_20k();
Neels Hofmeyr21863562020-11-26 00:34:33 +00004516 f_vty_amr_start_mode_set(fr, start_mode);
Philipp Maierd0e64b02019-03-13 14:15:23 +01004517 f_sleep(1.0);
4518
4519 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
4520 vc_conn.done;
4521 f_allow_amr_rate_5_90k();
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004522 f_vty_amr_start_mode_restore(fr);
Philipp Maierd0e64b02019-03-13 14:15:23 +01004523}
4524
4525function f_TC_assignment_codec_amr_fail(boolean fr, bitstring s8_s0)
4526runs on test_CT {
4527
4528 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4529 var MSC_ConnHdlr vc_conn;
4530
4531 if (fr) {
4532 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_F}));
4533 } else {
4534 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_H}));
4535 }
4536 pars.ass_codec_list.codecElements[0].s0_7 := s8_s0;
4537 pars.ass_codec_list.codecElements[0].s8_15 := '00000111'B;
4538
4539 f_init(1, true);
4540 f_allow_amr_rate_4_75k_5_90k_7_40k_12_20k();
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004541 f_vty_amr_start_mode_set(fr, "1");
Philipp Maierd0e64b02019-03-13 14:15:23 +01004542 f_sleep(1.0);
4543
4544 vc_conn := f_start_handler(refers(f_TC_assignment_codec_fail), pars);
4545 vc_conn.done;
4546 f_allow_amr_rate_5_90k();
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004547 f_vty_amr_start_mode_restore(fr);
Philipp Maierd0e64b02019-03-13 14:15:23 +01004548}
4549
4550
4551/* Set S1, we expect an AMR multirate configuration IE with all four rates
4552 * set. */
4553testcase TC_assignment_codec_amr_f_S1() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004554 f_TC_assignment_codec_amr(true, '289520882208'O, '00000010'B, '00000010'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004555 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004556}
4557
4558/* Set S1, we expect an AMR multirate configuration IE with the lower three
4559 * rates set. */
4560testcase TC_assignment_codec_amr_h_S1() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004561 f_TC_assignment_codec_amr(false, '2815208820'O, '00000010'B, '00000010'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004562 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004563}
4564
4565/* Set S1 and two other rates, we expect an AMR MULTIRATE CONFIGURATION IE with
4566 * all four rates (and only S1 set in the ASSIGNMENT COMPLETE) */
4567testcase TC_assignment_codec_amr_f_S124() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004568 f_TC_assignment_codec_amr(true, '289520882208'O, '00010110'B, '00000010'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004569 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004570}
4571
4572/* Set S1 and two other rates, we expect an AMR MULTIRATE CONFIGURATION IE with
4573 * all four rates (and only S1 set in the ASSIGNMENT COMPLETE) */
4574testcase TC_assignment_codec_amr_h_S124() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004575 f_TC_assignment_codec_amr(false, '2815208820'O, '00010110'B, '00000010'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004576 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004577}
4578
4579/* The following block of tests selects more and more rates until all four
4580 * possible rates are in the active set (full rate) */
4581testcase TC_assignment_codec_amr_f_S0() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004582 f_TC_assignment_codec_amr(true, '2801'O, '00000001'B, '00000001'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004583 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004584}
4585
4586testcase TC_assignment_codec_amr_f_S02() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004587 f_TC_assignment_codec_amr(true, '28052080'O, '00000101'B, '00000101'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004588 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004589}
4590
4591testcase TC_assignment_codec_amr_f_S024() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004592 f_TC_assignment_codec_amr(true, '2815208820'O, '00010101'B, '00010101'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004593 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004594}
4595
4596testcase TC_assignment_codec_amr_f_S0247() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004597 f_TC_assignment_codec_amr(true, '289520882208'O, '10010101'B, '10010101'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004598 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004599}
4600
4601/* The following block of tests selects more and more rates until all three
4602 * possible rates are in the active set (half rate) */
4603testcase TC_assignment_codec_amr_h_S0() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004604 f_TC_assignment_codec_amr(false, '2801'O, '00000001'B, '00000001'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004605 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004606}
4607
4608testcase TC_assignment_codec_amr_h_S02() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004609 f_TC_assignment_codec_amr(false, '28052080'O, '00000101'B, '00000101'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004610 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004611}
4612
4613testcase TC_assignment_codec_amr_h_S024() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004614 f_TC_assignment_codec_amr(false, '2815208820'O, '00010101'B, '00010101'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004615 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004616}
4617
4618/* The following block tests what happens when the MSC does offer rate
4619 * configurations that are not supported by the BSC. Normally such situations
4620 * should not happen because the MSC gets informed by the BSC in advance via
4621 * the L3 COMPLETE message which rates are applicable. The MSC should not try
4622 * to offer rates that are not applicable anyway. */
4623
4624testcase TC_assignment_codec_amr_h_S0247() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004625 /* Try to include 12,2k in into the active set even though the channel
4626 * is half rate only. The BSC is expected to remove the 12,0k */
4627 f_TC_assignment_codec_amr(false, '2815208820'O, '10010101'B, '00010101'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004628 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004629}
4630
4631testcase TC_assignment_codec_amr_f_S01234567() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004632 /* See what happens when all rates are selected at once. Since then
4633 * Also S1 is selected, this setting will be prefered and we should
4634 * get 12.2k, 7,40k, 5,90k, and 4,75k in the active set. */
4635 f_TC_assignment_codec_amr(true, '289520882208'O, '11111111'B, '00000010'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004636 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004637}
4638
4639testcase TC_assignment_codec_amr_f_S0234567() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004640 /* Same as above, but with S1 missing, the MSC is then expected to
4641 * select the currently supported rates, which are also 12.2k, 7,40k,
4642 * 5,90k, and 4,75k, into the active set. */
4643 f_TC_assignment_codec_amr(true, '289520882208'O, '11111101'B, '10010101'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004644 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004645}
4646
4647testcase TC_assignment_codec_amr_f_zero() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004648 /* Try to select no rates at all */
4649 f_TC_assignment_codec_amr_fail(true, '00000000'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004650 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004651}
4652
4653testcase TC_assignment_codec_amr_f_unsupp() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004654 /* Try to select only unsupported rates */
4655 f_TC_assignment_codec_amr_fail(true, '01101000'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004656 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004657}
4658
4659testcase TC_assignment_codec_amr_h_S7() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004660 /* Try to select 12,2k for half rate */
4661 f_TC_assignment_codec_amr_fail(false, '10000000'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004662 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004663}
4664
Neels Hofmeyr21863562020-11-26 00:34:33 +00004665testcase TC_assignment_codec_amr_f_start_mode_auto() runs on test_CT {
4666 f_TC_assignment_codec_amr(true, '209520882208'O, '11111111'B, '00000010'B,
4667 start_mode := "auto");
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +01004668 f_shutdown_helper();
Neels Hofmeyr21863562020-11-26 00:34:33 +00004669}
4670
4671testcase TC_assignment_codec_amr_h_start_mode_auto() runs on test_CT {
4672 f_TC_assignment_codec_amr(false, '2015208820'O, '10010101'B, '00010101'B,
4673 start_mode := "auto");
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +01004674 f_shutdown_helper();
Neels Hofmeyr21863562020-11-26 00:34:33 +00004675}
4676
Neels Hofmeyr3eb94562020-11-26 02:40:26 +00004677testcase TC_assignment_codec_amr_f_start_mode_4() runs on test_CT {
Vadim Yanitskiy7815f482021-01-03 17:07:37 +01004678 /* "amr tch-f modes 0 2 4 7" => total 4 modes and start mode 4 => '11'B on the wire */
Neels Hofmeyr3eb94562020-11-26 02:40:26 +00004679 f_TC_assignment_codec_amr(true, '2b9520882208'O, '11111111'B, '00000010'B,
4680 start_mode := "4");
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +01004681 f_shutdown_helper();
Neels Hofmeyr3eb94562020-11-26 02:40:26 +00004682}
4683
4684testcase TC_assignment_codec_amr_h_start_mode_4() runs on test_CT {
Vadim Yanitskiy7815f482021-01-03 17:07:37 +01004685 /* "amr tch-h modes 0 2 4" => total 3 modes and start mode 4 => '10'B on the wire */
4686 f_TC_assignment_codec_amr(false, '2a15208820'O, '10010101'B, '00010101'B,
Neels Hofmeyr3eb94562020-11-26 02:40:26 +00004687 start_mode := "4");
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +01004688 f_shutdown_helper();
Neels Hofmeyr3eb94562020-11-26 02:40:26 +00004689}
4690
Philipp Maierac09bfc2019-01-08 13:41:39 +01004691private function f_disable_all_tch_f() runs on test_CT {
Philipp Maierc704a882019-01-29 15:58:52 +01004692 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 1 sub-slot 0 borken");
4693 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 2 sub-slot 0 borken");
4694 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 3 sub-slot 0 borken");
4695 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 4 sub-slot 0 borken");
Philipp Maierac09bfc2019-01-08 13:41:39 +01004696}
4697
4698private function f_disable_all_tch_h() runs on test_CT {
Philipp Maierc704a882019-01-29 15:58:52 +01004699 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 5 sub-slot 0 borken");
4700 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 5 sub-slot 1 borken");
Philipp Maierac09bfc2019-01-08 13:41:39 +01004701}
4702
4703private function f_enable_all_tch() runs on test_CT {
Philipp Maierc704a882019-01-29 15:58:52 +01004704 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 1 sub-slot 0 unused");
4705 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 2 sub-slot 0 unused");
4706 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 3 sub-slot 0 unused");
4707 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 4 sub-slot 0 unused");
4708 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 5 sub-slot 0 unused");
4709 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 5 sub-slot 1 unused");
Philipp Maierac09bfc2019-01-08 13:41:39 +01004710}
4711
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004712private function f_disable_all_sdcch() runs on test_CT {
4713 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 0 borken");
4714 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 1 borken");
4715 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 2 borken");
4716 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 3 borken");
4717}
4718
4719private function f_enable_all_sdcch() runs on test_CT {
4720 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 0 unused");
4721 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 1 unused");
4722 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 2 unused");
4723 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 3 unused");
4724}
4725
Philipp Maierac09bfc2019-01-08 13:41:39 +01004726/* Allow HR only */
4727private function f_TC_assignment_codec_xr_exhausted_req_hr(charstring id) runs on MSC_ConnHdlr {
4728 g_pars := f_gen_test_hdlr_pars();
4729 var PDU_BSSAP ass_cmd := f_gen_ass_req();
4730 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
4731 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
4732 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '09'O;
4733 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '05'O;
4734 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR}));
4735 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004736 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01004737}
4738
4739/* Allow FR only */
4740private function f_TC_assignment_codec_xr_exhausted_req_fr(charstring id) runs on MSC_ConnHdlr {
4741 g_pars := f_gen_test_hdlr_pars();
4742 var PDU_BSSAP ass_cmd := f_gen_ass_req();
4743 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
4744 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
4745 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '08'O;
4746 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '01'O;
4747 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
4748 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004749 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01004750}
4751
4752/* Allow HR only (expect assignment failure) */
4753private function f_TC_assignment_codec_xr_exhausted_req_hr_fail(charstring id) runs on MSC_ConnHdlr {
4754 g_pars := f_gen_test_hdlr_pars();
4755 var PDU_BSSAP ass_cmd := f_gen_ass_req();
4756 var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
4757 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
4758 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '09'O;
4759 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '05'O;
4760 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR}));
4761 f_establish_fully(ass_cmd, exp_fail);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004762 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01004763}
4764
4765/* Allow FR only (expect assignment failure) */
4766private function f_TC_assignment_codec_xr_exhausted_req_fr_fail(charstring id) runs on MSC_ConnHdlr {
4767 g_pars := f_gen_test_hdlr_pars();
4768 var PDU_BSSAP ass_cmd := f_gen_ass_req();
4769 var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
4770 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
4771 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '08'O;
4772 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '01'O;
4773 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
4774 f_establish_fully(ass_cmd, exp_fail);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004775 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01004776}
4777
4778/* Allow FR and HR, but prefer FR */
4779private function f_TC_assignment_codec_fr_exhausted_req_fr_hr(charstring id) runs on MSC_ConnHdlr {
4780 g_pars := f_gen_test_hdlr_pars();
4781 var PDU_BSSAP ass_cmd := f_gen_ass_req();
4782 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
4783 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
4784 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '0A'O; /* Prefer FR */
4785 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '8105'O;
4786 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR, ts_CodecHR}));
4787 exp_compl.pdu.bssmap.assignmentComplete.speechVersion.speechVersionIdentifier := '0000101'B; /* Expect HR */
4788 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004789 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01004790}
4791
4792/* Allow FR and HR, but prefer HR */
4793private function f_TC_assignment_codec_fr_exhausted_req_hr_fr(charstring id) runs on MSC_ConnHdlr {
4794 g_pars := f_gen_test_hdlr_pars();
4795 var PDU_BSSAP ass_cmd := f_gen_ass_req();
4796 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
4797 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
4798 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '0B'O; /* Prefer HR */
4799 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '8501'O;
4800 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR, ts_CodecFR}));
4801 exp_compl.pdu.bssmap.assignmentComplete.speechVersion.speechVersionIdentifier := '0000101'B; /* Expect HR */
4802 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004803 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01004804}
4805
4806/* Allow FR and HR, but prefer FR */
4807private function f_TC_assignment_codec_hr_exhausted_req_fr_hr(charstring id) runs on MSC_ConnHdlr {
4808 g_pars := f_gen_test_hdlr_pars();
4809 var PDU_BSSAP ass_cmd := f_gen_ass_req();
4810 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
4811 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
4812 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '0A'O; /* Prefer FR */
4813 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '8105'O;
4814 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR, ts_CodecHR}));
4815 exp_compl.pdu.bssmap.assignmentComplete.speechVersion.speechVersionIdentifier := '0000001'B; /* Expect FR */
4816 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004817 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01004818}
4819
4820/* Allow FR and HR, but prefer HR */
4821private function f_TC_assignment_codec_hr_exhausted_req_hr_fr(charstring id) runs on MSC_ConnHdlr {
4822 g_pars := f_gen_test_hdlr_pars();
4823 var PDU_BSSAP ass_cmd := f_gen_ass_req();
4824 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
4825 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
4826 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '0B'O; /* Prefer HR */
4827 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '8501'O;
4828 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR, ts_CodecFR}));
4829 exp_compl.pdu.bssmap.assignmentComplete.speechVersion.speechVersionIdentifier := '0000001'B; /* Expect FR */
4830 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004831 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01004832}
4833
4834/* Request a HR channel while all FR channels are exhausted, this is expected
4835 * to work without conflicts */
4836testcase TC_assignment_codec_fr_exhausted_req_hr() runs on test_CT {
4837 var MSC_ConnHdlr vc_conn;
4838 f_init(1, true);
4839 f_sleep(1.0);
4840 f_enable_all_tch();
4841 f_disable_all_tch_f();
4842 vc_conn := f_start_handler(refers(f_TC_assignment_codec_xr_exhausted_req_hr));
4843 vc_conn.done;
4844 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004845 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01004846}
4847
4848/* Request a FR channel while all FR channels are exhausted, this is expected
4849 * to fail. */
4850testcase TC_assignment_codec_fr_exhausted_req_fr() runs on test_CT {
4851 var MSC_ConnHdlr vc_conn;
4852 f_init(1, true);
4853 f_sleep(1.0);
4854 f_enable_all_tch();
4855 f_disable_all_tch_f();
4856 vc_conn := f_start_handler(refers(f_TC_assignment_codec_xr_exhausted_req_fr_fail));
4857 vc_conn.done;
4858 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004859 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01004860}
4861
4862/* Request a FR (prefered) or alternatively a HR channel while all FR channels
4863 * are exhausted, this is expected to be resolved by selecting a HR channel. */
4864testcase TC_assignment_codec_fr_exhausted_req_fr_hr() runs on test_CT {
4865 var MSC_ConnHdlr vc_conn;
4866 f_init(1, true);
4867 f_sleep(1.0);
4868 f_enable_all_tch();
4869 f_disable_all_tch_f();
4870 vc_conn := f_start_handler(refers(f_TC_assignment_codec_fr_exhausted_req_fr_hr));
4871 vc_conn.done;
4872 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004873 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01004874}
4875
4876/* Request a HR (prefered) or alternatively a FR channel while all FR channels
4877 * are exhausted, this is expected to work without conflicts. */
4878testcase TC_assignment_codec_fr_exhausted_req_hr_fr() runs on test_CT {
4879 var MSC_ConnHdlr vc_conn;
4880 f_init(1, true);
4881 f_sleep(1.0);
4882 f_enable_all_tch();
4883 f_disable_all_tch_f();
4884 vc_conn := f_start_handler(refers(f_TC_assignment_codec_fr_exhausted_req_hr_fr));
4885 vc_conn.done;
4886 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004887 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01004888}
4889
4890/* Request a FR channel while all HR channels are exhausted, this is expected
4891 * to work without conflicts */
4892testcase TC_assignment_codec_hr_exhausted_req_fr() runs on test_CT {
4893 var MSC_ConnHdlr vc_conn;
4894 f_init(1, true);
4895 f_sleep(1.0);
4896 f_enable_all_tch();
4897 f_disable_all_tch_h();
4898 vc_conn := f_start_handler(refers(f_TC_assignment_codec_xr_exhausted_req_fr));
4899 vc_conn.done;
4900 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004901 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01004902}
4903
4904/* Request a HR channel while all HR channels are exhausted, this is expected
4905 * to fail. */
4906testcase TC_assignment_codec_hr_exhausted_req_hr() runs on test_CT {
4907 var MSC_ConnHdlr vc_conn;
4908 f_init(1, true);
4909 f_sleep(1.0);
4910 f_enable_all_tch();
4911 f_disable_all_tch_h();
4912 vc_conn := f_start_handler(refers(f_TC_assignment_codec_xr_exhausted_req_hr_fail));
4913 vc_conn.done;
4914 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004915 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01004916}
4917
4918/* Request a HR (prefered) or alternatively a FR channel while all HR channels
4919 * are exhausted, this is expected to be resolved by selecting a FR channel. */
4920testcase TC_assignment_codec_hr_exhausted_req_hr_fr() runs on test_CT {
4921 var MSC_ConnHdlr vc_conn;
4922 f_init(1, true);
4923 f_sleep(1.0);
4924 f_enable_all_tch();
4925 f_disable_all_tch_h();
4926 vc_conn := f_start_handler(refers(f_TC_assignment_codec_hr_exhausted_req_hr_fr));
4927 vc_conn.done;
4928 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004929 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01004930}
4931
4932/* Request a FR (prefered) or alternatively a HR channel while all HR channels
4933 * are exhausted, this is expected to work without conflicts. */
4934testcase TC_assignment_codec_hr_exhausted_req_fr_hr() runs on test_CT {
4935 var MSC_ConnHdlr vc_conn;
4936 f_init(1, true);
4937 f_sleep(1.0);
4938 f_enable_all_tch();
4939 f_disable_all_tch_h();
4940 vc_conn := f_start_handler(refers(f_TC_assignment_codec_hr_exhausted_req_fr_hr));
4941 vc_conn.done;
4942 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004943 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01004944}
4945
4946/* Allow FR and HR, but prefer HR */
4947private function f_TC_assignment_codec_req_hr_fr(charstring id) runs on MSC_ConnHdlr {
4948 g_pars := f_gen_test_hdlr_pars();
4949 var PDU_BSSAP ass_cmd := f_gen_ass_req();
4950 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
4951 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
4952 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '0B'O; /* Prefer HR */
4953 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '8501'O;
4954 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR, ts_CodecFR}));
4955 exp_compl.pdu.bssmap.assignmentComplete.speechVersion.speechVersionIdentifier := '0000101'B; /* Expect HR */
4956 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004957 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01004958}
4959
4960/* Allow FR and HR, but prefer FR */
4961private function f_TC_assignment_codec_req_fr_hr(charstring id) runs on MSC_ConnHdlr {
4962 g_pars := f_gen_test_hdlr_pars();
4963 var PDU_BSSAP ass_cmd := f_gen_ass_req();
4964 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
4965 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
4966 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '0A'O; /* Prefer FR */
4967 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '8105'O;
4968 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR, ts_CodecHR}));
4969 exp_compl.pdu.bssmap.assignmentComplete.speechVersion.speechVersionIdentifier := '0000001'B; /* Expect FR */
4970 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01004971 f_perform_clear();
Philipp Maierac09bfc2019-01-08 13:41:39 +01004972}
4973
4974/* Request a HR (prefered) or alternatively a FR channel, it is expected that
4975 * HR, which is the prefered type, is selected. */
4976testcase TC_assignment_codec_req_hr_fr() runs on test_CT {
4977 var MSC_ConnHdlr vc_conn;
4978 f_init(1, true);
4979 f_sleep(1.0);
4980 f_enable_all_tch();
4981 vc_conn := f_start_handler(refers(f_TC_assignment_codec_req_hr_fr));
4982 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004983 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01004984}
4985
4986/* Request a FR (prefered) or alternatively a HR channel, it is expected that
4987 * FR, which is the prefered type, is selected. */
4988testcase TC_assignment_codec_req_fr_hr() runs on test_CT {
4989 var MSC_ConnHdlr vc_conn;
4990 f_init(1, true);
4991 f_sleep(1.0);
4992 f_enable_all_tch();
4993 vc_conn := f_start_handler(refers(f_TC_assignment_codec_req_fr_hr));
4994 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004995 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01004996}
4997
Pau Espin Pedrol14475352021-07-22 15:48:16 +02004998/* request a signalling channel with all SDCCH exhausted, it is expected that a TCH will be selected */
4999private function f_TC_assignment_sdcch_exhausted_req_signalling(charstring id) runs on MSC_ConnHdlr {
5000 g_pars := f_gen_test_hdlr_pars();
5001 g_pars.ra := '02'O; /* RA containing reason=LU */
5002
5003 var MobileIdentityLV mi := valueof(ts_MI_IMSI_LV(g_pars.imsi));
5004 var PDU_ML3_MS_NW l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, mi));
5005 var octetstring l3_enc := enc_PDU_ML3_MS_NW(l3_info);
5006 var template uint3_t tsc := ?;
5007
5008 f_MscConnHdlr_init(g_pars.media_nr, host_bts, host_mgw_mgcp, FR_AMR);
5009 f_create_bssmap_exp(l3_enc);
5010 /* call helper function for CHAN_RQD -> IMM ASS ->EST_IND */
5011 RSL_Emulation.f_chan_est(g_pars.ra, l3_enc, g_pars.link_id, g_pars.fn, tsc);
5012
5013 /* we should now have a COMPL_L3 at the MSC */
5014 timer T := 10.0;
5015 T.start;
5016 alt {
5017 [] BSSAP.receive(tr_BSSMAP_ComplL3);
5018 [] T.timeout {
5019 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout waiting for COMPLETE LAYER 3 INFORMATION");
5020 }
5021 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005022
5023 f_perform_clear();
Pau Espin Pedrol14475352021-07-22 15:48:16 +02005024}
5025testcase TC_assignment_sdcch_exhausted_req_signalling() runs on test_CT {
5026 var MSC_ConnHdlr vc_conn;
5027 f_init(1, true);
5028 f_sleep(1.0);
5029 f_disable_all_sdcch();
5030 vc_conn := f_start_handler(refers(f_TC_assignment_sdcch_exhausted_req_signalling));
5031 vc_conn.done;
5032 f_enable_all_sdcch();
5033 f_shutdown_helper();
5034}
5035
5036/* Request a signalling channel with all SDCCH exhausted, it is
5037 expected that no TCH will be selected for signalling and assigment will fail
5038 because it's dictated by VTY config */
5039testcase TC_assignment_sdcch_exhausted_req_signalling_tch_forbidden() runs on test_CT {
5040 var RSL_Message rsl_unused, rsl_msg;
5041 var GsmRrMessage rr;
5042 f_init(1, false);
5043 f_sleep(1.0);
5044 f_vty_allow_tch_for_signalling(false, 0);
5045 f_disable_all_sdcch();
5046
5047 /* RA containing reason=LU */
5048 f_ipa_tx(0, ts_RSL_CHAN_RQD('02'O, 2342));
5049 rsl_msg := f_exp_ipa_rx(0, tr_RSL_IMM_ASSIGN(0));
5050 rr := dec_GsmRrMessage(rsl_msg.ies[1].body.full_imm_ass_info.payload);
5051 if (rr.header.message_type != IMMEDIATE_ASSIGNMENT_REJECT) {
5052 setverdict(fail, "Expected reject");
5053 }
5054
5055 f_vty_allow_tch_for_signalling(true, 0);
5056 f_enable_all_sdcch();
5057 f_shutdown_helper();
5058}
5059
5060/* Request a voice channel with all SDCCH exhausted, it is
5061 * expected that TCH channel will be allocated since the VTY option is only
5062 * aimed at signalling requests */
5063private function f_TC_assignment_sdcch_exhausted_req_voice_tch_forbidden(charstring id) runs on MSC_ConnHdlr {
5064 g_pars := f_gen_test_hdlr_pars();
5065 g_pars.ra := '43'O; /* RA containing reason=originating speech call*/
5066
5067 var MobileIdentityLV mi := valueof(ts_MI_IMSI_LV(g_pars.imsi));
5068 var PDU_ML3_MS_NW l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, mi));
5069 var octetstring l3_enc := enc_PDU_ML3_MS_NW(l3_info);
5070 var template uint3_t tsc := ?;
5071
5072 f_MscConnHdlr_init(g_pars.media_nr, host_bts, host_mgw_mgcp, FR_AMR);
5073 f_create_bssmap_exp(l3_enc);
5074 /* call helper function for CHAN_RQD -> IMM ASS ->EST_IND */
5075 RSL_Emulation.f_chan_est(g_pars.ra, l3_enc, g_pars.link_id, g_pars.fn, tsc);
5076
5077 /* we should now have a COMPL_L3 at the MSC */
5078 timer T := 10.0;
5079 T.start;
5080 alt {
5081 [] BSSAP.receive(tr_BSSMAP_ComplL3);
5082 [] T.timeout {
5083 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout waiting for COMPLETE LAYER 3 INFORMATION");
5084 }
5085 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005086 f_perform_clear();
Pau Espin Pedrol14475352021-07-22 15:48:16 +02005087}
5088testcase TC_assignment_sdcch_exhausted_req_voice_tch_forbidden() runs on test_CT {
5089 var MSC_ConnHdlr vc_conn;
5090 f_init(1, true);
5091 f_sleep(1.0);
5092 f_vty_allow_tch_for_signalling(false, 0);
5093 f_disable_all_sdcch();
5094
5095 vc_conn := f_start_handler(refers(f_TC_assignment_sdcch_exhausted_req_voice_tch_forbidden));
5096 vc_conn.done;
5097
5098 f_vty_allow_tch_for_signalling(true, 0);
5099 f_enable_all_sdcch();
5100 f_shutdown_helper();
5101}
5102
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02005103testcase TC_assignment_osmux() runs on test_CT {
5104 var TestHdlrParams pars := f_gen_test_hdlr_pars();
5105 var MSC_ConnHdlr vc_conn;
5106
5107 /* See note above */
5108 var RSL_IE_Body mr_conf := {
5109 other := {
5110 len := 2,
5111 payload := '2804'O
5112 }
5113 };
5114
5115 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_H}));
5116 pars.ass_codec_list.codecElements[0].s0_7 := '00000100'B; /* 5,90k */
5117 pars.ass_codec_list.codecElements[0].s8_15 := '00000111'B;
5118 pars.expect_mr_conf_ie := mr_conf;
5119 pars.use_osmux := true;
5120
5121 f_init(1, true, true);
5122 f_sleep(1.0);
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00005123 f_vty_amr_start_mode_set(false, "1");
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02005124
5125 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
5126 vc_conn.done;
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00005127
5128 f_vty_amr_start_mode_restore(false);
Vadim Yanitskiy292e5962021-01-03 14:18:47 +01005129 f_shutdown_helper();
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02005130}
5131
Neels Hofmeyr92b12b72018-09-18 14:30:23 +02005132/* test the procedure of the MSC requesting a Classmark Update:
5133 * a) BSSMAP Classmark Request should result in RR CLASSMARK ENQUIRY,
5134 * b) L3 RR CLASSMARK CHANGE should result in BSSMAP CLASSMARK UPDATE */
Harald Welte898113b2018-01-31 18:32:21 +01005135private function f_tc_classmark(charstring id) runs on MSC_ConnHdlr {
Philipp Maier48604732018-10-09 15:00:37 +02005136 g_pars := f_gen_test_hdlr_pars();
5137
Harald Weltea0630032018-03-20 21:09:55 +01005138 f_create_chan_and_exp();
Harald Welte898113b2018-01-31 18:32:21 +01005139 /* we should now have a COMPL_L3 at the MSC */
Harald Welte898113b2018-01-31 18:32:21 +01005140
Neels Hofmeyr92b12b72018-09-18 14:30:23 +02005141 BSSAP.send(ts_BSSMAP_ClassmarkRequest);
5142 RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_CM_ENQUIRY));
5143
Harald Welte898113b2018-01-31 18:32:21 +01005144 f_rsl_send_l3(ts_RRM_CM_CHG(valueof(ts_CM2)));
5145 BSSAP.receive(tr_BSSMAP_ClassmarkUpd(?, omit));
5146 setverdict(pass);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005147
5148 f_perform_clear();
Harald Welte898113b2018-01-31 18:32:21 +01005149}
5150testcase TC_classmark() runs on test_CT {
5151 var MSC_ConnHdlr vc_conn;
5152 f_init(1, true);
5153 f_sleep(1.0);
Harald Welte8863fa12018-05-10 20:15:27 +02005154 vc_conn := f_start_handler(refers(f_tc_classmark));
Harald Welte898113b2018-01-31 18:32:21 +01005155 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005156 f_shutdown_helper();
Harald Welte898113b2018-01-31 18:32:21 +01005157}
5158
Harald Welteeddf0e92020-06-21 19:42:15 +02005159/* Send a CommonID from the simulated MSC and verify that the information is used to
5160 * fill BSC-internal data structures (specifically, bsc_subscr associated with subscr_conn) */
5161private function f_tc_common_id(charstring id) runs on MSC_ConnHdlr {
5162 g_pars := f_gen_test_hdlr_pars();
5163 f_MscConnHdlr_init_vty();
5164
5165 f_create_chan_and_exp();
5166 /* we should now have a COMPL_L3 at the MSC */
Harald Welteeddf0e92020-06-21 19:42:15 +02005167
5168 /* Send CommonID */
5169 BSSAP.send(ts_BSSMAP_CommonId(g_pars.imsi));
5170
5171 /* Use VTY to verify that the IMSI of the subscr_conn is set */
5172 var charstring regex := "*(IMSI: " & hex2str(g_pars.imsi) & ")*";
5173 f_vty_transceive_match_regexp_retry(BSCVTY, "show conns", regex, 0, 4, 1.0);
5174
5175 setverdict(pass);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005176
5177 f_perform_clear();
Harald Welteeddf0e92020-06-21 19:42:15 +02005178}
5179testcase TC_common_id() runs on test_CT {
5180 var MSC_ConnHdlr vc_conn;
5181 f_init(1, true);
5182 f_sleep(1.0);
5183 vc_conn := f_start_handler(refers(f_tc_common_id));
5184 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005185 f_shutdown_helper();
Harald Welteeddf0e92020-06-21 19:42:15 +02005186}
5187
Harald Weltee3bd6582018-01-31 22:51:25 +01005188private function f_est_single_l3(template PDU_ML3_MS_NW l3) runs on MSC_ConnHdlr {
Philipp Maier48604732018-10-09 15:00:37 +02005189 g_pars := f_gen_test_hdlr_pars();
Harald Weltea0630032018-03-20 21:09:55 +01005190 f_create_chan_and_exp();
Harald Welte898113b2018-01-31 18:32:21 +01005191 /* we should now have a COMPL_L3 at the MSC */
Harald Welte898113b2018-01-31 18:32:21 +01005192
Harald Weltee3bd6582018-01-31 22:51:25 +01005193 /* send the single message we want to send */
5194 f_rsl_send_l3(l3);
5195}
5196
5197private function f_bssap_expect_nothing(float sec := 5.00) runs on MSC_ConnHdlr {
5198 timer T := sec;
5199 var PDU_BSSAP bssap;
Harald Welte898113b2018-01-31 18:32:21 +01005200 T.start;
5201 alt {
Harald Weltee3bd6582018-01-31 22:51:25 +01005202 [] BSSAP.receive(PDU_BSSAP:?) -> value bssap {
5203 setverdict(fail, "Unexpected BSSMAP ", bssap);
Daniel Willmannafce8662018-07-06 23:11:32 +02005204 mtc.stop;
Harald Welte898113b2018-01-31 18:32:21 +01005205 }
5206 [] T.timeout {
5207 setverdict(pass);
5208 }
5209 }
5210}
5211
Harald Weltee3bd6582018-01-31 22:51:25 +01005212/* unsolicited ASSIGNMENT FAIL (without ASSIGN) from MS shouldn't bring BSC down */
5213private function f_tc_unsol_ass_fail(charstring id) runs on MSC_ConnHdlr {
5214 f_est_single_l3(ts_RRM_AssignmentFailure('00'O));
5215 f_bssap_expect_nothing();
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005216 f_perform_clear();
Harald Weltee3bd6582018-01-31 22:51:25 +01005217}
Harald Welte898113b2018-01-31 18:32:21 +01005218testcase TC_unsol_ass_fail() runs on test_CT {
5219 var MSC_ConnHdlr vc_conn;
5220 f_init(1, true);
5221 f_sleep(1.0);
Harald Welte8863fa12018-05-10 20:15:27 +02005222 vc_conn := f_start_handler(refers(f_tc_unsol_ass_fail));
Harald Welte898113b2018-01-31 18:32:21 +01005223 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005224 f_shutdown_helper();
Harald Welte898113b2018-01-31 18:32:21 +01005225}
Harald Welte552620d2017-12-16 23:21:36 +01005226
Harald Welteea99a002018-01-31 20:46:43 +01005227
5228/* unsolicited ASSIGNMENT COMPLETE (without ASSIGN) from MS shouldn't bring BSC down */
5229private function f_tc_unsol_ass_compl(charstring id) runs on MSC_ConnHdlr {
Harald Weltee3bd6582018-01-31 22:51:25 +01005230 f_est_single_l3(ts_RRM_AssignmentComplete('00'O));
5231 f_bssap_expect_nothing();
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005232 f_perform_clear();
Harald Welteea99a002018-01-31 20:46:43 +01005233}
5234testcase TC_unsol_ass_compl() runs on test_CT {
5235 var MSC_ConnHdlr vc_conn;
5236 f_init(1, true);
5237 f_sleep(1.0);
Harald Welte8863fa12018-05-10 20:15:27 +02005238 vc_conn := f_start_handler(refers(f_tc_unsol_ass_compl));
Harald Welteea99a002018-01-31 20:46:43 +01005239 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005240 f_shutdown_helper();
Harald Welteea99a002018-01-31 20:46:43 +01005241}
5242
5243
Harald Weltefbf9b5e2018-01-31 20:41:23 +01005244/* unsolicited HANDOVER FAIL (without ASSIGN) from MS shouldn't bring BSC down */
5245private function f_tc_unsol_ho_fail(charstring id) runs on MSC_ConnHdlr {
Harald Weltee3bd6582018-01-31 22:51:25 +01005246 f_est_single_l3(ts_RRM_HandoverFailure('00'O));
5247 f_bssap_expect_nothing();
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005248 f_perform_clear();
Harald Weltefbf9b5e2018-01-31 20:41:23 +01005249}
Harald Weltefbf9b5e2018-01-31 20:41:23 +01005250testcase TC_unsol_ho_fail() runs on test_CT {
5251 var MSC_ConnHdlr vc_conn;
5252 f_init(1, true);
5253 f_sleep(1.0);
Harald Welte8863fa12018-05-10 20:15:27 +02005254 vc_conn := f_start_handler(refers(f_tc_unsol_ho_fail));
Harald Weltefbf9b5e2018-01-31 20:41:23 +01005255 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005256 f_shutdown_helper();
Harald Weltefbf9b5e2018-01-31 20:41:23 +01005257}
5258
5259
Harald Weltee3bd6582018-01-31 22:51:25 +01005260/* short message from MS should be ignored */
5261private function f_tc_err_82_short_msg(charstring id) runs on MSC_ConnHdlr {
Philipp Maier48604732018-10-09 15:00:37 +02005262 g_pars := f_gen_test_hdlr_pars();
Harald Weltea0630032018-03-20 21:09:55 +01005263 f_create_chan_and_exp();
Harald Weltee3bd6582018-01-31 22:51:25 +01005264 /* we should now have a COMPL_L3 at the MSC */
Harald Weltee3bd6582018-01-31 22:51:25 +01005265
5266 /* send short message */
5267 RSL.send(ts_RSL_DATA_IND(g_chan_nr, valueof(ts_RslLinkID_DCCH(0)), ''O));
5268 f_bssap_expect_nothing();
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005269 f_perform_clear();
Harald Weltee3bd6582018-01-31 22:51:25 +01005270}
5271testcase TC_err_82_short_msg() runs on test_CT {
5272 var MSC_ConnHdlr vc_conn;
5273 f_init(1, true);
5274 f_sleep(1.0);
Harald Welte8863fa12018-05-10 20:15:27 +02005275 vc_conn := f_start_handler(refers(f_tc_err_82_short_msg));
Harald Weltee3bd6582018-01-31 22:51:25 +01005276 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005277 f_shutdown_helper();
Harald Weltee3bd6582018-01-31 22:51:25 +01005278}
5279
5280
Harald Weltee9e02e42018-01-31 23:36:25 +01005281/* 24.008 8.4 Unknown message must trigger RR STATUS */
5282private function f_tc_err_84_unknown_msg(charstring id) runs on MSC_ConnHdlr {
5283 f_est_single_l3(ts_RRM_UL_REL('00'O));
5284 timer T := 3.0
5285 alt {
5286 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_STATUS)) {
5287 setverdict(pass);
5288 }
5289 [] BSSAP.receive { setverdict(fail, "unexpected BSSAP"); }
Harald Welte458fd372018-03-21 11:26:23 +01005290 [] T.timeout { setverdict(fail, "Timeout waiting for RR STATUS"); }
Harald Weltee9e02e42018-01-31 23:36:25 +01005291 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005292 f_perform_clear();
Harald Weltee9e02e42018-01-31 23:36:25 +01005293}
5294testcase TC_err_84_unknown_msg() runs on test_CT {
5295 var MSC_ConnHdlr vc_conn;
5296 f_init(1, true);
5297 f_sleep(1.0);
Harald Welte8863fa12018-05-10 20:15:27 +02005298 vc_conn := f_start_handler(refers(f_tc_err_84_unknown_msg));
Harald Weltee9e02e42018-01-31 23:36:25 +01005299 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005300 f_shutdown_helper();
Harald Weltee9e02e42018-01-31 23:36:25 +01005301}
5302
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01005303/***********************************************************************
5304 * Handover
5305 ***********************************************************************/
5306
Harald Welte94e0c342018-04-07 11:33:23 +02005307/* execute a "bts <0-255> trx <0-255> timeslot <0-7> " command on given Dchan */
5308private function f_vty_ts_action(charstring suffix, integer bts_nr, integer trx_nr, integer ts_nr)
5309runs on test_CT {
5310 var charstring cmd := "bts "&int2str(bts_nr)&" trx "&int2str(trx_nr)&
5311 " timeslot "&int2str(ts_nr)&" ";
5312 f_vty_transceive(BSCVTY, cmd & suffix);
5313}
5314
Harald Welte261af4b2018-02-12 21:20:39 +01005315/* 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 +07005316private function f_vty_ss_action(TELNETasp_PT pt, charstring suffix,
5317 uint8_t bts_nr, uint8_t trx_nr,
5318 in RslChannelNr chan_nr)
5319{
Harald Welte261af4b2018-02-12 21:20:39 +01005320 /* FIXME: resolve those from component-global state */
5321 var integer ts_nr := chan_nr.tn;
5322 var integer ss_nr;
5323 if (ischosen(chan_nr.u.ch0)) {
5324 ss_nr := 0;
5325 } else if (ischosen(chan_nr.u.lm)) {
5326 ss_nr := chan_nr.u.lm.sub_chan;
5327 } else if (ischosen(chan_nr.u.sdcch4)) {
5328 ss_nr := chan_nr.u.sdcch4.sub_chan;
5329 } else if (ischosen(chan_nr.u.sdcch8)) {
5330 ss_nr := chan_nr.u.sdcch8.sub_chan;
5331 } else {
5332 setverdict(fail, "Invalid ChanNr ", chan_nr);
Daniel Willmannafce8662018-07-06 23:11:32 +02005333 mtc.stop;
Harald Welte261af4b2018-02-12 21:20:39 +01005334 }
5335
5336 var charstring cmd := "bts "&int2str(bts_nr)&" trx "&int2str(trx_nr)&
5337 " timeslot "&int2str(ts_nr)&" sub-slot "&int2str(ss_nr)&" ";
Vadim Yanitskiy00070722020-09-02 17:27:57 +07005338 f_vty_transceive(pt, cmd & suffix);
Harald Welte261af4b2018-02-12 21:20:39 +01005339}
5340
Neels Hofmeyr91401012019-07-11 00:42:35 +02005341/* Even though the VTY command to trigger handover takes a new BTS number as argument, behind the scenes osmo-bsc always
5342 * translates that to a target ARFCN+BSIC first. See bsc_vty.c trigger_ho_or_as(), which puts the selected BTS' neighbor
5343 * ident key (ARFCN + BSIC) in the struct passed on to handover_request(). handover_start() then resolves that to a
5344 * viable actual neighbor cell. So from the internal osmo-bsc perspective, we always request handover to an ARFCN + BSIC
5345 * pair, not really to a specific BTS number. */
Vadim Yanitskiy00070722020-09-02 17:27:57 +07005346private function f_vty_handover(TELNETasp_PT pt, uint8_t bts_nr, uint8_t trx_nr,
5347 in RslChannelNr chan_nr, uint8_t new_bts_nr)
5348{
5349 f_vty_ss_action(pt, "handover " & int2str(new_bts_nr), bts_nr, trx_nr, chan_nr);
Harald Welte261af4b2018-02-12 21:20:39 +01005350}
5351
5352/* intra-BSC hand-over between BTS0 and BTS1 */
5353private function f_tc_ho_int(charstring id) runs on MSC_ConnHdlr {
Harald Welteed848512018-05-24 22:27:58 +02005354 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5355 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Harald Welte261af4b2018-02-12 21:20:39 +01005356
5357 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5358 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
5359
Harald Weltea0630032018-03-20 21:09:55 +01005360 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr666f0432020-07-04 00:53:07 +02005361 f_bts_0_cfg(BSCVTY, {"neighbor bts 1"});
Harald Welte261af4b2018-02-12 21:20:39 +01005362
5363 var HandoverState hs := {
5364 rr_ho_cmpl_seen := false,
5365 handover_done := false,
Neels Hofmeyrc741fcb2021-10-02 14:52:28 +02005366 old_chan_nr := -,
5367 expect_target_tsc := BTS_TSC[1]
Harald Welte261af4b2018-02-12 21:20:39 +01005368 };
Neels Hofmeyrc2cf4542021-10-02 12:26:38 +02005369 /* issue hand-over command on VTY, from BTS 0 to BTS 1 */
Vadim Yanitskiy00070722020-09-02 17:27:57 +07005370 f_vty_handover(BSCVTY, 0, 0, g_chan_nr, 1);
Harald Welte261af4b2018-02-12 21:20:39 +01005371 /* temporarily suspend DChan processing on BTS1 to avoid race with RSLEM_register */
5372 f_rslem_suspend(RSL1_PROC);
Philipp Maier3e2af5d2018-07-11 17:01:05 +02005373
5374 /* From the MGW perspective, a handover is is characterized by
5375 * performing one MDCX operation with the MGW. So we expect to see
5376 * one more MDCX during handover. */
5377 g_media.mgcp_conn[0].mdcx_seen_exp := g_media.mgcp_conn[0].crcx_seen_exp + 1;
5378
Harald Welte261af4b2018-02-12 21:20:39 +01005379 alt {
5380 [] as_handover(hs);
Harald Welte261af4b2018-02-12 21:20:39 +01005381 }
Philipp Maier3e2af5d2018-07-11 17:01:05 +02005382
Philipp Maier4dae0652018-11-12 12:03:26 +01005383 /* Since this is an internal handover we expect the BSC to inform the
5384 * MSC about the event */
5385 BSSAP.receive(tr_BSSMAP_HandoverPerformed);
5386
Philipp Maier3e2af5d2018-07-11 17:01:05 +02005387 /* Check the amount of MGCP transactions is still consistant with the
5388 * test expectation */
5389 f_check_mgcp_expectations()
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005390
Neels Hofmeyrc2cf4542021-10-02 12:26:38 +02005391 var RSL_Message chan_act := f_rslem_get_last_act(RSL1_PROC, 0, g_chan_nr);
5392
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005393 /* Ensure the Channel Activation for the new channel contained the right encryption params. as_handover() set
5394 * 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 +02005395 f_verify_encr_info(chan_act);
5396
5397 f_chan_act_verify_tsc(chan_act, BTS_TSC[1]);
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005398
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005399 f_perform_clear(RSL1, RSL1_PROC);
5400
Neels Hofmeyr861a4c12018-11-07 01:23:17 +01005401 f_sleep(0.5);
Harald Welte261af4b2018-02-12 21:20:39 +01005402}
5403
5404testcase TC_ho_int() runs on test_CT {
Neels Hofmeyr5f7a9df2021-06-21 01:30:43 +02005405 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte261af4b2018-02-12 21:20:39 +01005406 var MSC_ConnHdlr vc_conn;
5407 f_init(2, true);
5408 f_sleep(1.0);
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00005409
Neels Hofmeyrc2cf4542021-10-02 12:26:38 +02005410 pars.expect_tsc := BTS_TSC[0];
5411
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01005412 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00005413
Neels Hofmeyr5f7a9df2021-06-21 01:30:43 +02005414 vc_conn := f_start_handler(refers(f_tc_ho_int), pars);
Harald Welte261af4b2018-02-12 21:20:39 +01005415 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00005416
5417 /* from f_establish_fully() */
5418 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
5419 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
5420 /* from handover */
5421 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
5422 f_ctrs_bsc_and_bts_add(0, "handover:completed");
5423 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
5424 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:completed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01005425 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:attempted");
5426 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:completed");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00005427 f_ctrs_bsc_and_bts_verify();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005428 f_shutdown_helper();
Harald Welte261af4b2018-02-12 21:20:39 +01005429}
Harald Weltee9e02e42018-01-31 23:36:25 +01005430
Oliver Smith7eabd312021-07-12 14:18:56 +02005431function 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 +02005432 var MSC_ConnHdlr vc_conn;
5433 var TestHdlrParams pars := f_gen_test_hdlr_pars();
5434 pars.encr := valueof(t_EncrParams(encr_alg, f_rnd_octstring(8), f_rnd_octstring(16)));
5435
5436 f_init(2, true);
Oliver Smith7eabd312021-07-12 14:18:56 +02005437 f_vty_encryption_a5(enc_a5);
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005438 f_sleep(1.0);
5439
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01005440 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005441
5442 vc_conn := f_start_handler(refers(f_tc_ho_int), pars);
5443 vc_conn.done;
5444
5445 /* from f_establish_fully() */
5446 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
5447 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
5448 /* from handover */
5449 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
5450 f_ctrs_bsc_and_bts_add(0, "handover:completed");
5451 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
5452 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:completed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01005453 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:attempted");
5454 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:completed");
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005455 f_ctrs_bsc_and_bts_verify();
Oliver Smith7eabd312021-07-12 14:18:56 +02005456 f_vty_encryption_a5_reset();
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005457 f_shutdown_helper();
5458}
5459
5460testcase TC_ho_int_a5_0() runs on test_CT {
5461 f_tc_ho_int_a5('01'O);
5462}
5463
5464testcase TC_ho_int_a5_1() runs on test_CT {
5465 f_tc_ho_int_a5('02'O);
5466}
5467
5468testcase TC_ho_int_a5_3() runs on test_CT {
5469 f_tc_ho_int_a5('08'O);
5470}
5471
5472testcase TC_ho_int_a5_4() runs on test_CT {
Oliver Smith7eabd312021-07-12 14:18:56 +02005473 f_tc_ho_int_a5('10'O, "0 1 3 4");
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005474}
5475
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005476/* intra-BSC hand-over with CONNection FAILure and cause Radio Link Failure: check RR release cause */
5477private function f_tc_ho_int_radio_link_failure(charstring id) runs on MSC_ConnHdlr {
5478 g_pars := f_gen_test_hdlr_pars();
5479 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5480 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005481
5482 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5483 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
5484
5485 f_establish_fully(ass_cmd, exp_compl);
5486 f_bts_0_cfg(BSCVTY, {"neighbor bts 1"});
5487
5488 var HandoverState hs := {
5489 rr_ho_cmpl_seen := false,
5490 handover_done := false,
Neels Hofmeyrc741fcb2021-10-02 14:52:28 +02005491 old_chan_nr := -,
5492 expect_target_tsc := BTS_TSC[1]
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005493 };
5494 /* issue hand-over command on VTY */
5495 f_vty_handover(BSCVTY, 0, 0, g_chan_nr, 1);
5496 /* temporarily suspend DChan processing on BTS1 to avoid race with RSLEM_register */
5497 f_rslem_suspend(RSL1_PROC);
5498
5499 /* From the MGW perspective, a handover is is characterized by
5500 * performing one MDCX operation with the MGW. So we expect to see
5501 * one more MDCX during handover. */
5502 g_media.mgcp_conn[0].mdcx_seen_exp := g_media.mgcp_conn[0].crcx_seen_exp + 1;
5503
5504 var RSL_Message rsl;
5505 var PDU_ML3_NW_MS l3;
5506 var RslChannelNr new_chan_nr;
5507 var GsmArfcn arfcn;
5508 RSL.receive(tr_RSL_DATA_REQ(g_chan_nr)) -> value rsl {
5509 l3 := dec_PDU_ML3_NW_MS(rsl.ies[2].body.l3_info.payload);
5510 if (not ischosen(l3.msgs.rrm.handoverCommand)) {
5511 setverdict(fail, "Expected handoverCommand");
5512 mtc.stop;
5513 }
5514 }
5515 f_ChDesc2RslChanNr(l3.msgs.rrm.handoverCommand.channelDescription2,
5516 new_chan_nr, arfcn);
5517
5518 f_rslem_register(0, new_chan_nr, RSL1_PROC);
5519
5520 /* resume processing of RSL DChan messages, which was temporarily suspended
5521 * before performing a hand-over */
5522 f_rslem_resume(RSL1_PROC);
5523 RSL1.receive(tr_RSL_IPA_CRCX(new_chan_nr));
5524
5525 f_sleep(1.0);
5526
5527 /* Handover fails because no HANDO DET appears on the new lchan,
5528 * and the old lchan reports a Radio Link Failure. */
5529 RSL.send(ts_RSL_CONN_FAIL_IND(g_chan_nr, RSL_ERR_RADIO_LINK_FAIL));
5530
5531 var PDU_BSSAP rx_clear_request;
5532 BSSAP.receive(tr_BSSMAP_ClearRequest) -> value rx_clear_request;
5533 var BssmapCause cause := bit2int(rx_clear_request.pdu.bssmap.clearRequest.cause.causeValue);
5534 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
5535
5536 var RR_Cause rr_cause := GSM48_RR_CAUSE_ABNORMAL_UNSPEC;
5537
5538 var MgcpCommand mgcp;
5539 interleave {
5540 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_RELEASE(int2oct(enum2int(rr_cause), 1)))) {}
5541 [] RSL.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {}
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +02005542 [] RSL.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005543 RSL.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
Neels Hofmeyre680b012021-07-22 19:19:09 +02005544 f_rslem_unregister(0, g_chan_nr);
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005545 }
5546 [] RSL1.receive(tr_RSL_DEACT_SACCH(new_chan_nr)) {}
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +02005547 [] RSL1.receive(tr_RSL_RF_CHAN_REL(new_chan_nr)) {
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005548 RSL1.send(ts_RSL_RF_CHAN_REL_ACK(new_chan_nr));
Neels Hofmeyre680b012021-07-22 19:19:09 +02005549 f_rslem_unregister(0, g_chan_nr, PT := RSL1_PROC);
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005550 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005551 [] BSSAP.receive(tr_BSSMAP_ClearComplete) {
5552 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
5553 }
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005554 }
5555
5556 f_sleep(0.5);
5557 setverdict(pass);
5558}
5559testcase TC_ho_int_radio_link_failure() runs on test_CT {
5560 var MSC_ConnHdlr vc_conn;
5561 f_init(2, true);
5562 f_sleep(1.0);
5563
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01005564 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005565
5566 vc_conn := f_start_handler(refers(f_tc_ho_int_radio_link_failure));
5567 vc_conn.done;
5568
5569 /* from f_establish_fully() */
5570 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
5571 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
5572 /* from handover */
5573 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
5574 f_ctrs_bsc_and_bts_add(0, "handover:stopped");
5575 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
5576 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:stopped");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01005577 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:attempted");
5578 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:stopped");
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005579 f_ctrs_bsc_and_bts_verify();
5580 f_shutdown_helper();
5581}
5582
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005583/* Expecting MGCP to DLCX the endpoint's two connections: towards BTS and towards MSC */
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02005584private function f_expect_dlcx_conns() runs on MSC_ConnHdlr {
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005585 var MgcpCommand mgcp;
Pau Espin Pedrolfd02ad42019-06-18 17:45:20 +02005586 var template MgcpResponse mgcp_resp;
5587 var MGCP_RecvFrom mrf;
5588 var template MgcpMessage msg_resp;
5589 var template MgcpMessage msg_dlcx := {
5590 command := tr_DLCX()
5591 }
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005592
Pau Espin Pedrolfd02ad42019-06-18 17:45:20 +02005593 if (g_pars.aoip) {
5594 MGCP.receive(tr_DLCX()) -> value mgcp {
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005595 log("Got first DLCX: ", mgcp);
5596 MGCP.send(ts_DLCX_ACK2(mgcp.line.trans_id));
Pau Espin Pedrolfd02ad42019-06-18 17:45:20 +02005597 };
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005598
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005599 MGCP.receive(tr_DLCX()) -> value mgcp {
5600 log("Got second DLCX: ", mgcp);
5601 MGCP.send(ts_DLCX_ACK2(mgcp.line.trans_id));
5602 };
Pau Espin Pedrolfd02ad42019-06-18 17:45:20 +02005603 } else {
5604 /* For SCCPLite, BSC doesn't handle the MSC-side */
5605 MGCP_MULTI.receive(tr_MGCP_RecvFrom_any(msg_dlcx)) -> value mrf {
5606 log("Got first DLCX: ", mrf.msg.command);
5607 msg_resp := {
5608 response := ts_DLCX_ACK2(mrf.msg.command.line.trans_id)
5609 }
5610 MGCP_MULTI.send(t_MGCP_SendToMrf(mrf, msg_resp));
5611 };
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005612 }
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005613}
5614
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02005615private 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 +01005616
Neels Hofmeyrafe2ea52021-11-24 15:16:12 +01005617 var NcellReports neighbor_rep := {
5618 { rxlev := 20, bcch_freq := 0, bsic := 11 }
5619 };
5620 var octetstring l3_mr := enc_GsmRrL3Message(valueof(ts_MEAS_REP(true, 8, 8, reps := neighbor_rep)));
5621 RSL.send(ts_RSL_MEAS_RES(g_chan_nr, 0, ts_RSL_IE_UplinkMeas, ts_RSL_IE_BS_Power(0), ts_RSL_IE_L1Info,
5622 l3_mr, 0));
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01005623
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02005624 BSSAP.receive(tr_BSSMAP_HandoverRequired(exp_oldToNewBSSIEs));
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01005625
5626 f_sleep(0.5);
5627 /* The MSC negotiates Handover Request and Handover Request Ack with
5628 * the other BSS and comes back with a BSSMAP Handover Command
5629 * containing an RR Handover Command coming from the target BSS... */
5630
5631 var PDU_ML3_NW_MS rr_ho_cmd := valueof(ts_RR_HandoverCommand);
5632 log("Remote cell's RR Handover Command passed through as L3 Info: ", rr_ho_cmd);
5633 var octetstring rr_ho_cmd_enc := enc_PDU_ML3_NW_MS(rr_ho_cmd);
5634 log("Remote cell's RR Handover Command passed through as L3 Info, encoded: ", rr_ho_cmd_enc);
5635 BSSAP.send(ts_BSSMAP_HandoverCommand(rr_ho_cmd_enc));
5636
5637 /* expect the Handover Command to go out on RR */
5638 var RSL_Message rsl_ho_cmd
5639 RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, ?)) -> value rsl_ho_cmd;
5640 log("RSL Data Req went out to first BTS: ", rsl_ho_cmd);
5641 var RSL_IE_Body rsl_ho_cmd_l3;
5642 if (not f_rsl_find_ie(rsl_ho_cmd, RSL_IE_L3_INFO, rsl_ho_cmd_l3)) {
5643 log("RSL message contains no L3 Info IE, expected RR Handover Command");
5644 setverdict(fail);
5645 } else {
5646 log("Found L3 Info: ", rsl_ho_cmd_l3);
5647 if (rsl_ho_cmd_l3.l3_info.payload != rr_ho_cmd_enc) {
5648 log("FAIL: the BSC sent out a different L3 Info, not matching the RR Handover Command the other BSS forwarded.");
5649 setverdict(fail);
5650 } else {
5651 log("Success: the BSC sent out the same RR Handover Command the other BSS forwarded.");
5652 setverdict(pass);
5653 }
5654 }
5655
5656 /* When the other BSS has reported a completed handover, this side is
5657 * torn down. */
5658
5659 var myBSSMAP_Cause cause_val := GSM0808_CAUSE_HANDOVER_SUCCESSFUL;
5660 var BssmapCause cause := enum2int(cause_val);
5661 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
5662
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02005663 f_expect_dlcx_conns();
Pau Espin Pedrol06199952021-06-15 11:30:00 +02005664
5665 interleave {
5666 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_RELEASE));
5667 [] RSL.receive(tr_RSL_DEACT_SACCH(g_chan_nr));
5668 [] RSL.receive(tr_RSL_RF_CHAN_REL(g_chan_nr));
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005669 [] BSSAP.receive(tr_BSSMAP_ClearComplete) {
5670 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
5671 }
Pau Espin Pedrol06199952021-06-15 11:30:00 +02005672 }
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01005673 setverdict(pass);
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02005674}
5675
5676private function f_tc_ho_out_of_this_bsc(charstring id) runs on MSC_ConnHdlr {
5677 g_pars := f_gen_test_hdlr_pars();
5678 var PDU_BSSAP ass_req := f_gen_ass_req();
5679 ass_req.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5680 ass_req.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
5681 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5682 f_establish_fully(ass_req, exp_compl);
5683
5684 f_ho_out_of_this_bsc();
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01005685}
5686testcase TC_ho_out_of_this_bsc() runs on test_CT {
5687 var MSC_ConnHdlr vc_conn;
5688
Neels Hofmeyrafe2ea52021-11-24 15:16:12 +01005689 f_init_vty();
5690 f_bts_0_cfg(BSCVTY,
5691 {"neighbor-list mode automatic",
5692 "handover 1",
5693 "handover algorithm 2",
5694 "handover2 window rxlev averaging 1",
Neels Hofmeyr6cc90eb2021-12-15 12:49:39 +01005695 "no neighbors",
Neels Hofmeyrafe2ea52021-11-24 15:16:12 +01005696 "neighbor lac 99 arfcn 123 bsic any"});
5697 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
5698
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01005699 f_init(1, true);
5700 f_sleep(1.0);
5701
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01005702 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00005703
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01005704 vc_conn := f_start_handler(refers(f_tc_ho_out_of_this_bsc));
5705 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00005706
5707 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
5708 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
5709 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
5710 f_ctrs_bsc_and_bts_add(0, "handover:completed");
5711 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
5712 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:completed");
5713 f_ctrs_bsc_and_bts_verify();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005714 f_shutdown_helper();
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01005715}
5716
Neels Hofmeyr0aa719b2020-10-12 18:43:09 +00005717private function f_mo_l3_transceive(RSL_DCHAN_PT rsl := RSL,
5718 template (value) RslLinkId link_id := ts_RslLinkID_DCCH(0),
Vadim Yanitskiy2ef6a2f2020-10-08 23:17:32 +07005719 template (present) OCT1 dlci := ?,
Vadim Yanitskiyb93aa432020-10-01 14:23:11 +07005720 octetstring l3 := '0123456789'O)
5721runs on MSC_ConnHdlr {
Neels Hofmeyr43654812020-09-25 01:35:35 +02005722 /* The old lchan and conn should still be active. See that arbitrary L3
5723 * is still going through. */
Neels Hofmeyr0aa719b2020-10-12 18:43:09 +00005724 rsl.send(ts_RSL_DATA_IND(g_chan_nr, link_id, l3));
Neels Hofmeyr43654812020-09-25 01:35:35 +02005725 var template PDU_BSSAP exp_data := {
5726 discriminator := '1'B,
5727 spare := '0000000'B,
Vadim Yanitskiyb93aa432020-10-01 14:23:11 +07005728 dlci := dlci,
5729 lengthIndicator := lengthof(l3),
Neels Hofmeyr43654812020-09-25 01:35:35 +02005730 pdu := {
5731 dtap := l3
5732 }
5733 };
5734 BSSAP.receive(exp_data);
5735 setverdict(pass);
5736}
5737
Neels Hofmeyr0aa719b2020-10-12 18:43:09 +00005738private function f_mt_l3_transceive(RSL_DCHAN_PT rsl := RSL,
5739 template (present) RslLinkId link_id := tr_RslLinkID_DCCH(0),
Vadim Yanitskiy0033a3b2020-10-01 22:21:16 +07005740 template (value) OCT1 dlci := '00'O,
5741 octetstring l3 := '0123456789'O)
5742runs on MSC_ConnHdlr {
5743 BSSAP.send(PDU_BSSAP:{
5744 discriminator := '1'B,
5745 spare := '0000000'B,
5746 dlci := dlci,
5747 lengthIndicator := lengthof(l3),
5748 pdu := {
5749 dtap := l3
5750 }
5751 });
Neels Hofmeyr0aa719b2020-10-12 18:43:09 +00005752 rsl.receive(tr_RSL_DATA_REQ(g_chan_nr, link_id, l3));
Vadim Yanitskiy0033a3b2020-10-01 22:21:16 +07005753 setverdict(pass);
5754}
5755
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02005756/* BSC asks for inter-BSC HO, but the MSC decides that it won't happen and
5757 * simply never sends a BSSMAP Handover Command. */
5758private function f_tc_ho_out_fail_no_msc_response(charstring id) runs on MSC_ConnHdlr {
Daniel Willmann3b59eb52018-10-29 15:40:55 +01005759 g_pars := f_gen_test_hdlr_pars();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02005760
5761 var PDU_BSSAP ass_req := f_gen_ass_req();
5762 ass_req.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5763 ass_req.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
5764 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5765 f_establish_fully(ass_req, exp_compl);
5766
Neels Hofmeyr6cc90eb2021-12-15 12:49:39 +01005767 f_bts_0_cfg(BSCVTY, {"no neighbor lac 99", "neighbor lac 99 arfcn 123 bsic any"});
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02005768 f_vty_transceive(BSCVTY, "handover any to arfcn 123 bsic any");
5769
5770 BSSAP.receive(tr_BSSMAP_HandoverRequired);
5771
5772 /* osmo-bsc should time out 10 seconds after the handover started.
5773 * Let's give it a bit extra. */
5774 f_sleep(15.0);
5775
Vadim Yanitskiy74ae5eb2020-10-01 22:13:29 +07005776 f_mo_l3_transceive();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02005777 f_sleep(1.0);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005778 f_perform_clear();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02005779}
5780testcase TC_ho_out_fail_no_msc_response() runs on test_CT {
5781 var MSC_ConnHdlr vc_conn;
5782
5783 f_init(1, true);
5784 f_sleep(1.0);
5785
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01005786 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00005787
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02005788 vc_conn := f_start_handler(refers(f_tc_ho_out_fail_no_msc_response));
5789 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00005790
5791 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
5792 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
5793 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
5794 f_ctrs_bsc_and_bts_add(0, "handover:timeout");
5795 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
5796 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:timeout");
5797 f_ctrs_bsc_and_bts_verify();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005798 f_shutdown_helper();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02005799}
5800
5801/* BSC asks for inter-BSC HO, receives BSSMAP Handover Command, but MS reports
5802 * RR Handover Failure. */
5803private function f_tc_ho_out_fail_rr_ho_failure(charstring id) runs on MSC_ConnHdlr {
Daniel Willmann3b59eb52018-10-29 15:40:55 +01005804 g_pars := f_gen_test_hdlr_pars();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02005805
5806 var PDU_BSSAP ass_req := f_gen_ass_req();
5807 ass_req.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5808 ass_req.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
5809 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5810 f_establish_fully(ass_req, exp_compl);
5811
Neels Hofmeyr6cc90eb2021-12-15 12:49:39 +01005812 f_bts_0_cfg(BSCVTY, {"no neighbor lac 99", "neighbor lac 99 arfcn 123 bsic any"});
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02005813 f_vty_transceive(BSCVTY, "handover any to arfcn 123 bsic any");
5814
5815 BSSAP.receive(tr_BSSMAP_HandoverRequired);
5816
5817 f_sleep(0.5);
5818 /* The MSC negotiates Handover Request and Handover Request Ack with
5819 * the other BSS and comes back with a BSSMAP Handover Command
5820 * containing an RR Handover Command coming from the target BSS... */
5821
5822 var PDU_ML3_NW_MS rr_ho_cmd := valueof(ts_RR_HandoverCommand);
5823 log("Remote cell's RR Handover Command passed through as L3 Info: ", rr_ho_cmd);
5824 var octetstring rr_ho_cmd_enc := enc_PDU_ML3_NW_MS(rr_ho_cmd);
5825 log("Remote cell's RR Handover Command passed through as L3 Info, encoded: ", rr_ho_cmd_enc);
5826 BSSAP.send(ts_BSSMAP_HandoverCommand(rr_ho_cmd_enc));
5827
5828 /* expect the Handover Command to go out on RR */
5829 var RSL_Message rsl_ho_cmd
5830 RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, ?)) -> value rsl_ho_cmd;
5831 log("RSL Data Req went out to first BTS: ", rsl_ho_cmd);
5832 var RSL_IE_Body rsl_ho_cmd_l3;
5833 if (not f_rsl_find_ie(rsl_ho_cmd, RSL_IE_L3_INFO, rsl_ho_cmd_l3)) {
5834 log("RSL message contains no L3 Info IE, expected RR Handover Command");
5835 setverdict(fail);
5836 } else {
5837 log("Found L3 Info: ", rsl_ho_cmd_l3);
5838 if (rsl_ho_cmd_l3.l3_info.payload != rr_ho_cmd_enc) {
5839 log("FAIL: the BSC sent out a different L3 Info, not matching the RR Handover Command the other BSS forwarded.");
5840 setverdict(fail);
5841 } else {
5842 log("Success: the BSC sent out the same RR Handover Command the other BSS forwarded.");
5843 setverdict(pass);
5844 }
5845 }
5846
5847 f_sleep(0.2);
5848 f_rsl_send_l3(ts_RRM_HandoverFailure('00'O));
5849
5850 /* Should tell the MSC about the failure */
5851 BSSAP.receive(tr_BSSMAP_HandoverFailure);
5852
5853 f_sleep(1.0);
5854
Vadim Yanitskiy74ae5eb2020-10-01 22:13:29 +07005855 f_mo_l3_transceive();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02005856 f_sleep(1.0);
5857
5858 setverdict(pass);
5859 f_sleep(1.0);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005860 f_perform_clear();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02005861}
5862testcase TC_ho_out_fail_rr_ho_failure() runs on test_CT {
5863 var MSC_ConnHdlr vc_conn;
5864
5865 f_init(1, true);
5866 f_sleep(1.0);
5867
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01005868 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00005869
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02005870 vc_conn := f_start_handler(refers(f_tc_ho_out_fail_rr_ho_failure));
5871 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00005872
5873 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
5874 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
5875 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
5876 f_ctrs_bsc_and_bts_add(0, "handover:failed");
5877 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
5878 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:failed");
5879 f_ctrs_bsc_and_bts_verify();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005880 f_shutdown_helper();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02005881}
5882
Neels Hofmeyr10f2bfa2019-07-09 19:33:29 +02005883/* BSC asks for inter-BSC-out HO, receives BSSMAP Handover Command, but then no reply is received about HO outcome
5884 * (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 +02005885 * and the lchan is released. */
5886private function f_tc_ho_out_fail_no_result_after_ho_cmd(charstring id) runs on MSC_ConnHdlr {
Daniel Willmann3b59eb52018-10-29 15:40:55 +01005887 g_pars := f_gen_test_hdlr_pars();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02005888
5889 var PDU_BSSAP ass_req := f_gen_ass_req();
5890 ass_req.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5891 ass_req.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
5892 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5893 f_establish_fully(ass_req, exp_compl);
5894
Neels Hofmeyr6cc90eb2021-12-15 12:49:39 +01005895 f_bts_0_cfg(BSCVTY, {"no neighbor lac 99", "neighbor lac 99 arfcn 123 bsic any"});
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02005896 f_vty_transceive(BSCVTY, "handover any to arfcn 123 bsic any");
5897
5898 BSSAP.receive(tr_BSSMAP_HandoverRequired);
5899
5900 f_sleep(0.5);
5901 /* The MSC negotiates Handover Request and Handover Request Ack with
5902 * the other BSS and comes back with a BSSMAP Handover Command
5903 * containing an RR Handover Command coming from the target BSS... */
5904
5905 var PDU_ML3_NW_MS rr_ho_cmd := valueof(ts_RR_HandoverCommand);
5906 log("Remote cell's RR Handover Command passed through as L3 Info: ", rr_ho_cmd);
5907 var octetstring rr_ho_cmd_enc := enc_PDU_ML3_NW_MS(rr_ho_cmd);
5908 log("Remote cell's RR Handover Command passed through as L3 Info, encoded: ", rr_ho_cmd_enc);
5909 BSSAP.send(ts_BSSMAP_HandoverCommand(rr_ho_cmd_enc));
5910
5911 /* expect the Handover Command to go out on RR */
5912 var RSL_Message rsl_ho_cmd
5913 RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, ?)) -> value rsl_ho_cmd;
5914 log("RSL Data Req went out to first BTS: ", rsl_ho_cmd);
5915 var RSL_IE_Body rsl_ho_cmd_l3;
5916 if (not f_rsl_find_ie(rsl_ho_cmd, RSL_IE_L3_INFO, rsl_ho_cmd_l3)) {
5917 log("RSL message contains no L3 Info IE, expected RR Handover Command");
5918 setverdict(fail);
5919 } else {
5920 log("Found L3 Info: ", rsl_ho_cmd_l3);
5921 if (rsl_ho_cmd_l3.l3_info.payload != rr_ho_cmd_enc) {
5922 log("FAIL: the BSC sent out a different L3 Info, not matching the RR Handover Command the other BSS forwarded.");
5923 setverdict(fail);
5924 } else {
5925 log("Success: the BSC sent out the same RR Handover Command the other BSS forwarded.");
5926 setverdict(pass);
5927 }
5928 }
5929
Neels Hofmeyr10f2bfa2019-07-09 19:33:29 +02005930 /* We get neither success nor failure report from the remote BSS. Eventually T8 times out and we run into 3GPP
5931 * TS 48.008 3.1.5.3.3 "Abnormal Conditions": Clear Request should go to the MSC, and RR should be released
5932 * after Clear Command */
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02005933
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02005934 var PDU_BSSAP rx_clear_request;
Neels Hofmeyre1797aa2019-07-09 19:34:04 +02005935 BSSAP.receive(tr_BSSMAP_ClearRequest) -> value rx_clear_request;
5936 log("Got BSSMAP Clear Request");
5937 /* Instruct BSC to clear channel */
5938 var BssmapCause cause := bit2int(rx_clear_request.pdu.bssmap.clearRequest.cause.causeValue);
5939 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
5940
5941 var MgcpCommand mgcp;
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02005942 interleave {
Neels Hofmeyr861a4c12018-11-07 01:23:17 +01005943 [] RSL.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {
5944 log("Got Deact SACCH");
5945 }
Harald Welte924b6ea2019-02-04 01:05:34 +01005946 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_RELEASE)) {
Neels Hofmeyr211169d2018-11-07 00:37:29 +01005947 log("Got RR Release");
5948 }
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +02005949 [] RSL.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02005950 log("Got RF Chan Rel");
5951 RSL.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
Neels Hofmeyre680b012021-07-22 19:19:09 +02005952 f_rslem_unregister(0, g_chan_nr);
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02005953 }
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02005954 }
5955
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02005956 f_expect_dlcx_conns();
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02005957 BSSAP.receive(tr_BSSMAP_ClearComplete);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01005958 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005959
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02005960 setverdict(pass);
5961 f_sleep(1.0);
5962}
Neels Hofmeyrd8a602c2019-07-09 19:46:01 +02005963testcase TC_ho_out_fail_no_result_after_ho_cmd() runs on test_CT {
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02005964 var MSC_ConnHdlr vc_conn;
5965
5966 f_init(1, true);
5967 f_sleep(1.0);
5968
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01005969 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00005970
Neels Hofmeyrd8a602c2019-07-09 19:46:01 +02005971 vc_conn := f_start_handler(refers(f_tc_ho_out_fail_no_result_after_ho_cmd));
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02005972 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00005973
5974 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
5975 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
5976 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
5977 f_ctrs_bsc_and_bts_add(0, "handover:timeout");
5978 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
5979 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:timeout");
5980 f_ctrs_bsc_and_bts_verify();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005981 f_shutdown_helper();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02005982}
5983
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02005984private function f_ho_into_this_bsc(charstring id, template (omit) BSSMAP_oldToNewBSSIEs oldToNewBSSIEs := omit) runs on MSC_ConnHdlr {
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01005985 /* Hack: the proper way would be to wait for the BSSMAP Handover Request ACK and extract the
5986 * actual assigned chan_nr from its L3 (RR Handover Command) message. But osmo-bsc starts acting
5987 * on the lchan even before we get a chance to evaluate the BSSMAP Handover Request ACK. So we
5988 * need to assume that osmo-bsc will activate TS 1 and already set up this lchan's RSL emulation
5989 * before we get started. */
5990 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
5991 f_rslem_register(0, new_chan_nr);
5992 g_chan_nr := new_chan_nr;
Neels Hofmeyr34174bd2021-10-02 14:52:57 +02005993 var uint3_t expect_target_tsc := BTS_TSC[0];
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01005994 f_sleep(1.0);
5995
5996 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
5997 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
5998 activate(as_Media());
5999
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006000 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02006001 f_gen_handover_req(aoip_tla := g_pars.host_aoip_tla,
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02006002 oldToNewBSSIEs := oldToNewBSSIEs,
6003 enc := g_pars.encr)));
Harald Welte6811d102019-04-14 22:23:14 +02006004 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006005
6006 /* The RSL Emulation magically accepts the Chan Activ behind the scenes. */
6007
6008 var PDU_BSSAP rx_bssap;
6009 var octetstring ho_command_str;
6010
6011 BSSAP.receive(tr_BSSMAP_HandoverRequestAcknowledge(?)) -> value rx_bssap;
Pau Espin Pedrol76ba5412019-06-10 11:00:33 +02006012
Neels Hofmeyr34174bd2021-10-02 14:52:57 +02006013 /* we're sure that the channel activation is done now, verify the parameters in it */
6014 var RSL_Message chan_act := f_rslem_get_last_act(RSL_PROC, 0, g_chan_nr);
6015 f_verify_encr_info(chan_act);
6016 f_chan_act_verify_tsc(chan_act, expect_target_tsc);
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02006017
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006018 ho_command_str := rx_bssap.pdu.bssmap.handoverRequestAck.layer3Information.layer3info;
6019 log("Received L3 Info in HO Request Ack: ", ho_command_str);
6020 var PDU_ML3_NW_MS ho_command := dec_PDU_ML3_NW_MS(ho_command_str);
6021 log("L3 Info in HO Request Ack is ", ho_command);
6022
6023 var GsmArfcn arfcn;
6024 var RslChannelNr actual_new_chan_nr;
6025 f_ChDesc2RslChanNr(ho_command.msgs.rrm.handoverCommand.channelDescription2,
6026 actual_new_chan_nr, arfcn);
6027
6028 if (actual_new_chan_nr != new_chan_nr) {
6029 log("ERROR: osmo-bsc assigned a different lchan than we assumed above -- this test will fail now.",
6030 " Assumed: ", new_chan_nr, " Assigned: ", actual_new_chan_nr);
6031 setverdict(fail);
6032 return;
6033 }
6034 log("Handover Command chan_nr is", actual_new_chan_nr);
6035
Neels Hofmeyr34174bd2021-10-02 14:52:57 +02006036 var uint3_t got_tsc := rr_chan_desc_tsc(ho_command.msgs.rrm.handoverCommand.channelDescription2);
6037 if (not match(got_tsc, expect_target_tsc)) {
6038 setverdict(fail, "RR Handover Command: unexpected TSC in Channel Description: expected ",
6039 expect_target_tsc, " got ", got_tsc);
6040 mtc.stop;
6041 } else {
6042 log("handoverCommand: verified TSC = ", got_tsc);
6043 }
6044
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006045 /* Now the MSC forwards the RR Handover Command to the other BSC, which
6046 * tells the MS to handover to the new lchan. Here comes the new MS on
6047 * the new lchan with a Handover RACH: */
6048
6049 /* send handover detect */
6050
6051 RSL.send(ts_RSL_HANDO_DET(new_chan_nr));
6052
6053 BSSAP.receive(tr_BSSMAP_HandoverDetect);
6054
6055 /* send handover complete over the new channel */
6056
6057 var PDU_ML3_MS_NW l3_tx := valueof(ts_RRM_HandoverComplete('00'O));
6058 RSL.send(ts_RSL_EST_IND(new_chan_nr, valueof(ts_RslLinkID_DCCH(0)),
6059 enc_PDU_ML3_MS_NW(l3_tx)));
6060
6061 BSSAP.receive(tr_BSSMAP_HandoverComplete);
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006062 setverdict(pass);
6063}
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02006064
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006065private function f_tc_ho_into_this_bsc(charstring id) runs on MSC_ConnHdlr {
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006066 var template PDU_ML3_NW_MS exp_rr_rel_tmpl;
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006067 var template (omit) BSSMAP_oldToNewBSSIEs oldToNewBSSIEs := omit;
6068 if (not istemplatekind(g_pars.last_used_eutran_plmn, "omit")) {
6069 oldToNewBSSIEs := f_ts_BSSMAP_oldToNewBSSIEs(ts_BSSMAP_LastUsedEUTRANPLMNId(g_pars.last_used_eutran_plmn));
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006070 }
6071 if (g_pars.exp_fast_return) {
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006072 exp_rr_rel_tmpl := tr_RRM_RR_RELEASE_CellSelectInd;
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006073 } else {
6074 exp_rr_rel_tmpl := tr_RRM_RR_RELEASE;
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006075 }
6076 f_ho_into_this_bsc(id, oldToNewBSSIEs);
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02006077 f_perform_clear(exp_rr_rel_tmpl := exp_rr_rel_tmpl);
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006078 setverdict(pass);
6079}
Pau Espin Pedrol07866632020-09-03 19:10:55 +02006080function f_tc_ho_into_this_bsc_main(TestHdlrParams pars) runs on test_CT {
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006081 var MSC_ConnHdlr vc_conn;
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006082
6083 f_init(1, true);
6084 f_sleep(1.0);
6085
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006086 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006087
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006088 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
6089 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006090
6091 vc_conn := f_start_handler(refers(f_tc_ho_into_this_bsc), pars);
6092 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006093
6094 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6095 f_ctrs_bsc_and_bts_add(0, "handover:completed");
6096 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:attempted");
6097 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:completed");
6098 f_ctrs_bsc_and_bts_verify();
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006099}
6100
Pau Espin Pedrol07866632020-09-03 19:10:55 +02006101testcase TC_ho_into_this_bsc() runs on test_CT {
6102 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6103 f_tc_ho_into_this_bsc_main(pars);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02006104 f_shutdown_helper();
Pau Espin Pedrol07866632020-09-03 19:10:55 +02006105}
6106
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02006107function f_tc_ho_into_this_bsc_a5(OCT1 encr_alg) runs on test_CT {
6108 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6109 pars.encr := valueof(t_EncrParams(encr_alg, f_rnd_octstring(8), f_rnd_octstring(16)));
6110 f_tc_ho_into_this_bsc_main(pars);
6111 f_shutdown_helper();
6112}
6113
6114testcase TC_ho_into_this_bsc_a5_0() runs on test_CT {
6115 f_tc_ho_into_this_bsc_a5('01'O);
6116}
6117
6118testcase TC_ho_into_this_bsc_a5_1() runs on test_CT {
6119 f_tc_ho_into_this_bsc_a5('02'O);
6120}
6121
6122testcase TC_ho_into_this_bsc_a5_3() runs on test_CT {
6123 f_tc_ho_into_this_bsc_a5('08'O);
6124}
6125
6126testcase TC_ho_into_this_bsc_a5_4() runs on test_CT {
6127 f_tc_ho_into_this_bsc_a5('10'O);
6128}
6129
Pau Espin Pedrol07866632020-09-03 19:10:55 +02006130testcase TC_ho_into_this_bsc_tla_v6() runs on test_CT {
6131 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6132 pars.host_aoip_tla := "::6";
6133 f_tc_ho_into_this_bsc_main(pars);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02006134 f_shutdown_helper();
Pau Espin Pedrol07866632020-09-03 19:10:55 +02006135}
6136
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02006137/* Similar to TC_ho_into_this_bsc, but when in SRVCC, HO Req contains "Old BSS
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006138 to New BSS Information" IE with "Last Used E-UTRAN PLMN Id", which, when the
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02006139 channel is later released (RR CHannel Release), should trigger inclusion of
6140 IE "Cell Selection Indicator after Release of all TCH and SDCCH" with E-UTRAN
6141 neighbors. */
6142testcase TC_srvcc_eutran_to_geran() runs on test_CT {
6143 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6144 pars.last_used_eutran_plmn := '323454'O;
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006145 pars.exp_fast_return := true;
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02006146 f_tc_ho_into_this_bsc_main(pars);
Pau Espin Pedrol211a7142021-06-15 16:43:03 +02006147
6148 f_ctrs_bsc_and_bts_add(0, "srvcc:attempted");
6149 f_ctrs_bsc_and_bts_add(0, "srvcc:completed");
6150 f_ctrs_bsc_and_bts_verify();
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02006151 f_shutdown_helper();
6152}
6153
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006154/* Same as TC_srvcc_eutran_to_geran, but test explicitly forbiding fast return
6155 on the BTS. As a result, RR Release shouldn't contain the EUTRAN neighbor
6156 list when the channel is released. */
6157testcase TC_srvcc_eutran_to_geran_forbid_fast_return() runs on test_CT {
6158 f_init_vty();
6159 f_vty_allow_srvcc_fast_return(true, 0)
6160
6161 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6162 pars.last_used_eutran_plmn := '323454'O;
6163 pars.exp_fast_return := false;
6164 f_tc_ho_into_this_bsc_main(pars);
6165 f_vty_allow_srvcc_fast_return(false, 0);
6166 f_shutdown_helper();
6167}
6168
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006169private function f_tc_srvcc_eutran_to_geran_ho_out(charstring id) runs on MSC_ConnHdlr {
6170 var template (omit) BSSMAP_oldToNewBSSIEs oldToNewBSSIEs;
6171 oldToNewBSSIEs := f_ts_BSSMAP_oldToNewBSSIEs(ts_BSSMAP_LastUsedEUTRANPLMNId(g_pars.last_used_eutran_plmn));
6172 f_ho_into_this_bsc(id, oldToNewBSSIEs);
6173 f_ho_out_of_this_bsc(oldToNewBSSIEs);
6174 setverdict(pass);
6175}
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006176
6177private function f_tc_srvcc_eutran_to_geran_ho_out_main(boolean disable_fast_return)
6178 runs on test_CT {
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006179 var MSC_ConnHdlr vc_conn;
6180 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6181
Neels Hofmeyr6cc90eb2021-12-15 12:49:39 +01006182 f_init_vty();
6183 f_bts_0_cfg(BSCVTY,
6184 {"neighbor-list mode automatic",
6185 "handover 1",
6186 "handover algorithm 2",
6187 "handover2 window rxlev averaging 1",
6188 "no neighbors",
6189 "neighbor lac 99 arfcn 123 bsic any"});
6190 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
6191
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006192 f_init(1, true);
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006193 if (disable_fast_return) {
6194 f_vty_allow_srvcc_fast_return(true, 0);
6195 }
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006196 f_sleep(1.0);
6197
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006198 f_ctrs_bsc_and_bts_handover_init();
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006199
6200 pars.last_used_eutran_plmn := '323454'O;
6201 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
6202 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
6203
6204 vc_conn := f_start_handler(refers(f_tc_srvcc_eutran_to_geran_ho_out), pars);
6205 vc_conn.done;
6206
6207 f_ctrs_bsc_and_bts_add(0, "handover:attempted", 2);
6208 f_ctrs_bsc_and_bts_add(0, "handover:completed", 2);
6209 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:attempted", 1);
6210 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:completed", 1);
6211 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted", 1);
6212 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:completed", 1);
Pau Espin Pedrol211a7142021-06-15 16:43:03 +02006213
6214 f_ctrs_bsc_and_bts_add(0, "srvcc:attempted", 1);
6215 f_ctrs_bsc_and_bts_add(0, "srvcc:completed", 1);
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006216 f_ctrs_bsc_and_bts_verify();
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006217
6218 if (disable_fast_return) {
6219 f_vty_allow_srvcc_fast_return(false, 0);
6220 }
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006221 f_shutdown_helper();
6222}
6223
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006224/* First, HO into BSC from EUTRAN (SRVCC): HO Request contains "Old BSS to New
6225 BSS Information" IE with "Last Used E-UTRAN PLMN Id".
6226 Second, HO to another BSC: HO Required contains "Old BSS to New BSS Information"
6227 IE with "Last Used E-UTRAN PLMN Id" from first step. */
6228testcase TC_srvcc_eutran_to_geran_ho_out() runs on test_CT {
6229 f_tc_srvcc_eutran_to_geran_ho_out_main(false);
6230}
6231/* Validate subsequent intra-GSM-HO works the same (with OldBSSToNewBSSInfo IE)
6232 * independently of fast-reture allowed/forbidden in local BTS */
6233testcase TC_srvcc_eutran_to_geran_ho_out_forbid_fast_return() runs on test_CT {
6234 f_tc_srvcc_eutran_to_geran_ho_out_main(true);
6235}
6236
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006237private function f_tc_ho_in_fail_msc_clears(charstring id) runs on MSC_ConnHdlr {
6238 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
6239 f_rslem_register(0, new_chan_nr);
6240 g_chan_nr := new_chan_nr;
6241 f_sleep(1.0);
6242
6243 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
6244 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
6245 activate(as_Media());
6246
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006247 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006248 f_gen_handover_req()));
Harald Welte6811d102019-04-14 22:23:14 +02006249 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006250
6251 /* The RSL Emulation magically accepts the Chan Activ behind the scenes. */
6252
6253 var PDU_BSSAP rx_bssap;
6254 var octetstring ho_command_str;
6255
6256 BSSAP.receive(tr_BSSMAP_HandoverRequestAcknowledge(?)) -> value rx_bssap;
6257
6258 ho_command_str := rx_bssap.pdu.bssmap.handoverRequestAck.layer3Information.layer3info;
6259 log("Received L3 Info in HO Request Ack: ", ho_command_str);
6260 var PDU_ML3_NW_MS ho_command := dec_PDU_ML3_NW_MS(ho_command_str);
6261 log("L3 Info in HO Request Ack is ", ho_command);
6262
6263 var GsmArfcn arfcn;
6264 var RslChannelNr actual_new_chan_nr;
6265 f_ChDesc2RslChanNr(ho_command.msgs.rrm.handoverCommand.channelDescription2,
6266 actual_new_chan_nr, arfcn);
6267
6268 if (actual_new_chan_nr != new_chan_nr) {
6269 log("ERROR: osmo-bsc assigned a different lchan than we assumed above -- this test will fail now.",
6270 " Assumed: ", new_chan_nr, " Assigned: ", actual_new_chan_nr);
6271 setverdict(fail);
6272 return;
6273 }
6274 log("Handover Command chan_nr is", actual_new_chan_nr);
6275
Neels Hofmeyr61ca08d2019-05-06 23:52:22 +02006276 /* For deterministic test results, give some time for the MGW endpoint to be configured */
6277 f_sleep(1.0);
6278
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006279 /* Now the MSC forwards the RR Handover Command to the other BSC, which
6280 * tells the MS to handover to the new lchan. In this case, the MS
6281 * reports a Handover Failure to the old BSS, which forwards a BSSMAP
6282 * Handover Failure to the MSC. The procedure according to 3GPP TS
6283 * 48.008 3.1.5.3.2 "Handover Failure" is then that the MSC sends a
6284 * BSSMAP Clear Command: */
6285
6286 var myBSSMAP_Cause cause_val := GSM0808_CAUSE_RADIO_INTERFACE_FAILURE_REVERSION;
6287 var BssmapCause cause := enum2int(cause_val);
6288 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
6289
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02006290 f_expect_dlcx_conns();
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02006291 BSSAP.receive(tr_BSSMAP_ClearComplete);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01006292 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02006293
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006294 setverdict(pass);
6295 f_sleep(1.0);
6296
6297 setverdict(pass);
6298}
6299testcase TC_ho_in_fail_msc_clears() runs on test_CT {
6300 var MSC_ConnHdlr vc_conn;
6301 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6302
6303 f_init(1, true);
6304 f_sleep(1.0);
6305
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006306 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006307
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006308 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
6309 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006310
6311 vc_conn := f_start_handler(refers(f_tc_ho_in_fail_msc_clears), pars);
6312 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006313
6314 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6315 f_ctrs_bsc_and_bts_add(0, "handover:stopped");
6316 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:attempted");
6317 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:stopped");
6318 f_ctrs_bsc_and_bts_verify();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02006319 f_shutdown_helper();
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006320}
6321
6322private function f_tc_ho_in_fail_msc_clears_after_ho_detect(charstring id) runs on MSC_ConnHdlr {
6323 /* Hack: the proper way would be to wait for the BSSMAP Handover Request ACK and extract the
6324 * actual assigned chan_nr from its L3 (RR Handover Command) message. But osmo-bsc starts acting
6325 * on the lchan even before we get a chance to evaluate the BSSMAP Handover Request ACK. So we
6326 * need to assume that osmo-bsc will activate TS 1 and already set up this lchan's RSL emulation
6327 * before we get started. */
6328 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
6329 f_rslem_register(0, new_chan_nr);
6330 g_chan_nr := new_chan_nr;
6331 f_sleep(1.0);
6332
6333 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
6334 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
6335 activate(as_Media());
6336
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006337 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006338 f_gen_handover_req()));
Harald Welte6811d102019-04-14 22:23:14 +02006339 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006340
6341 /* The RSL Emulation magically accepts the Chan Activ behind the scenes. */
6342
6343 var PDU_BSSAP rx_bssap;
6344 var octetstring ho_command_str;
6345
6346 BSSAP.receive(tr_BSSMAP_HandoverRequestAcknowledge(?)) -> value rx_bssap;
6347
6348 ho_command_str := rx_bssap.pdu.bssmap.handoverRequestAck.layer3Information.layer3info;
6349 log("Received L3 Info in HO Request Ack: ", ho_command_str);
6350 var PDU_ML3_NW_MS ho_command := dec_PDU_ML3_NW_MS(ho_command_str);
6351 log("L3 Info in HO Request Ack is ", ho_command);
6352
6353 var GsmArfcn arfcn;
6354 var RslChannelNr actual_new_chan_nr;
6355 f_ChDesc2RslChanNr(ho_command.msgs.rrm.handoverCommand.channelDescription2,
6356 actual_new_chan_nr, arfcn);
6357
6358 if (actual_new_chan_nr != new_chan_nr) {
6359 log("ERROR: osmo-bsc assigned a different lchan than we assumed above -- this test will fail now.",
6360 " Assumed: ", new_chan_nr, " Assigned: ", actual_new_chan_nr);
6361 setverdict(fail);
6362 return;
6363 }
6364 log("Handover Command chan_nr is", actual_new_chan_nr);
6365
6366 /* Now the MSC forwards the RR Handover Command to the other BSC, which
6367 * tells the MS to handover to the new lchan. Here comes the new MS on
6368 * the new lchan with a Handover RACH: */
6369
6370 /* send handover detect */
6371
6372 RSL.send(ts_RSL_HANDO_DET(new_chan_nr));
6373
6374 BSSAP.receive(tr_BSSMAP_HandoverDetect);
6375
6376 /* The MSC chooses to clear the connection now, maybe we got the
6377 * Handover RACH on the new cell but the MS still signaled Handover
6378 * Failure to the old BSS? */
6379
6380 var myBSSMAP_Cause cause_val := GSM0808_CAUSE_RADIO_INTERFACE_FAILURE_REVERSION;
6381 var BssmapCause cause := enum2int(cause_val);
6382 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
6383
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02006384 f_expect_dlcx_conns();
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02006385 BSSAP.receive(tr_BSSMAP_ClearComplete);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01006386 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02006387
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006388 f_sleep(1.0);
6389}
6390testcase TC_ho_in_fail_msc_clears_after_ho_detect() runs on test_CT {
6391 var MSC_ConnHdlr vc_conn;
6392 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6393
6394 f_init(1, true);
6395 f_sleep(1.0);
6396
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006397 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006398
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006399 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
6400 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006401
6402 vc_conn := f_start_handler(refers(f_tc_ho_in_fail_msc_clears_after_ho_detect), pars);
6403 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006404
6405 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6406 f_ctrs_bsc_and_bts_add(0, "handover:stopped");
6407 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:attempted");
6408 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:stopped");
6409 f_ctrs_bsc_and_bts_verify();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02006410 f_shutdown_helper();
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006411}
6412
6413/* The new BSS's lchan times out before the MSC decides that handover failed. */
6414private function f_tc_ho_in_fail_no_detect(charstring id) runs on MSC_ConnHdlr {
6415 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
6416 f_rslem_register(0, new_chan_nr);
6417 g_chan_nr := new_chan_nr;
6418 f_sleep(1.0);
6419
6420 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
6421 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
6422 activate(as_Media());
6423
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006424 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006425 f_gen_handover_req()));
Harald Welte6811d102019-04-14 22:23:14 +02006426 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006427
6428 /* The RSL Emulation magically accepts the Chan Activ behind the scenes. */
6429
6430 var PDU_BSSAP rx_bssap;
6431 var octetstring ho_command_str;
6432
6433 BSSAP.receive(tr_BSSMAP_HandoverRequestAcknowledge(?)) -> value rx_bssap;
6434
6435 ho_command_str := rx_bssap.pdu.bssmap.handoverRequestAck.layer3Information.layer3info;
6436 log("Received L3 Info in HO Request Ack: ", ho_command_str);
6437 var PDU_ML3_NW_MS ho_command := dec_PDU_ML3_NW_MS(ho_command_str);
6438 log("L3 Info in HO Request Ack is ", ho_command);
6439
6440 var GsmArfcn arfcn;
6441 var RslChannelNr actual_new_chan_nr;
6442 f_ChDesc2RslChanNr(ho_command.msgs.rrm.handoverCommand.channelDescription2,
6443 actual_new_chan_nr, arfcn);
6444
6445 if (actual_new_chan_nr != new_chan_nr) {
6446 log("ERROR: osmo-bsc assigned a different lchan than we assumed above -- this test will fail now.",
6447 " Assumed: ", new_chan_nr, " Assigned: ", actual_new_chan_nr);
6448 setverdict(fail);
6449 return;
6450 }
6451 log("Handover Command chan_nr is", actual_new_chan_nr);
6452
6453 /* Now the MSC forwards the RR Handover Command to the other BSC, which
6454 * tells the MS to handover to the new lchan. But the MS never shows up
6455 * on the new lchan. */
6456
6457 BSSAP.receive(tr_BSSMAP_HandoverFailure);
6458
6459 /* Did osmo-bsc also send a Clear Request? */
6460 timer T := 0.5;
6461 T.start;
6462 alt {
6463 [] BSSAP.receive(tr_BSSMAP_ClearRequest);
6464 [] T.timeout { }
6465 }
6466
6467 /* MSC plays along with a Clear Command (no matter whether osmo-bsc
6468 * asked for it, this is a Handover Failure after all). */
6469
6470 var myBSSMAP_Cause cause_val := GSM0808_CAUSE_RADIO_INTERFACE_FAILURE_REVERSION;
6471 var BssmapCause cause := enum2int(cause_val);
6472 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
6473
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02006474 f_expect_dlcx_conns();
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02006475 BSSAP.receive(tr_BSSMAP_ClearComplete);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01006476 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02006477
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006478 f_sleep(1.0);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006479}
6480testcase TC_ho_in_fail_no_detect() runs on test_CT {
6481 var MSC_ConnHdlr vc_conn;
6482 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6483
6484 f_init(1, true);
6485 f_sleep(1.0);
6486
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006487 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006488
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006489 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
6490 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006491
6492 vc_conn := f_start_handler(refers(f_tc_ho_in_fail_no_detect), pars);
6493 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006494
6495 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6496 f_ctrs_bsc_and_bts_add(0, "handover:error");
6497 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:attempted");
6498 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:error");
6499 f_ctrs_bsc_and_bts_verify();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02006500 f_shutdown_helper();
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006501}
6502
6503/* Same as f_tc_ho_in_fail_no_detect, but MSC fails to send a Clear Command */
6504private function f_tc_ho_in_fail_no_detect2(charstring id) runs on MSC_ConnHdlr {
6505 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
6506 f_rslem_register(0, new_chan_nr);
6507 g_chan_nr := new_chan_nr;
6508 f_sleep(1.0);
6509
6510 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
6511 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
6512 activate(as_Media());
6513
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006514 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006515 f_gen_handover_req()));
Harald Welte6811d102019-04-14 22:23:14 +02006516 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006517
6518 /* The RSL Emulation magically accepts the Chan Activ behind the scenes. */
6519
6520 var PDU_BSSAP rx_bssap;
6521 var octetstring ho_command_str;
6522
6523 BSSAP.receive(tr_BSSMAP_HandoverRequestAcknowledge(?)) -> value rx_bssap;
6524
6525 ho_command_str := rx_bssap.pdu.bssmap.handoverRequestAck.layer3Information.layer3info;
6526 log("Received L3 Info in HO Request Ack: ", ho_command_str);
6527 var PDU_ML3_NW_MS ho_command := dec_PDU_ML3_NW_MS(ho_command_str);
6528 log("L3 Info in HO Request Ack is ", ho_command);
6529
6530 var GsmArfcn arfcn;
6531 var RslChannelNr actual_new_chan_nr;
6532 f_ChDesc2RslChanNr(ho_command.msgs.rrm.handoverCommand.channelDescription2,
6533 actual_new_chan_nr, arfcn);
6534
6535 if (actual_new_chan_nr != new_chan_nr) {
6536 log("ERROR: osmo-bsc assigned a different lchan than we assumed above -- this test will fail now.",
6537 " Assumed: ", new_chan_nr, " Assigned: ", actual_new_chan_nr);
6538 setverdict(fail);
6539 return;
6540 }
6541 log("Handover Command chan_nr is", actual_new_chan_nr);
6542
6543 /* Now the MSC forwards the RR Handover Command to the other BSC, which
6544 * tells the MS to handover to the new lchan. But the MS never shows up
6545 * on the new lchan. */
6546
6547 BSSAP.receive(tr_BSSMAP_HandoverFailure);
6548
6549 /* MSC plays dumb and sends no Clear Command */
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006550 var PDU_BSSAP rx_clear_request;
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02006551
6552 BSSAP.receive(tr_BSSMAP_ClearRequest) -> value rx_clear_request {
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006553 var BssmapCause cause := bit2int(rx_clear_request.pdu.bssmap.clearRequest.cause.causeValue);
6554 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
6555 };
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02006556 f_expect_dlcx_conns();
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02006557 BSSAP.receive(tr_BSSMAP_ClearComplete);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01006558 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02006559
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006560 f_sleep(1.0);
6561}
6562testcase TC_ho_in_fail_no_detect2() runs on test_CT {
6563 var MSC_ConnHdlr vc_conn;
6564 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6565
6566 f_init(1, true);
6567 f_sleep(1.0);
6568
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006569 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006570
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006571 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
6572 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006573
6574 vc_conn := f_start_handler(refers(f_tc_ho_in_fail_no_detect2), pars);
6575 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006576
6577 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6578 f_ctrs_bsc_and_bts_add(0, "handover:error");
6579 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:attempted");
6580 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:error");
6581 f_ctrs_bsc_and_bts_verify();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02006582 f_shutdown_helper();
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006583}
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006584
Neels Hofmeyr91401012019-07-11 00:42:35 +02006585type record of charstring Commands;
6586
Neels Hofmeyr666f0432020-07-04 00:53:07 +02006587private function f_bts_0_cfg(TELNETasp_PT pt, Commands cmds := {})
Neels Hofmeyr91401012019-07-11 00:42:35 +02006588{
Neels Hofmeyr666f0432020-07-04 00:53:07 +02006589 f_vty_enter_cfg_bts(pt, 0);
Neels Hofmeyr91401012019-07-11 00:42:35 +02006590 for (var integer i := 0; i < sizeof(cmds); i := i+1) {
Neels Hofmeyr666f0432020-07-04 00:53:07 +02006591 f_vty_transceive(pt, cmds[i]);
Neels Hofmeyr91401012019-07-11 00:42:35 +02006592 }
Neels Hofmeyr666f0432020-07-04 00:53:07 +02006593 f_vty_transceive(pt, "end");
Neels Hofmeyr91401012019-07-11 00:42:35 +02006594}
6595
Pau Espin Pedrolc675b612020-01-09 19:55:40 +01006596private function f_cs7_inst_0_cfg(TELNETasp_PT pt, Commands cmds := {})
6597{
6598 f_vty_enter_cfg_cs7_inst(pt, 0);
6599 for (var integer i := 0; i < sizeof(cmds); i := i+1) {
6600 f_vty_transceive(pt, cmds[i]);
6601 }
6602 f_vty_transceive(pt, "end");
6603}
6604
Neels Hofmeyr91401012019-07-11 00:42:35 +02006605private function f_probe_for_handover(charstring log_label,
6606 charstring log_descr,
6607 charstring handover_vty_cmd,
6608 boolean expect_handover,
Neels Hofmeyr6a955cc2021-10-02 14:53:48 +02006609 boolean is_inter_bsc_handover := false,
6610 template uint3_t expect_target_tsc := ?)
Neels Hofmeyr91401012019-07-11 00:42:35 +02006611runs on MSC_ConnHdlr
6612{
Neels Hofmeyrb3fc8982020-05-11 00:16:42 +02006613 /* We're going to thwart any and all handover attempts, just be ready to handle (and ignore) handover target
6614 * lchans to be established on bts 1 or bts 2. */
6615 f_rslem_suspend(RSL1_PROC);
6616 f_rslem_suspend(RSL2_PROC);
6617
Neels Hofmeyr91401012019-07-11 00:42:35 +02006618 var RSL_Message rsl;
6619
6620 var charstring log_msg := " (expecting handover)"
6621 if (not expect_handover) {
6622 log_msg := " (expecting NO handover)";
6623 }
6624 log("f_probe_for_handover starting: " & log_label & ": " & log_descr & log_msg);
6625 f_vty_transceive(BSCVTY, handover_vty_cmd);
6626
Neels Hofmeyr91401012019-07-11 00:42:35 +02006627 timer T := 2.0;
6628 T.start;
6629
6630 alt {
6631 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr)) -> value rsl {
6632 var PDU_ML3_NW_MS l3 := dec_PDU_ML3_NW_MS(rsl.ies[2].body.l3_info.payload);
6633 log("Rx L3 from net: ", l3);
6634 if (ischosen(l3.msgs.rrm.handoverCommand)) {
6635 var RslChannelNr new_chan_nr;
6636 var GsmArfcn arfcn;
6637 f_ChDesc2RslChanNr(l3.msgs.rrm.handoverCommand.channelDescription2,
6638 new_chan_nr, arfcn);
6639 log("Handover to new chan ", new_chan_nr, " on ARFCN ", arfcn);
6640 log(l3.msgs.rrm.handoverCommand);
6641
Neels Hofmeyr6a955cc2021-10-02 14:53:48 +02006642 /* Verify correct TSC in handoverCommand */
6643 var uint3_t got_tsc := rr_chan_desc_tsc(l3.msgs.rrm.handoverCommand.channelDescription2);
6644 if (not match(got_tsc, expect_target_tsc)) {
6645 setverdict(fail, "RR Handover Command: unexpected TSC in Channel Description: expected ",
6646 expect_target_tsc, " got ", got_tsc);
6647 mtc.stop;
6648 } else {
6649 log("handoverCommand: verified TSC = ", got_tsc, " (matches ",
6650 expect_target_tsc, ")");
6651 }
6652
Neels Hofmeyr91401012019-07-11 00:42:35 +02006653 /* Need to register for new lchan on new BTS -- it's either bts 1 or bts 2. It doesn't really
6654 * matter on which BTS it really is, we're not going to follow through an entire handover
6655 * anyway. */
6656 f_rslem_register(0, new_chan_nr, RSL1_PROC);
6657 f_rslem_resume(RSL1_PROC);
6658 f_rslem_register(0, new_chan_nr, RSL2_PROC);
6659 f_rslem_resume(RSL2_PROC);
6660
6661 if (expect_handover and not is_inter_bsc_handover) {
6662 setverdict(pass);
6663 log("f_probe_for_handover(" & log_label & "): Got RSL Handover Command as expected.");
6664 } else {
6665 setverdict(fail, "f_probe_for_handover(" & log_label & "): Expected none, but got RSL Handover Command. "
6666 & log_label & ": " & log_descr);
6667 }
6668
6669 log("f_probe_for_handover(" & log_label & "): Ending the test: Handover Failure stops the procedure.");
6670 /* osmo-bsc has triggered Handover. That's all we need to know for this test, reply with
6671 * Handover Failure. */
6672 f_rsl_send_l3(ts_RRM_HandoverFailure('00'O));
6673
6674 /* target BTS is told to release lchan again; don't care which BTS nor what messages. */
6675 f_sleep(0.5);
6676 RSL1.clear;
6677 RSL2.clear;
6678 log("f_probe_for_handover(" & log_label & "): done (got RSL Handover Command)");
6679 break;
6680 } else {
6681 repeat;
6682 }
6683 }
6684 [] BSSAP.receive(tr_BSSMAP_HandoverRequired) {
6685 if (expect_handover and is_inter_bsc_handover) {
6686 setverdict(pass);
6687 log("f_probe_for_handover(" & log_label & "): Got BSSMAP Handover Required as expected.");
6688 } else {
6689 setverdict(fail, "f_probe_for_handover(" & log_label & "): Expected none, but got BSSMAP Handover Required. "
6690 & log_label & ": " & log_descr);
6691 }
6692
6693 log("f_probe_for_handover(" & log_label & "): done (got BSSMAP Handover Required)");
6694
6695 /* Note: f_tc_ho_neighbor_config_start() sets T7, the timeout for BSSMAP Handover Required, to
6696 * 1 second. There is no legal way to quickly abort a handover after a BSSMAP Handover Required,
6697 * setting a short timeout and waiting is the only way. */
6698 log("f_probe_for_handover(" & log_label & "): waiting for inter-BSC HO to time out...");
6699 f_sleep(1.5);
6700 log("f_probe_for_handover(" & log_label & "): ...done");
6701
6702 break;
6703 }
6704 [] T.timeout {
6705 if (expect_handover) {
6706 setverdict(fail, "f_probe_for_handover(" & log_label & "): Expected Handover, but got none. "
6707 & log_label & ": " & log_descr);
6708 } else {
6709 setverdict(pass);
6710 log("f_probe_for_handover(" & log_label & "): Got no Handover, as expected.");
6711 }
6712 log("f_probe_for_handover(" & log_label & "): done (got no Handover)");
6713 break;
6714 }
6715 }
6716
6717 f_rslem_resume(RSL1_PROC);
6718 f_rslem_resume(RSL2_PROC);
6719 f_sleep(3.0);
6720 RSL.clear;
6721
6722 log("f_probe_for_handover(" & log_label & "): done clearing");
6723}
6724
6725/* Test the effect of various neighbor configuration scenarios:
6726 *
6727 * To avoid complexity, block off any actual handover operation, and always remain on the lchan at bts 0.
6728 * Reconfigure the neighbors for bts 0, trigger a Handover, and probe whether osmo-bsc does or doesn't start HO.
6729 */
6730private function f_tc_ho_neighbor_config_start() runs on MSC_ConnHdlr {
6731 g_pars := f_gen_test_hdlr_pars();
6732 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
6733 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Neels Hofmeyr91401012019-07-11 00:42:35 +02006734
6735 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
6736 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
6737
6738 /* Establish lchan at bts 0 */
6739 f_establish_fully(ass_cmd, exp_compl);
6740
6741 /* Shorten the inter-BSC Handover timeout, to not wait so long for inter-BSC Handovers */
6742 f_vty_enter_cfg_network(BSCVTY);
6743 f_vty_transceive(BSCVTY, "timer T7 1");
6744 f_vty_transceive(BSCVTY, "end");
6745}
6746
6747private function f_tc_ho_neighbor_config_1(charstring id) runs on MSC_ConnHdlr {
6748 f_tc_ho_neighbor_config_start();
6749
6750 /*
6751 * bts 0 ARFCN 871 BSIC 10
6752 * bts 1 ARFCN 871 BSIC 11
6753 * bts 2 ARFCN 871 BSIC 12
6754 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
6755 */
6756
6757 log("f_tc_ho_neighbor_config: 1. No 'neighbor' config");
Neels Hofmeyr666f0432020-07-04 00:53:07 +02006758 f_bts_0_cfg(BSCVTY, {"no neighbors"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02006759 f_probe_for_handover("1.a", "HO to bts 1 works, implicitly listed as neighbor (legacy behavior when none are configured)",
6760 "handover any to arfcn 871 bsic 11",
Neels Hofmeyr6a955cc2021-10-02 14:53:48 +02006761 true, expect_target_tsc := BTS_TSC[1]);
Neels Hofmeyr91401012019-07-11 00:42:35 +02006762
6763 f_probe_for_handover("1.b", "HO to unknown cell does not start",
6764 "handover any to arfcn 13 bsic 39",
6765 false);
6766
6767 f_probe_for_handover("1.c", "HO to 871-12 is ambiguous = error",
6768 "handover any to arfcn 871 bsic 12",
6769 false);
6770
6771 f_probe_for_handover("1.d", "HO to 871-11 still works (verify that this test properly cleans up)",
6772 "handover any to arfcn 871 bsic 11",
Neels Hofmeyr6a955cc2021-10-02 14:53:48 +02006773 true, expect_target_tsc := BTS_TSC[1]);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01006774
6775 f_perform_clear();
Neels Hofmeyr91401012019-07-11 00:42:35 +02006776}
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006777testcase TC_ho_neighbor_config_1() runs on test_CT {
6778 var MSC_ConnHdlr vc_conn;
6779 f_init(3, true, guard_timeout := 60.0);
6780 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006781 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006782 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_1));
6783 vc_conn.done;
6784
6785 /* f_tc_ho_neighbor_config_start() */
6786 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
6787 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
6788
6789 /* 1.a */
6790 /* "failed" means a handover was triggered and started (which is all this test aims for) and the test ended the
6791 * handover quickly by sending a Handover Failure message. */
6792 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6793 f_ctrs_bsc_and_bts_add(0, "handover:failed");
6794 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
6795 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:failed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006796 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:attempted");
6797 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:failed");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006798
6799 /* 1.b */
6800 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6801 f_ctrs_bsc_and_bts_add(0, "handover:error");
6802
6803 /* 1.c */
6804 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6805 f_ctrs_bsc_and_bts_add(0, "handover:error");
6806
6807 /* 1.d */
6808 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6809 f_ctrs_bsc_and_bts_add(0, "handover:failed");
6810 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
6811 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:failed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006812 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:attempted");
6813 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:failed");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006814
6815 f_ctrs_bsc_and_bts_verify();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02006816 f_shutdown_helper();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006817}
6818
Neels Hofmeyr91401012019-07-11 00:42:35 +02006819private function f_tc_ho_neighbor_config_2(charstring id) runs on MSC_ConnHdlr {
6820 f_tc_ho_neighbor_config_start();
6821
6822 /*
6823 * bts 0 ARFCN 871 BSIC 10
6824 * bts 1 ARFCN 871 BSIC 11
6825 * bts 2 ARFCN 871 BSIC 12
6826 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
6827 */
6828
6829 log("f_tc_ho_neighbor_config: 2. explicit local neighbor: 'neighbor bts 1'");
Neels Hofmeyr666f0432020-07-04 00:53:07 +02006830 f_bts_0_cfg(BSCVTY, {"neighbor bts 1"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02006831 f_sleep(0.5);
6832
6833 f_probe_for_handover("2.a", "HO to bts 1 works, explicitly listed as neighbor",
6834 "handover any to arfcn 871 bsic 11",
Neels Hofmeyr6a955cc2021-10-02 14:53:48 +02006835 true, expect_target_tsc := BTS_TSC[1]);
Neels Hofmeyr91401012019-07-11 00:42:35 +02006836
6837 f_probe_for_handover("2.b", "HO to bts 2 doesn't work, not listed as neighbor",
6838 "handover any to arfcn 871 bsic 12",
6839 false);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01006840 f_perform_clear();
Neels Hofmeyr91401012019-07-11 00:42:35 +02006841}
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006842testcase TC_ho_neighbor_config_2() runs on test_CT {
6843 var MSC_ConnHdlr vc_conn;
6844 f_init(3, true, guard_timeout := 50.0);
6845 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006846 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006847 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_2));
6848 vc_conn.done;
6849
6850 /* f_tc_ho_neighbor_config_start() */
6851 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
6852 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
6853
6854 /* 2.a */
6855 /* "failed" means a handover was triggered and started (which is all this test aims for) and the test ended the
6856 * handover quickly by sending a Handover Failure message. */
6857 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6858 f_ctrs_bsc_and_bts_add(0, "handover:failed");
6859 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
6860 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:failed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006861 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:attempted");
6862 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:failed");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006863
6864 /* 2.b */
6865 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6866 f_ctrs_bsc_and_bts_add(0, "handover:error");
6867
6868 f_ctrs_bsc_and_bts_verify();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02006869 f_shutdown_helper();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006870}
6871
Neels Hofmeyr91401012019-07-11 00:42:35 +02006872private function f_tc_ho_neighbor_config_3(charstring id) runs on MSC_ConnHdlr {
6873 f_tc_ho_neighbor_config_start();
6874
6875 /*
6876 * bts 0 ARFCN 871 BSIC 10
6877 * bts 1 ARFCN 871 BSIC 11
6878 * bts 2 ARFCN 871 BSIC 12
6879 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
6880 */
6881
6882 log("f_tc_ho_neighbor_config: 3. explicit local neighbor: 'neighbor bts 2'");
Neels Hofmeyr666f0432020-07-04 00:53:07 +02006883 f_bts_0_cfg(BSCVTY, {"no neighbors", "neighbor bts 2"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02006884 f_sleep(0.5);
6885
6886 f_probe_for_handover("3.a", "HO to bts 1 doesn't work, not listed as neighbor",
6887 "handover any to arfcn 871 bsic 11",
6888 false);
6889 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",
6890 "handover any to arfcn 871 bsic 12",
Neels Hofmeyr6a955cc2021-10-02 14:53:48 +02006891 true, expect_target_tsc := BTS_TSC[2]);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01006892 f_perform_clear();
Neels Hofmeyr91401012019-07-11 00:42:35 +02006893}
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006894testcase TC_ho_neighbor_config_3() runs on test_CT {
6895 var MSC_ConnHdlr vc_conn;
6896 f_init(3, true, guard_timeout := 50.0);
6897 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006898 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006899 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_3));
6900 vc_conn.done;
6901
6902 /* f_tc_ho_neighbor_config_start() */
6903 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
6904 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
6905
6906 /* 3.a */
6907 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6908 f_ctrs_bsc_and_bts_add(0, "handover:error");
6909
6910 /* 3.b */
6911 /* "failed" means a handover was triggered and started (which is all this test aims for) and the test ended the
6912 * handover quickly by sending a Handover Failure message. */
6913 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6914 f_ctrs_bsc_and_bts_add(0, "handover:failed");
6915 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
6916 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:failed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006917 f_ctrs_bts_add(2, "incoming_intra_bsc_ho:attempted");
6918 f_ctrs_bts_add(2, "incoming_intra_bsc_ho:failed");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006919
6920 f_ctrs_bsc_and_bts_verify();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02006921 f_shutdown_helper();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006922}
6923
Neels Hofmeyr91401012019-07-11 00:42:35 +02006924private function f_tc_ho_neighbor_config_4(charstring id) runs on MSC_ConnHdlr {
6925 f_tc_ho_neighbor_config_start();
6926
6927 /*
6928 * bts 0 ARFCN 871 BSIC 10
6929 * bts 1 ARFCN 871 BSIC 11
6930 * bts 2 ARFCN 871 BSIC 12
6931 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
6932 */
6933
6934 log("f_tc_ho_neighbor_config: 4. explicit remote neighbor: 'neighbor lac 99 arfcn 123 bsic 45'");
Neels Hofmeyr666f0432020-07-04 00:53:07 +02006935 f_bts_0_cfg(BSCVTY, {"no neighbors", "neighbor lac 99 arfcn 123 bsic 45"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02006936 f_sleep(0.5);
6937
6938 f_probe_for_handover("4.a", "HO to bts 1 doesn't work, not listed as neighbor",
6939 "handover any to arfcn 871 bsic 11",
6940 false);
6941 f_probe_for_handover("4.b", "HO to bts 2 doesn't work, not listed as neighbor",
6942 "handover any to arfcn 871 bsic 12",
6943 false);
6944 f_probe_for_handover("4.c", "HO to 123-45 triggers inter-BSC HO",
6945 "handover any to arfcn 123 bsic 45",
6946 true, true);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01006947 f_perform_clear();
Neels Hofmeyr91401012019-07-11 00:42:35 +02006948}
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006949testcase TC_ho_neighbor_config_4() runs on test_CT {
6950 var MSC_ConnHdlr vc_conn;
6951 f_init(3, true, guard_timeout := 50.0);
6952 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006953 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006954 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_4));
6955 vc_conn.done;
6956
6957 /* f_tc_ho_neighbor_config_start() */
6958 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
6959 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
6960
6961 /* 4.a */
6962 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6963 f_ctrs_bsc_and_bts_add(0, "handover:error");
6964
6965 /* 4.b */
6966 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6967 f_ctrs_bsc_and_bts_add(0, "handover:error");
6968
6969 /* 4.c */
6970 /* "timeout" means a handover was triggered and started (which is all this test aims for) and the test ended the
6971 * handover quickly by timing out after the Handover Required message */
6972 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6973 f_ctrs_bsc_and_bts_add(0, "handover:timeout");
6974 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
6975 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:timeout");
6976
6977 f_ctrs_bsc_and_bts_verify();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02006978 f_shutdown_helper();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006979}
6980
Neels Hofmeyr91401012019-07-11 00:42:35 +02006981private function f_tc_ho_neighbor_config_5(charstring id) runs on MSC_ConnHdlr {
6982 f_tc_ho_neighbor_config_start();
6983
6984 /*
6985 * bts 0 ARFCN 871 BSIC 10
6986 * bts 1 ARFCN 871 BSIC 11
6987 * bts 2 ARFCN 871 BSIC 12
6988 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
6989 */
6990
6991 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 +02006992 f_bts_0_cfg(BSCVTY, {"no neighbors", "neighbor lac 99 arfcn 871 bsic 12"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02006993 f_sleep(0.5);
6994
6995 f_probe_for_handover("5.a", "HO to 871-12 triggers inter-BSC HO (ignoring local cells with same ARFCN+BSIC)",
6996 "handover any to arfcn 871 bsic 12",
6997 true, true);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01006998 f_perform_clear();
Neels Hofmeyr91401012019-07-11 00:42:35 +02006999}
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007000testcase TC_ho_neighbor_config_5() runs on test_CT {
7001 var MSC_ConnHdlr vc_conn;
7002 f_init(3, true);
7003 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007004 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007005 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_5));
7006 vc_conn.done;
7007
7008 /* f_tc_ho_neighbor_config_start() */
7009 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
7010 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
7011
7012 /* 5 */
7013 /* "timeout" means a handover was triggered and started (which is all this test aims for) and the test ended the
7014 * handover quickly by timing out after the Handover Required message */
7015 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7016 f_ctrs_bsc_and_bts_add(0, "handover:timeout");
7017 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
7018 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:timeout");
7019
7020 f_ctrs_bsc_and_bts_verify();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02007021 f_shutdown_helper();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007022}
7023
Neels Hofmeyr91401012019-07-11 00:42:35 +02007024private function f_tc_ho_neighbor_config_6(charstring id) runs on MSC_ConnHdlr {
7025 f_tc_ho_neighbor_config_start();
7026
7027 /*
7028 * bts 0 ARFCN 871 BSIC 10
7029 * bts 1 ARFCN 871 BSIC 11
7030 * bts 2 ARFCN 871 BSIC 12
7031 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
7032 */
7033
7034 log("f_tc_ho_neighbor_config: 6. config error: explicit local and remote neighbors with ambiguous ARFCN+BSIC:"
7035 & " 'neighbor bts 2; neighbor lac 99 arfcn 871 bsic 12'");
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007036 f_bts_0_cfg(BSCVTY, {"no neighbors", "neighbor bts 2", "neighbor lac 99 arfcn 871 bsic 12"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02007037 f_sleep(0.5);
7038
7039 f_probe_for_handover("6.a", "HO to 871-12 is ambiguous = error",
7040 "handover any to arfcn 871 bsic 12",
7041 false);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007042 f_perform_clear();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007043}
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007044testcase TC_ho_neighbor_config_6() runs on test_CT {
7045 var MSC_ConnHdlr vc_conn;
7046 f_init(3, true);
7047 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007048 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007049 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_6));
7050 vc_conn.done;
7051
7052 /* f_tc_ho_neighbor_config_start() */
7053 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
7054 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
7055
7056 /* 6.a */
7057 /* "timeout" means a handover was triggered and started (which is all this test aims for) and the test ended the
7058 * handover quickly by timing out after the Handover Required message */
7059 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7060 f_ctrs_bsc_and_bts_add(0, "handover:error");
7061
7062 f_ctrs_bsc_and_bts_verify();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02007063 f_shutdown_helper();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007064}
7065
Neels Hofmeyr91401012019-07-11 00:42:35 +02007066private function f_tc_ho_neighbor_config_7(charstring id) runs on MSC_ConnHdlr {
7067 f_tc_ho_neighbor_config_start();
7068
7069 /*
7070 * bts 0 ARFCN 871 BSIC 10
7071 * bts 1 ARFCN 871 BSIC 11
7072 * bts 2 ARFCN 871 BSIC 12
7073 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
7074 */
7075
7076 log("f_tc_ho_neighbor_config: 7. explicit local and remote neighbors:"
7077 & " 'neighbor bts 2; neighbor lac 99 arfcn 123 bsic 45'");
Neels Hofmeyr666f0432020-07-04 00:53:07 +02007078 f_bts_0_cfg(BSCVTY, {"no neighbors", "neighbor bts 2", "neighbor lac 99 arfcn 123 bsic 45"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02007079 f_sleep(0.5);
7080
7081 f_probe_for_handover("7.a", "HO to 871-12 does HO to bts 2",
7082 "handover any to arfcn 871 bsic 12",
Neels Hofmeyr6a955cc2021-10-02 14:53:48 +02007083 true, expect_target_tsc := BTS_TSC[2]);
Neels Hofmeyr91401012019-07-11 00:42:35 +02007084 f_probe_for_handover("7.b", "HO to 123-45 triggers inter-BSC HO",
7085 "handover any to arfcn 123 bsic 45",
7086 true, true);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007087 f_perform_clear();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007088}
Neels Hofmeyr91401012019-07-11 00:42:35 +02007089testcase TC_ho_neighbor_config_7() runs on test_CT {
7090 var MSC_ConnHdlr vc_conn;
Neels Hofmeyrf2b88032020-06-16 00:35:04 +02007091 f_init(3, true, guard_timeout := 50.0);
Neels Hofmeyr91401012019-07-11 00:42:35 +02007092 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007093 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007094 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_7));
7095 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007096
7097 /* f_tc_ho_neighbor_config_start() */
7098 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
7099 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
7100
7101 /* 7.a */
7102 /* "failed" means a handover was triggered and started (which is all this test aims for) and the test ended the
7103 * handover quickly by sending a Handover Failure message. */
7104 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7105 f_ctrs_bsc_and_bts_add(0, "handover:failed");
7106 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
7107 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:failed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007108 f_ctrs_bts_add(2, "incoming_intra_bsc_ho:attempted");
7109 f_ctrs_bts_add(2, "incoming_intra_bsc_ho:failed");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007110
7111 /* 7.b */
7112 /* "timeout" means a handover was triggered and started (which is all this test aims for) and the test ended the
7113 * handover quickly by timing out after the Handover Required message */
7114 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7115 f_ctrs_bsc_and_bts_add(0, "handover:timeout");
7116 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
7117 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:timeout");
7118
7119 f_ctrs_bsc_and_bts_verify();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02007120 f_shutdown_helper();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007121}
7122
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +01007123/* OS#3041: Open and close N connections in a normal fashion, and expect no
7124 * BSSMAP Reset just because of that. */
7125testcase TC_bssap_rlsd_does_not_cause_bssmap_reset() runs on test_CT {
7126 var default d;
7127 var integer i;
7128 var DchanTuple dt;
7129
7130 f_init();
7131
7132 /* Wait for initial BSSMAP Reset to pass */
7133 f_sleep(4.0);
7134
7135 d := activate(no_bssmap_reset());
7136
7137 /* Setup up a number of connections and RLSD them again from the MSC
7138 * side. In the buggy behavior, the fourth one triggers BSSMAP Reset.
7139 * Let's do it some more times for good measure. */
Harald Weltec3260d92018-06-11 17:48:16 +02007140 for (i := 0; i < 4; i := i+1) {
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +01007141 /* Since we're doing a lot of runs, give each one a fresh
7142 * T_guard from the top. */
7143 T_guard.start;
7144
7145 /* Setup a BSSAP connection and clear it right away. This is
7146 * the MSC telling the BSC about a planned release, it's not an
7147 * erratic loss of a connection. */
Harald Weltea1897182018-06-11 13:53:09 +02007148 dt := f_est_dchan(int2oct(i,1), 23+i, '00010203040506'O);
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +01007149
7150 /* MSC disconnects (RLSD). */
7151 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
7152 }
7153
7154 /* In the buggy behavior, a timeout of 2 seconds happens between above
7155 * trigger (logs "SIGTRAN connection down, reconnecting...") and the
7156 * actual BSSMAP Reset. Wait a bit longer just to make sure. */
7157 f_sleep(4.0);
7158
7159 deactivate(d);
7160 f_shutdown_helper();
7161}
Harald Welte552620d2017-12-16 23:21:36 +01007162
Neels Hofmeyr4ff93282018-03-12 04:25:35 +01007163/* OS#3041: Open and close N connections in a normal fashion, and expect no
7164 * BSSMAP Reset just because of that. Invoke the release by a BSSMAP Clear from
7165 * the MSC. */
7166testcase TC_bssmap_clear_does_not_cause_bssmap_reset() runs on test_CT {
7167 var default d;
7168 var integer i;
7169 var DchanTuple dt;
7170 var BSSAP_N_DATA_ind rx_di;
Neels Hofmeyr4ff93282018-03-12 04:25:35 +01007171 var myBSSMAP_Cause cause_val := GSM0808_CAUSE_CALL_CONTROL;
7172 var BssmapCause cause := enum2int(cause_val);
7173
7174 f_init();
7175
7176 /* Wait for initial BSSMAP Reset to pass */
7177 f_sleep(4.0);
7178
7179 d := activate(no_bssmap_reset());
7180
7181 /* Setup up a number of connections and RLSD them again from the MSC
7182 * side. In the buggy behavior, the fourth one triggers BSSMAP Reset.
7183 * Let's do it some more times for good measure. */
7184 for (i := 0; i < 8; i := i+1) {
7185 /* Since we're doing a lot of runs, give each one a fresh
7186 * T_guard from the top. */
7187 T_guard.start;
7188
7189 /* Setup a BSSAP connection and clear it right away. This is
7190 * the MSC telling the BSC about a planned release, it's not an
7191 * erratic loss of a connection. */
Harald Weltea1897182018-06-11 13:53:09 +02007192 dt := f_est_dchan(int2oct(i,1), 23+i, '00010203040506'O);
Neels Hofmeyr4ff93282018-03-12 04:25:35 +01007193
7194 /* Instruct BSC to clear channel */
7195 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
7196
7197 /* expect BSC to disable the channel */
Harald Welte641fcbe2018-06-14 10:58:35 +02007198 f_exp_chan_rel_and_clear(dt, 0);
Neels Hofmeyr4ff93282018-03-12 04:25:35 +01007199 }
7200
7201 /* In the buggy behavior, a timeout of 2 seconds happens between above
7202 * trigger (logs "SIGTRAN connection down, reconnecting...") and the
7203 * actual BSSMAP Reset. Wait a bit longer just to make sure. */
7204 f_sleep(4.0);
7205
7206 deactivate(d);
7207 f_shutdown_helper();
7208}
7209
Neels Hofmeyrfd445c32018-03-09 15:39:31 +01007210/* OS#3041: Open and close N connections in a normal fashion, and expect no
7211 * BSSMAP Reset just because of that. Close connections from the MS side with a
7212 * Release Ind on RSL. */
7213testcase TC_ms_rel_ind_does_not_cause_bssmap_reset() runs on test_CT {
7214 var default d;
7215 var integer i;
7216 var DchanTuple dt;
7217 var BSSAP_N_DATA_ind rx_di;
Neels Hofmeyrfd445c32018-03-09 15:39:31 +01007218 var integer j;
7219
7220 f_init();
7221
7222 /* Wait for initial BSSMAP Reset to pass */
7223 f_sleep(4.0);
7224
7225 d := activate(no_bssmap_reset());
7226
7227 /* Setup up a number of connections and RLSD them again from the MSC
7228 * side. In the buggy behavior, the fourth one triggers BSSMAP Reset.
7229 * Let's do it some more times for good measure. */
7230 for (i := 0; i < 8; i := i+1) {
7231 /* Since we're doing a lot of runs, give each one a fresh
7232 * T_guard from the top. */
7233 T_guard.start;
7234
7235 /* Setup a BSSAP connection and clear it right away. This is
7236 * the MSC telling the BSC about a planned release, it's not an
7237 * erratic loss of a connection. */
7238 dt := f_est_dchan('23'O, 23, '00010203040506'O);
7239
7240 /* simulate RLL REL IND */
7241 f_ipa_tx(0, ts_RSL_REL_IND(dt.rsl_chan_nr, valueof(ts_RslLinkID_DCCH(0))));
7242
7243 /* expect Clear Request on MSC side */
7244 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearRequest)) -> value rx_di;
7245
7246 /* Instruct BSC to clear channel */
7247 var BssmapCause cause := bit2int(rx_di.userData.pdu.bssmap.clearRequest.cause.causeValue);
7248 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
7249
7250 /* expect BSC to disable the channel */
Harald Welte641fcbe2018-06-14 10:58:35 +02007251 f_exp_chan_rel_and_clear(dt, 0);
Neels Hofmeyrfd445c32018-03-09 15:39:31 +01007252 }
7253
7254 /* In the buggy behavior, a timeout of 2 seconds happens between above
7255 * trigger (logs "SIGTRAN connection down, reconnecting...") and the
7256 * actual BSSMAP Reset. Wait a bit longer just to make sure. */
7257 f_sleep(4.0);
7258
7259 deactivate(d);
7260 f_shutdown_helper();
7261}
7262
Harald Welte94e0c342018-04-07 11:33:23 +02007263/***********************************************************************
7264 * IPA style dynamic PDCH
7265 ***********************************************************************/
7266
7267private function f_dyn_ipa_pdch_act(integer bts_nr, integer trx_nr, integer ts_nr,
7268 template (omit) RSL_Cause nack := omit)
7269runs on test_CT {
7270 var RslChannelNr chan_nr := valueof(t_RslChanNr_Bm(ts_nr));
7271 var RSL_Message rsl_unused;
7272 /* ask BSC via VTY to activate a given IPA style chan as PDCH */
7273 f_vty_ts_action("pdch activate", bts_nr, trx_nr, ts_nr);
7274 /* expect the BSC to issue the related RSL command */
7275 rsl_unused := f_exp_ipa_rx(0, tr_RSL_IPA_PDCH_ACT(chan_nr));
7276 if (istemplatekind(nack, "omit")) {
7277 /* respond with a related acknowledgement */
7278 f_ipa_tx(0, ts_RSL_IPA_PDCH_ACT_ACK(chan_nr, ts_RSL_IE_FrameNumber(2342)));
7279 } else {
7280 f_ipa_tx(0, ts_RSL_IPA_PDCH_ACT_NACK(chan_nr, valueof(nack)));
7281 }
7282}
7283
7284private function f_dyn_ipa_pdch_deact(integer bts_nr, integer trx_nr, integer ts_nr,
7285 template (omit) RSL_Cause nack := omit)
7286runs on test_CT {
7287 var RslChannelNr chan_nr := valueof(t_RslChanNr_Bm(ts_nr));
7288 var RSL_Message rsl_unused;
7289 /* ask BSC via VTY to activate a given IPA style chan as PDCH */
7290 f_vty_ts_action("pdch deactivate", bts_nr, trx_nr, ts_nr);
7291 /* expect the BSC to issue the related RSL command */
7292 rsl_unused := f_exp_ipa_rx(0, tr_RSL_IPA_PDCH_DEACT(chan_nr));
7293 if (istemplatekind(nack, "omit")) {
7294 /* respond with a related acknowledgement */
7295 f_ipa_tx(0, ts_RSL_IPA_PDCH_DEACT_ACK(chan_nr));
7296 } else {
7297 f_ipa_tx(0, ts_RSL_IPA_PDCH_DEACT_NACK(chan_nr, valueof(nack)));
7298 }
7299}
7300
7301private function f_ts_dyn_mode_get(integer bts_nr, integer trx_nr, integer ts_nr)
7302runs on test_CT return charstring {
7303 var charstring cmd, resp;
7304 cmd := "show timeslot "&int2str(bts_nr)&" "&int2str(trx_nr)&" "&int2str(ts_nr);
Stefan Sperlingcff13562018-11-13 15:24:06 +01007305 return f_vty_transceive_match_regexp_retry(BSCVTY, cmd, "*\((*)\)*", 0, 4, 1.0);
Harald Welte94e0c342018-04-07 11:33:23 +02007306}
7307
7308private function f_ts_dyn_mode_assert(integer bts_nr, integer trx_nr, integer ts_nr,
7309 template charstring exp)
7310runs on test_CT {
7311 var charstring mode := f_ts_dyn_mode_get(bts_nr, trx_nr, ts_nr);
7312 if (not match(mode, exp)) {
7313 setverdict(fail, "Unexpected TS Mode: ", mode);
Daniel Willmannafce8662018-07-06 23:11:32 +02007314 mtc.stop;
Harald Welte94e0c342018-04-07 11:33:23 +02007315 }
7316}
7317
7318private function f_ts_set_chcomb(integer bts_nr, integer trx_nr, integer ts_nr, charstring chcomb)
7319runs on test_CT {
7320 f_vty_enter_cfg_ts(BSCVTY, bts_nr, trx_nr, ts_nr);
7321 f_vty_transceive(BSCVTY, "phys_chan_config " & chcomb);
7322 f_vty_transceive(BSCVTY, "end");
7323}
7324
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02007325
7326private function f_ts_reset_chcomb(integer bts_nr) runs on test_CT {
7327 var integer i;
7328 for (i := 0; i < 8; i := i + 1) {
7329 f_ts_set_chcomb(bts_nr, 0, i, phys_chan_config[i]);
7330 }
7331}
7332
Harald Welte94e0c342018-04-07 11:33:23 +02007333private const charstring TCHF_MODE := "TCH/F mode";
7334private const charstring TCHH_MODE := "TCH/H mode";
7335private const charstring PDCH_MODE := "PDCH mode";
7336private const charstring NONE_MODE := "NONE mode";
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02007337private const charstring SDCCH8_MODE := "SDCCH8 mode";
Harald Welte94e0c342018-04-07 11:33:23 +02007338
7339/* Test IPA PDCH activation / deactivation triggered by VTY */
7340testcase TC_dyn_pdch_ipa_act_deact() runs on test_CT {
7341 var RSL_Message rsl_unused;
7342
7343 /* change Timeslot 6 before f_init() starts RSL */
7344 f_init_vty();
7345 f_ts_set_chcomb(0, 0, 6, "TCH/F_PDCH");
7346 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
7347
7348 f_init(1, false);
7349 f_sleep(1.0);
7350
7351 var RslChannelNr chan_nr := valueof(t_RslChanNr_Bm(6));
7352
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02007353 log("TCH/F_PDCH pchan starts out in TCH/F mode:");
Harald Welte94e0c342018-04-07 11:33:23 +02007354 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, TCHF_MODE);
7355 /* The BSC will activate the dynamic PDCH by default, so confirm that */
7356 rsl_unused := f_exp_ipa_rx(0, tr_RSL_IPA_PDCH_ACT(chan_nr));
7357 f_ipa_tx(0, ts_RSL_IPA_PDCH_ACT_ACK(chan_nr, ts_RSL_IE_FrameNumber(2342)));
7358 f_sleep(1.0);
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02007359 log("TCH/F_PDCH pchan, PDCH ACT was ACKed, so now in PDCH mode:");
Harald Welte94e0c342018-04-07 11:33:23 +02007360 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, PDCH_MODE);
7361
7362 /* De-activate it via VTY */
7363 f_dyn_ipa_pdch_deact(0, 0, chan_nr.tn);
7364 f_sleep(1.0);
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02007365 log("TCH/F_PDCH pchan, PDCH DEACT via VTY, so now back in TCH/F mode:");
Harald Welte94e0c342018-04-07 11:33:23 +02007366 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, TCHF_MODE);
7367
7368 /* re-activate it via VTY */
7369 f_dyn_ipa_pdch_act(0, 0, chan_nr.tn);
7370 f_sleep(1.0);
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02007371 log("TCH/F_PDCH pchan, PDCH ACT via VTY, so now in PDCH mode:");
Harald Welte94e0c342018-04-07 11:33:23 +02007372 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, PDCH_MODE);
7373
7374 /* and finally de-activate it again */
7375 f_dyn_ipa_pdch_deact(0, 0, chan_nr.tn);
7376 f_sleep(1.0);
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02007377 log("TCH/F_PDCH pchan, PDCH DEACT via VTY, so now back in TCH/F mode:");
Harald Welte94e0c342018-04-07 11:33:23 +02007378 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, TCHF_MODE);
7379
Neels Hofmeyr887e8f12018-06-27 01:01:55 +02007380 /* clean up config */
7381 f_ts_set_chcomb(0, 0, 6, "PDCH");
7382
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02007383 f_shutdown_helper();
Harald Welte94e0c342018-04-07 11:33:23 +02007384}
7385
7386/* Test IPA PDCH activation NACK */
7387testcase TC_dyn_pdch_ipa_act_nack() runs on test_CT {
7388 var RSL_Message rsl_unused;
7389
7390 /* change Timeslot 6 before f_init() starts RSL */
7391 f_init_vty();
7392 f_ts_set_chcomb(0, 0, 6, "TCH/F_PDCH");
7393 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
7394
7395 f_init(1, false);
7396 f_sleep(1.0);
7397
7398 var RslChannelNr chan_nr := valueof(t_RslChanNr_Bm(6));
7399
7400 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, TCHF_MODE);
7401 /* The BSC will activate the dynamic PDCH by default, so confirm that */
7402 rsl_unused := f_exp_ipa_rx(0, tr_RSL_IPA_PDCH_ACT(chan_nr));
7403 f_ipa_tx(0, ts_RSL_IPA_PDCH_ACT_ACK(chan_nr, ts_RSL_IE_FrameNumber(2342)));
7404 f_sleep(1.0);
7405 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, PDCH_MODE);
7406
7407 /* De-activate it via VTY */
7408 f_dyn_ipa_pdch_deact(0, 0, chan_nr.tn);
7409 f_sleep(1.0);
7410 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, TCHF_MODE);
7411
7412 /* re-activate it via VTY, but fail that; check BSC still assumes TCH/F mode */
7413 f_dyn_ipa_pdch_act(0, 0, chan_nr.tn, RSL_ERR_EQUIPMENT_FAIL);
7414 f_sleep(1.0);
7415 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, TCHF_MODE);
7416
Neels Hofmeyr887e8f12018-06-27 01:01:55 +02007417 /* clean up config */
7418 f_ts_set_chcomb(0, 0, 6, "PDCH");
7419
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02007420 f_shutdown_helper();
Harald Welte94e0c342018-04-07 11:33:23 +02007421}
7422
7423
7424/***********************************************************************
7425 * Osmocom style dynamic PDCH
7426 ***********************************************************************/
7427
7428private function f_dyn_osmo_pdch_act(integer bts_nr, integer trx_nr, integer ts_nr,
7429 template (omit) RSL_Cause nack := omit)
7430runs on test_CT {
7431 var RslChannelNr chan_nr := valueof(t_RslChanNr_PDCH(ts_nr));
7432 var RSL_Message rsl_unused;
Pau Espin Pedrol64adf372021-06-28 16:25:47 +02007433 /* ask BSC via VTY to activate a given OSMO style chan as PDCH */
Harald Welte94e0c342018-04-07 11:33:23 +02007434 /* FIXME: no VTY command to activate Osmocom PDCH !! */
7435 /* expect the BSC to issue the related RSL command */
7436 rsl_unused := f_exp_ipa_rx(0, tr_RSL_CHAN_ACT(chan_nr, ?));
7437 if (istemplatekind(nack, "omit")) {
7438 /* respond with a related acknowledgement */
7439 f_ipa_tx(0, ts_RSL_CHAN_ACT_ACK(chan_nr, 2342));
7440 } else {
7441 f_ipa_tx(0, ts_RSL_CHAN_ACT_NACK(chan_nr, valueof(nack)));
7442 }
7443}
7444
7445private function f_dyn_osmo_pdch_deact(integer bts_nr, integer trx_nr, integer ts_nr,
7446 template (omit) RSL_Cause nack := omit)
7447runs on test_CT {
7448 var RslChannelNr chan_nr := valueof(t_RslChanNr_PDCH(ts_nr));
7449 var RSL_Message rsl_unused;
Pau Espin Pedrol64adf372021-06-28 16:25:47 +02007450 /* ask BSC via VTY to activate a given OSMO style chan as PDCH */
Harald Welte94e0c342018-04-07 11:33:23 +02007451 /* FIXME: no VTY command to activate Osmocom PDCH !! */
7452 /* expect the BSC to issue the related RSL command */
7453 rsl_unused := f_exp_ipa_rx(0, tr_RSL_RF_CHAN_REL(chan_nr));
7454 if (istemplatekind(nack, "omit")) {
7455 /* respond with a related acknowledgement */
7456 f_ipa_tx(0, ts_RSL_RF_CHAN_REL_ACK(chan_nr));
7457 } else {
7458 //f_ipa_tx(0, ts_RSL_RF_CHAN_REL_NACK(chan_nr, valueof(nack)));
7459 }
7460}
7461
7462/* Test Osmocom dyn PDCH activation / deactivation triggered by VTY */
7463testcase TC_dyn_pdch_osmo_act_deact() runs on test_CT {
7464 var RSL_Message rsl_unused;
7465
7466 /* change Timeslot 6 before f_init() starts RSL */
7467 f_init_vty();
7468 f_ts_set_chcomb(0, 0, 6, "TCH/F_TCH/H_PDCH");
7469 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
7470
7471 f_init(1, false);
7472 f_sleep(1.0);
7473
7474 var RslChannelNr chan_nr := valueof(t_RslChanNr_PDCH(6));
7475
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02007476 log("TCH/F_TCH/H_PDCH pchan starts out in disabled mode:");
Harald Welte94e0c342018-04-07 11:33:23 +02007477 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, NONE_MODE);
7478 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiy58b16532021-10-09 20:27:39 +06007479 rsl_unused := f_exp_ipa_rx(0, tr_RSL_CHAN_ACT_PDCH(chan_nr));
Harald Welte94e0c342018-04-07 11:33:23 +02007480
7481 f_ipa_tx(0, ts_RSL_CHAN_ACT_ACK(chan_nr, 2342));
7482 f_sleep(1.0);
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02007483 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 +02007484 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, PDCH_MODE);
7485
Neels Hofmeyr887e8f12018-06-27 01:01:55 +02007486 /* clean up config */
7487 f_ts_set_chcomb(0, 0, 6, "PDCH");
7488
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02007489 f_shutdown_helper();
Harald Welte94e0c342018-04-07 11:33:23 +02007490}
7491
7492/* Test Osmocom dyn PDCH activation NACK behavior */
7493testcase TC_dyn_pdch_osmo_act_nack() runs on test_CT {
7494 var RSL_Message rsl_unused;
7495
7496 /* change Timeslot 6 before f_init() starts RSL */
7497 f_init_vty();
7498 f_ts_set_chcomb(0, 0, 6, "TCH/F_TCH/H_PDCH");
7499 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
7500
7501 f_init(1, false);
7502 f_sleep(1.0);
7503
7504 var RslChannelNr chan_nr := valueof(t_RslChanNr_PDCH(6));
7505
7506 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, NONE_MODE);
7507 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiy58b16532021-10-09 20:27:39 +06007508 rsl_unused := f_exp_ipa_rx(0, tr_RSL_CHAN_ACT_PDCH(chan_nr));
Harald Welte94e0c342018-04-07 11:33:23 +02007509
7510 /* NACK this activation and expect the "show timeslot" mode still to be NONE */
7511 f_ipa_tx(0, ts_RSL_CHAN_ACT_NACK(chan_nr, RSL_ERR_EQUIPMENT_FAIL));
7512 f_sleep(1.0);
7513 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, NONE_MODE);
7514
Neels Hofmeyr887e8f12018-06-27 01:01:55 +02007515 /* clean up config */
7516 f_ts_set_chcomb(0, 0, 6, "PDCH");
7517
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02007518 f_shutdown_helper();
Harald Welte94e0c342018-04-07 11:33:23 +02007519}
7520
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02007521/* Test Osmocom dyn TS SDCCH8 activation / deactivation */
7522testcase TC_dyn_ts_sdcch8_act_deact() runs on test_CT {
7523 var RSL_Message rsl_unused, rsl_msg;
7524 var DchanTuple dt;
7525 var BSSAP_N_CONNECT_ind rx_c_ind;
7526
7527 /* change Timeslot 6 before f_init() starts RSL */
7528 f_init_vty();
7529 f_ts_set_chcomb(0, 0, 6, "TCH/F_TCH/H_SDCCH8_PDCH");
7530 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
7531
7532 f_init(1, false);
7533 f_sleep(1.0);
7534
7535 var RslChannelNr pdch_chan_nr := valueof(t_RslChanNr_PDCH(6));
7536
7537 log("TCH/F_TCH/H_SDCCH8_PDCH pchan starts out in disabled mode:");
7538 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, NONE_MODE);
7539 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiy58b16532021-10-09 20:27:39 +06007540 rsl_unused := f_exp_ipa_rx(0, tr_RSL_CHAN_ACT_PDCH(pdch_chan_nr));
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02007541
7542 f_ipa_tx(0, ts_RSL_CHAN_ACT_ACK(pdch_chan_nr, 2342));
7543 f_sleep(1.0);
7544 log("TCH/F_TCH/H_SDCCH8_PDC requested to PDCH ACT on startup, which was ACKed, so now in PDCH:");
7545 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, PDCH_MODE);
7546
7547 /* Fill TS0 SDCCH channels (NOTE: only 3 SDCCH/4 channels are available
7548 * on CCCH+SDCCH4+CBCH) */
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007549 var DchanTuples sdcch_cleanup := {};
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02007550 var integer i;
Pau Espin Pedrolce4d5bb2021-10-25 13:31:25 +02007551 for (i := 0; i < NUM_SDCCH_PER_BTS; i := i + 1) {
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02007552 dt := f_est_dchan('23'O, i, '00010203040506'O);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007553 sdcch_cleanup := sdcch_cleanup & { dt };
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02007554 }
7555
7556 /* Now the dyn ts is selected. First PDCH is released, then sdcch chan is activated */
7557 f_ipa_tx(0, ts_RSL_CHAN_RQD(int2oct(oct2int('23'O) + i, 1), 2342));
7558 rsl_unused := f_exp_ipa_rx(0, tr_RSL_RF_CHAN_REL(pdch_chan_nr));
7559 f_ipa_tx(0, ts_RSL_RF_CHAN_REL_ACK(pdch_chan_nr));
7560
7561 rsl_msg := f_exp_ipa_rx(0, tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
7562 dt.rsl_chan_nr := rsl_msg.ies[0].body.chan_nr;
7563
7564 f_ts_dyn_mode_assert(0, 0, dt.rsl_chan_nr.tn, SDCCH8_MODE);
7565 f_ipa_tx(0, ts_RSL_CHAN_ACT_ACK(dt.rsl_chan_nr, 2342));
7566 rsl_msg := f_exp_ipa_rx(0, tr_RSL_IMM_ASSIGN(0));
7567 f_ts_dyn_mode_assert(0, 0, dt.rsl_chan_nr.tn, SDCCH8_MODE);
7568
7569 f_ipa_tx(0, ts_RSL_EST_IND(dt.rsl_chan_nr, valueof(ts_RslLinkID_DCCH(0)), '1234'O));
7570 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3('1234'O))) -> value rx_c_ind;
7571 dt.sccp_conn_id := rx_c_ind.connectionId;
7572 BSSAP.send(ts_BSSAP_CONNECT_res(dt.sccp_conn_id));
7573
7574 /* Instruct BSC to clear channel */
7575 var BssmapCause cause := 0;
7576 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
7577 f_exp_chan_rel_and_clear(dt, 0);
7578
7579 /* The BSC will switch the TS back to PDCH once the only lchan using it is released: */
Vadim Yanitskiy58b16532021-10-09 20:27:39 +06007580 rsl_unused := f_exp_ipa_rx(0, tr_RSL_CHAN_ACT_PDCH(pdch_chan_nr));
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02007581 f_ipa_tx(0, ts_RSL_CHAN_ACT_ACK(pdch_chan_nr, 2342));
7582 f_sleep(1.0);
7583 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, PDCH_MODE);
7584
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007585 /* Clean up SDCCH lchans */
7586 for (i := 0; i < lengthof(sdcch_cleanup); i := i + 1) {
7587 f_perform_clear_test_ct(sdcch_cleanup[i]);
7588 }
7589
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02007590 /* clean up config */
7591 f_ts_set_chcomb(0, 0, 6, "PDCH");
7592
7593 f_shutdown_helper();
7594}
7595
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02007596/* Validate all 8 subslots of a dynamics TS configured as SDCCH8 are used */
7597testcase TC_dyn_ts_sdcch8_all_subslots_used() runs on test_CT {
7598 var ASP_RSL_Unitdata rsl_ud;
7599 var integer i;
7600 var integer chreq_total, chreq_nochan;
7601
7602 f_init_vty();
7603 for (i := 1; i < 8; i := i + 1) {
7604 if (i == 2) {
7605 f_ts_set_chcomb(0, 0, i, "TCH/F_TCH/H_SDCCH8_PDCH");
7606 } else {
7607 f_ts_set_chcomb(0, 0, i, "PDCH");
7608 }
7609 }
7610 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
7611
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007612 f_init(1, guard_timeout := 60.0);
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02007613
7614 /* The dyn TS want to activate PDCH mode, ACK that. */
7615 var RslChannelNr chan_nr;
7616 chan_nr := valueof(t_RslChanNr_PDCH(2));
Vadim Yanitskiy58b16532021-10-09 20:27:39 +06007617 f_exp_ipa_rx(0, tr_RSL_CHAN_ACT_PDCH(chan_nr));
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02007618 f_ipa_tx(0, ts_RSL_CHAN_ACT_ACK(chan_nr, 2342));
7619
7620 f_sleep(1.0);
7621
7622 /* Exhaust all dedicated SDCCH lchans.
7623 /* GSM 44.018 Table 9.1.8.2:
7624 * RA = '13'O -> Establishment cause = 0001xxxx (MS dual rate capable and asks for "SDCCH").
7625 */
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007626 var DchanTuples chan_cleanup := {};
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02007627 for (i := 0; i < NUM_SDCCH_PER_BTS; i := i+1) {
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007628 chan_cleanup := chan_cleanup & { f_est_dchan('13'O, NUM_SDCCH_PER_BTS + i, '00010203040506'O) };
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02007629 }
7630
7631 /* Only the dyn TS is still available. Its first lchan gets converted to SDCCH8 */
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007632 chan_cleanup := chan_cleanup & { f_est_dchan_dyn('33'O, NUM_SDCCH_PER_BTS + i, '00010203040506'O) };
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02007633 /* Also occupy the seven other SDCCH of the dyn TS */
7634 for (i := 0; i < 7; i := i+1) {
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007635 chan_cleanup := chan_cleanup & { f_est_dchan('33'O, NUM_SDCCH_PER_BTS + i, '00010203040506'O) };
7636 }
7637
7638 /* Clean up SDCCH lchans */
7639 for (i := 0; i < lengthof(chan_cleanup); i := i + 1) {
7640 f_perform_clear_test_ct(chan_cleanup[i]);
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02007641 }
7642
7643 /* clean up config */
7644 f_ts_reset_chcomb(0);
7645
7646 f_shutdown_helper();
7647}
7648
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02007649/* Test Osmocom dyn TS SDCCH8 activation / deactivation: If activating dyn TS as
7650 SDCCH8 would end up in having no free TCH, then BSC should decide to activate
7651 it as TCH directly instead. SYS#5309. */
7652testcase TC_dyn_ts_sdcch8_tch_call_act_deact() runs on test_CT {
7653 var RSL_Message rsl_unused, rsl_msg;
7654 var DchanTuple dt;
7655 var BSSAP_N_CONNECT_ind rx_c_ind;
7656 var integer i;
7657
7658 /* change Timeslot 6 before f_init() starts RSL */
7659 f_init_vty();
7660 for (i := 1; i < 8; i := i + 1) {
7661 if (i == 6) {
7662 f_ts_set_chcomb(0, 0, i, "TCH/F_TCH/H_SDCCH8_PDCH");
7663 } else {
7664 f_ts_set_chcomb(0, 0, i, "PDCH");
7665 }
7666 }
7667 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
7668
7669 f_init(1, false);
7670 f_sleep(1.0);
7671
7672 var RslChannelNr pdch_chan_nr := valueof(t_RslChanNr_PDCH(6));
7673
7674 log("TCH/F_TCH/H_SDCCH8_PDCH pchan starts out in disabled mode:");
7675 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, NONE_MODE);
7676 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiy58b16532021-10-09 20:27:39 +06007677 rsl_unused := f_exp_ipa_rx(0, tr_RSL_CHAN_ACT_PDCH(pdch_chan_nr));
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02007678
7679 f_ipa_tx(0, ts_RSL_CHAN_ACT_ACK(pdch_chan_nr, 2342));
7680 f_sleep(1.0);
7681 log("TCH/F_TCH/H_SDCCH8_PDC requested to PDCH ACT on startup, which was ACKed, so now in PDCH:");
7682 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, PDCH_MODE);
7683
7684 /* Fill TS0 SDCCH channels (NOTE: only 3 SDCCH/4 channels are available
7685 * on CCCH+SDCCH4+CBCH) */
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007686 var DchanTuples chan_cleanup := {};
Pau Espin Pedrol2ebbe7c2021-07-23 16:17:09 +02007687 var OCT1 ra := '43'O; /* RA containing reason=originating speech call*/
Pau Espin Pedrolce4d5bb2021-10-25 13:31:25 +02007688 for (i := 0; i < NUM_SDCCH_PER_BTS; i := i + 1) {
Pau Espin Pedrol2ebbe7c2021-07-23 16:17:09 +02007689 dt := f_est_dchan(ra, i, '00010203040506'O);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007690 chan_cleanup := chan_cleanup & { dt };
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02007691 }
7692
7693 /* Now the dyn ts is selected. First PDCH is released, then TCH chan is activated */
Pau Espin Pedrol2ebbe7c2021-07-23 16:17:09 +02007694 f_ipa_tx(0, ts_RSL_CHAN_RQD(int2oct(oct2int(ra) + i, 1), 2342));
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02007695 rsl_unused := f_exp_ipa_rx(0, tr_RSL_RF_CHAN_REL(pdch_chan_nr));
7696 f_ipa_tx(0, ts_RSL_RF_CHAN_REL_ACK(pdch_chan_nr));
7697
7698 rsl_msg := f_exp_ipa_rx(0, tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
7699 dt.rsl_chan_nr := rsl_msg.ies[0].body.chan_nr;
7700
7701 f_ts_dyn_mode_assert(0, 0, dt.rsl_chan_nr.tn, TCHH_MODE);
7702 f_ipa_tx(0, ts_RSL_CHAN_ACT_ACK(dt.rsl_chan_nr, 2342));
7703 rsl_msg := f_exp_ipa_rx(0, tr_RSL_IMM_ASSIGN(0));
7704 f_ts_dyn_mode_assert(0, 0, dt.rsl_chan_nr.tn, TCHH_MODE);
7705
7706 f_ipa_tx(0, ts_RSL_EST_IND(dt.rsl_chan_nr, valueof(ts_RslLinkID_DCCH(0)), '1234'O));
7707 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3('1234'O))) -> value rx_c_ind;
7708 dt.sccp_conn_id := rx_c_ind.connectionId;
7709 BSSAP.send(ts_BSSAP_CONNECT_res(dt.sccp_conn_id));
7710
7711 /* Instruct BSC to clear channel */
7712 var BssmapCause cause := 0;
7713 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
7714 f_exp_chan_rel_and_clear(dt, 0);
7715
7716 /* The BSC will switch the TS back to PDCH once the only lchan using it is released: */
Vadim Yanitskiy58b16532021-10-09 20:27:39 +06007717 rsl_unused := f_exp_ipa_rx(0, tr_RSL_CHAN_ACT_PDCH(pdch_chan_nr));
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02007718 f_ipa_tx(0, ts_RSL_CHAN_ACT_ACK(pdch_chan_nr, 2342));
7719 f_sleep(1.0);
7720 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, PDCH_MODE);
7721
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007722 /* Clean up SDCCH lchans */
7723 for (i := 0; i < lengthof(chan_cleanup); i := i + 1) {
7724 f_perform_clear_test_ct(chan_cleanup[i]);
7725 }
7726
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02007727 /* clean up config */
7728 f_ts_reset_chcomb(0);
7729 /* TODO: clean up other channels? */
7730
7731 f_shutdown_helper();
7732}
7733
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02007734/* Test Osmocom dyn TS SDCCH8 activation / deactivation when SDCCH fails at BTS */
7735testcase TC_dyn_ts_sdcch8_act_nack() runs on test_CT {
7736 var RSL_Message rsl_unused, rsl_msg;
7737 var DchanTuple dt;
7738 var BSSAP_N_CONNECT_ind rx_c_ind;
7739 var GsmRrMessage rr;
7740
7741 /* change Timeslot 6 before f_init() starts RSL */
7742 f_init_vty();
7743 f_ts_set_chcomb(0, 0, 6, "TCH/F_TCH/H_SDCCH8_PDCH");
7744 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
7745
7746 f_init(1, false);
7747 f_sleep(1.0);
7748
7749 var RslChannelNr pdch_chan_nr := valueof(t_RslChanNr_PDCH(6));
7750
7751 log("TCH/F_TCH/H_SDCCH8_PDCH pchan starts out in disabled mode:");
7752 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, NONE_MODE);
7753 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiy58b16532021-10-09 20:27:39 +06007754 rsl_unused := f_exp_ipa_rx(0, tr_RSL_CHAN_ACT_PDCH(pdch_chan_nr));
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02007755
7756 f_ipa_tx(0, ts_RSL_CHAN_ACT_ACK(pdch_chan_nr, 2342));
7757 f_sleep(1.0);
7758 log("TCH/F_TCH/H_SDCCH8_PDC requested to PDCH ACT on startup, which was ACKed, so now in PDCH:");
7759 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, PDCH_MODE);
7760
7761 /* Fill TS0 SDCCH channels (NOTE: only 3 SDCCH/4 channels are available
7762 * on CCCH+SDCCH4+CBCH) */
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007763 var DchanTuples chan_cleanup := {};
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02007764 var integer i;
Pau Espin Pedrolce4d5bb2021-10-25 13:31:25 +02007765 for (i := 0; i < NUM_SDCCH_PER_BTS; i := i + 1) {
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02007766 dt := f_est_dchan('23'O, i, '00010203040506'O);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007767 chan_cleanup := chan_cleanup & { dt };
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02007768 }
7769
7770 /* Now the dyn ts is selected. First PDCH is released, then sdcch chan is activated */
7771 f_ipa_tx(0, ts_RSL_CHAN_RQD(int2oct(oct2int('23'O) + i, 1), 2342));
7772 rsl_unused := f_exp_ipa_rx(0, tr_RSL_RF_CHAN_REL(pdch_chan_nr));
7773 f_ipa_tx(0, ts_RSL_RF_CHAN_REL_ACK(pdch_chan_nr));
7774
7775 rsl_msg := f_exp_ipa_rx(0, tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
7776 dt.rsl_chan_nr := rsl_msg.ies[0].body.chan_nr;
7777
7778 f_ts_dyn_mode_assert(0, 0, dt.rsl_chan_nr.tn, SDCCH8_MODE);
7779 f_ipa_tx(0, ts_RSL_CHAN_ACT_NACK(dt.rsl_chan_nr, RSL_ERR_EQUIPMENT_FAIL));
7780 rsl_msg := f_exp_ipa_rx(0, tr_RSL_IMM_ASSIGN(0));
7781 rr := dec_GsmRrMessage(rsl_msg.ies[1].body.full_imm_ass_info.payload);
7782 if (rr.header.message_type != IMMEDIATE_ASSIGNMENT_REJECT) {
7783 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Expected reject");
7784 }
7785
7786 /* FIXME? Currently the TS stays in state BORKEN: */
7787
7788 /* The BSC will switch the TS back to PDCH once the only lchan using it is released: */
Vadim Yanitskiy58b16532021-10-09 20:27:39 +06007789 /* rsl_unused := f_exp_ipa_rx(0, tr_RSL_CHAN_ACT_PDCH(pdch_chan_nr));
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02007790 * f_ipa_tx(0, ts_RSL_CHAN_ACT_ACK(pdch_chan_nr, 2342));
7791 * f_sleep(1.0);
7792 * f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, PDCH_MODE)
7793 */
7794
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007795 /* Clean up SDCCH lchans */
7796 for (i := 0; i < lengthof(chan_cleanup); i := i + 1) {
7797 f_perform_clear_test_ct(chan_cleanup[i]);
7798 }
7799
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02007800 /* clean up config */
7801 f_ts_set_chcomb(0, 0, 6, "PDCH");
7802
7803 f_shutdown_helper();
7804}
7805
Stefan Sperling0796a822018-10-05 13:01:39 +02007806testcase TC_chopped_ipa_ping() runs on test_CT {
Stefan Sperling554123f2018-10-09 14:12:30 +02007807 const Integers bsc_ipa_ports := {mp_bsc_rsl_port, mp_bsc_oml_port, mp_bsc_ctrl_port};
Stefan Sperling0796a822018-10-05 13:01:39 +02007808 for (var integer i := 0; i < lengthof(bsc_ipa_ports); i := i + 1) {
7809 IPA_Testing.f_run_TC_chopped_ipa_ping(mp_bsc_ip, bsc_ipa_ports[i], CONNECT_TO_SERVER);
7810 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02007811 f_shutdown_helper();
Stefan Sperling0796a822018-10-05 13:01:39 +02007812}
7813
Stefan Sperlingaa1e60f2018-10-15 16:34:07 +02007814testcase TC_chopped_ipa_payload() runs on test_CT {
7815 const Integers bsc_ipa_ports := {mp_bsc_rsl_port, mp_bsc_oml_port
7816 /* TODO: mp_bsc_ctrl_port does not work yet */};
7817 for (var integer i := 0; i < lengthof(bsc_ipa_ports); i := i + 1) {
7818 IPA_Testing.f_run_TC_chopped_ipa_payload(mp_bsc_ip, bsc_ipa_ports[i], CONNECT_TO_SERVER);
7819 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02007820 f_shutdown_helper();
Stefan Sperlingaa1e60f2018-10-15 16:34:07 +02007821}
7822
Pau Espin Pedrol8f773632019-11-05 11:46:53 +01007823/* Verify the BSC sends the MS Power Parameters IE during CHAN ACT to make sure
7824 the BTS does autonomous MS power control loop */
7825testcase TC_assignment_verify_ms_power_params_ie() runs on test_CT {
7826 var MSC_ConnHdlr vc_conn;
7827 var TestHdlrParams pars := f_gen_test_hdlr_pars();
7828 //pars.encr := valueof(t_EncrParams('01'O, f_rnd_octstring(8)));
7829 pars.exp_ms_power_params := true;
7830
7831 f_init(1, true);
7832 f_sleep(1.0);
7833 vc_conn := f_start_handler(refers(f_tc_assignment_fr_a5), pars);
7834 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02007835 f_shutdown_helper();
Pau Espin Pedrol8f773632019-11-05 11:46:53 +01007836}
Stefan Sperlingaa1e60f2018-10-15 16:34:07 +02007837
Vadim Yanitskiy4b233042021-06-30 00:58:43 +02007838/* Verify activation and deactivation of the BCCH carrier power reduction mode */
7839testcase TC_c0_power_red_mode() runs on test_CT {
7840 f_init(1);
7841
7842 for (var integer red := 6; red >= 0; red := red - 2) {
7843 /* Configure BCCH carrier power reduction mode via the VTY */
7844 f_vty_transceive(BSCVTY, "bts 0 c0-power-reduction " & int2str(red));
7845
7846 /* Expect Osmocom specific BS Power Control message on the RSL */
7847 var template RSL_Message tr_rsl_pdu := tr_RSL_BS_PWR_CTRL(
7848 chan_nr := t_RslChanNr_BCCH(0),
7849 bs_power := tr_RSL_IE_BS_Power(red / 2));
7850 tr_rsl_pdu.msg_disc := tr_RSL_MsgDisc(RSL_MDISC_CCHAN, false);
7851 var RSL_Message unused := f_exp_ipa_rx(0, tr_rsl_pdu);
7852
7853 /* Additionally verify the applied value over the CTRL interface */
7854 var CtrlValue cred := f_ctrl_get_bts(IPA_CTRL, 0, "c0-power-reduction");
7855 if (cred != int2str(red)) {
7856 setverdict(fail, "Unexpected BCCH carrier power reduction value ",
7857 cred, " (expected ", red, ")");
7858 }
7859 }
7860
7861 f_shutdown_helper();
7862}
7863
Neels Hofmeyr4f118412020-06-04 15:25:10 +02007864/***********************************************************************
7865 * MSC Pooling
7866 ***********************************************************************/
7867
Neels Hofmeyr4f118412020-06-04 15:25:10 +02007868template MobileIdentityLV ts_MI_TMSI_NRI_LV(integer nri_v, integer nri_bitlen := 10) :=
Harald Weltebf397612021-01-14 20:39:46 +01007869 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 +02007870
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02007871private 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 +02007872runs on MSC_ConnHdlr {
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02007873 interleave {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02007874 [] rsl_pt.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch exp_rr_rel_tmpl)) {
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02007875 f_logp(BSCVTY, "Got RSL RR Release");
7876 }
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02007877 [] rsl_pt.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02007878 f_logp(BSCVTY, "Got RSL Deact SACCH");
7879 }
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +02007880 [] rsl_pt.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02007881 f_logp(BSCVTY, "Got RSL RF Chan Rel, sending Rel Ack");
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02007882 rsl_pt.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
7883 f_rslem_unregister(0, g_chan_nr, PT := rsl_proc_pt);
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02007884 break;
7885 }
7886 }
7887}
7888
Neels Hofmeyr6289af12021-12-16 18:17:49 +01007889private altstep as_mgcp_ack_all_dlcx() runs on MSC_ConnHdlr {
7890 var MgcpCommand mgcp_cmd;
7891 [] MGCP.receive(tr_DLCX(?)) -> value mgcp_cmd {
7892 MGCP.send(ts_DLCX_ACK2(mgcp_cmd.line.trans_id));
7893 repeat;
7894 }
7895}
7896
7897private altstep as_rsl_ack_all_rel_req() runs on MSC_ConnHdlr {
7898 var RslLinkId main_dcch := valueof(ts_RslLinkID_DCCH(0));
7899 [] RSL.receive(tr_RSL_REL_REQ(g_chan_nr, ?)) {
7900 RSL.send(ts_RSL_REL_CONF(g_chan_nr, main_dcch));
7901 repeat;
7902 }
7903}
7904
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02007905friend function f_perform_clear(RSL_DCHAN_PT rsl_pt := RSL, RSLEM_PROC_PT rsl_proc_pt := RSL_PROC,
7906 template PDU_ML3_NW_MS exp_rr_rel_tmpl := tr_RRM_RR_RELEASE)
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02007907runs on MSC_ConnHdlr {
Neels Hofmeyr6289af12021-12-16 18:17:49 +01007908 var default ack_dlcx := activate(as_mgcp_ack_all_dlcx());
7909 var default ack_rel_req := activate(as_rsl_ack_all_rel_req());
Neels Hofmeyr767548a2020-08-09 20:26:07 +00007910 f_logp(BSCVTY, "MSC instructs BSC to clear channel");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02007911 BSSAP.send(ts_BSSMAP_ClearCommand(0));
7912 interleave {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02007913 [] rsl_pt.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch exp_rr_rel_tmpl)) {
Neels Hofmeyr767548a2020-08-09 20:26:07 +00007914 f_logp(BSCVTY, "Got RSL RR Release");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02007915 }
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02007916 [] rsl_pt.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {
Neels Hofmeyr767548a2020-08-09 20:26:07 +00007917 f_logp(BSCVTY, "Got RSL Deact SACCH");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02007918 }
7919 [] BSSAP.receive(tr_BSSMAP_ClearComplete) {
Neels Hofmeyr767548a2020-08-09 20:26:07 +00007920 f_logp(BSCVTY, "Got BSSMAP Clear Complete");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02007921 /* Also drop the SCCP connection */
7922 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
7923 }
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +02007924 [] rsl_pt.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
Neels Hofmeyr767548a2020-08-09 20:26:07 +00007925 f_logp(BSCVTY, "Got RSL RF Chan Rel, sending Rel Ack");
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02007926 rsl_pt.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
7927 f_rslem_unregister(0, g_chan_nr, PT := rsl_proc_pt);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02007928 }
7929 }
Neels Hofmeyr6289af12021-12-16 18:17:49 +01007930 deactivate(ack_dlcx);
7931 deactivate(ack_rel_req);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02007932}
7933
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01007934private function f_perform_clear_test_ct(DchanTuple dt)
7935 runs on test_CT
7936{
7937 /* Instruct BSC to clear channel */
7938 var BssmapCause cause := 0;
7939 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
7940 f_exp_chan_rel_and_clear(dt, 0);
7941}
7942
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02007943private function f_perform_compl_l3(RSL_DCHAN_PT rsl_pt, RSLEM_PROC_PT rsl_proc_pt,
7944 template PDU_ML3_MS_NW l3_info, boolean do_clear := true, boolean expect_bssmap_l3 := true)
Neels Hofmeyr4f118412020-06-04 15:25:10 +02007945runs on MSC_ConnHdlr {
7946 timer T := 10.0;
7947 var octetstring l3_enc := enc_PDU_ML3_MS_NW(valueof(l3_info));
7948
Neels Hofmeyr767548a2020-08-09 20:26:07 +00007949 f_logp(BSCVTY, "establish channel, send Complete Layer 3 Info");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02007950 f_create_bssmap_exp(l3_enc);
7951
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02007952 /* RSL_Emulation.f_chan_est() on rsl_pt:
7953 * This is basically code dup with s/RSL/rsl_pt from:
Neels Hofmeyr4f118412020-06-04 15:25:10 +02007954 * RSL_Emulation.f_chan_est(g_pars.ra, l3_enc, g_pars.link_id, g_pars.fn);
7955 */
7956 var RSL_Message rx_rsl;
7957 var GsmRrMessage rr;
7958
7959 /* request a channel to be established */
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02007960 rsl_pt.send(ts_RSLDC_ChanRqd(g_pars.ra, g_pars.fn));
Neels Hofmeyr4f118412020-06-04 15:25:10 +02007961 /* expect immediate assignment.
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02007962 * Code dup with s/RSL/rsl_pt from:
Neels Hofmeyr4f118412020-06-04 15:25:10 +02007963 * rx_rsl := f_rx_or_fail(tr_RSL_IMM_ASSIGN);
7964 */
7965 timer Tt := 10.0;
7966
7967 /* request a channel to be established */
7968 Tt.start;
7969 alt {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02007970 [] rsl_pt.receive(tr_RSL_IMM_ASSIGN) -> value rx_rsl {
Neels Hofmeyr4f118412020-06-04 15:25:10 +02007971 Tt.stop;
7972 }
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02007973 [] rsl_pt.receive {
Neels Hofmeyr4f118412020-06-04 15:25:10 +02007974 setverdict(fail, "Unexpected RSL message on DCHAN");
7975 mtc.stop;
7976 }
7977 [] Tt.timeout {
7978 setverdict(fail, "Timeout waiting for RSL on DCHAN");
7979 mtc.stop;
7980 }
7981 }
7982 rr := dec_GsmRrMessage(rx_rsl.ies[1].body.full_imm_ass_info.payload);
7983 g_chan_nr := rr.payload.imm_ass.chan_desc.chan_nr;
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02007984 rsl_pt.send(ts_RSL_EST_IND(g_chan_nr, valueof(g_pars.link_id), l3_enc));
Neels Hofmeyr4f118412020-06-04 15:25:10 +02007985
7986
Neels Hofmeyr66e15092020-10-12 18:44:41 +00007987 if (expect_bssmap_l3) {
7988 f_logp(BSCVTY, "expect BSSAP Complete Layer 3 Info at MSC");
7989 var template PDU_BSSAP exp_l3_compl;
7990 exp_l3_compl := tr_BSSMAP_ComplL3()
7991 if (g_pars.aoip == false) {
7992 exp_l3_compl.pdu.bssmap.completeLayer3Information.codecList := omit;
7993 } else {
7994 exp_l3_compl.pdu.bssmap.completeLayer3Information.codecList := ?;
7995 }
Neels Hofmeyr4f118412020-06-04 15:25:10 +02007996
Neels Hofmeyr66e15092020-10-12 18:44:41 +00007997 var PDU_BSSAP bssap;
7998 T.start;
7999 alt {
8000 [] BSSAP.receive(exp_l3_compl) -> value bssap {
8001 f_logp(BSCVTY, "received expected Complete Layer 3 Info at MSC");
8002 log("rx exp_l3_compl = ", bssap);
8003 }
8004 [] BSSAP.receive(tr_BSSMAP_ComplL3) {
8005 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Received non-matching COMPLETE LAYER 3 INFORMATION");
8006 }
8007 [] T.timeout {
8008 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout waiting for COMPLETE LAYER 3 INFORMATION");
8009 }
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008010 }
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008011
Neels Hofmeyr66e15092020-10-12 18:44:41 +00008012 /* start ciphering, if requested */
8013 if (ispresent(g_pars.encr)) {
8014 f_logp(BSCVTY, "start ciphering");
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008015 f_cipher_mode(g_pars.encr, rsl_pt := rsl_pt, rsl_proc_pt := rsl_proc_pt);
Neels Hofmeyr66e15092020-10-12 18:44:41 +00008016 }
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008017 }
8018
8019 if (do_clear) {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008020 f_perform_clear(rsl_pt, rsl_proc_pt);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008021 }
8022 setverdict(pass);
8023 f_sleep(1.0);
8024}
8025
8026private function f_tc_mscpool_compl_l3(charstring id) runs on MSC_ConnHdlr {
8027 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
8028 if (g_pars.mscpool.rsl_idx == 0) {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008029 f_perform_compl_l3(RSL, RSL_PROC, g_pars.mscpool.l3_info);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008030 } else if (g_pars.mscpool.rsl_idx == 1) {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008031 f_perform_compl_l3(RSL1, RSL1_PROC, g_pars.mscpool.l3_info);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008032 } else if (g_pars.mscpool.rsl_idx == 2) {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008033 f_perform_compl_l3(RSL2, RSL2_PROC, g_pars.mscpool.l3_info);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008034 }
8035}
8036
8037/* Various Complete Layer 3 by IMSI all end up with the first MSC, because the other MSCs are not connected. */
8038private function f_tc_mscpool_L3Compl_on_1_msc(charstring id) runs on MSC_ConnHdlr {
8039 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008040 f_perform_compl_l3(RSL, RSL_PROC, ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_IMSI_LV('001010000000001'H)), '00F110'O) );
8041 f_perform_compl_l3(RSL, RSL_PROC, ts_CM_SERV_REQ(CM_TYPE_MO_SMS, valueof(ts_MI_IMSI_LV('001010000000002'H))) );
8042 f_perform_compl_l3(RSL, RSL_PROC, ts_PAG_RESP(valueof(ts_MI_IMSI_LV('001010000000003'H))) );
8043 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 +02008044}
8045testcase TC_mscpool_L3Compl_on_1_msc() runs on test_CT {
8046
8047 f_init(1, true);
8048 f_sleep(1.0);
8049 var MSC_ConnHdlr vc_conn;
8050 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008051
8052 f_ctrs_msc_init();
8053
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008054 vc_conn := f_start_handler(refers(f_tc_mscpool_L3Compl_on_1_msc), pars);
8055 vc_conn.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008056
8057 f_ctrs_msc_expect(0, "mscpool:subscr:new", 4);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008058 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008059}
8060
8061/* Three Layer 3 Complete by IMSI are round-robin'ed across two connected MSCs */
8062/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8063 * just as well using only RSL. */
8064testcase TC_mscpool_L3Complete_by_imsi_round_robin() runs on test_CT {
8065
8066 f_init(nr_bts := 3, handler_mode := true, nr_msc := 2);
8067 f_sleep(1.0);
8068
8069 /* Control which MSC gets chosen next by the round-robin, otherwise
8070 * would be randomly affected by which other tests ran before this. */
8071 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
8072
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008073 f_ctrs_msc_init();
8074
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008075 var MSC_ConnHdlr vc_conn1;
8076 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
8077 pars1.mscpool.rsl_idx := 0;
8078 pars1.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_IMSI_LV('001010000000001'H)), '00F110'O));
8079 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8080 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008081 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008082
8083 var MSC_ConnHdlr vc_conn2;
8084 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 1);
8085 pars2.mscpool.rsl_idx := 1;
8086 pars2.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, valueof(ts_MI_IMSI_LV('001010000000002'H))));
8087 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8088 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008089 f_ctrs_msc_expect(1, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008090
8091 /* Test round-robin wrap to the first MSC */
8092 var MSC_ConnHdlr vc_conn3;
8093 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 0);
8094 pars3.mscpool.rsl_idx := 2;
8095 pars3.mscpool.l3_info := valueof(ts_PAG_RESP(valueof(ts_MI_IMSI_LV('001010000000003'H))));
8096 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8097 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008098 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008099 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008100}
8101
8102/* Three LU by TMSI are round-robin'ed across two connected MSCs, because they contain the NULL-NRI 0
8103 * (configured in osmo-bsc.cfg). */
8104/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8105 * just as well using only RSL. */
8106testcase TC_mscpool_LU_by_tmsi_null_nri_0_round_robin() runs on test_CT {
8107
8108 f_init(nr_bts := 3, handler_mode := true, nr_msc := 2);
8109 f_sleep(1.0);
8110
8111 /* Control which MSC gets chosen next by the round-robin, otherwise
8112 * would be randomly affected by which other tests ran before this. */
8113 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
8114
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008115 f_ctrs_msc_init();
8116
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008117 var MSC_ConnHdlr vc_conn1;
8118 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
8119 pars1.mscpool.rsl_idx := 0;
8120 pars1.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(0)), '00F110'O));
8121 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8122 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008123 f_ctrs_msc_expect(0, "mscpool:subscr:reattach");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008124
8125 var MSC_ConnHdlr vc_conn2;
8126 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 1);
8127 pars2.mscpool.rsl_idx := 1;
8128 pars2.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(0)), '00F110'O));
8129 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8130 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008131 f_ctrs_msc_expect(1, "mscpool:subscr:reattach");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008132
8133 /* Test round-robin wrap to the first MSC */
8134 var MSC_ConnHdlr vc_conn3;
8135 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 0);
8136 pars3.mscpool.rsl_idx := 2;
8137 pars3.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(0)), '00F110'O));
8138 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8139 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008140 f_ctrs_msc_expect(0, "mscpool:subscr:reattach");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008141 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008142}
8143
8144/* Three LU by TMSI are round-robin'ed across two connected MSCs, because they contain the NULL-NRI 1
8145 * (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
8146 * NULL-NRI setting is stronger than that. */
8147/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8148 * just as well using only RSL. */
8149testcase TC_mscpool_LU_by_tmsi_null_nri_1_round_robin() runs on test_CT {
8150
8151 f_init(nr_bts := 3, handler_mode := true, nr_msc := 2);
8152 f_sleep(1.0);
8153
8154 /* Control which MSC gets chosen next by the round-robin, otherwise
8155 * would be randomly affected by which other tests ran before this. */
8156 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
8157
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008158 f_ctrs_msc_init();
8159
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008160 var MSC_ConnHdlr vc_conn1;
8161 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
8162 pars1.mscpool.rsl_idx := 0;
8163 pars1.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(1)), '00F110'O));
8164 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8165 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008166 f_ctrs_msc_expect(0, "mscpool:subscr:reattach");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008167
8168 var MSC_ConnHdlr vc_conn2;
8169 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 1);
8170 pars2.mscpool.rsl_idx := 1;
8171 pars2.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(1)), '00F110'O));
8172 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8173 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008174 f_ctrs_msc_expect(1, "mscpool:subscr:reattach");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008175
8176 /* Test round-robin wrap to the first MSC */
8177 var MSC_ConnHdlr vc_conn3;
8178 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 0);
8179 pars3.mscpool.rsl_idx := 2;
8180 pars3.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(1)), '00F110'O));
8181 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8182 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008183 f_ctrs_msc_expect(0, "mscpool:subscr:reattach");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008184 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008185}
8186
8187/* Three Layer 3 Complete by TMSI are round-robin'ed across two connected MSCs, because they contain an NRI not
8188 * assigned to any MSC (configured in osmo-bsc.cfg). */
8189/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8190 * just as well using only RSL. */
8191testcase TC_mscpool_L3Complete_by_tmsi_unassigned_nri_round_robin() runs on test_CT {
8192
8193 f_init(nr_bts := 3, handler_mode := true, nr_msc := 2);
8194 f_sleep(1.0);
8195
8196 /* Control which MSC gets chosen next by the round-robin, otherwise
8197 * would be randomly affected by which other tests ran before this. */
8198 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
8199
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008200 f_ctrs_msc_init();
8201
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008202 var MSC_ConnHdlr vc_conn1;
8203 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
8204 pars1.mscpool.rsl_idx := 0;
8205 /* An NRI that is not assigned to any MSC */
8206 pars1.mscpool.l3_info := valueof(ts_ML3_MO_MM_IMSI_DET_Ind(valueof(ts_MI_TMSI_NRI_LV(1023))));
8207 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8208 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008209 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008210
8211 var MSC_ConnHdlr vc_conn2;
8212 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 1);
8213 pars2.mscpool.rsl_idx := 1;
8214 /* An NRI that is not assigned to any MSC */
8215 pars2.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(768)), '00F110'O));
8216 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8217 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008218 f_ctrs_msc_expect(1, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008219
8220 /* Test round-robin wrap to the first MSC */
8221 var MSC_ConnHdlr vc_conn3;
8222 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 0);
8223 pars3.mscpool.rsl_idx := 2;
8224 /* An NRI that is not assigned to any MSC */
8225 pars3.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_SS_ACT, valueof(ts_MI_TMSI_NRI_LV(819))));
8226 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8227 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008228 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008229 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008230}
8231
8232/* Three Layer 3 Complete by TMSI are round-robin'ed across two connected MSCs, because they contain an NRI
8233 * assigned to an MSC that is currently not connected (configured in osmo-bsc.cfg). */
8234/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8235 * just as well using only RSL. */
8236testcase TC_mscpool_L3Complete_by_tmsi_valid_nri_msc_not_connected_round_robin() runs on test_CT {
8237
8238 f_init(nr_bts := 3, handler_mode := true, nr_msc := 2);
8239 f_sleep(1.0);
8240
8241 /* Control which MSC gets chosen next by the round-robin, otherwise
8242 * would be randomly affected by which other tests ran before this. */
8243 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
8244
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008245 f_ctrs_msc_init();
8246
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008247 var MSC_ConnHdlr vc_conn1;
8248 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
8249 pars1.mscpool.rsl_idx := 0;
8250 /* An NRI that is assigned to an unconnected MSC */
8251 pars1.mscpool.l3_info := valueof(ts_PAG_RESP(valueof(ts_MI_TMSI_NRI_LV(512))));
8252 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8253 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008254 f_ctrs_msc_add(2, "mscpool:subscr:attach_lost");
8255 f_ctrs_msc_add(0, "mscpool:subscr:new");
8256 f_ctrs_msc_verify();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008257
8258 var MSC_ConnHdlr vc_conn2;
8259 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 1);
8260 pars2.mscpool.rsl_idx := 1;
8261 /* An NRI that is assigned to an unconnected MSC */
8262 pars2.mscpool.l3_info := valueof(ts_ML3_MO_MM_IMSI_DET_Ind(valueof(ts_MI_TMSI_NRI_LV(767))));
8263 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8264 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008265 f_ctrs_msc_add(2, "mscpool:subscr:attach_lost");
8266 f_ctrs_msc_add(1, "mscpool:subscr:new");
8267 f_ctrs_msc_verify();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008268
8269 /* Test round-robin wrap to the first MSC */
8270 var MSC_ConnHdlr vc_conn3;
8271 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 0);
8272 pars3.mscpool.rsl_idx := 2;
8273 /* An NRI that is assigned to an unconnected MSC */
8274 pars3.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(750)), '00F110'O));
8275 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8276 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008277 f_ctrs_msc_add(2, "mscpool:subscr:attach_lost");
8278 f_ctrs_msc_add(0, "mscpool:subscr:new");
8279 f_ctrs_msc_verify();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008280 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008281}
8282
8283/* Three Layer 3 Complete by TMSI with valid NRI for the second MSC are all directed to the second MSC (configured in
8284 * osmo-bsc.cfg). */
8285/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8286 * just as well using only RSL. */
8287testcase TC_mscpool_L3Complete_by_tmsi_valid_nri_1() runs on test_CT {
8288
8289 f_init(nr_bts := 3, handler_mode := true, nr_msc := 2);
8290 f_sleep(1.0);
8291
8292 /* All TMSIs in this test point at the second MSC, set the round robin to point at the first MSC to make sure
8293 * this is not using round-robin. */
8294 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
8295
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008296 f_ctrs_msc_init();
8297
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008298 var MSC_ConnHdlr vc_conn1;
8299 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 1);
8300 pars1.mscpool.rsl_idx := 0;
8301 /* An NRI of the second MSC's range (256-511) */
8302 pars1.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_SMS, valueof(ts_MI_TMSI_NRI_LV(256))));
8303 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8304 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008305 f_ctrs_msc_expect(1, "mscpool:subscr:known");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008306
8307 var MSC_ConnHdlr vc_conn2;
8308 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 1);
8309 pars2.mscpool.rsl_idx := 1;
8310 /* An NRI of the second MSC's range (256-511) */
8311 pars2.mscpool.l3_info := valueof(ts_PAG_RESP(valueof(ts_MI_TMSI_NRI_LV(260))));
8312 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8313 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008314 f_ctrs_msc_expect(1, "mscpool:subscr:known");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008315
8316 var MSC_ConnHdlr vc_conn3;
8317 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 1);
8318 pars3.mscpool.rsl_idx := 2;
8319 /* An NRI of the second MSC's range (256-511) */
8320 pars3.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(511)), '00F110'O));
8321 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8322 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008323 f_ctrs_msc_expect(1, "mscpool:subscr:known");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008324 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008325}
8326
8327/* Layer 3 Complete by TMSI with valid NRI for the third MSC are directed to the third MSC (configured in osmo-bsc.cfg),
8328 * while a round-robin remains unaffected by that. */
8329/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8330 * just as well using only RSL. */
8331testcase TC_mscpool_L3Complete_by_tmsi_valid_nri_2() runs on test_CT {
8332
8333 f_init(nr_bts := 3, handler_mode := true, nr_msc := 3);
8334 f_sleep(1.0);
8335
8336 /* All TMSIs in this test point at the third MSC, set the round robin to point at the second MSC to make sure
8337 * this is not using round-robin. */
8338 f_vty_transceive(BSCVTY, "mscpool roundrobin next 1");
8339
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008340 f_ctrs_msc_init();
8341
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008342 var MSC_ConnHdlr vc_conn1;
8343 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 2);
8344 pars1.mscpool.rsl_idx := 0;
8345 /* An NRI of the third MSC's range (512-767) */
8346 pars1.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_SMS, valueof(ts_MI_TMSI_NRI_LV(512))));
8347 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8348 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008349 f_ctrs_msc_expect(2, "mscpool:subscr:known");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008350
8351 var MSC_ConnHdlr vc_conn2;
8352 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 2);
8353 pars2.mscpool.rsl_idx := 1;
8354 /* An NRI of the third MSC's range (512-767) */
8355 pars2.mscpool.l3_info := valueof(ts_PAG_RESP(valueof(ts_MI_TMSI_NRI_LV(678))));
8356 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8357 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008358 f_ctrs_msc_expect(2, "mscpool:subscr:known");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008359
8360 /* The above forwardings to third MSC have not affected the round robin, which still points at the second MSC */
8361 var MSC_ConnHdlr vc_conn3;
8362 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 1);
8363 pars3.mscpool.rsl_idx := 2;
8364 pars3.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_IMSI_LV('001010000000013'H)), '00F110'O));
8365 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8366 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008367 f_ctrs_msc_expect(1, "mscpool:subscr:new");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008368 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008369}
8370
8371/* LU with a TMSI but indicating a different PLMN in its previous LAI: ignore the NRI. */
8372/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8373 * just as well using only RSL. */
8374testcase TC_mscpool_LU_by_tmsi_from_other_PLMN() runs on test_CT {
8375
8376 f_init(nr_bts := 3, handler_mode := true, nr_msc := 3);
8377 f_sleep(1.0);
8378
8379 /* The TMSIs in this test points at the second MSC, but since it is from a different PLMN, round-robin is used
8380 * instead, and hits msc 0. */
8381 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
8382
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008383 f_ctrs_msc_init();
8384
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008385 /* An NRI of the second MSC's range (256-511), but a PLMN that doesn't match with osmo-bsc.cfg */
8386 var MSC_ConnHdlr vc_conn1;
8387 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
8388 pars1.mscpool.rsl_idx := 0;
8389 pars1.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(260)), '99F999'O));
8390 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8391 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008392 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008393
8394 /* An NRI of the third MSC's range (512-767) and a matching PLMN gets directed by NRI. */
8395 var MSC_ConnHdlr vc_conn2;
8396 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 2);
8397 pars2.mscpool.rsl_idx := 1;
8398 pars2.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(555)), '00F110'O));
8399 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8400 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008401 f_ctrs_msc_expect(2, "mscpool:subscr:known");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008402 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008403}
8404
8405/* Make sure that whichever MSC paged a subscriber will also get the Paging Response. Page by IMSI, which would be
8406 * round-robined to another MSC, to make sure the Paging->Response relation is stronger than the NRI->MSC mapping. */
8407private function f_tc_mscpool_paging_imsi(charstring id) runs on MSC_ConnHdlr {
8408 var template BSSMAP_FIELD_CellIdentificationList cid_list := { cIl_CI := { ts_BSSMAP_CI_CI(0) } };
8409 //cid_list := { cIl_allInBSS := ''O };
8410 var RSL_ChanNeeded rsl_chneed := RSL_CHANNEED_SDCCH;
8411 var template BSSMAP_IE_ChannelNeeded bssmap_chneed := ts_BSSMAP_IE_ChanNeeded(int2bit(enum2int(valueof(rsl_chneed)),2));
8412 var BSSAP_N_UNITDATA_req paging;
8413 var hexstring imsi := '001010000000123'H;
8414
8415 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
8416
Neels Hofmeyr90f80962020-06-12 16:16:55 +02008417 paging := valueof(ts_BSSAP_UNITDATA_req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008418 valueof(ts_BSSMAP_Paging(imsi, cid_list, omit, bssmap_chneed))));
8419 BSSAP.send(paging);
8420
8421 /* Register any RSL conn so that the Paging Command gets received here. With the current RSL_Emulation's main()
8422 * handling of '[bts_role] IPA_PT.receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD()))' it doesn't matter at all which
8423 * channel number is picked here. */
8424 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(0, RSL_CHAN_NR_INVALID));
8425 f_rslem_register(0, new_chan_nr);
8426 RSL.receive(tr_RSL_PAGING_CMD(tr_MI_IMSI(imsi)));
8427 f_rslem_unregister(0, new_chan_nr);
8428
8429 /* Despite the round robin pointing at the second MSC ('roundrobin next 1'), the earlier Paging for the same IMSI
8430 * causes this Paging Response to go to the first MSC (bssap_idx := 0). */
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008431 f_perform_compl_l3(RSL, RSL_PROC, ts_PAG_RESP(valueof(ts_MI_IMSI_LV(imsi))) );
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008432 f_sleep(1.0);
8433}
8434testcase TC_mscpool_paging_and_response_imsi() runs on test_CT {
8435 f_init(nr_bts := 1, handler_mode := true, nr_msc := 3);
8436 f_sleep(1.0);
8437
8438 /* Testing a Paging on the first MSC to get a Paging Response back to the first MSC. Set round robin to the
8439 * second MSC to make sure we're getting the Paging logic, not a coincidental round robin match. */
8440 f_vty_transceive(BSCVTY, "mscpool roundrobin next 1");
8441
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008442 f_ctrs_msc_init();
8443
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008444 var MSC_ConnHdlr vc_conn1;
8445 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
8446 pars1.mscpool.rsl_idx := 0;
Neels Hofmeyr90f80962020-06-12 16:16:55 +02008447 pars1.sccp_addr_bsc := g_bssap[pars1.mscpool.bssap_idx].sccp_addr_peer;
8448 pars1.sccp_addr_msc := g_bssap[pars1.mscpool.bssap_idx].sccp_addr_own;
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008449 vc_conn1 := f_start_handler(refers(f_tc_mscpool_paging_imsi), pars1);
8450 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008451 f_ctrs_msc_expect(0, "mscpool:subscr:paged");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008452 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008453}
8454
8455/* Make sure that whichever MSC paged a subscriber will also get the Paging Response. Page by TMSI with an NRI value
8456 * that matches a different MSC, to make sure the Paging->Response relation is stronger than the NRI->MSC mapping. */
8457private function f_tc_mscpool_paging_tmsi(charstring id) runs on MSC_ConnHdlr {
8458 var template BSSMAP_FIELD_CellIdentificationList cid_list := { cIl_CI := { ts_BSSMAP_CI_CI(0) } };
8459 //cid_list := { cIl_allInBSS := ''O };
8460 var RSL_ChanNeeded rsl_chneed := RSL_CHANNEED_SDCCH;
8461 var template BSSMAP_IE_ChannelNeeded bssmap_chneed := ts_BSSMAP_IE_ChanNeeded(int2bit(enum2int(valueof(rsl_chneed)),2));
8462 var integer nri_v := 300; /* <-- second MSC's NRI */
Harald Weltebf397612021-01-14 20:39:46 +01008463 var octetstring tmsi := f_gen_tmsi(suffix := 0, nri_v := nri_v);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008464 var BSSAP_N_UNITDATA_req paging;
8465
8466 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
8467
Neels Hofmeyr90f80962020-06-12 16:16:55 +02008468 paging := valueof(ts_BSSAP_UNITDATA_req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008469 valueof(ts_BSSMAP_Paging('001010000000011'H, cid_list, tmsi, bssmap_chneed))));
8470 BSSAP.send(paging);
8471
8472 /* Register any RSL conn so that the Paging Command gets received here. With the current RSL_Emulation's main()
8473 * handling of '[bts_role] IPA_PT.receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD()))' it doesn't matter at all which
8474 * channel number is picked here. */
8475 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(0, RSL_CHAN_NR_INVALID));
8476 f_rslem_register(0, new_chan_nr);
8477 RSL.receive(tr_RSL_PAGING_CMD(t_MI_TMSI(tmsi)));
8478 f_rslem_unregister(0, new_chan_nr);
8479
8480 /* Despite the NRI matching the second MSC (NRI from 'msc 1' in osmo-bsc.cfg) and round robin pointing at the
8481 * third MSC ('roundrobin next 2'), the earlier Paging for the same TMSI causes this Paging Response to go to
8482 * the first MSC (bssap_idx := 0). */
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008483 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 +02008484 f_sleep(1.0);
8485}
8486testcase TC_mscpool_paging_and_response_tmsi() runs on test_CT {
8487 f_init(nr_bts := 1, handler_mode := true, nr_msc := 3);
8488 f_sleep(1.0);
8489
8490 /* Testing a Paging on the first MSC to get a Paging Response back to the first MSC. Set round robin to the
8491 * third MSC to make sure we're getting the Paging logic, not a coincidental round robin match. */
8492 f_vty_transceive(BSCVTY, "mscpool roundrobin next 2");
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;
Neels Hofmeyr90f80962020-06-12 16:16:55 +02008499 pars1.sccp_addr_bsc := g_bssap[pars1.mscpool.bssap_idx].sccp_addr_peer;
8500 pars1.sccp_addr_msc := g_bssap[pars1.mscpool.bssap_idx].sccp_addr_own;
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008501 vc_conn1 := f_start_handler(refers(f_tc_mscpool_paging_tmsi), pars1);
8502 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008503 f_ctrs_msc_expect(0, "mscpool:subscr:paged");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008504 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008505}
8506
8507/* For round-robin, skip an MSC that has 'no allow-attach' set. */
8508/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8509 * just as well using only RSL. */
8510testcase TC_mscpool_no_allow_attach_round_robin() runs on test_CT {
8511
8512 f_init(nr_bts := 3, handler_mode := true, nr_msc := 3);
8513 f_sleep(1.0);
Neels Hofmeyra460f1f2020-08-09 20:17:03 +00008514 /* Mark the second MSC as offloading, round-robin should skip this MSC now. */
8515 f_vty_msc_allow_attach(BSCVTY, {true, false, true});
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008516
8517 /* Control which MSC gets chosen next by the round-robin, otherwise
8518 * would be randomly affected by which other tests ran before this. */
8519 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
8520
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008521 f_ctrs_msc_init();
8522
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008523 var MSC_ConnHdlr vc_conn1;
8524 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
8525 pars1.mscpool.rsl_idx := 0;
8526 pars1.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_IMSI_LV('001010000000001'H)), '00F110'O));
8527 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8528 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008529 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008530
8531 var MSC_ConnHdlr vc_conn2;
8532 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 2);
8533 pars2.mscpool.rsl_idx := 1;
8534 pars2.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, valueof(ts_MI_IMSI_LV('001010000000002'H))));
8535 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8536 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008537 f_ctrs_msc_expect(2, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008538
8539 var MSC_ConnHdlr vc_conn3;
8540 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 0);
8541 pars3.mscpool.rsl_idx := 2;
8542 pars3.mscpool.l3_info := valueof(ts_PAG_RESP(valueof(ts_MI_IMSI_LV('001010000000003'H))));
8543 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8544 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008545 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008546 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008547}
8548
8549/* An MSC that has 'no allow-attach' set should still serve subscribers that are already attached according to their
8550 * TMSI NRI. */
8551testcase TC_mscpool_no_allow_attach_valid_nri() runs on test_CT {
8552
8553 f_init(nr_bts := 3, handler_mode := true, nr_msc := 3);
8554 f_sleep(1.0);
8555
Neels Hofmeyra460f1f2020-08-09 20:17:03 +00008556 /* Mark the second MSC as offloading, round-robin should skip this MSC now. */
8557 f_vty_msc_allow_attach(BSCVTY, {true, false, true});
8558
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008559 /* Control which MSC gets chosen next by the round-robin, otherwise
8560 * would be randomly affected by which other tests ran before this. */
8561 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
8562
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008563 f_ctrs_msc_init();
8564
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008565 /* Round robin points at msc 0, but the valid NRI directs to msc 1, even though msc 1 has 'no allow-attach'. */
8566 var MSC_ConnHdlr vc_conn1;
8567 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 1);
8568 pars1.mscpool.rsl_idx := 0;
8569 /* An NRI of the second MSC's range (256-511) */
8570 pars1.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, valueof(ts_MI_TMSI_NRI_LV(260))));
8571 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8572 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008573 f_ctrs_msc_expect(1, "mscpool:subscr:known");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008574
8575 var MSC_ConnHdlr vc_conn2;
8576 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 0);
8577 pars2.mscpool.rsl_idx := 1;
8578 pars2.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, valueof(ts_MI_IMSI_LV('001010000000002'H))));
8579 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8580 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008581 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008582
8583 var MSC_ConnHdlr vc_conn3;
8584 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 2);
8585 pars3.mscpool.rsl_idx := 2;
8586 pars3.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, valueof(ts_MI_IMSI_LV('001010000000003'H))));
8587 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8588 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008589 f_ctrs_msc_expect(2, "mscpool:subscr:new");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008590 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008591}
8592
Philipp Maier783681c2020-07-16 16:47:06 +02008593/* Allow/Deny emergency calls globally via VTY */
8594private function f_vty_allow_emerg_msc(boolean allow) runs on test_CT {
8595 f_vty_enter_cfg_msc(BSCVTY, 0);
8596 if (allow) {
8597 f_vty_transceive(BSCVTY, "allow-emergency allow");
8598 } else {
8599 f_vty_transceive(BSCVTY, "allow-emergency deny");
8600 }
8601 f_vty_transceive(BSCVTY, "exit");
8602 f_vty_transceive(BSCVTY, "exit");
8603}
8604
8605/* Allow/Deny emergency calls per BTS via VTY */
8606private function f_vty_allow_emerg_bts(boolean allow, integer bts_nr) runs on test_CT {
8607 f_vty_enter_cfg_bts(BSCVTY, bts_nr);
8608 if (allow) {
8609 f_vty_transceive(BSCVTY, "rach emergency call allowed 1");
8610 } else {
8611 f_vty_transceive(BSCVTY, "rach emergency call allowed 0");
8612 }
8613 f_vty_transceive(BSCVTY, "exit");
8614 f_vty_transceive(BSCVTY, "exit");
Neels Hofmeyrb6ed80c2020-10-12 22:52:39 +00008615 f_vty_transceive(BSCVTY, "exit");
Philipp Maier783681c2020-07-16 16:47:06 +02008616}
8617
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02008618/* Allow/Forbid Fast Return after SRVCC on a given BTS via VTY */
8619private function f_vty_allow_srvcc_fast_return(boolean allow, integer bts_nr) runs on test_CT {
8620 f_vty_enter_cfg_bts(BSCVTY, bts_nr);
8621 if (allow) {
8622 f_vty_transceive(BSCVTY, "srvcc fast-return allow");
8623 } else {
8624 f_vty_transceive(BSCVTY, "srvcc fast-return forbid");
8625 }
8626 f_vty_transceive(BSCVTY, "exit");
8627 f_vty_transceive(BSCVTY, "exit");
8628 f_vty_transceive(BSCVTY, "exit");
8629}
8630
Pau Espin Pedrol14475352021-07-22 15:48:16 +02008631/* Allow/Forbid TCH for signalling if SDCCH exhausted on a given BTS via VTY */
8632private function f_vty_allow_tch_for_signalling(boolean allow, integer bts_nr) runs on test_CT {
8633 f_vty_enter_cfg_bts(BSCVTY, bts_nr);
8634 if (allow) {
8635 f_vty_transceive(BSCVTY, "channel allocator allow-tch-for-signalling 1");
8636 } else {
8637 f_vty_transceive(BSCVTY, "channel allocator allow-tch-for-signalling 0");
8638 }
8639 f_vty_transceive(BSCVTY, "exit");
8640 f_vty_transceive(BSCVTY, "exit");
8641 f_vty_transceive(BSCVTY, "exit");
8642}
8643
Philipp Maier783681c2020-07-16 16:47:06 +02008644/* Begin assignmet procedure and send an EMERGENCY SETUP (RR) */
8645private function f_assignment_emerg_setup() runs on MSC_ConnHdlr {
8646 var PDU_ML3_MS_NW emerg_setup;
8647 var octetstring emerg_setup_enc;
8648 var RSL_Message emerg_setup_data_ind;
8649
8650 f_establish_fully(omit, omit);
8651
8652 emerg_setup := valueof(ts_ML3_MO_CC_EMERG_SETUP(1, valueof(ts_Bcap_voice)));
8653 emerg_setup_enc := enc_PDU_ML3_MS_NW(emerg_setup);
8654 emerg_setup_data_ind := valueof(ts_RSL_DATA_IND(g_chan_nr, valueof(ts_RslLinkID_DCCH(0)), emerg_setup_enc));
8655
8656 RSL.send(emerg_setup_data_ind);
8657}
8658
8659/* Test if the EMERGENCY SETUP gets passed on to the MSC via A when EMERGENCY
8660 * CALLS are permitted by the BSC config. */
8661private function f_TC_assignment_emerg_setup_allow(charstring id) runs on MSC_ConnHdlr {
8662 var PDU_BSSAP emerg_setup_data_ind_bssap;
8663 var PDU_ML3_MS_NW emerg_setup;
8664 timer T := 3.0;
8665
8666 f_assignment_emerg_setup()
8667
8668 T.start;
8669 alt {
8670 [] BSSAP.receive(tr_BSSAP_DTAP) -> value emerg_setup_data_ind_bssap {
8671 emerg_setup := dec_PDU_ML3_MS_NW(emerg_setup_data_ind_bssap.pdu.dtap);
8672 if (not isbound(emerg_setup.msgs.cc.emergencySetup)) {
8673 setverdict(fail, "no emergency setup");
8674 }
8675 }
8676 [] BSSAP.receive {
8677 setverdict(fail, "unexpected BSSAP message!");
8678 }
8679 [] T.timeout {
8680 setverdict(fail, "timout waiting for EMERGENCY SETUP!");
8681 }
8682 }
8683
8684 setverdict(pass);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008685 f_perform_clear();
Philipp Maier783681c2020-07-16 16:47:06 +02008686}
8687
8688/* Test if the EMERGENCY SETUP gets blocked by the BSC if EMERGENCY CALLS are
8689 * forbidden by the BSC config. */
8690private function f_TC_assignment_emerg_setup_deny(charstring id) runs on MSC_ConnHdlr {
8691 var PDU_BSSAP emerg_setup_data_ind_bssap;
8692 timer T := 3.0;
8693
8694 f_assignment_emerg_setup()
8695
8696 T.start;
8697 alt {
8698 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_RELEASE)) {
8699 setverdict(pass);
8700 }
8701 [] RSL.receive {
8702 setverdict(fail, "unexpected RSL message!");
8703 }
8704 [] T.timeout {
8705 setverdict(fail, "timout waiting for RR CHANNEL RELEASE!");
8706 }
8707 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01008708 BSSAP.receive(tr_BSSMAP_ClearRequest);
8709 f_perform_clear();
Philipp Maier783681c2020-07-16 16:47:06 +02008710}
8711
8712/* EMERGENCY CALL situation #1, allowed globally and by BTS */
8713testcase TC_assignment_emerg_setup_allow() runs on test_CT {
8714 var TestHdlrParams pars := f_gen_test_hdlr_pars();
8715 var MSC_ConnHdlr vc_conn;
8716
8717 f_init(1, true);
8718 f_sleep(1.0);
8719
8720 f_vty_allow_emerg_msc(true);
8721 f_vty_allow_emerg_bts(true, 0);
8722 vc_conn := f_start_handler(refers(f_TC_assignment_emerg_setup_allow), pars);
8723 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008724 f_shutdown_helper();
Philipp Maier783681c2020-07-16 16:47:06 +02008725}
8726
8727/* EMERGENCY CALL situation #2, forbidden globally but allowed by BTS */
8728testcase TC_assignment_emerg_setup_deny_msc() runs on test_CT {
8729 var TestHdlrParams pars := f_gen_test_hdlr_pars();
8730 var MSC_ConnHdlr vc_conn;
8731
8732 f_init(1, true);
8733 f_sleep(1.0);
8734
8735 f_vty_allow_emerg_msc(false);
8736 f_vty_allow_emerg_bts(true, 0);
8737 vc_conn := f_start_handler(refers(f_TC_assignment_emerg_setup_deny), pars);
8738 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008739 f_shutdown_helper();
Philipp Maier783681c2020-07-16 16:47:06 +02008740}
8741
8742/* EMERGENCY CALL situation #3, allowed globally but forbidden by BTS */
8743testcase TC_assignment_emerg_setup_deny_bts() runs on test_CT {
8744 var TestHdlrParams pars := f_gen_test_hdlr_pars();
8745 var MSC_ConnHdlr vc_conn;
8746
8747 /* Note: This simulates a spec violation by the MS, correct MS
8748 * implementations would not try to establish an emergency call because
8749 * the system information tells in advance that emergency calls are
8750 * not forbidden */
8751
8752 f_init(1, true);
8753 f_sleep(1.0);
8754
8755 f_vty_allow_emerg_msc(true);
8756 f_vty_allow_emerg_bts(false, 0);
8757 vc_conn := f_start_handler(refers(f_TC_assignment_emerg_setup_deny), pars);
8758 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008759 f_shutdown_helper();
Philipp Maier783681c2020-07-16 16:47:06 +02008760}
8761
Philipp Maier82812002020-08-13 18:48:27 +02008762/* Test what happens when an emergency call arrives while all TCH channels are
8763 * busy, the BSC is expected to terminate one call in favor of the incoming
8764 * emergency call */
8765testcase TC_emerg_premption() runs on test_CT {
8766 var ASP_RSL_Unitdata rsl_ud;
8767 var integer i;
8768 var integer chreq_total, chreq_nochan;
8769 var RSL_Message rx_rsl;
8770 var RslChannelNr chan_nr;
8771
8772 f_init(1);
8773 f_sleep(1.0);
8774
8775 f_vty_allow_emerg_msc(true);
8776 f_vty_allow_emerg_bts(true, 0);
8777
8778 /* Fill up all channels on the BTS */
8779 chreq_total := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:total");
8780 chreq_nochan := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:no_channel");
8781 for (i := 0; i < NUM_TCHF_PER_BTS + NUM_TCHH_PER_BTS + NUM_SDCCH_PER_BTS; i := i+1) {
8782 chan_nr := f_chreq_act_ack('33'O, i);
8783 }
8784 IPA_RSL[0].clear;
8785 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:total",
8786 chreq_total + NUM_TCHF_PER_BTS + NUM_TCHH_PER_BTS + NUM_SDCCH_PER_BTS);
8787
8788 /* Send Channel request for emegergency call */
8789 f_ipa_tx(0, ts_RSL_CHAN_RQD('A5'O, 23));
8790
8791 /* Expect the BSC to release one (the first) TCH/F on the BTS */
8792 chan_nr := valueof(t_RslChanNr_Bm(1));
8793 f_expect_chan_rel(0, chan_nr, expect_rr_chan_rel := false, expect_rll_rel_req := false);
8794
8795 /* Expect the BSC to send activate/assign the a channel for the emergency call */
8796 rx_rsl := f_exp_ipa_rx(0, tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
8797 chan_nr := rx_rsl.ies[0].body.chan_nr;
8798 f_ipa_tx(0, ts_RSL_CHAN_ACT_ACK(chan_nr, 33));
8799 rx_rsl := f_exp_ipa_rx(0, tr_RSL_IMM_ASSIGN(0));
Philipp Maier104f4c02020-09-11 18:12:18 +02008800
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008801 f_shutdown_helper();
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07008802}
8803
8804/* Hopping parameters per a timeslot */
Vadim Yanitskiybc6654a2020-09-13 01:27:40 +07008805private type record length(0..64) of GsmArfcn ArfcnList;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07008806private type record FHParamsTs {
8807 boolean enabled,
8808 uint6_t hsn,
8809 uint6_t maio,
8810 ArfcnList ma
8811};
8812
8813/* Hopping parameters per a transceiver */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07008814private type record FHParamsTrx {
Philipp Maier798d8952021-10-19 14:43:19 +02008815 GsmBandArfcn arfcn,
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07008816 FHParamsTs ts[8]
8817};
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07008818
8819/* Randomly generate the hopping parameters for the given timeslot numbers */
8820private function f_TC_fh_params_gen(template integer tr_tn := (1, 3, 5))
8821runs on test_CT return FHParamsTrx {
8822 var FHParamsTrx fhp;
8823
Philipp Maier798d8952021-10-19 14:43:19 +02008824 /* Generate a random ARFCN in the range of 0 - 3. This ARFCN will
8825 * fall in the GSM900 band. */
8826 fhp.arfcn.arfcn := f_rnd_int(3);
8827 fhp.arfcn.pcs := false;
Vadim Yanitskiye7c8c6e2020-09-13 14:33:03 +07008828
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07008829 for (var integer tn := 0; tn < 8; tn := tn + 1) {
8830 if (not match(tn, tr_tn)) {
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07008831 fhp.ts[tn].enabled := false;
8832 fhp.ts[tn].ma := { };
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07008833 continue;
8834 }
8835
8836 /* Random HSN / MAIO values: 0..63 */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07008837 fhp.ts[tn].hsn := f_rnd_int(64);
8838 fhp.ts[tn].maio := f_rnd_int(64);
8839 fhp.ts[tn].ma := { };
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07008840
8841 /* Random Mobile Allocation (hopping channels) */
8842 var integer ma_len := 2 + f_rnd_int(9); /* 2..10 channels */
8843 var integer step := 3 + f_rnd_int(4); /* 3..6 stepping */
8844 for (var integer i := 1; i <= ma_len; i := i + 1) {
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07008845 fhp.ts[tn].ma := fhp.ts[tn].ma & { i * step };
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07008846 }
8847
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07008848 fhp.ts[tn].enabled := true;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07008849 }
8850
8851 log("f_TC_fh_params_gen(): ", fhp);
8852 return fhp;
8853}
8854
8855/* Make sure that the given Channel Description IE matches the hopping configuration */
8856private function f_TC_fh_params_match_chan_desc(in FHParamsTrx fhp, in ChannelDescription cd)
8857{
8858 var template (present) ChannelDescription tr_cd;
8859 var template (present) MaioHsn tr_maio_hsn;
8860 var uint3_t tn := cd.chan_nr.tn;
8861
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07008862 if (fhp.ts[tn].enabled) {
8863 tr_maio_hsn := tr_HsnMaio(fhp.ts[tn].hsn, fhp.ts[tn].maio);
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07008864 tr_cd := tr_ChanDescH1(cd.chan_nr, tr_maio_hsn);
8865 } else {
Philipp Maier798d8952021-10-19 14:43:19 +02008866 tr_cd := tr_ChanDescH0(cd.chan_nr, fhp.arfcn.arfcn);
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07008867 }
8868
8869 if (not match(cd, tr_cd)) {
8870 setverdict(fail, "Channel Description IE does not match: ",
8871 cd, " vs expected ", tr_cd);
8872 }
8873}
8874
8875/* Make sure that the given Mobile Allocation IE matches the hopping configuration */
8876private function f_TC_fh_params_match_ma(in FHParamsTrx fhp, uint3_t tn,
8877 in MobileAllocationLV ma)
8878{
8879 var template MobileAllocationLV tr_ma := f_TC_fh_params_gen_tr_ma(fhp, tn, ma);
8880
8881 if (not match(ma, tr_ma)) {
8882 setverdict(fail, "Mobile Allocation IE does not match (tn := ",
8883 tn, "): ", ma, " vs expected: ", tr_ma);
8884 } else {
8885 setverdict(pass);
8886 }
8887}
8888
8889private function f_TC_fh_params_gen_tr_ma(in FHParamsTrx fhp, uint3_t tn,
8890 in MobileAllocationLV ma)
8891return template MobileAllocationLV {
8892 /* Mobile Allocation IE is expected to be empty if hopping is not enabled */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07008893 if (not fhp.ts[tn].enabled) {
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07008894 return { len := 0, ma := ''B };
8895 }
8896
8897 var bitstring full_mask := f_pad_bit(''B, 1024, '0'B);
8898 var bitstring slot_mask := f_pad_bit(''B, 1024, '0'B);
8899 var bitstring ma_mask := ''B;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07008900
8901 /* Compose the full bit-mask (all channels, up to 1024 entries) */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07008902 for (var integer i := 0; i < lengthof(fhp.ts); i := i + 1) {
8903 for (var integer j := 0; j < lengthof(fhp.ts[i].ma); j := j + 1) {
8904 if (full_mask[fhp.ts[i].ma[j]] == '1'B)
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07008905 { continue; }
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07008906 full_mask[fhp.ts[i].ma[j]] := '1'B;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07008907 }
8908 }
8909
Vadim Yanitskiye7c8c6e2020-09-13 14:33:03 +07008910 /* Take ARFCN of the TRX itself into account */
Philipp Maier798d8952021-10-19 14:43:19 +02008911 full_mask[fhp.arfcn.arfcn] := '1'B;
Vadim Yanitskiye7c8c6e2020-09-13 14:33:03 +07008912
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07008913 /* Compose a bit-mask for the given timeslot number */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07008914 for (var integer i := 0; i < lengthof(fhp.ts[tn].ma); i := i + 1) {
8915 slot_mask[fhp.ts[tn].ma[i]] := '1'B;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07008916 }
8917
8918 /* Finally, compose the Mobile Allocation bit-mask */
Vadim Yanitskiy3e997362020-09-05 21:08:34 +07008919 for (var integer i := 1; i < lengthof(full_mask); i := i + 1) {
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07008920 if (full_mask[i] != '1'B)
8921 { continue; }
8922
8923 /* FIXME: ma_mask := ma_mask & slot_mask[i]; // triggers a bug in TITAN */
8924 if (slot_mask[i] == '1'B) {
8925 ma_mask := ma_mask & '1'B;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07008926 } else {
8927 ma_mask := ma_mask & '0'B;
8928 }
8929 }
8930
Vadim Yanitskiy3e997362020-09-05 21:08:34 +07008931 /* ARFCN 0 (if present) goes to the last position of the bit-mask */
8932 if (full_mask[0] == '1'B) {
8933 /* FIXME: ma_mask := ma_mask & slot_mask[0]; // triggers a bug in TITAN */
8934 if (slot_mask[0] == '1'B) {
8935 ma_mask := ma_mask & '1'B;
8936 } else {
8937 ma_mask := ma_mask & '0'B;
8938 }
8939 }
8940
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07008941 /* Ensure that ma_mask is octet-aligned */
Vadim Yanitskiy2aa02522020-09-06 14:05:23 +07008942 var integer ma_mask_len := (lengthof(ma_mask) + 8 - 1) / 8;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07008943 ma_mask := f_pad_bit(ma_mask, ma_mask_len * 8, '0'B);
8944
8945 return { len := ma_mask_len, ma := ma_mask };
8946}
8947
Philipp Maier798d8952021-10-19 14:43:19 +02008948/* Configure the appropriate band for a given arfcn, exc */
8949private function f_TC_set_band_by_arfcn(integer bts_nr, GsmBandArfcn arfcn) runs on test_CT
8950{
8951 var charstring band;
8952 var GsmBandArfcn arfcn_ := valueof(ts_GsmBandArfcn(arfcn.arfcn, arfcn.pcs, false));
8953
8954 select (arfcn_) {
8955 case (tr_GsmBandArfcn((259..293), false, ?)) { band := "GSM450"; }
8956 case (tr_GsmBandArfcn((306..340), false, ?)) { band := "GSM480"; }
8957 case (tr_GsmBandArfcn((438..511), false, ?)) { band := "GSM750"; }
8958 case (tr_GsmBandArfcn((128..251), false, ?)) { band := "GSM850"; }
8959 case (tr_GsmBandArfcn((0..124), false, ?)) { band := "GSM900"; }
8960 case (tr_GsmBandArfcn((955..1023), false, ?)) { band := "GSM900"; }
8961 case (tr_GsmBandArfcn((512..885), false, ?)) { band := "DCS1800"; }
8962 case (tr_GsmBandArfcn((512..810), true, ?)) { band := "PCS1900"; }
8963 case else { return; }
8964 }
8965
8966 f_vty_enter_cfg_bts(BSCVTY, bts_nr);
8967 f_vty_transceive(BSCVTY, "band " & band);
8968 f_vty_transceive(BSCVTY, "end");
8969}
8970
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07008971/* Configure the hopping parameters in accordance with the given record */
8972private function f_TC_fh_params_set(in FHParamsTrx fhp,
8973 uint8_t bts_nr := 0,
8974 uint8_t trx_nr := 0)
8975runs on test_CT {
Philipp Maier798d8952021-10-19 14:43:19 +02008976
8977 f_TC_set_band_by_arfcn(bts_nr, fhp.arfcn);
8978
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07008979 /* Enter the configuration node for the given BTS/TRX numbers */
8980 f_vty_enter_cfg_trx(BSCVTY, bts_nr, trx_nr);
8981
Philipp Maier798d8952021-10-19 14:43:19 +02008982 f_vty_transceive(BSCVTY, "arfcn " & int2str(fhp.arfcn.arfcn));
Vadim Yanitskiye7c8c6e2020-09-13 14:33:03 +07008983
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07008984 for (var integer tn := 0; tn < lengthof(fhp.ts); tn := tn + 1) {
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07008985 f_vty_transceive(BSCVTY, "timeslot " & int2str(tn));
8986
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07008987 if (not fhp.ts[tn].enabled) {
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07008988 f_vty_transceive(BSCVTY, "hopping enabled 0");
8989 f_vty_transceive(BSCVTY, "exit"); /* go back */
8990 continue;
8991 }
8992
8993 /* Configure HSN / MAIO values */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07008994 f_vty_transceive(BSCVTY, "hopping sequence-number " & int2str(fhp.ts[tn].hsn));
8995 f_vty_transceive(BSCVTY, "hopping maio " & int2str(fhp.ts[tn].maio));
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07008996
8997 /* Configure the Mobile Allocation (hopping channels) */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07008998 for (var integer i := 0; i < lengthof(fhp.ts[tn].ma); i := i + 1) {
8999 f_vty_transceive(BSCVTY, "hopping arfcn add " & int2str(fhp.ts[tn].ma[i]));
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009000 }
9001
9002 f_vty_transceive(BSCVTY, "hopping enabled 1");
9003 f_vty_transceive(BSCVTY, "exit"); /* go back */
9004 }
9005
9006 f_vty_transceive(BSCVTY, "end");
9007}
9008
9009/* Disable frequency hopping on all timeslots */
9010private function f_TC_fh_params_unset(in FHParamsTrx fhp,
9011 uint8_t bts_nr := 0,
Vadim Yanitskiye7c8c6e2020-09-13 14:33:03 +07009012 uint8_t trx_nr := 0,
Philipp Maier798d8952021-10-19 14:43:19 +02009013 GsmBandArfcn arfcn := {pcs := false, arfcn := 871})
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009014runs on test_CT {
Philipp Maier798d8952021-10-19 14:43:19 +02009015
9016 f_TC_set_band_by_arfcn(bts_nr, arfcn);
9017
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009018 /* Enter the configuration node for the given BTS/TRX numbers */
9019 f_vty_enter_cfg_trx(BSCVTY, bts_nr, trx_nr);
9020
Philipp Maier798d8952021-10-19 14:43:19 +02009021 f_vty_transceive(BSCVTY, "arfcn " & int2str(arfcn.arfcn));
Vadim Yanitskiye7c8c6e2020-09-13 14:33:03 +07009022
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009023 for (var integer tn := 0; tn < lengthof(fhp.ts); tn := tn + 1) {
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009024 f_vty_transceive(BSCVTY, "timeslot " & int2str(tn));
9025
9026 /* Delete all ARFCNs from the Mobile Allocation (if any) */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07009027 for (var integer i := 0; i < lengthof(fhp.ts[tn].ma); i := i + 1) {
9028 f_vty_transceive(BSCVTY, "hopping arfcn del " & int2str(fhp.ts[tn].ma[i]));
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009029 }
9030
9031 f_vty_transceive(BSCVTY, "hopping enabled 0");
9032 f_vty_transceive(BSCVTY, "exit"); /* go back */
9033 }
9034
9035 f_vty_transceive(BSCVTY, "end");
9036 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
9037}
9038
9039/* Verify presence and correctness of the hopping parameters (HSN, MAIO)
9040 * in the Channel Identification IE of the RSL CHANnel ACTIVation message. */
9041testcase TC_fh_params_chan_activ() runs on test_CT {
9042 var FHParamsTrx fhp := f_TC_fh_params_gen();
9043 var RSL_Message rsl_msg;
9044 var RSL_IE_Body ie;
9045
9046 f_init_vty();
9047
9048 f_TC_fh_params_set(fhp); /* Enable frequency hopping */
9049 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
9050
9051 f_init(1);
9052
9053 /* CS domain: 3 (SDCCH/4+CBCH) + 4 (TCH/F) + 2 (TCH/H) channels available */
9054 for (var integer i := 0; i < 9; i := i + 1) {
9055 f_ipa_tx(0, ts_RSL_CHAN_RQD(f_rnd_ra_cs(), 23));
9056 rsl_msg := f_exp_ipa_rx(0, tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
9057
9058 /* Make sure that Channel Identification IE is present */
9059 if (not f_rsl_find_ie(rsl_msg, RSL_IE_CHAN_IDENT, ie)) {
9060 setverdict(fail, "RSL Channel Identification IE is absent");
9061 continue;
9062 }
9063
9064 /* Make sure that hopping parameters (HSN/MAIO) match */
9065 f_TC_fh_params_match_chan_desc(fhp, ie.chan_ident.ch_desc.v);
9066
9067 /* "Mobile Allocation shall be included but empty" - let's check this */
9068 if (ie.chan_ident.ma.v.len != 0) {
9069 setverdict(fail, "Mobile Allocation IE is not empty: ",
9070 ie.chan_ident.ma, ", despite it shall be");
9071 continue;
9072 }
9073 }
9074
9075 /* Disable frequency hopping */
9076 f_TC_fh_params_unset(fhp);
9077
Vadim Yanitskiy21726312020-09-04 01:45:36 +07009078 f_shutdown_helper();
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07009079}
9080
9081/* Verify the hopping parameters (HSN, MAIO, MA) in (RR) Immediate Assignment */
9082testcase TC_fh_params_imm_ass() runs on test_CT {
9083 var FHParamsTrx fhp := f_TC_fh_params_gen();
9084 var RSL_Message rsl_msg;
9085 var RSL_IE_Body ie;
9086
9087 f_init_vty();
9088
9089 f_TC_fh_params_set(fhp); /* Enable frequency hopping */
9090 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
9091
9092 f_init(1);
9093
9094 /* CS domain: 3 (SDCCH/4+CBCH) + 4 (TCH/F) + 2 (TCH/H) channels available */
9095 for (var integer i := 0; i < 9; i := i + 1) {
9096 f_ipa_tx(0, ts_RSL_CHAN_RQD(f_rnd_ra_cs(), 23));
9097 rsl_msg := f_exp_ipa_rx(0, tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
9098
9099 f_ipa_tx(0, ts_RSL_CHAN_ACT_ACK(rsl_msg.ies[0].body.chan_nr, 33));
9100 rsl_msg := f_exp_ipa_rx(0, tr_RSL_MsgTypeC(RSL_MT_IMMEDIATE_ASSIGN_CMD));
9101
9102 /* Make sure that Full Immediate Assign Info IE is present */
9103 if (not f_rsl_find_ie(rsl_msg, RSL_IE_FULL_IMM_ASS_INFO, ie)) {
9104 setverdict(fail, "RSL Full Immediate Assign Info IE is absent");
9105 continue;
9106 }
9107
9108 /* Decode the actual Immediate Assignment message */
9109 var GsmRrMessage rr_msg := dec_GsmRrMessage(ie.full_imm_ass_info.payload);
9110 if (not match(rr_msg.header, t_RrHeader(IMMEDIATE_ASSIGNMENT, ?))) {
9111 setverdict(fail, "Failed to match Immediate Assignment: ", rr_msg);
9112 continue;
9113 }
9114
9115 /* Make sure that hopping parameters (HSN/MAIO) match */
9116 f_TC_fh_params_match_chan_desc(fhp, rr_msg.payload.imm_ass.chan_desc);
9117
9118 /* Make sure that the Mobile Allocation IE matches */
9119 f_TC_fh_params_match_ma(fhp, rr_msg.payload.imm_ass.chan_desc.chan_nr.tn,
9120 rr_msg.payload.imm_ass.mobile_allocation);
9121 }
9122
9123 /* Disable frequency hopping */
9124 f_TC_fh_params_unset(fhp);
Philipp Maier82812002020-08-13 18:48:27 +02009125
Vadim Yanitskiy21726312020-09-04 01:45:36 +07009126 f_shutdown_helper();
Philipp Maier82812002020-08-13 18:48:27 +02009127}
9128
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +07009129/* Verify the hopping parameters (HSN, MAIO, MA) in (RR) Assignment Command */
9130testcase TC_fh_params_assignment_cmd() runs on test_CT {
9131 var FHParamsTrx fhp := f_TC_fh_params_gen();
9132 var RSL_Message rsl_msg;
9133 var RSL_IE_Body ie;
9134
9135 f_init_vty();
9136
9137 f_TC_fh_params_set(fhp); /* Enable frequency hopping */
9138 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
9139
9140 f_init(1);
9141
9142 /* HACK: work around "Couldn't find Expect for CRCX" */
9143 vc_MGCP.stop;
9144
9145 var template PDU_BSSAP ass_cmd := f_gen_ass_req();
9146 ass_cmd.pdu.bssmap.assignmentRequest.codecList := ts_BSSMAP_IE_CodecList({ts_CodecFR});
9147
9148 /* CS domain (TCH): 4 (TCH/F) + 2 (TCH/H) channels available
9149 * NOTE: only 3 SDCCH/4 channels are available on CCCH+SDCCH4+CBCH */
9150 for (var integer i := 0; i < 3; i := i + 1) {
9151 /* Establish a dedicated channel, so we can trigger (late) TCH assignment */
9152 var DchanTuple dt := f_est_dchan(f_rnd_ra_cs(), 23, f_rnd_octstring(16));
9153
9154 /* Send a BSSMAP Assignment Command, expect CHANnel ACTIVation */
9155 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ass_cmd));
9156 rsl_msg := f_exp_ipa_rx(0, tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
9157
9158 /* ACKnowledge CHANnel ACTIVation, expect RSL DATA REQuest */
9159 f_ipa_tx(0, ts_RSL_CHAN_ACT_ACK(rsl_msg.ies[0].body.chan_nr, 33));
9160 rsl_msg := f_exp_ipa_rx(0, tr_RSL_MsgTypeR(RSL_MT_DATA_REQ));
9161
9162 /* Make sure that L3 Information IE is present */
9163 if (not f_rsl_find_ie(rsl_msg, RSL_IE_L3_INFO, ie)) {
9164 setverdict(fail, "RSL L3 Information IE is absent");
9165 continue;
9166 }
9167
9168 /* Decode the L3 message and make sure it is (RR) Assignment Command */
9169 var GsmRrL3Message l3_msg := dec_GsmRrL3Message(ie.l3_info.payload);
9170 if (not match(l3_msg.header, t_RrL3Header(ASSIGNMENT_COMMAND))) {
9171 setverdict(fail, "Failed to match Assignment Command: ", l3_msg);
9172 continue;
9173 }
9174
9175 /* Make sure that hopping parameters (HSN/MAIO) match */
9176 var ChannelDescription chan_desc := l3_msg.payload.ass_cmd.chan_desc;
9177 f_TC_fh_params_match_chan_desc(fhp, chan_desc);
9178
9179 /* Make sure that Cell Channel Description IE is present if FH is enabled */
9180 if (chan_desc.h and not ispresent(l3_msg.payload.ass_cmd.cell_chan_desc)) {
Vadim Yanitskiy38d069d2020-09-02 17:18:57 +07009181 setverdict(fail, "FH enabled, but Cell Channel Description IE is absent");
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +07009182 continue;
9183 }
9184
9185 /* Make sure that the Mobile Allocation IE matches (if present) */
9186 var boolean ma_present := ispresent(l3_msg.payload.ass_cmd.mobile_allocation);
9187 if (chan_desc.h and ma_present) {
9188 f_TC_fh_params_match_ma(fhp, chan_desc.chan_nr.tn,
9189 l3_msg.payload.ass_cmd.mobile_allocation.v);
9190 } else if (chan_desc.h and not ma_present) {
9191 setverdict(fail, "FH enabled, but Mobile Allocation IE is absent");
9192 continue;
9193 } else if (not chan_desc.h and ma_present) {
9194 setverdict(fail, "FH disabled, but Mobile Allocation IE is present");
9195 continue;
9196 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01009197
9198 f_perform_clear_test_ct(dt);
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +07009199 }
9200
9201 /* Give the IUT some time to release all channels */
9202 f_sleep(3.0);
9203
9204 /* Disable frequency hopping */
9205 f_TC_fh_params_unset(fhp);
9206
Vadim Yanitskiy21726312020-09-04 01:45:36 +07009207 f_shutdown_helper();
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +07009208}
9209
Vadim Yanitskiy8f5430d2020-09-02 18:51:38 +07009210/* Verify the hopping parameters (HSN, MAIO, MA) in (RR) Handover Command */
9211private function f_TC_fh_params_handover_cmd(in FHParamsTrx fhp)
9212runs on test_CT {
9213 var RSL_Message rsl_msg;
9214 var RSL_IE_Body ie;
9215 var DchanTuple dt;
9216
9217 /* Establish a dedicated channel, so we can trigger handover */
9218 dt := f_est_dchan(f_rnd_ra_cs(), 23, f_rnd_octstring(16));
Vadim Yanitskiyc18ff472021-11-18 20:15:37 +03009219 f_sleep(0.5);
Vadim Yanitskiy8f5430d2020-09-02 18:51:38 +07009220
9221 /* Trigger handover from BTS0 to BTS1 */
9222 f_bts_0_cfg(BSCVTY, { "neighbor bts 1" });
9223 f_vty_handover(BSCVTY, 0, 0, dt.rsl_chan_nr, 1);
9224
9225 /* Expect RSL CHANnel ACTIVation on BTS1/TRX0/TS1 */
9226 rsl_msg := f_exp_ipa_rx(1, tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
9227
9228 /* ACKnowledge channel activation and expect (RR) Handover Command */
9229 f_ipa_tx(1, ts_RSL_CHAN_ACT_ACK(rsl_msg.ies[0].body.chan_nr, 33));
9230 rsl_msg := f_exp_ipa_rx(0, tr_RSL_MsgTypeR(RSL_MT_DATA_REQ));
9231
9232 /* Make sure that L3 Information IE is present */
9233 if (not f_rsl_find_ie(rsl_msg, RSL_IE_L3_INFO, ie)) {
9234 setverdict(fail, "RSL L3 Information IE is absent");
9235 return;
9236 }
9237
9238 /* Decode the L3 message and make sure it is (RR) Handover Command */
9239 var GsmRrL3Message l3_msg := dec_GsmRrL3Message(ie.l3_info.payload);
9240 if (not match(l3_msg.header, t_RrL3Header(HANDOVER_COMMAND))) {
9241 setverdict(fail, "Failed to match Handover Command: ", l3_msg);
9242 return;
9243 }
9244
9245 /* Make sure that we've got SDCCH/8 on TS1 (expected to be hopping) */
9246 var ChannelDescription chan_desc := l3_msg.payload.ho_cmd.chan_desc;
9247 if (not match(chan_desc.chan_nr, t_RslChanNr_SDCCH8(1, ?))) {
9248 setverdict(fail, "Unexpected channel number: ", chan_desc.chan_nr);
9249 return;
9250 }
9251
9252 /* Make sure that hopping parameters (HSN/MAIO) match */
9253 f_TC_fh_params_match_chan_desc(fhp, chan_desc);
9254
9255 /* Make sure that Cell Channel Description IE is present */
9256 if (not ispresent(l3_msg.payload.ho_cmd.cell_chan_desc)) {
9257 setverdict(fail, "FH enabled, but Cell Channel Description IE is absent");
9258 return;
9259 }
9260
9261 /* Make sure that the Mobile Allocation (after time) IE is present and matches */
9262 var boolean ma_present := ispresent(l3_msg.payload.ho_cmd.mobile_allocation);
9263 if (ma_present) {
9264 f_TC_fh_params_match_ma(fhp, chan_desc.chan_nr.tn,
9265 l3_msg.payload.ho_cmd.mobile_allocation.v);
9266 } else {
9267 setverdict(fail, "FH enabled, but Mobile Allocation IE is absent");
9268 return;
9269 }
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +01009270
9271 f_perform_clear_test_ct(dt);
Vadim Yanitskiy8f5430d2020-09-02 18:51:38 +07009272}
9273testcase TC_fh_params_handover_cmd() runs on test_CT {
9274 var FHParamsTrx fhp := f_TC_fh_params_gen();
9275
9276 f_init_vty();
9277
9278 /* (Re)configure TS0 as BCCH and TS1 as SDCCH8 on BTS1/TRX0 */
9279 f_vty_enter_cfg_trx(BSCVTY, bts := 1, trx := 0);
9280
9281 f_vty_transceive(BSCVTY, "timeslot 0");
9282 f_vty_transceive(BSCVTY, "phys_chan_config ccch");
9283 f_vty_transceive(BSCVTY, "exit"); /* go back */
9284
9285 f_vty_transceive(BSCVTY, "timeslot 1");
9286 f_vty_transceive(BSCVTY, "phys_chan_config sdcch8");
9287 f_vty_transceive(BSCVTY, "end"); /* we're done */
9288
9289 f_TC_fh_params_set(fhp, 1); /* Enable frequency hopping on BTS1 */
9290 f_vty_transceive(BSCVTY, "drop bts connection 1 oml");
9291
9292 f_init(2);
9293
9294 f_TC_fh_params_handover_cmd(fhp);
9295
9296 /* Disable frequency hopping on BTS1 */
9297 f_TC_fh_params_unset(fhp, 1);
9298
9299 /* (Re)configure TS0 as CCCH+SDCCH4+CBCH and TS1 as TCH/F */
9300 f_vty_enter_cfg_trx(BSCVTY, bts := 1, trx := 0);
9301
9302 f_vty_transceive(BSCVTY, "timeslot 0");
9303 f_vty_transceive(BSCVTY, "phys_chan_config ccch+sdcch4+cbch");
9304 f_vty_transceive(BSCVTY, "exit"); /* go back */
9305
9306 f_vty_transceive(BSCVTY, "timeslot 1");
9307 f_vty_transceive(BSCVTY, "phys_chan_config tch/f");
9308 f_vty_transceive(BSCVTY, "end"); /* we're done */
9309
9310 f_shutdown_helper();
9311}
9312
Vadim Yanitskiyca974032020-09-01 07:20:39 +07009313/* Verify the hopping parameters in System Information Type 4 */
9314testcase TC_fh_params_si4_cbch() runs on test_CT {
9315 var FHParamsTrx fhp := f_TC_fh_params_gen(tr_tn := 1);
9316 var ASP_RSL_Unitdata rx_rsl_ud;
9317 timer T := 5.0;
9318
9319 f_init_vty();
9320
9321 /* (Re)configure TS0 as BCCH and TS1 as SDCCH8+CBCH */
9322 f_vty_enter_cfg_trx(BSCVTY, trx := 0);
9323
9324 f_vty_transceive(BSCVTY, "timeslot 0");
9325 f_vty_transceive(BSCVTY, "phys_chan_config ccch");
9326 f_vty_transceive(BSCVTY, "exit"); /* go back */
9327
9328 f_vty_transceive(BSCVTY, "timeslot 1");
9329 f_vty_transceive(BSCVTY, "phys_chan_config sdcch8+cbch");
9330 f_vty_transceive(BSCVTY, "end"); /* we're done */
9331
9332 f_TC_fh_params_set(fhp); /* Enable frequency hopping */
9333 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
9334
9335 f_init(1);
9336
9337 T.start;
9338 alt {
9339 [] IPA_RSL[0].receive(tr_ASP_RSL_UD(tr_RSL_BCCH_INFO(RSL_SYSTEM_INFO_4))) -> value rx_rsl_ud {
9340 var RSL_IE_Body ie := rx_rsl_ud.rsl.ies[2].body; /* FULL BCCH Information IE */
9341 var SystemInformation si := dec_SystemInformation(ie.other.payload);
9342
9343 /* Make sure that what we decoded is System Information Type 4 */
9344 if (si.header.message_type != SYSTEM_INFORMATION_TYPE_4) {
9345 setverdict(fail, "RSL FULL BCCH Information IE contains: ", si);
9346 repeat;
9347 }
9348
9349 /* Make sure that CBCH Channel Description IE is present */
9350 if (not ispresent(si.payload.si4.cbch_chan_desc)) {
9351 setverdict(fail, "CBCH Channel Description IE is absent");
9352 break;
9353 }
9354
9355 /* Finally, check the hopping parameters (HSN, MAIO) */
9356 var ChannelDescription chan_desc := si.payload.si4.cbch_chan_desc.v;
9357 f_TC_fh_params_match_chan_desc(fhp, chan_desc);
9358
9359 /* 3GPP TS 44.018, section 9.1.36.2 "CBCH Mobile Allocation":
9360 * The CBCH Mobile Allocation IE *shall* be present if FH is enabled. */
9361 if (chan_desc.h and not ispresent(si.payload.si4.cbch_mobile_alloc)) {
9362 setverdict(fail, "FH enabled, but Mobile Allocation IE is absent");
9363 break;
9364 } else if (chan_desc.h and ispresent(si.payload.si4.cbch_mobile_alloc)) {
9365 f_TC_fh_params_match_ma(fhp, chan_desc.chan_nr.tn,
9366 si.payload.si4.cbch_mobile_alloc.v);
9367 }
9368 }
9369 [] IPA_RSL[0].receive { repeat; }
9370 [] T.timeout {
9371 setverdict(fail, "Timeout waiting for RSL BCCH INFOrmation (SI4)");
9372 }
9373 }
9374
9375 /* Disable frequency hopping */
9376 f_TC_fh_params_unset(fhp);
9377
Vadim Yanitskiy8bc46012020-09-06 12:38:01 +07009378 /* (Re)configure TS0 as CCCH+SDCCH4+CBCH and TS1 as TCH/F */
Vadim Yanitskiyca974032020-09-01 07:20:39 +07009379 f_vty_enter_cfg_trx(BSCVTY, trx := 0);
9380
9381 f_vty_transceive(BSCVTY, "timeslot 0");
Vadim Yanitskiy8bc46012020-09-06 12:38:01 +07009382 f_vty_transceive(BSCVTY, "phys_chan_config ccch+sdcch4+cbch");
Vadim Yanitskiyca974032020-09-01 07:20:39 +07009383 f_vty_transceive(BSCVTY, "exit"); /* go back */
9384
9385 f_vty_transceive(BSCVTY, "timeslot 1");
9386 f_vty_transceive(BSCVTY, "phys_chan_config tch/f");
9387 f_vty_transceive(BSCVTY, "end"); /* we're done */
9388
Vadim Yanitskiy21726312020-09-04 01:45:36 +07009389 f_shutdown_helper();
Vadim Yanitskiyca974032020-09-01 07:20:39 +07009390}
9391
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02009392template (value) PDU_BSSAP_LE ts_BSSMAP_LE_BSSLAP(template (value) BSSLAP_PDU bsslap)
9393 := ts_BSSMAP_LE_ConnInfo(BSSMAP_LE_PROT_BSSLAP, data := enc_BSSLAP_PDU(valueof(bsslap)));
9394
9395private function f_match_bsslap(PDU_BSSAP_LE got_bsslap_msg,
9396 template (present) BSSLAP_PDU expect_bsslap)
9397{
9398 var BSSLAP_PDU bsslap := dec_BSSLAP_PDU(got_bsslap_msg.pdu.bssmap.co_info.bsslap_apdu.data);
9399 if (not match(bsslap, expect_bsslap)) {
9400 log("EXPECTING BSSLAP: ", expect_bsslap);
9401 log("GOT BSSLAP: ", bsslap);
9402 setverdict(fail, "BSSLAP is not as expected");
9403 mtc.stop;
9404 }
9405 setverdict(pass);
9406}
9407
9408/* GAD: this is an Ellipsoid point with uncertainty circle, encoded as in 3GPP TS 23.032 §7.3.2. */
9409const octetstring gad_ell_point_unc_circle := '10b0646d0d5f6627'O;
9410
9411private function f_expect_bsslap(template (present) BSSLAP_PDU expect_rx_bsslap) runs on MSC_ConnHdlr {
9412 var PDU_BSSAP_LE rx_bsslap;
9413 BSSAP_LE.receive(tr_BSSMAP_LE_ConnInfo(BSSMAP_LE_PROT_BSSLAP, ?)) -> value(rx_bsslap);
9414 f_match_bsslap(rx_bsslap, expect_rx_bsslap);
9415}
9416
9417/* With an active lchan, start BSSMAP Perform Location Request on A interface, starting BSSMAP-LE Perform Location
9418 * Request on Lb interface. Either with or without the SMLC doing a BSSLAP TA Request. */
9419private function f_lcs_loc_req_for_active_ms(boolean do_ta_request := false) runs on MSC_ConnHdlr {
9420 f_sleep(1.0);
9421
9422 f_establish_fully(omit, omit);
9423 f_bssap_le_register_imsi(g_pars.imsi, omit);
9424
9425 BSSAP.send(valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
9426 ts_CellId_CGI('262'H, '42'H, 23, 42))));
9427
9428 var PDU_BSSAP_LE plr;
9429 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?)) -> value(plr);
9430
9431 if (not do_ta_request) {
9432 /* verify TA Layer 3 in APDU. First the APDU type (BSSLAP), then the BSSLAP data contents. */
9433 var template BSSMAP_LE_IE_APDU expect_apdu := tr_BSSMAP_LE_APDU(BSSMAP_LE_PROT_BSSLAP, ?);
9434 if (not match(plr.pdu.bssmap.perf_loc_req.bsslap_apdu, expect_apdu)) {
9435 log("EXPECTING BSSMAP-LE APDU IE ", expect_apdu);
9436 log("GOT BSSMAP-LE APDU IE ", plr.pdu.bssmap.perf_loc_req.bsslap_apdu);
9437 setverdict(fail, "BSSMAP-LE APDU IE is not as expected");
9438 mtc.stop;
9439 }
9440 var template BSSLAP_PDU expect_ta_layer3 := tr_BSSLAP_TA_Layer3(tr_BSSLAP_IE_TA(0));
9441 var BSSLAP_PDU bsslap := dec_BSSLAP_PDU(plr.pdu.bssmap.perf_loc_req.bsslap_apdu.data);
9442 if (not match(bsslap, expect_ta_layer3)) {
9443 log("EXPECTING BSSLAP TA Layer 3: ", expect_ta_layer3);
9444 log("GOT BSSLAP: ", bsslap);
9445 setverdict(fail, "BSSLAP is not as expected");
9446 mtc.stop;
9447 }
9448 /* OsmoBSC directly sent the TA as BSSLAP APDU in the BSSMAP-LE Perform Location Request to the SMLC. The SMLC
9449 * has no need to request the TA from the BSC and directly responds. */
9450 } else {
9451 /* SMLC wants to ask the TA from the BSC explicitly in a BSSLAP TA Request message */
9452 BSSAP_LE.send(ts_BSSMAP_LE_BSSLAP(ts_BSSLAP_TA_Req));
9453 f_expect_bsslap(tr_BSSLAP_TA_Resp(?, ?));
9454 }
9455
9456 /* SMLC got the TA from the BSC, now responds with geo information data. */
9457 BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(gad_ell_point_unc_circle, omit));
9458 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
9459 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(tr_BSSMAP_IE_LocationEstimate(gad_ell_point_unc_circle)));
9460
9461 /* The LCS was using an active A-interface conn. It should still remain active after this. */
9462 f_mo_l3_transceive();
9463
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02009464 f_perform_clear();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02009465
9466 f_sleep(2.0);
9467 setverdict(pass);
9468}
9469
9470/* With an active lchan, start BSSMAP Perform Location Request on A interface, starting BSSMAP-LE Perform Location
9471 * Request on Lb interface. Without the SMLC doing a BSSLAP TA Request. */
9472private function f_tc_lcs_loc_req_for_active_ms(charstring id) runs on MSC_ConnHdlr {
9473 f_lcs_loc_req_for_active_ms(false);
9474}
9475testcase TC_lcs_loc_req_for_active_ms() runs on test_CT {
9476 var MSC_ConnHdlr vc_conn;
9477 var TestHdlrParams pars := f_gen_test_hdlr_pars();
9478
9479 f_init(1, true);
9480 f_sleep(1.0);
9481 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_for_active_ms), pars);
9482 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +01009483 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02009484}
9485
9486/* With an active lchan, start BSSMAP Perform Location Request on A interface, starting BSSMAP-LE Perform Location
9487 * Request on Lb interface. With the SMLC doing a BSSLAP TA Request. */
9488private function f_tc_lcs_loc_req_for_active_ms_ta_req(charstring id) runs on MSC_ConnHdlr {
9489 f_lcs_loc_req_for_active_ms(true);
9490}
9491testcase TC_lcs_loc_req_for_active_ms_ta_req() runs on test_CT {
9492 var MSC_ConnHdlr vc_conn;
9493 var TestHdlrParams pars := f_gen_test_hdlr_pars();
9494
9495 f_init(1, true);
9496 f_sleep(1.0);
9497 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_for_active_ms_ta_req), pars);
9498 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +01009499 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02009500}
9501
9502/* Clear the A-interface conn only, without doing anything on Abis. Useful for LCS, for cases where there is only an A
9503 * conn without an active lchan. */
9504private function f_clear_A_conn() runs on MSC_ConnHdlr
9505{
9506 var BssmapCause cause := 0;
9507 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
9508 BSSAP.receive(tr_BSSMAP_ClearComplete);
9509 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
9510
9511 timer no_more_bssap := 5.0;
9512 no_more_bssap.start;
9513 alt {
9514 [] no_more_bssap.timeout { break; }
9515 [] BSSAP.receive(tr_BSSAP_BSSMAP) {
9516 setverdict(fail, "Expected no more BSSAP after Clear Complete");
9517 mtc.stop;
9518 }
9519 }
9520 setverdict(pass);
9521}
9522
9523/* Verify that the A-interface connection is still working, and then clear it, without doing anything on Abis. Useful
9524 * for LCS, for cases where there is only an A conn without an active lchan. */
9525private function f_verify_active_A_conn_and_clear() runs on MSC_ConnHdlr
9526{
9527 f_logp(BSCVTY, "f_verify_active_A_conn_and_clear: test A link, then clear");
9528
9529 /* When an lchan is active, we can send some L3 data from the BTS side and verify that it shows up on the other
9530 * side towards the MSC. When there is no lchan, this is not possible. To probe whether the A-interface
9531 * connection is still up, we need something that echos back on the A-interface. Another LCS request! */
9532 BSSAP.send(valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
9533 ts_CellId_CGI('262'H, '42'H, 23, 42))));
9534 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?));
9535
9536 /* Right, the Perform Location Request showed up on Lb, now we can clear the A conn. */
9537 f_clear_A_conn();
9538 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocAbort(BSSMAP_LE_LCS_CAUSE_REQUEST_ABORTED));
9539 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
9540}
9541
9542/* With *no* active lchan, start BSSMAP Perform Location Request on A interface, starting BSSMAP-LE Perform Location
9543 * Request on Lb interface. BSC will Page for the subscriber as soon as we (virtual SMLC) request the TA via BSSLAP.
9544 */
9545private function f_tc_lcs_loc_req_for_idle_ms(charstring id) runs on MSC_ConnHdlr {
9546 f_sleep(1.0);
9547
9548 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
9549 f_bssap_le_register_imsi(g_pars.imsi, omit);
9550
9551 /* Register to receive the Paging Command */
9552 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
9553 g_chan_nr := new_chan_nr;
9554 f_rslem_register(0, g_chan_nr);
9555
9556 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
9557 valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
9558 ts_CellId_CGI('001'H, '01'H, 1, 0)))));
9559 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
9560
9561 var PDU_BSSAP_LE plr;
9562 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?)) -> value(plr);
9563
9564 /* SMLC wants to ask the TA from the BSC explicitly in a BSSLAP TA Request message */
9565 BSSAP_LE.send(ts_BSSMAP_LE_BSSLAP(ts_BSSLAP_TA_Req));
9566
9567 /* OsmoBSC needs to Page */
9568 RSL.receive(tr_RSL_PAGING_CMD(tr_MI_IMSI(g_pars.imsi)));
9569 f_logp(BSCVTY, "got Paging Command");
9570
9571 /* MS requests channel. Since the Paging was for LCS, the Paging Response does not trigger a Complete Layer 3 to
9572 * the MSC, and releases the lchan directly. */
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02009573 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);
9574 f_expect_lchan_rel(RSL, RSL_PROC);
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02009575
9576 /* From the Paging Response, the TA is now known to the BSC, and it responds to the SMLC. */
9577
9578 f_expect_bsslap(tr_BSSLAP_TA_Resp(?, ?));
9579
9580 /* SMLC got the TA from the BSC, now responds with geo information data. */
9581 BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(gad_ell_point_unc_circle, omit));
9582 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
9583
9584 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(tr_BSSMAP_IE_LocationEstimate(gad_ell_point_unc_circle)));
9585
9586 /* The lchan is gone, the A-interface conn was created for the LCS only.
9587 * Still it is clearly the MSC's job to decide whether to tear down the conn or not. */
9588 f_verify_active_A_conn_and_clear();
9589
9590 f_sleep(2.0);
9591 setverdict(pass);
9592}
9593testcase TC_lcs_loc_req_for_idle_ms() runs on test_CT {
9594 var MSC_ConnHdlr vc_conn;
9595 var TestHdlrParams pars := f_gen_test_hdlr_pars();
9596
9597 f_init(1, true);
9598 f_sleep(1.0);
9599
9600 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
9601 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
9602
9603 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_for_idle_ms), pars);
9604 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +01009605 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02009606}
9607
9608/* With no active lchan, start BSSMAP Perform Location Request on A interface, but omit IMSI; expect failure response.
9609 */
9610private function f_tc_lcs_loc_req_no_subscriber(charstring id) runs on MSC_ConnHdlr {
9611 f_sleep(1.0);
9612
9613 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
9614 f_bssap_le_register_imsi(g_pars.imsi, omit);
9615
9616 /* provoke an abort by omitting both IMSI and IMEI */
9617 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
9618 valueof(ts_BSSMAP_Perform_Location_Request(omit,
9619 ts_CellId_CGI('262'H, '42'H, 23, 42)))));
9620 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
9621
9622 /* BSC tells MSC about failure */
9623 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(
9624 locationEstimate := omit, positioningData := omit,
9625 lCS_Cause := tr_BSSMAP_LcsCause(BSSMAP_LCS_CAUSE_DATA_MISSING_IN_REQ)));
9626
9627 /* There is no lchan. Still the MSC's job to decide whether to tear down the conn or not. */
9628 f_verify_active_A_conn_and_clear();
9629
9630 f_sleep(2.0);
9631 setverdict(pass);
9632}
9633testcase TC_lcs_loc_req_no_subscriber() runs on test_CT {
9634 var MSC_ConnHdlr vc_conn;
9635 var TestHdlrParams pars := f_gen_test_hdlr_pars();
9636
9637 f_init(1, true);
9638 f_sleep(1.0);
9639
9640 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
9641 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
9642
9643 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_no_subscriber), pars);
9644 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +01009645 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02009646}
9647
9648/* With an active lchan, start a Perform Location Request on the A-interface, but virtual SMLC does not answer with
9649 * BSSMAP-LE Perform Location Response (before or after sending a BSSLAP TA Request) */
9650private function f_lcs_loc_req_for_active_ms_le_timeout(boolean do_ta) runs on MSC_ConnHdlr {
9651 f_sleep(1.0);
9652
9653 f_establish_fully(omit, omit);
9654 f_bssap_le_register_imsi(g_pars.imsi, omit);
9655
9656 BSSAP.send(valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
9657 ts_CellId_CGI('262'H, '42'H, 23, 42))));
9658
9659 var PDU_BSSAP_LE plr;
9660 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?)) -> value(plr);
9661
9662 if (do_ta) {
9663 /* SMLC wants to ask the TA from the BSC explicitly in a BSSLAP TA Request message */
9664 BSSAP_LE.send(ts_BSSMAP_LE_BSSLAP(ts_BSSLAP_TA_Req));
9665 f_expect_bsslap(tr_BSSLAP_TA_Resp(?, ?));
9666 }
9667
9668 /* SMLC fails to respond, BSC runs into timeout */
9669 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocAbort(BSSMAP_LE_LCS_CAUSE_SYSTEM_FAILURE));
9670 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
9671
9672 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(
9673 locationEstimate := omit, positioningData := omit,
9674 lCS_Cause := tr_BSSMAP_LcsCause(BSSMAP_LCS_CAUSE_SYSTEM_FAILURE)));
9675
9676 /* There is no lchan. Still the MSC's job to decide whether to tear down the conn or not. */
9677 f_verify_active_A_conn_and_clear();
9678
9679 f_sleep(2.0);
9680 setverdict(pass);
9681}
9682
9683/* With an active lchan, start a Perform Location Request on the A-interface, but virtual SMLC does not answer with
9684 * BSSMAP-LE Perform Location Response, without sending a BSSLAP TA Request. */
9685private function f_tc_lcs_loc_req_for_active_ms_le_timeout(charstring id) runs on MSC_ConnHdlr {
9686 f_lcs_loc_req_for_active_ms_le_timeout(false);
9687}
9688
9689testcase TC_lcs_loc_req_for_active_ms_le_timeout() runs on test_CT {
9690 var MSC_ConnHdlr vc_conn;
9691 var TestHdlrParams pars := f_gen_test_hdlr_pars();
9692
9693 f_init(1, true);
9694 f_sleep(1.0);
9695 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_for_active_ms_le_timeout), pars);
9696 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +01009697 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02009698}
9699
9700/* With an active lchan, start a Perform Location Request on the A-interface, but virtual SMLC does not answer with
9701 * BSSMAP-LE Perform Location Response, after sending a BSSLAP TA Request. */
9702private function f_tc_lcs_loc_req_for_active_ms_le_timeout2(charstring id) runs on MSC_ConnHdlr {
9703 f_lcs_loc_req_for_active_ms_le_timeout(true);
9704}
9705
9706testcase TC_lcs_loc_req_for_active_ms_le_timeout2() runs on test_CT {
9707 var MSC_ConnHdlr vc_conn;
9708 var TestHdlrParams pars := f_gen_test_hdlr_pars();
9709
9710 f_init(1, true);
9711 f_sleep(1.0);
9712 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_for_active_ms_le_timeout2), pars);
9713 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +01009714 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02009715}
9716
9717/* With *no* active lchan, start a Perform Location Request, expecting that the MS will be Paged. */
9718private function f_tc_lcs_loc_req_for_idle_ms_no_pag_resp(charstring id) runs on MSC_ConnHdlr {
9719 f_sleep(1.0);
9720
9721 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
9722 f_bssap_le_register_imsi(g_pars.imsi, omit);
9723
9724 /* Register to receive the Paging Command */
9725 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
9726 g_chan_nr := new_chan_nr;
9727 f_rslem_register(0, g_chan_nr);
9728
9729 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
9730 valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
9731 ts_CellId_CGI('001'H, '01'H, 1, 0)))));
9732 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
9733
9734 var PDU_BSSAP_LE plr;
9735 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?)) -> value(plr);
9736
9737 /* SMLC wants to ask the TA from the BSC explicitly in a BSSLAP TA Request message */
9738 BSSAP_LE.send(ts_BSSMAP_LE_BSSLAP(ts_BSSLAP_TA_Req));
9739
9740 /* OsmoBSC needs to Page */
9741 var PDU_BSSAP_LE rx_bsslap;
9742 alt {
9743 [] RSL.receive(tr_RSL_PAGING_CMD(tr_MI_IMSI(g_pars.imsi))) {
9744 f_logp(BSCVTY, "got Paging Command");
9745 repeat;
9746 }
9747 [] BSSAP_LE.receive(tr_BSSMAP_LE_ConnInfo(BSSMAP_LE_PROT_BSSLAP, ?)) -> value(rx_bsslap) {
9748 /* MS does not respond to Paging, TA Req runs into timeout. */
9749 f_match_bsslap(rx_bsslap, tr_BSSLAP_Abort(?));
9750 }
9751 }
9752
9753 /* SMLC responds with failure */
9754 BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(omit, BSSMAP_LE_LCS_CAUSE_REQUEST_ABORTED));
9755 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
9756
9757 /* BSC tells MSC about failure */
9758 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(
9759 locationEstimate := omit, positioningData := omit,
9760 lCS_Cause := tr_BSSMAP_LcsCause(BSSMAP_LCS_CAUSE_REQUEST_ABORTED)));
9761
9762 /* There is no lchan. Still the MSC's job to decide whether to tear down the conn or not. */
9763 f_verify_active_A_conn_and_clear();
9764
9765 f_sleep(2.0);
9766 setverdict(pass);
9767}
9768testcase TC_lcs_loc_req_for_idle_ms_no_pag_resp() runs on test_CT {
9769 var MSC_ConnHdlr vc_conn;
9770 var TestHdlrParams pars := f_gen_test_hdlr_pars();
9771
9772 f_init(1, true);
9773 f_sleep(1.0);
9774
9775 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
9776 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
9777
9778 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_for_idle_ms_no_pag_resp), pars);
9779 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +01009780 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02009781}
9782
9783/* During an ongoing Location Request, the MS sends a CM Service Request. Expect the same A-conn to be re-used / taken
9784 * over. */
9785private function f_tc_cm_service_during_lcs_loc_req(charstring id) runs on MSC_ConnHdlr {
9786 f_sleep(1.0);
9787
9788 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
9789 f_bssap_le_register_imsi(g_pars.imsi, omit);
9790
9791 /* Register to receive the Paging Command */
9792 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
9793 g_chan_nr := new_chan_nr;
9794 f_rslem_register(0, g_chan_nr);
9795
9796 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
9797 valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
9798 ts_CellId_CGI('001'H, '01'H, 1, 0)))));
9799 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
9800
9801 var PDU_BSSAP_LE plr;
9802 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?)) -> value(plr);
9803
9804 /* As the A-interface conn was established for LCS, the MS coincidentally decides to issue a CM Service Request
9805 * and establish Layer 3. It should use the existing A-interface conn. */
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02009806 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 +02009807 do_clear := false, expect_bssmap_l3 := true);
9808
9809 /* SMLC wants to ask the TA from the BSC explicitly in a BSSLAP TA Request message */
9810 BSSAP_LE.send(ts_BSSMAP_LE_BSSLAP(ts_BSSLAP_TA_Req));
9811
9812 /* OsmoBSC already has an lchan, no need to Page, just returns the TA */
9813 f_expect_bsslap(tr_BSSLAP_TA_Resp(?, ?));
9814
9815 /* SMLC got the TA from the BSC, now responds with geo information data. */
9816 BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(gad_ell_point_unc_circle, omit));
9817 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
9818 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(tr_BSSMAP_IE_LocationEstimate(gad_ell_point_unc_circle)));
9819
9820 /* The lchan should still exist, it was from a CM Service Request. */
9821 f_mo_l3_transceive();
9822
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02009823 f_perform_clear();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02009824
9825 f_sleep(2.0);
9826 setverdict(pass);
9827}
9828testcase TC_cm_service_during_lcs_loc_req() runs on test_CT {
9829 var MSC_ConnHdlr vc_conn;
9830 var TestHdlrParams pars := f_gen_test_hdlr_pars();
9831
9832 f_init(1, true);
9833 f_sleep(1.0);
9834
9835 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
9836 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
9837
9838 vc_conn := f_start_handler(refers(f_tc_cm_service_during_lcs_loc_req), pars);
9839 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +01009840 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02009841}
9842
9843/* During an ongoing Perform Location Request, do a Handover, an expect a BSSLAP Reset message from the BSC to indicate
9844 * the new lchan after handover. */
9845private function f_tc_ho_during_lcs_loc_req(charstring id) runs on MSC_ConnHdlr {
9846 f_sleep(1.0);
9847
9848 f_establish_fully(omit, omit);
9849 f_bssap_le_register_imsi(g_pars.imsi, omit);
9850
9851 BSSAP.send(valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
9852 ts_CellId_CGI('262'H, '42'H, 23, 42))));
9853
9854 var PDU_BSSAP_LE plr;
9855 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?)) -> value(plr);
9856
9857 /* SMLC ponders the Location Request, in the meantime the BSC decides to handover */
9858 f_bts_0_cfg(BSCVTY, {"neighbor bts 1"});
9859
9860 var HandoverState hs := {
9861 rr_ho_cmpl_seen := false,
9862 handover_done := false,
Neels Hofmeyrc741fcb2021-10-02 14:52:28 +02009863 old_chan_nr := -,
9864 expect_target_tsc := BTS_TSC[1]
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02009865 };
9866 /* issue hand-over command on VTY */
9867 f_vty_handover(BSCVTY, 0, 0, g_chan_nr, 1);
9868 /* temporarily suspend DChan processing on BTS1 to avoid race with RSLEM_register */
9869 f_rslem_suspend(RSL1_PROC);
9870
9871 /* From the MGW perspective, a handover is is characterized by
9872 * performing one MDCX operation with the MGW. So we expect to see
9873 * one more MDCX during handover. */
9874 g_media.mgcp_conn[0].mdcx_seen_exp := g_media.mgcp_conn[0].crcx_seen_exp + 1;
9875
9876 alt {
9877 [] as_handover(hs);
9878 }
9879
9880 var PDU_BSSAP_LE rx_bsslap;
9881
9882 interleave {
9883 /* Expect the BSC to inform the MSC about the handover */
9884 [] BSSAP.receive(tr_BSSMAP_HandoverPerformed);
9885
9886 /* Expect the BSC to inform the SMLC about the handover */
9887 [] BSSAP_LE.receive(tr_BSSMAP_LE_ConnInfo(BSSMAP_LE_PROT_BSSLAP, ?)) -> value(rx_bsslap) {
9888 f_match_bsslap(rx_bsslap, tr_BSSLAP_Reset(BSSLAP_CAUSE_INTRA_BSS_HO));
9889 }
9890 }
9891
9892 /* SMLC now responds with geo information data. */
9893 BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(gad_ell_point_unc_circle, omit));
9894 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
9895 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(tr_BSSMAP_IE_LocationEstimate(gad_ell_point_unc_circle)));
9896
9897 /* lchan still active */
9898 f_mo_l3_transceive(RSL1);
9899
9900 /* MSC decides it is done now. */
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02009901 f_perform_clear(RSL1, RSL1_PROC);
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02009902
9903 f_sleep(2.0);
9904 setverdict(pass);
9905}
9906testcase TC_ho_during_lcs_loc_req() runs on test_CT {
9907 var MSC_ConnHdlr vc_conn;
9908 var TestHdlrParams pars := f_gen_test_hdlr_pars();
9909
9910 f_init(2, true);
9911 f_sleep(1.0);
9912 vc_conn := f_start_handler(refers(f_tc_ho_during_lcs_loc_req), pars);
9913 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +01009914 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02009915}
9916
Neels Hofmeyrbf037052020-10-28 22:52:02 +00009917/* Attempt Complete Layer 3 without any MSC available (OS#4832) */
9918private function f_tc_no_msc(charstring id) runs on MSC_ConnHdlr {
9919 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
9920
9921 /* Also disable attach for the single connected MSC */
9922 f_vty_msc_allow_attach(BSCVTY, { false });
9923
9924 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) ));
9925 f_chan_est(g_pars.ra, l3_enc, g_pars.link_id, g_pars.fn);
9926
9927 /* No MSC is found, expecting a proper release on RSL */
9928 interleave {
9929 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_RELEASE)) {
9930 f_logp(BSCVTY, "Got RSL RR Release");
9931 }
9932 [] RSL.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {
9933 f_logp(BSCVTY, "Got RSL Deact SACCH");
9934 }
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +02009935 [] RSL.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
Neels Hofmeyrbf037052020-10-28 22:52:02 +00009936 f_logp(BSCVTY, "Got RSL RF Chan Rel, sending Rel Ack");
9937 RSL.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
Neels Hofmeyre680b012021-07-22 19:19:09 +02009938 f_rslem_unregister(0, g_chan_nr);
Neels Hofmeyrbf037052020-10-28 22:52:02 +00009939 }
9940 }
9941 setverdict(pass);
9942}
9943testcase TC_no_msc() runs on test_CT {
9944
9945 f_init(1, true);
9946 f_sleep(1.0);
9947 var MSC_ConnHdlr vc_conn;
9948 var TestHdlrParams pars := f_gen_test_hdlr_pars();
9949
9950 f_ctrs_bsc_init(counternames_bsc_mscpool);
9951
9952 vc_conn := f_start_handler(refers(f_tc_no_msc), pars);
9953 vc_conn.done;
9954
9955 f_ctrs_bsc_add("mscpool:subscr:no_msc");
9956 f_ctrs_bsc_verify();
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +01009957 f_shutdown_helper();
Neels Hofmeyrbf037052020-10-28 22:52:02 +00009958}
9959
Harald Welte0ea2d5e2018-04-07 21:40:29 +02009960/* Dyn PDCH todo:
9961 * activate OSMO as TCH/F
9962 * activate OSMO as TCH/H
9963 * does the BSC-located PCU socket get the updated INFO?
9964 * what if no PCU is connected at the time?
9965 * is the info correct on delayed PCU (re)connect?
9966 */
Harald Welte94e0c342018-04-07 11:33:23 +02009967
Neels Hofmeyr87857ec2021-04-25 16:17:47 +00009968private function f_TC_refuse_mode_modif_to_vamos(charstring id) runs on MSC_ConnHdlr {
9969 var PDU_BSSAP ass_cmd := f_gen_ass_req(g_pars.use_osmux);
9970 var template PDU_BSSAP exp_compl := f_gen_exp_compl(g_pars.use_osmux);
9971
9972 /* puzzle together the ASSIGNMENT REQ for given codec[s] */
9973 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
9974 ass_cmd.pdu.bssmap.assignmentRequest.codecList := g_pars.ass_codec_list;
9975 exp_compl.pdu.bssmap.assignmentComplete.speechCodec.codecElements[0] :=
9976 g_pars.ass_codec_list.codecElements[0];
9977 if (isvalue(g_pars.expect_mr_s0_s7)) {
9978 exp_compl.pdu.bssmap.assignmentComplete.speechCodec.codecElements[0].s0_7 :=
9979 g_pars.expect_mr_s0_s7;
9980 }
9981 }
9982 ass_cmd.pdu.bssmap.assignmentRequest.channelType :=
9983 f_BSSMAP_chtype_from_codec(g_pars.ass_codec_list.codecElements[0]);
9984 log("expecting ASS COMPL like this: ", exp_compl);
9985
9986 f_establish_fully(ass_cmd, exp_compl);
9987
Neels Hofmeyr8746b0d2021-06-01 17:25:39 +02009988 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 +00009989
9990 var RSL_Message rsl;
9991
9992 timer T := 5.0;
9993 T.start;
9994 alt {
9995 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr)) -> value rsl {
9996 var PDU_ML3_NW_MS l3 := dec_PDU_ML3_NW_MS(rsl.ies[2].body.l3_info.payload);
9997 log("Rx L3 from net: ", l3);
9998 if (ischosen(l3.msgs.rrm.channelModeModify)) {
9999 setverdict(fail, "Mode Modify to VAMOS succeeded even though BTS does not support VAMOS");
10000 mtc.stop;
10001 }
10002 }
10003 [] RSL.receive(tr_RSL_MODE_MODIFY_REQ(g_chan_nr, ?)) -> value rsl {
10004 setverdict(fail, "Mode Modify to VAMOS succeeded even though BTS does not support VAMOS");
10005 mtc.stop;
10006 }
10007 [] T.timeout {
10008 /* The BTS does not exhibit BTS_FEAT_VAMOS, so no VAMOS related Mode Modify should happen. */
10009 setverdict(pass);
10010 }
10011 }
10012 T.stop;
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010010013
10014 f_perform_clear();
Neels Hofmeyr87857ec2021-04-25 16:17:47 +000010015}
10016
10017/* The BSC does *not* indicate BTS_FEAT_VAMOS; make sure that a channel Mode Modify to VAMOS mode is refused by
10018 * osmo-bsc. */
10019testcase TC_refuse_mode_modif_to_vamos() runs on test_CT {
10020 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10021 var MSC_ConnHdlr vc_conn;
10022
10023 f_init(1, true);
10024 f_sleep(1.0);
10025
10026 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
10027 vc_conn := f_start_handler(refers(f_TC_refuse_mode_modif_to_vamos), pars);
10028 vc_conn.done;
10029 f_shutdown_helper();
10030}
10031
10032/* The BSC does *not* indicate BTS_FEAT_VAMOS; make sure that a channel activation to VAMOS mode is refused by osmo-bsc.
10033 */
10034testcase TC_refuse_chan_act_to_vamos() runs on test_CT {
10035 f_init_vty();
10036
10037 f_init(1, false);
10038 f_sleep(1.0);
10039
10040 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 1 sub-slot 0 activate-vamos fr");
10041
10042 var ASP_RSL_Unitdata rx_rsl_ud;
10043 timer T := 5.0;
10044
10045 T.start;
10046 alt {
10047 [] IPA_RSL[0].receive(tr_ASP_RSL_UD(?, IPAC_PROTO_RSL_TRX0)) -> value rx_rsl_ud {
10048 if (rx_rsl_ud.rsl.msg_type == RSL_MT_CHAN_ACTIV) {
10049 T.stop;
10050 setverdict(fail, "CHANnel ACTivate in VAMOS mode succeeded even though BTS does not support VAMOS");
10051 mtc.stop;
10052 }
10053 repeat;
10054 }
10055 [] T.timeout {
10056 /* The BTS does not exhibit BTS_FEAT_VAMOS, so no VAMOS related CHANnel ACTivate should happen. */
10057 setverdict(pass);
10058 }
10059 }
10060}
10061
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000010062private function f_TC_reassignment_codec(charstring id) runs on MSC_ConnHdlr {
10063 /* First fully set up a speech lchan */
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010010064 f_assignment_codec(id, do_perform_clear := false);
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000010065
10066 /* Trigger re-assignment to another lchan */
10067 var AssignmentState assignment_st := valueof(ts_AssignmentStateInit);
10068
10069 /* Re-Assignment should tell the MGW endpoint the new lchan's RTP address and port, so expecting to see exactly
10070 * one MDCX on MGCP. */
10071 g_media.mgcp_conn[0].mdcx_seen_exp := g_media.mgcp_conn[0].mdcx_seen_exp + 1;
10072
10073 /* The new lchan will see all-new IPAC_CRCX and IPAC_MDCX messages telling the BTS the same RTP address and port
10074 * as the old lchan used. */
10075 g_media.bts.ipa_crcx_seen := false;
10076 g_media.bts.ipa_mdcx_seen := false;
10077
10078 /* Send different BTS side RTP port number for the new lchan */
10079 g_media.bts.bts.port_nr := 4223;
10080
10081 f_rslem_register(0, valueof(ts_RslChanNr_Bm(2))); /* <-- FIXME: can we somehow infer the timeslot that will be used? */
10082
10083 /* Trigger re-assignment. */
10084 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot " & int2str(g_chan_nr.tn) & " sub-slot 0 assignment");
10085
10086 timer T := 5.0;
10087 T.start;
10088 alt {
10089 [] as_assignment(assignment_st);
10090 [] as_Media();
10091 [] T.timeout {
10092 break;
10093 }
10094 }
10095
10096 if (not assignment_st.assignment_done) {
10097 setverdict(fail, "Assignment did not complete");
10098 mtc.stop;
10099 }
10100
10101 f_check_mgcp_expectations()
10102 setverdict(pass);
10103
10104 f_sleep(2.0);
10105 log("show lchan summary: ", f_vty_transceive_ret(BSCVTY, "show lchan summary"));
10106
10107 /* Instruct BSC to clear channel */
10108 var BssmapCause cause := 0;
10109 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
10110 interleave {
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000010111 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_RELEASE)) {}
10112 [] RSL.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {}
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +020010113 [] RSL.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000010114 RSL.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
Neels Hofmeyre680b012021-07-22 19:19:09 +020010115 f_rslem_unregister(0, g_chan_nr);
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000010116 }
10117 [] BSSAP.receive(tr_BSSMAP_ClearComplete) {
10118 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
10119 }
10120 }
Neels Hofmeyr40a45d12021-09-23 22:57:12 +020010121 f_expect_dlcx_conns();
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000010122
10123 f_sleep(0.5);
10124}
10125
10126testcase TC_reassignment_fr() runs on test_CT {
10127 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10128 var MSC_ConnHdlr vc_conn;
10129
10130 f_init(1, true);
10131 f_sleep(1.0);
10132
Neels Hofmeyrac432fa2021-11-02 16:45:56 +010010133 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000010134
10135 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
10136 vc_conn := f_start_handler(refers(f_TC_reassignment_codec), pars);
10137 vc_conn.done;
10138
10139 /* from f_establish_fully() */
10140 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
10141 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
10142 /* from re-assignment */
10143 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
10144 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
10145 f_ctrs_bsc_and_bts_verify();
10146 f_shutdown_helper();
10147}
10148
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020010149const charstring REEST_LOST_CONNECTION := "REEST_LOST_CONNECTION";
10150const charstring REEST_CLEAR := "REEST_CLEAR";
10151const charstring REEST_CLEAR_DONE := "REEST_CLEAR_DONE";
10152
10153/* CM Re-Establishment, 3GPP TS 24.008 4.5.1.6.
10154 * The MS <-> BTS loses radio connection, MS shows up on second BTS and asks for CM Re-Establishment.
10155 * BSC should establish a separate A conn for the same MS, the original A conn is then cleared by
10156 * the MSC as the CM Re-Establishment is handled.
10157 *
10158 * MS bts0 bts1 bsc msc test-component
10159 * |<----->|<----------------->|<-0-->| _1 Establish channel on bts 0
10160 * | | _1 wait a bit, to settle down
10161 * |<-x x--| | _1 "lose connection"
10162 * | | REEST_LOST_CONNECTION
10163 * |----------------->|------->|--1-->| _2 new A-conn: Chan Rqd, Imm Ass, Compl L3 with CM Re-Establishment Req
10164 * | | REEST_CLEAR
10165 * | |<-0---| _1 Clear Command on first A-conn
10166 * | |--0-->| _1 Clear Complete
10167 * | |<----------------->| | _1 Release first channel
10168 * | | REEST_CLEAR_DONE
10169 * |<-----------------|<-------|<-1---| _2 Chan Activ, Assignment Command
10170 * |<-----------------|<-------|<-1---| _2 Clear Command, Release
10171 *
10172 */
10173private function f_tc_cm_reestablishment_1(charstring id) runs on MSC_ConnHdlr {
10174 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
10175 var PDU_BSSAP ass_cmd := f_gen_ass_req();
10176
10177 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
10178 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
10179
10180 f_establish_fully(ass_cmd, exp_compl);
10181
10182 /* The original channel loses connection, MS attemts CM Re-Establishment on another cell, see
10183 * f_tc_cm_reestablishment_2(). This established channel stays active until MSC sends a Clear Command. The time
10184 * when exactly that happens is determined by f_tc_cm_reestablishment_2(). */
10185 f_sleep(2.0);
10186 COORD.send(REEST_LOST_CONNECTION);
10187
10188 alt {
10189 [] COORD.receive(REEST_CLEAR);
10190 [] RSL.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {
10191 setverdict(fail, "Unexpected channel release");
10192 mtc.stop;
10193 }
10194 [] RSL.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
10195 setverdict(fail, "Unexpected channel release");
10196 mtc.stop;
10197 }
10198 }
10199 f_perform_clear()
10200 f_expect_dlcx_conns();
Neels Hofmeyr969abd02021-09-23 22:24:08 +020010201 f_create_mgcp_delete_ep(g_media.mgcp_ep);
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020010202 COORD.send(REEST_CLEAR_DONE);
10203}
10204
10205private function f_tc_cm_reestablishment_2(charstring id) runs on MSC_ConnHdlr {
10206 f_MscConnHdlr_init(g_pars.media_nr, host_bts, host_mgw_mgcp, FR_AMR);
10207
10208 /* The MS lost the connection on the first channel, now establishes another one */
10209 COORD.receive(REEST_LOST_CONNECTION);
10210
10211 var MobileIdentityLV mi := valueof(ts_MI_IMSI_LV(g_pars.imsi));
10212 var PDU_ML3_MS_NW l3_info := valueof(ts_CM_REESTABL_REQ(mi));
10213 var octetstring l3_enc := enc_PDU_ML3_MS_NW(l3_info);
10214
10215 f_create_bssmap_exp(l3_enc);
Neels Hofmeyrc7b1f6d2021-07-20 23:21:36 +020010216 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 +020010217 BSSAP.receive(tr_BSSMAP_ComplL3(l3_enc));
10218
10219 /* MSC got the CM Re-Establishment request and first off clears the previous conn. */
10220 COORD.send(REEST_CLEAR);
10221 COORD.receive(REEST_CLEAR_DONE);
10222
10223 f_sleep(2.0);
10224
10225 /* Answer the CM Re-Establishment with an Assignment Command. */
10226 var template PDU_BSSAP expect_assignment_compl := f_gen_exp_compl();
10227 var PDU_BSSAP ass_cmd := f_gen_ass_req();
10228 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
10229 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
10230
10231 var AssignmentState st := valueof(ts_AssignmentStateInit);
10232 st.voice_call := true;
10233 st.is_assignment := true;
10234
10235 var ExpectCriteria mgcpcrit := {
10236 connid := omit,
10237 endpoint := omit,
10238 transid := omit
10239 };
10240 f_create_mgcp_expect(mgcpcrit);
10241
Neels Hofmeyrc7b1f6d2021-07-20 23:21:36 +020010242 f_rslem_dchan_queue_enable(RSL1_PROC);
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020010243
10244 BSSAP.send(ass_cmd);
10245
10246 var PDU_BSSAP bssap;
10247
10248 alt {
Neels Hofmeyrc7b1f6d2021-07-20 23:21:36 +020010249 [] as_assignment(st, rsl_pt := RSL1, rsl_proc_pt := RSL1_PROC);
10250 [] as_Media_ipacc(RSL1, RSL2);
10251 [] as_Media_mgw();
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020010252 [st.assignment_done] BSSAP.receive(expect_assignment_compl) {
10253 break;
10254 }
10255 }
10256
10257 f_sleep(3.0);
10258
10259 f_logp(BSCVTY, "f_tc_cm_reestablishment_2 clearing");
Neels Hofmeyrc7b1f6d2021-07-20 23:21:36 +020010260 f_perform_clear(RSL1, RSL1_PROC);
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020010261 f_expect_dlcx_conns();
10262}
10263
10264testcase TC_cm_reestablishment() runs on test_CT {
10265 var TestHdlrParams pars1 := f_gen_test_hdlr_pars();
10266 var MSC_ConnHdlr vc_conn1;
10267
10268 var TestHdlrParams pars2 := f_gen_test_hdlr_pars();
10269 var MSC_ConnHdlr vc_conn2;
10270 pars2.imsi := pars1.imsi;
10271 pars2.media_nr := 2;
Neels Hofmeyrbf720202021-10-02 12:58:24 +020010272 pars2.expect_tsc := BTS_TSC[1];
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020010273
10274 f_init(2, true, guard_timeout := 40.0);
10275 f_sleep(1.0);
10276
10277 vc_conn1 := f_start_handler_create(pars1);
10278 vc_conn2 := f_start_handler_create(pars2);
10279 connect(vc_conn1:COORD, vc_conn2:COORD);
10280 f_start_handler_run(vc_conn1, refers(f_tc_cm_reestablishment_1), pars1);
10281 f_start_handler_run(vc_conn2, refers(f_tc_cm_reestablishment_2), pars2);
10282 vc_conn1.done;
10283 vc_conn2.done;
10284
10285 f_shutdown_helper();
10286}
Neels Hofmeyr87857ec2021-04-25 16:17:47 +000010287
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020010288function f_exp_ipa_rx_nonfatal(integer bts_nr, template (present) RSL_Message t_rx, float t_secs := 2.0,
10289 IpaStreamId sid := IPAC_PROTO_RSL_TRX0, boolean ignore_other_rx := true)
10290runs on test_CT return template (omit) RSL_Message {
10291 var ASP_RSL_Unitdata rx_rsl_ud;
10292 timer T := t_secs;
10293
10294 T.start;
10295 alt {
10296 [] IPA_RSL[bts_nr].receive(tr_ASP_RSL_UD(t_rx, sid)) -> value rx_rsl_ud {
10297 T.stop;
10298 }
10299 [ignore_other_rx] IPA_RSL[bts_nr].receive { repeat; }
10300 [not ignore_other_rx] IPA_RSL[bts_nr].receive {
10301 log("f_exp_ipa_rx_nonfatal(): Got different message than ", t_rx);
10302 T.stop;
10303 return omit;
10304 }
10305 [] T.timeout {
10306 return omit;
10307 }
10308 }
10309 return rx_rsl_ud.rsl;
10310}
10311
10312private function f_vty_set_imm_ass(TELNETasp_PT pt, BtsNr bts_nr := 0, charstring imm_ass_setting := "post-chan-ack") {
10313 f_vty_enter_cfg_bts(pt, bts_nr);
10314 f_vty_transceive(pt, "immediate-assignment " & imm_ass_setting);
10315 f_vty_transceive(pt, "exit");
10316 f_vty_transceive(pt, "exit");
10317 f_vty_transceive(pt, "exit");
10318}
10319
10320private function f_verify_imm_ass(RSL_Message imm_ass, template uint8_t ra := ?, template GsmFrameNumber fn := ?,
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020010321 template RslChannelNr chan_nr := ?,
10322 template (present) uint12_t arfcn := ?,
10323 template (present) uint3_t tsc := ?)
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020010324{
10325 var RSL_IE_Body full_imm_ass_info;
10326 if (not f_rsl_find_ie(imm_ass, RSL_IE_FULL_IMM_ASS_INFO, full_imm_ass_info)) {
10327 setverdict(fail, "RSL Full Immediate Assign Info IE is absent");
10328 mtc.stop;
10329 }
10330
10331 var GsmRrMessage rr_imm_ass := dec_GsmRrMessage(full_imm_ass_info.full_imm_ass_info.payload);
10332 var template GsmRrMessage expect_imm_ass := tr_IMM_ASS(ra := ra,
10333 fn := fn,
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020010334 ch_desc := tr_ChanDescH0(chan_nr, arfcn, tsc),
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020010335 page_mode := ?);
10336 if (not match(rr_imm_ass, expect_imm_ass)) {
10337 log("Error: expected ", expect_imm_ass, " got ", rr_imm_ass);
10338 setverdict(fail, "Failed to match Immediate Assignment");
10339 mtc.stop;
10340 }
10341}
10342
10343testcase TC_imm_ass_post_chan_ack() runs on test_CT {
10344 var RSL_Message chan_act;
10345 var RSL_Message imm_ass;
10346
10347 f_init(1, false);
10348 f_sleep(1.0);
10349
10350 /* (should be the default anyway, just to make things clear) */
10351 f_vty_set_imm_ass(BSCVTY, 0, "post-chan-ack");
10352
10353 /* RA containing reason=LU */
10354 var GsmFrameNumber fn := 2342;
10355 var uint8_t ra := 2;
10356 f_ipa_tx(0, ts_RSL_CHAN_RQD(int2oct(ra, 1), fn));
10357
10358 chan_act := f_exp_ipa_rx(0, tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
10359
10360 /* First send the Chan Act ACK */
10361 var RslChannelNr chan_nr := chan_act.ies[0].body.chan_nr;
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010010362 var DchanTuple dt;
10363 dt.rsl_chan_nr := chan_nr;
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020010364 var RSL_IE_Body chan_ident_ie;
10365 if (not f_rsl_find_ie(chan_act, RSL_IE_CHAN_IDENT, chan_ident_ie)) {
10366 setverdict(fail, "RSL Channel Identification IE is absent");
10367 mtc.stop;
10368 }
10369
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020010370 f_ipa_tx(0, ts_RSL_CHAN_ACT_ACK(chan_nr, fn + 10));
10371
10372 /* Then expect the Immediate Assignment, after we ACKed the chan act */
10373 imm_ass := f_exp_ipa_rx(0, tr_RSL_IMM_ASSIGN(0));
10374
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020010375 f_verify_imm_ass(imm_ass, ra, fn, chan_nr, chan_ident_ie.chan_ident.ch_desc.v.arfcn,
10376 chan_ident_ie.chan_ident.ch_desc.v.tsc);
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020010377
10378 /* Check that the lchan is working */
10379 var octetstring l3 := '00010203040506'O;
10380 f_ipa_tx(0, ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3));
10381
10382 var BSSAP_N_CONNECT_ind rx_c_ind;
10383 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3))) -> value rx_c_ind;
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010010384 dt.sccp_conn_id := rx_c_ind.connectionId;
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020010385 BSSAP.send(ts_BSSAP_CONNECT_res(rx_c_ind.connectionId));
10386
10387 f_sleep(1.0);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010010388 f_perform_clear_test_ct(dt);
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020010389 f_shutdown_helper();
10390}
10391
10392testcase TC_imm_ass_pre_chan_ack() runs on test_CT {
10393 var RSL_Message chan_act;
10394 var RSL_Message imm_ass;
10395
10396 f_init(1, false);
10397 f_sleep(1.0);
10398
10399 f_vty_set_imm_ass(BSCVTY, 0, "pre-chan-ack");
10400
10401 /* RA containing reason=LU */
10402 var GsmFrameNumber fn := 2342;
10403 var uint8_t ra := 2;
10404 f_ipa_tx(0, ts_RSL_CHAN_RQD(int2oct(ra, 1), fn));
10405
10406 /* (set bts 0 cfg back to default) */
10407 f_vty_set_imm_ass(BSCVTY);
10408
10409 chan_act := f_exp_ipa_rx(0, tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
10410 var RslChannelNr chan_nr := chan_act.ies[0].body.chan_nr;
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010010411 var DchanTuple dt;
10412 dt.rsl_chan_nr := chan_nr;
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020010413 var RSL_IE_Body chan_ident_ie;
10414 if (not f_rsl_find_ie(chan_act, RSL_IE_CHAN_IDENT, chan_ident_ie)) {
10415 setverdict(fail, "RSL Channel Identification IE is absent");
10416 mtc.stop;
10417 }
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020010418
10419 /* *FIRST* expect the Immediate Assignment, before we ACK the chan act */
10420 imm_ass := f_exp_ipa_rx(0, tr_RSL_IMM_ASSIGN(0));
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020010421 f_verify_imm_ass(imm_ass, ra, fn, chan_nr, chan_ident_ie.chan_ident.ch_desc.v.arfcn,
10422 chan_ident_ie.chan_ident.ch_desc.v.tsc);
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020010423
10424 /* Only now send the Chan Act ACK */
10425 f_ipa_tx(0, ts_RSL_CHAN_ACT_ACK(chan_nr, fn+10));
10426
10427 /* Check that the lchan is working */
10428 var octetstring l3 := '00010203040506'O;
10429 f_ipa_tx(0, ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3));
10430
10431 var BSSAP_N_CONNECT_ind rx_c_ind;
10432 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3))) -> value rx_c_ind;
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010010433 dt.sccp_conn_id := rx_c_ind.connectionId;
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020010434 BSSAP.send(ts_BSSAP_CONNECT_res(rx_c_ind.connectionId));
10435
10436 f_sleep(1.0);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010010437 f_perform_clear_test_ct(dt);
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020010438 f_shutdown_helper();
10439}
10440
Neels Hofmeyr23158742021-09-07 19:08:07 +020010441testcase TC_imm_ass_pre_ts_ack() runs on test_CT {
10442 var RSL_Message chan_act;
10443 var RSL_Message imm_ass;
10444
10445 f_init(1, false);
10446 f_sleep(1.0);
10447
10448 f_vty_set_imm_ass(BSCVTY, 0, "pre-ts-ack");
10449
10450 /* RA containing reason=LU */
10451 var GsmFrameNumber fn := 2342;
10452 var uint8_t ra := 2;
10453 f_ipa_tx(0, ts_RSL_CHAN_RQD(int2oct(ra, 1), fn));
10454
10455 /* (set bts 0 cfg back to default) */
10456 f_vty_set_imm_ass(BSCVTY);
10457
10458 chan_act := f_exp_ipa_rx(0, tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
10459 var RslChannelNr chan_nr := chan_act.ies[0].body.chan_nr;
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010010460 var DchanTuple dt;
10461 dt.rsl_chan_nr := chan_nr;
Neels Hofmeyr23158742021-09-07 19:08:07 +020010462 var RSL_IE_Body chan_ident_ie;
10463 if (not f_rsl_find_ie(chan_act, RSL_IE_CHAN_IDENT, chan_ident_ie)) {
10464 setverdict(fail, "RSL Channel Identification IE is absent");
10465 mtc.stop;
10466 }
10467
10468 /* *FIRST* expect the Immediate Assignment, before we ACK the chan act */
10469 imm_ass := f_exp_ipa_rx(0, tr_RSL_IMM_ASSIGN(0));
10470 f_verify_imm_ass(imm_ass, ra, fn, chan_nr, chan_ident_ie.chan_ident.ch_desc.v.arfcn,
10471 chan_ident_ie.chan_ident.ch_desc.v.tsc);
10472
10473 /* Only now send the Chan Act ACK */
10474 f_ipa_tx(0, ts_RSL_CHAN_ACT_ACK(chan_nr, fn+10));
10475
10476 /* Check that the lchan is working */
10477 var octetstring l3 := '00010203040506'O;
10478 f_ipa_tx(0, ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3));
10479
10480 var BSSAP_N_CONNECT_ind rx_c_ind;
10481 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3))) -> value rx_c_ind;
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010010482 dt.sccp_conn_id := rx_c_ind.connectionId;
Neels Hofmeyr23158742021-09-07 19:08:07 +020010483 BSSAP.send(ts_BSSAP_CONNECT_res(rx_c_ind.connectionId));
10484
10485 f_sleep(1.0);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010010486 f_perform_clear_test_ct(dt);
Neels Hofmeyr23158742021-09-07 19:08:07 +020010487 f_shutdown_helper();
10488}
10489
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020010490testcase TC_imm_ass_pre_chan_ack_dyn_ts() runs on test_CT {
10491 /* change Timeslot 6 before f_init() starts RSL */
10492 f_init_vty();
10493 f_ts_set_chcomb(0, 0, 6, "TCH/F_TCH/H_PDCH");
10494 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
10495
10496 f_init(1, false);
10497 f_sleep(1.0);
10498
10499 var RslChannelNr chan_nr := valueof(t_RslChanNr_PDCH(6));
10500 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiy58b16532021-10-09 20:27:39 +060010501 f_exp_ipa_rx(0, tr_RSL_CHAN_ACT_PDCH(chan_nr));
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020010502 f_ipa_tx(0, ts_RSL_CHAN_ACT_ACK(chan_nr, 2323));
10503
10504 /* clean up timeslot 6 config, will only take effect when the OML drops the next time */
10505 f_ts_set_chcomb(0, 0, 6, "PDCH");
10506
10507 /* block all static timeslots so that the dyn TS will be used */
10508 f_disable_all_tch_f();
10509 f_disable_all_tch_h();
10510 f_disable_all_sdcch();
10511
10512 var RSL_Message chan_act;
10513 var RSL_Message imm_ass;
10514
10515 f_init(1, false);
10516 f_sleep(1.0);
10517
10518 f_vty_set_imm_ass(BSCVTY, 0, "pre-chan-ack");
10519
10520 /* RA containing reason=LU */
10521 var GsmFrameNumber fn := 2342;
10522 var uint8_t ra := 2;
10523 f_ipa_tx(0, ts_RSL_CHAN_RQD(int2oct(ra, 1), fn));
10524
10525 /* (set bts 0 cfg back to default) */
10526 f_vty_set_imm_ass(BSCVTY);
10527
10528 /* Expect the dyn TS to deactivate PDCH first */
10529 f_exp_ipa_rx(0, tr_RSL_RF_CHAN_REL(chan_nr));
10530 f_ipa_tx(0, ts_RSL_RF_CHAN_REL_ACK(chan_nr));
10531
10532 /* Now activation as SDCCH8 */
10533 chan_nr := valueof(t_RslChanNr_SDCCH8(tn := 6, sub_slot := 0));
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010010534 var DchanTuple dt;
10535 dt.rsl_chan_nr := chan_nr;
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020010536
10537 chan_act := f_exp_ipa_rx(0, tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020010538 var RSL_IE_Body chan_ident_ie;
10539 if (not f_rsl_find_ie(chan_act, RSL_IE_CHAN_IDENT, chan_ident_ie)) {
10540 setverdict(fail, "RSL Channel Identification IE is absent");
10541 mtc.stop;
10542 }
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020010543
10544 /* *FIRST* expect the Immediate Assignment, before we ACK the chan act */
10545 imm_ass := f_exp_ipa_rx(0, tr_RSL_IMM_ASSIGN(0));
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020010546 f_verify_imm_ass(imm_ass, ra, fn, chan_nr, chan_ident_ie.chan_ident.ch_desc.v.arfcn,
10547 chan_ident_ie.chan_ident.ch_desc.v.tsc);
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020010548
10549 /* Only now send the Chan Act ACK */
10550 f_ipa_tx(0, ts_RSL_CHAN_ACT_ACK(chan_nr, fn+10));
10551
10552 /* Check that the lchan is working */
10553 var octetstring l3 := '00010203040506'O;
10554 f_ipa_tx(0, ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3));
10555
10556 var BSSAP_N_CONNECT_ind rx_c_ind;
10557 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3))) -> value rx_c_ind;
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010010558 dt.sccp_conn_id := rx_c_ind.connectionId;
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020010559 BSSAP.send(ts_BSSAP_CONNECT_res(rx_c_ind.connectionId));
10560
10561 f_sleep(1.0);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010010562 f_perform_clear_test_ct(dt);
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020010563 f_shutdown_helper();
10564}
10565
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020010566testcase TC_imm_ass_pre_ts_ack_dyn_ts() runs on test_CT {
10567 /* change Timeslot 6 before f_init() starts RSL */
10568 f_init_vty();
10569 f_ts_set_chcomb(0, 0, 6, "TCH/F_TCH/H_PDCH");
10570 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
10571
10572 f_init(1, false);
10573 f_sleep(1.0);
10574
10575 var RslChannelNr chan_nr := valueof(t_RslChanNr_PDCH(6));
10576 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiy58b16532021-10-09 20:27:39 +060010577 f_exp_ipa_rx(0, tr_RSL_CHAN_ACT_PDCH(chan_nr));
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020010578 f_ipa_tx(0, ts_RSL_CHAN_ACT_ACK(chan_nr, 2323));
10579
10580 /* clean up timeslot 6 config, will only take effect when the OML drops the next time */
10581 f_ts_set_chcomb(0, 0, 6, "PDCH");
10582
10583 /* block all static timeslots so that the dyn TS will be used */
10584 f_disable_all_tch_f();
10585 f_disable_all_tch_h();
10586 f_disable_all_sdcch();
10587
10588 var RSL_Message chan_act;
10589 var RSL_Message imm_ass;
10590
10591 f_init(1, false);
10592 f_sleep(1.0);
10593
10594 f_vty_set_imm_ass(BSCVTY, 0, "pre-ts-ack");
10595
10596 /* RA containing reason=LU */
10597 var GsmFrameNumber fn := 2342;
10598 var uint8_t ra := 2;
10599 f_ipa_tx(0, ts_RSL_CHAN_RQD(int2oct(ra, 1), fn));
10600
10601 /* (set bts 0 cfg back to default) */
10602 f_vty_set_imm_ass(BSCVTY);
10603
10604 /* Expect the dyn TS to deactivate PDCH first */
10605 f_exp_ipa_rx(0, tr_RSL_RF_CHAN_REL(chan_nr));
10606
10607 /* And already the Immediate Assignment even before the PDCH Deact ACK */
10608 imm_ass := f_exp_ipa_rx(0, tr_RSL_IMM_ASSIGN(0));
10609
10610 /* continue the Osmo style PDCH Deact (usual chan rel) */
10611 f_ipa_tx(0, ts_RSL_RF_CHAN_REL_ACK(chan_nr));
10612
10613 /* Now activation as SDCCH8 */
10614 chan_nr := valueof(t_RslChanNr_SDCCH8(tn := 6, sub_slot := 0));
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010010615 var DchanTuple dt;
10616 dt.rsl_chan_nr := chan_nr;
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020010617
10618 chan_act := f_exp_ipa_rx(0, tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020010619 var RSL_IE_Body chan_ident_ie;
10620 if (not f_rsl_find_ie(chan_act, RSL_IE_CHAN_IDENT, chan_ident_ie)) {
10621 setverdict(fail, "RSL Channel Identification IE is absent");
10622 mtc.stop;
10623 }
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020010624 f_ipa_tx(0, ts_RSL_CHAN_ACT_ACK(chan_nr, fn+10));
10625
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020010626 f_verify_imm_ass(imm_ass, ra, fn, chan_nr, chan_ident_ie.chan_ident.ch_desc.v.arfcn,
10627 chan_ident_ie.chan_ident.ch_desc.v.tsc);
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020010628
10629 /* Check that the lchan is working */
10630 var octetstring l3 := '00010203040506'O;
10631 f_ipa_tx(0, ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3));
10632
10633 var BSSAP_N_CONNECT_ind rx_c_ind;
10634 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3))) -> value rx_c_ind;
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010010635 dt.sccp_conn_id := rx_c_ind.connectionId;
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020010636 BSSAP.send(ts_BSSAP_CONNECT_res(rx_c_ind.connectionId));
10637
10638 f_sleep(1.0);
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010010639 f_perform_clear_test_ct(dt);
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020010640 f_shutdown_helper();
10641}
10642
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020010643/* GET and SET the bts.N.trx.M.rf_locked CTRL variable */
10644testcase TC_ctrl_trx_rf_locked() runs on test_CT {
10645 var MSC_ConnHdlr vc_conn;
10646
10647 f_init(nr_bts := 2, handler_mode := true, nr_msc := 1);
10648 f_sleep(1.0);
10649
10650 /* BTS 0, 1, 2 are OML unlocked, only BTS 0, 1 are actually connected to RSL. */
10651 f_ctrl_get_exp(IPA_CTRL, "rf_states",
10652 "0,0,operational,unlocked,on,rsl-up;" &
10653 "1,0,operational,unlocked,on,rsl-up;" &
10654 "2,0,operational,unlocked,on,rsl-down;" &
10655 "3,0,inoperational,locked,on,rsl-down;");
10656
10657 f_logp(BSCVTY, "TC_ctrl_trx_rf_locked: lock BTS 1 TRX 0");
10658 f_ctrl_set(IPA_CTRL, "bts.1.trx.0.rf_locked", "1");
10659 /* give it a moment to settle the FSM status */
10660 f_sleep(1.0);
10661
10662 /* Now BTS 1 TRX 0 should reflect "locked". Note the RF policy stays "on", because this is still handled
10663 * globally in osmo-bsc. Probably after sending "rf_locked 1" for a TRX, that TRX should reflect an RF policy
10664 * of "off"? But that's for a future patch if at all. */
10665 f_ctrl_get_exp(IPA_CTRL, "rf_states",
10666 "0,0,operational,unlocked,on,rsl-up;" &
10667 "1,0,operational,locked,on,rsl-up;" &
10668 "2,0,operational,unlocked,on,rsl-down;" &
10669 "3,0,inoperational,locked,on,rsl-down;");
10670
10671 f_logp(BSCVTY, "TC_ctrl_trx_rf_locked: lock the already locked TRX, nothing should change");
10672 f_ctrl_set(IPA_CTRL, "bts.1.trx.0.rf_locked", "1");
10673 f_sleep(1.0);
10674 f_ctrl_get_exp(IPA_CTRL, "rf_states",
10675 "0,0,operational,unlocked,on,rsl-up;" &
10676 "1,0,operational,locked,on,rsl-up;" &
10677 "2,0,operational,unlocked,on,rsl-down;" &
10678 "3,0,inoperational,locked,on,rsl-down;");
10679
10680 f_logp(BSCVTY, "TC_ctrl_trx_rf_locked: unlock BTS 1 TRX 0");
10681 f_ctrl_set(IPA_CTRL, "bts.1.trx.0.rf_locked", "0");
10682 f_sleep(1.0);
10683 f_ctrl_get_exp(IPA_CTRL, "rf_states",
10684 "0,0,operational,unlocked,on,rsl-up;" &
10685 "1,0,operational,unlocked,on,rsl-up;" &
10686 "2,0,operational,unlocked,on,rsl-down;" &
10687 "3,0,inoperational,locked,on,rsl-down;");
10688
10689 f_logp(BSCVTY, "TC_ctrl_trx_rf_locked: unlock an already unlocked TRX, nothing should change");
10690 f_ctrl_set(IPA_CTRL, "bts.0.trx.0.rf_locked", "0");
10691 f_sleep(1.0);
10692 f_ctrl_get_exp(IPA_CTRL, "rf_states",
10693 "0,0,operational,unlocked,on,rsl-up;" &
10694 "1,0,operational,unlocked,on,rsl-up;" &
10695 "2,0,operational,unlocked,on,rsl-down;" &
10696 "3,0,inoperational,locked,on,rsl-down;");
10697
10698 f_logp(BSCVTY, "TC_ctrl_trx_rf_locked: unlock an inoperational TRX");
10699 f_ctrl_set(IPA_CTRL, "bts.3.trx.0.rf_locked", "0");
10700 f_sleep(1.0);
10701 f_ctrl_get_exp(IPA_CTRL, "rf_states",
10702 "0,0,operational,unlocked,on,rsl-up;" &
10703 "1,0,operational,unlocked,on,rsl-up;" &
10704 "2,0,operational,unlocked,on,rsl-down;" &
10705 "3,0,inoperational,locked,on,rsl-down;");
10706
10707 f_shutdown_helper();
10708}
10709
Neels Hofmeyrb7581872021-11-07 14:02:49 +010010710const CounterNameVals counternames_cm_serv_rej := {
10711 { "cm_serv_rej", 0 },
10712 { "cm_serv_rej:imsi_unknown_in_hlr", 0 },
10713 { "cm_serv_rej:illegal_ms", 0 },
10714 { "cm_serv_rej:imsi_unknown_in_vlr", 0 },
10715 { "cm_serv_rej:imei_not_accepted", 0 },
10716 { "cm_serv_rej:illegal_me", 0 },
10717 { "cm_serv_rej:plmn_not_allowed", 0 },
10718 { "cm_serv_rej:loc_not_allowed", 0 },
10719 { "cm_serv_rej:roaming_not_allowed", 0 },
10720 { "cm_serv_rej:network_failure", 0 },
10721 { "cm_serv_rej:synch_failure", 0 },
10722 { "cm_serv_rej:congestion", 0 },
10723 { "cm_serv_rej:srv_opt_not_supported", 0 },
10724 { "cm_serv_rej:rqd_srv_opt_not_supported", 0 },
10725 { "cm_serv_rej:srv_opt_tmp_out_of_order", 0 },
10726 { "cm_serv_rej:call_can_not_be_identified", 0 },
10727 { "cm_serv_rej:incorrect_message", 0 },
10728 { "cm_serv_rej:invalid_mandantory_inf", 0 },
10729 { "cm_serv_rej:msg_type_not_implemented", 0 },
10730 { "cm_serv_rej:msg_type_not_compatible", 0 },
10731 { "cm_serv_rej:inf_eleme_not_implemented", 0 },
10732 { "cm_serv_rej:condtional_ie_error", 0 },
10733 { "cm_serv_rej:msg_not_compatible", 0 },
10734 { "cm_serv_rej:protocol_error", 0 },
10735 { "cm_serv_rej:retry_in_new_cell", 0 }
10736};
10737
10738private function f_TC_cm_serv_rej(charstring id) runs on MSC_ConnHdlr
10739{
10740 f_create_chan_and_exp();
Vadim Yanitskiya7fc5a62021-12-04 20:10:08 +030010741 /* we should now have a COMPL_L3 at the MSC */
Neels Hofmeyrb7581872021-11-07 14:02:49 +010010742 BSSAP.send(ts_PDU_DTAP_MT(ts_CM_SERV_REJ('02'O), '00'O));
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010010743 RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_CM_SERV_REJ));
10744 f_perform_clear();
Neels Hofmeyr87a65612021-11-16 15:56:45 +010010745 f_sleep(1.0);
Neels Hofmeyrb7581872021-11-07 14:02:49 +010010746}
10747testcase TC_cm_serv_rej() runs on test_CT {
10748 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10749 var MSC_ConnHdlr vc_conn;
10750
10751 f_init(1, true);
10752 f_sleep(1.0);
10753
10754 f_ctrs_bts_init(1, counternames_cm_serv_rej);
10755
10756 vc_conn := f_start_handler(refers(f_TC_cm_serv_rej), pars);
10757 vc_conn.done;
10758
10759 f_ctrs_bts_add(0, "cm_serv_rej", 1);
10760 f_ctrs_bts_add(0, "cm_serv_rej:imsi_unknown_in_hlr", 1);
10761 f_ctrs_bts_verify();
10762
Neels Hofmeyr87a65612021-11-16 15:56:45 +010010763 f_sleep(1.0);
Neels Hofmeyrb7581872021-11-07 14:02:49 +010010764 f_shutdown_helper();
10765}
10766
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020010767/* Reproduce a segfault happening when the SDCCH (primary) lchan is lost in-between a TCH Channel Activ and its Channel
10768 * Activ Ack (SYS#5627). */
10769private function f_TC_lost_sdcch_during_assignment(charstring id) runs on MSC_ConnHdlr {
10770 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Vadim Yanitskiyf0310e32021-10-26 00:30:59 +030010771
10772 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
10773 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020010774
10775 var BSSMAP_FIELD_CodecType codecType;
10776 codecType := valueof(ass_cmd.pdu.bssmap.assignmentRequest.codecList.codecElements[0].codecType);
10777
10778 f_MscConnHdlr_init(g_pars.media_nr, host_bts, host_mgw_mgcp, codecType);
10779
10780 /* First establish a signalling lchan */
10781 f_create_chan_and_exp();
10782 f_rslem_dchan_queue_enable();
10783
10784 /* we should now have a COMPL_L3 at the MSC */
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020010785
10786 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
10787 activate(as_Media_mgw());
10788
10789 var RslChannelNr chan_nr := { u := { ch0 := RSL_CHAN_NR_Bm_ACCH }, tn := 1 };
10790 f_rslem_register(0, chan_nr);
10791
10792 f_rslem_set_auto_chan_act_ack(RSL_PROC, false);
10793 BSSAP.send(ass_cmd);
10794
10795
10796 /* Wait for the Channel Activ for the TCH channel */
10797 var ASP_RSL_Unitdata rx_rsl_ud;
10798 RSL.receive(tr_ASP_RSL_UD(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV), sid := ?)) -> value rx_rsl_ud;
10799
10800 /* make the original SDCCH disappear */
10801 RSL.send(ts_RSL_REL_IND(g_chan_nr, valueof(ts_RslLinkID_DCCH(0))));
10802
10803 /* and ACK the TCH channel activation. This caused a segfault up to OsmoBSC 1.7.0 (SYS#5627) */
10804 RSL.send(ts_ASP_RSL_UD(ts_RSL_CHAN_ACT_ACK(chan_nr, 23), rx_rsl_ud.streamId));
10805
10806 interleave {
10807 [] BSSAP.receive(tr_BSSMAP_AssignmentFail);
10808 [] BSSAP.receive(tr_BSSMAP_ClearRequest);
10809 }
10810
10811 BSSAP.send(ts_BSSMAP_ClearCommand(0));
10812 BSSAP.receive(tr_BSSMAP_ClearComplete);
10813 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
10814
10815 var MgcpCommand mgcp;
10816 MGCP.receive(tr_DLCX()) -> value mgcp {
10817 MGCP.send(ts_DLCX_ACK2(mgcp.line.trans_id));
10818 };
10819
10820 f_sleep(0.5);
10821}
10822testcase TC_lost_sdcch_during_assignment() runs on test_CT {
10823 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10824 var MSC_ConnHdlr vc_conn;
10825
10826 f_init(1, true);
10827 f_sleep(1.0);
10828
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020010829 vc_conn := f_start_handler(refers(f_TC_lost_sdcch_during_assignment), pars);
10830 vc_conn.done;
10831
10832 f_shutdown_helper();
10833}
10834
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020010835const CounterNameVals counternames_bsc_bts_all_available_allocated := {
10836 { "all_allocated:sdcch", 0 },
10837 { "all_allocated:static_sdcch", 0 },
10838 { "all_allocated:tch", 0 },
10839 { "all_allocated:static_tch", 0 }
10840}
10841
10842private function f_all_allocated_expect_counter_change(charstring_list expect_changed) runs on test_CT
10843{
10844 /* Make sure counters settle first */
10845 f_sleep(1.0);
10846
10847 /* Take a baseline of counters */
10848 f_ctrs_bsc_and_bts_init(1, counternames_bsc_bts_all_available_allocated);
10849
10850 /* Elapse some time so that we see changes in counters, hopefully where expected */
10851 f_sleep(2.0);
10852
10853 /* Get new counters */
10854 var charstring_list all_changed := {};
10855 all_changed := all_changed & f_counter_name_vals_get_changed_n(IPA_CTRL, "bsc", g_ctr_bsc);
10856 all_changed := all_changed & f_counter_name_vals_get_changed_n(IPA_CTRL, "bts", g_ctr_bts);
10857
10858 /* Compare with expectations */
10859 var charstring_list all_expect_changed := {};
10860 for (var integer i := 0; i < lengthof(expect_changed); i := i + 1) {
10861 all_expect_changed := all_expect_changed & { "bsc.0." & expect_changed[i], "bts.0." & expect_changed[i] };
10862 }
10863 f_counter_name_vals_expect_changed_list(all_changed, all_expect_changed);
10864}
10865
10866testcase TC_ratectr_all_available_allocated() runs on test_CT {
10867 var ASP_RSL_Unitdata rsl_ud;
10868 var integer i;
10869 var integer chreq_total, chreq_nochan;
10870
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010010871 f_init(1, guard_timeout := 60.0);
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020010872 f_sleep(1.0);
10873
10874 /* Exhaust all dedicated SDCCH lchans.
10875 /* GSM 44.018 Table 9.1.8.2:
10876 * RA = '13'O -> Establishment cause = 0001xxxx (MS dual rate capable and asks for "SDCCH").
10877 */
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010010878 var DchanTuples chan_cleanup := {};
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020010879 for (i := 0; i < NUM_SDCCH_PER_BTS; i := i+1) {
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010010880 chan_cleanup := chan_cleanup & { f_est_dchan('13'O, NUM_SDCCH_PER_BTS + i, '00010203040506'O) };
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020010881 }
10882
10883 /* Since only bts 0 is connected, expecting all_allocated to become true for both bts 0 and the "global" bsc
10884 * level.
10885 * All SDCCH are now occupied. */
10886 f_all_allocated_expect_counter_change({"all_allocated:sdcch", "all_allocated:static_sdcch"});
10887
10888 /* Also fill up all remaining (TCH) channels */
10889 for (i := 0; i < NUM_TCHF_PER_BTS + NUM_TCHH_PER_BTS; i := i+1) {
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010010890 chan_cleanup := chan_cleanup & { f_est_dchan('33'O, NUM_SDCCH_PER_BTS + i, '00010203040506'O) };
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020010891 }
10892
10893 /* All TCH are now also occupied */
10894 f_all_allocated_expect_counter_change({"all_allocated:sdcch", "all_allocated:static_sdcch",
10895 "all_allocated:tch", "all_allocated:static_tch"});
10896
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010010897 /* Clean up SDCCH lchans */
10898 for (i := 0; i < lengthof(chan_cleanup); i := i + 1) {
10899 f_perform_clear_test_ct(chan_cleanup[i]);
10900 }
10901
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020010902 f_shutdown_helper();
10903}
10904
10905testcase TC_ratectr_all_available_allocated_dyn() runs on test_CT {
10906 var ASP_RSL_Unitdata rsl_ud;
10907 var integer i;
10908 var integer chreq_total, chreq_nochan;
10909
10910 f_init_vty();
10911 f_ts_set_chcomb(0, 0, 2, "TCH/F_TCH/H_PDCH");
10912 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
10913 /* Now we have 3 TCH/F, 1 OSMO_DYN, 1 TCH/H */
10914
10915 f_init(1, guard_timeout := 60.0);
10916 f_sleep(1.0);
10917
10918 /* The dyn TS wants to activate PDCH mode, ACK that. */
10919 var RslChannelNr chan_nr;
10920 chan_nr := valueof(t_RslChanNr_PDCH(2));
Vadim Yanitskiy58b16532021-10-09 20:27:39 +060010921 f_exp_ipa_rx(0, tr_RSL_CHAN_ACT_PDCH(chan_nr));
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020010922 f_ipa_tx(0, ts_RSL_CHAN_ACT_ACK(chan_nr, 2342));
10923
10924 /* Exhaust all dedicated SDCCH lchans.
10925 /* GSM 44.018 Table 9.1.8.2:
10926 * RA = '13'O -> Establishment cause = 0001xxxx (MS dual rate capable and asks for "SDCCH").
10927 */
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010010928 var DchanTuples chan_cleanup := {};
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020010929 for (i := 0; i < NUM_SDCCH_PER_BTS; i := i+1) {
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010010930 chan_cleanup := chan_cleanup & { f_est_dchan('13'O, NUM_SDCCH_PER_BTS + i, '00010203040506'O) };
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020010931 }
10932
10933 /* The static SDCCH should now be occupied, while still 3x8 dynamic SDCCH potentially remain. So only
10934 * all_allocated:static_sdcch is counted, all_allocated:sdcch remains zero. */
10935 f_all_allocated_expect_counter_change({"all_allocated:static_sdcch"});
10936
10937 /* Request more SDCCH, hence convert the first dyn TS to SDCCH8.
10938 * Will release them later, so remember all the DchanTuples. */
10939 var DchanTuples dyn_sddch := {};
10940 dyn_sddch := dyn_sddch & { f_est_dchan_dyn('33'O, NUM_SDCCH_PER_BTS + i, '00010203040506'O) };
10941
10942 /* Also occupy the seven other SDCCH of the dyn TS */
10943 for (i := 0; i < 7; i := i+1) {
10944 dyn_sddch := dyn_sddch & { f_est_dchan('33'O, NUM_SDCCH_PER_BTS + i, '00010203040506'O) };
10945 }
10946
10947 /* Now all dynamic SDCCH are also occupied, so for the first time all_allocated:sdcch will trigger... */
10948 f_all_allocated_expect_counter_change({"all_allocated:sdcch", "all_allocated:static_sdcch"});
10949
10950 /* occupy the remaining TCH, three TCH/F and two TCH/H lchans */
10951 for (i := 0; i < 5; i := i+1) {
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010010952 chan_cleanup := chan_cleanup & { f_est_dchan('33'O, NUM_SDCCH_PER_BTS + i, '00010203040506'O) };
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020010953 }
10954
10955 /* All TCH lchans are now also occupied, both static and dynamic */
10956 f_all_allocated_expect_counter_change({"all_allocated:sdcch", "all_allocated:static_sdcch",
10957 "all_allocated:tch", "all_allocated:static_tch"});
10958
10959 /* Starting to release the dyn TS: as soon as the first SDCCH gets released, all_allocated:sdcch stops
10960 * incrementing. */
10961 var BssmapCause cause := 0;
10962 var DchanTuple dt := dyn_sddch[0];
10963 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
10964 f_exp_chan_rel_and_clear(dt, 0);
10965
10966 /* one dyn TS SDCCH is free again, so only the static_sdcch should increment. For tch, both static and dynamic
10967 * count as occupied, so those still both increment. */
10968 f_all_allocated_expect_counter_change({"all_allocated:static_sdcch",
10969 "all_allocated:tch", "all_allocated:static_tch"});
10970
10971 /* Release the remaining SDCCH of the dyn TS, so it becomes available as TCH again */
10972 for (i := 1; i < lengthof(dyn_sddch); i := i+1) {
10973 dt := dyn_sddch[i];
10974 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
10975 f_exp_chan_rel_and_clear(dt, 0);
10976 }
10977
10978 /* All SDCCH on the dyn TS are released, the dyn TS wants to activate PDCH again */
10979 chan_nr := valueof(t_RslChanNr_PDCH(2));
Vadim Yanitskiy58b16532021-10-09 20:27:39 +060010980 f_exp_ipa_rx(0, tr_RSL_CHAN_ACT_PDCH(chan_nr));
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020010981 f_ipa_tx(0, ts_RSL_CHAN_ACT_ACK(chan_nr, 2342));
10982
10983 /* Now all channels are occupied except the dyn TS, so expecting only the static counters to increment */
10984 f_all_allocated_expect_counter_change({"all_allocated:static_sdcch", "all_allocated:static_tch"});
10985
Neels Hofmeyr4d4cd7e2021-12-14 17:25:36 +010010986 /* Clean up SDCCH lchans */
10987 for (i := 0; i < lengthof(chan_cleanup); i := i + 1) {
10988 f_perform_clear_test_ct(chan_cleanup[i]);
10989 }
10990
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020010991 /* clean up config */
10992 f_ts_reset_chcomb(0);
10993
10994 f_shutdown_helper();
10995}
10996
Harald Welte28d943e2017-11-25 15:00:50 +010010997control {
Harald Welte898113b2018-01-31 18:32:21 +010010998 /* CTRL interface testing */
Harald Welte4003d112017-12-09 22:35:39 +010010999 execute( TC_ctrl_msc_connection_status() );
Stefan Sperlingb041b3d2018-01-03 17:14:55 +010011000 execute( TC_ctrl_msc0_connection_status() );
Neels Hofmeyrf65ce872021-09-23 18:40:10 +020011001 /* In SCCPlite tests, only one MSC is configured. These tests assume that three MSCs are configured, so only run
11002 * these in the AoIP test suite. */
11003 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
11004 execute( TC_stat_num_msc_connected_1() );
11005 execute( TC_stat_num_msc_connected_2() );
11006 execute( TC_stat_num_msc_connected_3() );
11007 }
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +020011008 execute( TC_stat_num_bts_connected_1() );
11009 execute( TC_stat_num_bts_connected_2() );
11010 execute( TC_stat_num_bts_connected_3() );
Harald Welte96c94412017-12-09 03:12:45 +010011011 execute( TC_ctrl() );
Neels Hofmeyrf246a922020-05-13 02:27:10 +020011012 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_SCCPlite_SERVER) {
Pau Espin Pedrol5a2d7432019-06-07 19:43:45 +020011013 execute( TC_ctrl_location() );
11014 }
Harald Welte898113b2018-01-31 18:32:21 +010011015
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +020011016 execute( TC_si_default() );
Neels Hofmeyr66aeba42020-07-06 02:21:21 +020011017 execute( TC_si2quater_2_earfcns() );
11018 execute( TC_si2quater_3_earfcns() );
11019 execute( TC_si2quater_4_earfcns() );
11020 execute( TC_si2quater_5_earfcns() );
11021 execute( TC_si2quater_6_earfcns() );
Neels Hofmeyrad132f22020-07-08 02:20:16 +020011022 execute( TC_si2quater_12_earfcns() );
11023 execute( TC_si2quater_23_earfcns() );
11024 execute( TC_si2quater_32_earfcns() );
11025 execute( TC_si2quater_33_earfcns() );
11026 execute( TC_si2quater_42_earfcns() );
11027 execute( TC_si2quater_48_earfcns() );
11028 execute( TC_si2quater_49_earfcns() );
Pau Espin Pedrol85a84432020-07-20 18:45:03 +020011029 execute( TC_si_acc_rotate() );
Alexander Couzens4ad3a352020-09-10 22:29:12 +020011030 execute( TC_si_acc_ramp_rotate() );
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +020011031
Harald Welte898113b2018-01-31 18:32:21 +010011032 /* RSL DCHAN Channel ACtivation / Deactivation */
Harald Welteae026692017-12-09 01:03:01 +010011033 execute( TC_chan_act_noreply() );
Harald Welte4003d112017-12-09 22:35:39 +010011034 execute( TC_chan_act_counter() );
Harald Welteae026692017-12-09 01:03:01 +010011035 execute( TC_chan_act_ack_noest() );
Philipp Maier9c60a622020-07-09 15:08:46 +020011036 execute( TC_chan_act_ack_noest_emerg() );
Philipp Maier606f07d2020-08-12 17:21:58 +020011037 execute( TC_chan_rqd_emerg_deny() );
Harald Welteae026692017-12-09 01:03:01 +010011038 execute( TC_chan_act_ack_est_ind_noreply() );
11039 execute( TC_chan_act_ack_est_ind_refused() );
Harald Welte618ef642017-12-14 14:58:20 +010011040 execute( TC_chan_act_nack() );
Harald Welte799c97b2017-12-14 17:50:30 +010011041 execute( TC_chan_exhaustion() );
Vadim Yanitskiy1ff1fdf2018-11-27 01:32:57 +070011042 execute( TC_chan_deact_silence() );
Harald Welte4003d112017-12-09 22:35:39 +010011043 execute( TC_chan_rel_rll_rel_ind() );
11044 execute( TC_chan_rel_conn_fail() );
11045 execute( TC_chan_rel_hard_clear() );
Pau Espin Pedrol841b90d2021-04-15 16:42:52 +020011046 execute( TC_chan_rel_last_eutran_plmn_hard_clear_no_csfb() );
11047 execute( TC_chan_rel_last_eutran_plmn_hard_clear_csfb() );
Harald Welte99787102019-02-04 10:41:36 +010011048 execute( TC_chan_rel_hard_clear_csfb() );
Harald Welted8c36cd2017-12-09 23:05:31 +010011049 execute( TC_chan_rel_hard_rlsd() );
Harald Welte550daf92018-06-11 19:22:13 +020011050 execute( TC_chan_rel_hard_rlsd_ms_dead() );
Harald Welte85804d42017-12-10 14:11:58 +010011051 execute( TC_chan_rel_a_reset() );
Pau Espin Pedrolc675b612020-01-09 19:55:40 +010011052 execute( TC_chan_rel_sccp_tiar_timeout() );
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +020011053 execute( TC_chan_rel_rr_cause() );
Harald Welte6f521d82017-12-11 19:52:02 +010011054
Harald Weltecfe2c962017-12-15 12:09:32 +010011055 execute( TC_outbound_connect() );
Harald Welte898113b2018-01-31 18:32:21 +010011056
11057 /* Assignment related */
Harald Welte16a4adf2017-12-14 18:54:01 +010011058 execute( TC_assignment_cic_only() );
Harald Welte235ebf12017-12-15 14:18:16 +010011059 execute( TC_assignment_csd() );
11060 execute( TC_assignment_ctm() );
11061 execute( TC_assignment_sign() );
Pau Espin Pedrol07866632020-09-03 19:10:55 +020011062 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
11063 execute( TC_assignment_aoip_tla_v6() );
11064 }
Harald Welte235ebf12017-12-15 14:18:16 +010011065 execute( TC_assignment_fr_a5_0() );
11066 execute( TC_assignment_fr_a5_1() );
Neels Hofmeyrf246a922020-05-13 02:27:10 +020011067 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
Harald Welte8f67d1d2018-05-25 20:38:42 +020011068 execute( TC_assignment_fr_a5_1_codec_missing() );
11069 }
Harald Welte235ebf12017-12-15 14:18:16 +010011070 execute( TC_assignment_fr_a5_3() );
Neels Hofmeyr0d8ec532021-06-11 00:09:48 +020011071 execute( TC_assignment_fr_a5_4() );
Neels Hofmeyr0faeb7a2021-06-10 23:59:35 +020011072 execute( TC_assignment_fr_a5_4_fail() );
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +020011073 execute( TC_assignment_fr_a5_not_sup() );
Harald Welte3c86ea02018-05-10 22:28:05 +020011074 execute( TC_ciph_mode_a5_0() );
11075 execute( TC_ciph_mode_a5_1() );
Oliver Smith50b98122021-07-09 15:00:28 +020011076 execute( TC_ciph_mode_a5_2_0() );
Oliver Smith1dff88d2021-07-09 08:45:51 +020011077 execute( TC_ciph_mode_a5_2_1() );
Harald Welte3c86ea02018-05-10 22:28:05 +020011078 execute( TC_ciph_mode_a5_3() );
Neels Hofmeyr81ad27f2021-06-11 00:09:40 +020011079 execute( TC_ciph_mode_a5_4() );
Harald Welte16a4adf2017-12-14 18:54:01 +010011080
Harald Welte60aa5762018-03-21 19:33:13 +010011081 execute( TC_assignment_codec_fr() );
Neels Hofmeyr559d5d02021-04-16 16:50:49 +020011082 execute( TC_assignment_codec_fr_by_mode_modify() );
Harald Welte60aa5762018-03-21 19:33:13 +010011083 execute( TC_assignment_codec_hr() );
11084 execute( TC_assignment_codec_efr() );
11085 execute( TC_assignment_codec_amr_f() );
11086 execute( TC_assignment_codec_amr_h() );
Philipp Maier8a581d22019-03-26 18:32:48 +010011087
Neels Hofmeyrf246a922020-05-13 02:27:10 +020011088 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
Philipp Maier8a581d22019-03-26 18:32:48 +010011089 execute( TC_assignment_codec_amr_f_S1() );
11090 execute( TC_assignment_codec_amr_h_S1() );
11091 execute( TC_assignment_codec_amr_f_S124() );
11092 execute( TC_assignment_codec_amr_h_S124() );
11093 execute( TC_assignment_codec_amr_f_S0() );
11094 execute( TC_assignment_codec_amr_f_S02() );
11095 execute( TC_assignment_codec_amr_f_S024() );
11096 execute( TC_assignment_codec_amr_f_S0247() );
11097 execute( TC_assignment_codec_amr_h_S0() );
11098 execute( TC_assignment_codec_amr_h_S02() );
11099 execute( TC_assignment_codec_amr_h_S024() );
11100 execute( TC_assignment_codec_amr_h_S0247() );
11101 execute( TC_assignment_codec_amr_f_S01234567() );
11102 execute( TC_assignment_codec_amr_f_S0234567() );
11103 execute( TC_assignment_codec_amr_f_zero() );
11104 execute( TC_assignment_codec_amr_f_unsupp() );
11105 execute( TC_assignment_codec_amr_h_S7() );
Neels Hofmeyr21863562020-11-26 00:34:33 +000011106 execute( TC_assignment_codec_amr_f_start_mode_auto() );
11107 execute( TC_assignment_codec_amr_h_start_mode_auto() );
Neels Hofmeyr3eb94562020-11-26 02:40:26 +000011108 execute( TC_assignment_codec_amr_f_start_mode_4() );
11109 execute( TC_assignment_codec_amr_h_start_mode_4() );
Neels Hofmeyr454d7922020-11-26 02:24:57 +000011110 execute( TC_assignment_codec_amr_startmode_cruft() );
Philipp Maier8a581d22019-03-26 18:32:48 +010011111 }
Harald Welte60aa5762018-03-21 19:33:13 +010011112
Philipp Maierac09bfc2019-01-08 13:41:39 +010011113 execute( TC_assignment_codec_fr_exhausted_req_hr() );
11114 execute( TC_assignment_codec_fr_exhausted_req_fr() );
11115 execute( TC_assignment_codec_fr_exhausted_req_fr_hr() );
11116 execute( TC_assignment_codec_fr_exhausted_req_hr_fr() );
11117 execute( TC_assignment_codec_hr_exhausted_req_fr() );
11118 execute( TC_assignment_codec_hr_exhausted_req_hr() );
11119 execute( TC_assignment_codec_hr_exhausted_req_hr_fr() );
11120 execute( TC_assignment_codec_hr_exhausted_req_fr_hr() );
11121 execute( TC_assignment_codec_req_hr_fr() );
11122 execute( TC_assignment_codec_req_fr_hr() );
Pau Espin Pedrol14475352021-07-22 15:48:16 +020011123 execute( TC_assignment_sdcch_exhausted_req_signalling() );
11124 execute( TC_assignment_sdcch_exhausted_req_signalling_tch_forbidden() );
11125 execute( TC_assignment_sdcch_exhausted_req_voice_tch_forbidden() );
Philipp Maierac09bfc2019-01-08 13:41:39 +010011126
Pau Espin Pedrol23510fb2021-07-20 17:00:38 +020011127 execute( TC_assignment_osmux() );
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +020011128
Harald Welte898113b2018-01-31 18:32:21 +010011129 /* RLL Establish Indication on inactive DCHAN / SAPI */
Harald Welte5cd20ed2017-12-13 21:03:20 +010011130 execute( TC_rll_est_ind_inact_lchan() );
11131 execute( TC_rll_est_ind_inval_sapi1() );
11132 execute( TC_rll_est_ind_inval_sapi3() );
11133 execute( TC_rll_est_ind_inval_sacch() );
11134
Vadim Yanitskiy61f784a2020-10-01 21:12:19 +070011135 /* DLCI / RSL Link ID conversion for MO/MT messages on SAPI0/SAPI3 */
11136 execute( TC_tch_dlci_link_id_sapi() );
11137
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +070011138 /* SAPI N Reject triggered by RLL establishment failures */
11139 execute( TC_rll_rel_ind_sapi_n_reject() );
11140 execute( TC_rll_err_ind_sapi_n_reject() );
11141 execute( TC_rll_timeout_sapi_n_reject() );
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +070011142 execute( TC_rll_sapi_n_reject_dlci_cc() );
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +070011143
Harald Welte898113b2018-01-31 18:32:21 +010011144 /* Paging related tests */
Harald Welte6f521d82017-12-11 19:52:02 +010011145 execute( TC_paging_imsi_nochan() );
11146 execute( TC_paging_tmsi_nochan() );
11147 execute( TC_paging_tmsi_any() );
11148 execute( TC_paging_tmsi_sdcch() );
11149 execute( TC_paging_tmsi_tch_f() );
11150 execute( TC_paging_tmsi_tch_hf() );
11151 execute( TC_paging_imsi_nochan_cgi() );
11152 execute( TC_paging_imsi_nochan_lac_ci() );
11153 execute( TC_paging_imsi_nochan_ci() );
11154 execute( TC_paging_imsi_nochan_lai() );
11155 execute( TC_paging_imsi_nochan_lac() );
11156 execute( TC_paging_imsi_nochan_all() );
Harald Welte751d3eb2018-01-31 15:51:06 +010011157 execute( TC_paging_imsi_nochan_plmn_lac_rnc() );
11158 execute( TC_paging_imsi_nochan_rnc() );
11159 execute( TC_paging_imsi_nochan_lac_rnc() );
11160 execute( TC_paging_imsi_nochan_lacs() );
11161 execute( TC_paging_imsi_nochan_lacs_empty() );
Stefan Sperling049a86e2018-03-20 15:51:00 +010011162 execute( TC_paging_imsi_nochan_cgi_unknown_cid() );
Harald Welte10985002017-12-12 09:29:15 +010011163 execute( TC_paging_imsi_a_reset() );
Harald Weltee65d40e2017-12-13 00:09:06 +010011164 execute( TC_paging_imsi_load() );
Philipp Maier779a7922018-02-16 11:00:37 +010011165 execute( TC_paging_counter() );
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +010011166 execute( TC_paging_resp_unsol() );
Harald Welte4e9b9cc2017-12-14 18:31:02 +010011167
11168 execute( TC_rsl_drop_counter() );
Stefan Sperling830dc9d2018-02-12 21:08:28 +010011169 execute( TC_rsl_unknown_unit_id() );
11170
11171 execute( TC_oml_unknown_unit_id() );
Harald Welte898113b2018-01-31 18:32:21 +010011172
11173 execute( TC_classmark() );
Harald Welteeddf0e92020-06-21 19:42:15 +020011174 execute( TC_common_id() );
Harald Welte898113b2018-01-31 18:32:21 +010011175 execute( TC_unsol_ass_fail() );
Harald Welteea99a002018-01-31 20:46:43 +010011176 execute( TC_unsol_ass_compl() );
Harald Weltefbf9b5e2018-01-31 20:41:23 +010011177 execute( TC_unsol_ho_fail() );
Harald Weltee3bd6582018-01-31 22:51:25 +010011178 execute( TC_err_82_short_msg() );
Harald Weltee9e02e42018-01-31 23:36:25 +010011179 execute( TC_err_84_unknown_msg() );
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +010011180
Harald Welte261af4b2018-02-12 21:20:39 +010011181 execute( TC_ho_int() );
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +020011182 execute( TC_ho_int_a5_0() );
11183 execute( TC_ho_int_a5_1() );
11184 execute( TC_ho_int_a5_3() );
11185 execute( TC_ho_int_a5_4() );
Neels Hofmeyr5f144212020-11-03 15:41:58 +000011186 execute( TC_ho_int_radio_link_failure() );
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +010011187
Neels Hofmeyrafe2ea52021-11-24 15:16:12 +010011188 /* TC_ho_out_of_this_bsc is run last, see comment below */
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +020011189 execute( TC_ho_out_fail_no_msc_response() );
11190 execute( TC_ho_out_fail_rr_ho_failure() );
Neels Hofmeyrd8a602c2019-07-09 19:46:01 +020011191 execute( TC_ho_out_fail_no_result_after_ho_cmd() );
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +010011192
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +010011193 execute( TC_ho_into_this_bsc() );
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +020011194 execute( TC_ho_into_this_bsc_a5_0() );
11195 execute( TC_ho_into_this_bsc_a5_1() );
11196 execute( TC_ho_into_this_bsc_a5_3() );
11197 execute( TC_ho_into_this_bsc_a5_4() );
Pau Espin Pedrol07866632020-09-03 19:10:55 +020011198 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
11199 execute( TC_ho_into_this_bsc_tla_v6() );
11200 }
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +020011201 execute( TC_srvcc_eutran_to_geran() );
Pau Espin Pedrol35801c32021-04-19 13:03:20 +020011202 execute( TC_srvcc_eutran_to_geran_ho_out() );
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +020011203 execute( TC_srvcc_eutran_to_geran_forbid_fast_return() );
11204 execute( TC_srvcc_eutran_to_geran_ho_out_forbid_fast_return() );
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +010011205 execute( TC_ho_in_fail_msc_clears() );
11206 execute( TC_ho_in_fail_msc_clears_after_ho_detect() );
11207 execute( TC_ho_in_fail_no_detect() );
11208 execute( TC_ho_in_fail_no_detect2() );
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +010011209
Neels Hofmeyr91401012019-07-11 00:42:35 +020011210 execute( TC_ho_neighbor_config_1() );
11211 execute( TC_ho_neighbor_config_2() );
11212 execute( TC_ho_neighbor_config_3() );
11213 execute( TC_ho_neighbor_config_4() );
11214 execute( TC_ho_neighbor_config_5() );
11215 execute( TC_ho_neighbor_config_6() );
11216 execute( TC_ho_neighbor_config_7() );
11217
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +010011218 execute( TC_bssap_rlsd_does_not_cause_bssmap_reset() );
Neels Hofmeyr4ff93282018-03-12 04:25:35 +010011219 execute( TC_bssmap_clear_does_not_cause_bssmap_reset() );
Neels Hofmeyrfd445c32018-03-09 15:39:31 +010011220 execute( TC_ms_rel_ind_does_not_cause_bssmap_reset() );
Harald Welte94e0c342018-04-07 11:33:23 +020011221
11222 execute( TC_dyn_pdch_ipa_act_deact() );
11223 execute( TC_dyn_pdch_ipa_act_nack() );
11224 execute( TC_dyn_pdch_osmo_act_deact() );
11225 execute( TC_dyn_pdch_osmo_act_nack() );
Pau Espin Pedrol37a4c152021-11-16 19:02:23 +010011226 execute( TC_dyn_ts_sdcch8_act_deact() );
11227 execute( TC_dyn_ts_sdcch8_all_subslots_used() );
11228 execute( TC_dyn_ts_sdcch8_tch_call_act_deact() );
11229 execute( TC_dyn_ts_sdcch8_act_nack() );
Harald Welte99f3ca02018-06-14 13:40:29 +020011230
Stefan Sperling0796a822018-10-05 13:01:39 +020011231 execute( TC_chopped_ipa_ping() );
Stefan Sperlingaa1e60f2018-10-15 16:34:07 +020011232 execute( TC_chopped_ipa_payload() );
Stefan Sperling0796a822018-10-05 13:01:39 +020011233
Pau Espin Pedrol8f773632019-11-05 11:46:53 +010011234 /* Power control related */
11235 execute( TC_assignment_verify_ms_power_params_ie() );
Vadim Yanitskiy4b233042021-06-30 00:58:43 +020011236 execute( TC_c0_power_red_mode() );
Neels Hofmeyr4f118412020-06-04 15:25:10 +020011237
11238 /* MSC pooling */
11239 /* FIXME: in SCCPlite, indicating how many MSCs should be connected does currently not work. Since
11240 * RESET->RESET-ACK is unconditionally negotiated for all configured MSCs, they always all appear as connected
11241 * to osmo-bsc. The MSC pooling tests however require disconnecting selected MSCs, and hence don't work out as
11242 * intended on SCCPlite. So for now, run these only for SCCP/M3UA. */
11243 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
11244 execute( TC_mscpool_L3Compl_on_1_msc() );
11245 execute( TC_mscpool_L3Complete_by_imsi_round_robin() );
11246 execute( TC_mscpool_LU_by_tmsi_null_nri_0_round_robin() );
11247 execute( TC_mscpool_LU_by_tmsi_null_nri_1_round_robin() );
11248 execute( TC_mscpool_L3Complete_by_tmsi_unassigned_nri_round_robin() );
11249 execute( TC_mscpool_L3Complete_by_tmsi_valid_nri_msc_not_connected_round_robin() );
11250 execute( TC_mscpool_L3Complete_by_tmsi_valid_nri_1() );
11251 execute( TC_mscpool_L3Complete_by_tmsi_valid_nri_2() );
11252 execute( TC_mscpool_LU_by_tmsi_from_other_PLMN() );
11253 execute( TC_mscpool_paging_and_response_imsi() );
11254 execute( TC_mscpool_paging_and_response_tmsi() );
11255 execute( TC_mscpool_no_allow_attach_round_robin() );
11256 execute( TC_mscpool_no_allow_attach_valid_nri() );
11257 }
11258
Harald Welte99f3ca02018-06-14 13:40:29 +020011259 execute( TC_early_conn_fail() );
11260 execute( TC_late_conn_fail() );
Oliver Smithaf03bef2021-08-24 15:34:51 +020011261 execute( TC_stats_conn_fail() );
Harald Welte99f3ca02018-06-14 13:40:29 +020011262
Philipp Maier783681c2020-07-16 16:47:06 +020011263 /* Emergency call handling (deny / allow) */
11264 execute( TC_assignment_emerg_setup_allow() );
11265 execute( TC_assignment_emerg_setup_deny_msc() );
11266 execute( TC_assignment_emerg_setup_deny_bts() );
Philipp Maier82812002020-08-13 18:48:27 +020011267 execute( TC_emerg_premption() );
11268
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +070011269 /* Frequency hopping parameters handling */
11270 execute( TC_fh_params_chan_activ() );
11271 execute( TC_fh_params_imm_ass() );
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +070011272 execute( TC_fh_params_assignment_cmd() );
Vadim Yanitskiy8f5430d2020-09-02 18:51:38 +070011273 execute( TC_fh_params_handover_cmd() );
Vadim Yanitskiyca974032020-09-01 07:20:39 +070011274 execute( TC_fh_params_si4_cbch() );
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020011275
11276 if (mp_enable_lcs_tests) {
11277 execute( TC_lcs_loc_req_for_active_ms() );
11278 execute( TC_lcs_loc_req_for_active_ms_ta_req() );
11279 execute( TC_lcs_loc_req_for_idle_ms() );
11280 execute( TC_lcs_loc_req_no_subscriber() );
11281 execute( TC_lcs_loc_req_for_active_ms_le_timeout() );
11282 execute( TC_lcs_loc_req_for_active_ms_le_timeout2() );
11283 execute( TC_lcs_loc_req_for_idle_ms_no_pag_resp() );
11284 execute( TC_cm_service_during_lcs_loc_req() );
11285 execute( TC_ho_during_lcs_loc_req() );
11286 }
Neels Hofmeyrbf037052020-10-28 22:52:02 +000011287
11288 execute( TC_no_msc() );
Neels Hofmeyr87857ec2021-04-25 16:17:47 +000011289
11290 execute( TC_refuse_chan_act_to_vamos() );
11291 execute( TC_refuse_mode_modif_to_vamos() );
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000011292
11293 execute( TC_reassignment_fr() );
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020011294
11295 execute( TC_cm_reestablishment() );
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011296
11297 execute( TC_imm_ass_post_chan_ack() );
11298 execute( TC_imm_ass_pre_chan_ack() );
Neels Hofmeyr23158742021-09-07 19:08:07 +020011299 execute( TC_imm_ass_pre_ts_ack() );
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011300 execute( TC_imm_ass_pre_chan_ack_dyn_ts() );
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011301 execute( TC_imm_ass_pre_ts_ack_dyn_ts() );
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020011302
11303 execute( TC_ctrl_trx_rf_locked() );
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020011304
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011305 execute( TC_ratectr_all_available_allocated() );
11306 execute( TC_ratectr_all_available_allocated_dyn() );
11307
Neels Hofmeyrb7581872021-11-07 14:02:49 +010011308 execute( TC_cm_serv_rej() );
11309
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020011310 execute( TC_lost_sdcch_during_assignment() );
Neels Hofmeyrafe2ea52021-11-24 15:16:12 +010011311
11312 /* Run TC_ho_out_of_this_bsc last, because it may trigger a segfault before osmo-bsc's patch
11313 * with change-id I5a3345ab0005a73597f5c27207480912a2f5aae6 */
11314 execute( TC_ho_out_of_this_bsc() );
Harald Welte28d943e2017-11-25 15:00:50 +010011315}
11316
11317}