blob: e7c459918a5858754af1f42c3e0d017f159df08b [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;
Harald Weltea5d2ab22017-12-09 14:21:42 +0100598
Daniel Willmann191e0d92018-01-17 12:44:35 +0100599 var MGCP_Emulation_CT vc_MGCP;
Harald Weltebc03c762018-02-12 18:09:38 +0100600 port TELNETasp_PT BSCVTY;
Daniel Willmann191e0d92018-01-17 12:44:35 +0100601
Daniel Willmannebdecc02020-08-12 15:30:17 +0200602 /* StatsD */
603 var StatsD_Checker_CT vc_STATSD;
604
Neels Hofmeyrf246a922020-05-13 02:27:10 +0200605 var RAN_Adapter g_bssap[NUM_MSC];
Harald Welte47cd0e32020-08-21 12:39:11 +0200606 var BSSAP_LE_Adapter g_bssap_le;
Harald Weltea4ca4462018-02-09 00:17:14 +0100607 /* for old legacy-tests only */
608 port BSSAP_CODEC_PT BSSAP;
Harald Welte47cd0e32020-08-21 12:39:11 +0200609 port BSSAP_LE_CODEC_PT BSSAP_LE;
Harald Weltea4ca4462018-02-09 00:17:14 +0100610
Harald Welte21b46bd2017-12-17 19:46:32 +0100611 /* are we initialized yet */
Harald Welte28d943e2017-11-25 15:00:50 +0100612 var boolean g_initialized := false;
Harald Welte21b46bd2017-12-17 19:46:32 +0100613
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +0200614 /* Osmux is enabled through VTY */
615 var boolean g_osmux_enabled := false;
616
Pau Espin Pedrolc675b612020-01-09 19:55:40 +0100617 /*Configure T(tias) over VTY, seconds */
618 var integer g_bsc_sccp_timer_ias := 7 * 60;
619 /*Configure T(tiar) over VTY, seconds */
620 var integer g_bsc_sccp_timer_iar := 15 * 60;
621
Neels Hofmeyr4fbad7f2020-06-16 00:30:47 +0200622 /* global test case guard timer (actual timeout value is set in f_init()) */
Harald Welteae026692017-12-09 01:03:01 +0100623 timer T_guard := 30.0;
624
Neels Hofmeyr22c3f792020-06-17 02:49:28 +0200625 var CounterNameValsList g_ctr_msc;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +0000626 var CounterNameValsList g_ctr_bsc;
627 var CounterNameValsList g_ctr_bts;
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +0200628
629 /* System Information bytes as received during RSL startup, for each RSL[idx]. */
630 var SystemInformationConfig_list g_system_information := {};
Harald Welte28d943e2017-11-25 15:00:50 +0100631}
632
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +0200633type record of charstring phys_chan_configs;
Harald Welte28d943e2017-11-25 15:00:50 +0100634modulepar {
Harald Welte21b46bd2017-12-17 19:46:32 +0100635 /* IP address at which the BSC can be reached */
Harald Welte696ddb62017-12-08 14:01:43 +0100636 charstring mp_bsc_ip := "127.0.0.1";
Stefan Sperling830dc9d2018-02-12 21:08:28 +0100637 /* port number to which to establish the IPA OML connections */
638 integer mp_bsc_oml_port := 3002;
Harald Welte21b46bd2017-12-17 19:46:32 +0100639 /* port number to which to establish the IPA RSL connections */
Harald Welte696ddb62017-12-08 14:01:43 +0100640 integer mp_bsc_rsl_port := 3003;
Harald Welte21b46bd2017-12-17 19:46:32 +0100641 /* port number to which to establish the IPA CTRL connection */
Harald Welte96c94412017-12-09 03:12:45 +0100642 integer mp_bsc_ctrl_port := 4249;
Daniel Willmannebdecc02020-08-12 15:30:17 +0200643 /* port number to which to listen for STATSD metrics */
644 integer mp_bsc_statsd_port := 8125;
Daniel Willmann191e0d92018-01-17 12:44:35 +0100645 /* IP address at which the test binds */
646 charstring mp_test_ip := "127.0.0.1";
Harald Weltea4ca4462018-02-09 00:17:14 +0100647
Neels Hofmeyrf246a922020-05-13 02:27:10 +0200648 RAN_Configurations mp_bssap_cfg := {
649 {
650 transport := BSSAP_TRANSPORT_AoIP,
651 sccp_service_type := "mtp3_itu",
652 sctp_addr := { 23905, "127.0.0.1", 2905, "127.0.0.1" },
653 own_pc := 185, /* 0.23.1 first MSC emulation */
654 own_ssn := 254,
655 peer_pc := 187, /* 0.23.3 osmo-bsc */
656 peer_ssn := 254,
657 sio := '83'O,
Harald Weltecb0cc432020-06-21 19:42:31 +0200658 rctx := 1
Neels Hofmeyrf246a922020-05-13 02:27:10 +0200659 },
660 {
661 transport := BSSAP_TRANSPORT_AoIP,
662 sccp_service_type := "mtp3_itu",
663 sctp_addr := { 23906, "127.0.0.1", 2905, "127.0.0.1" },
664 own_pc := 2, /* 0.0.2 second MSC emulation */
665 own_ssn := 254,
666 peer_pc := 187, /* 0.23.3 osmo-bsc */
667 peer_ssn := 254,
668 sio := '83'O,
669 rctx := 2
670 },
671 {
672 transport := BSSAP_TRANSPORT_AoIP,
673 sccp_service_type := "mtp3_itu",
674 sctp_addr := { 23907, "127.0.0.1", 2905, "127.0.0.1" },
675 own_pc := 3, /* 0.0.3 third MSC emulation */
676 own_ssn := 254,
677 peer_pc := 187, /* 0.23.3 osmo-bsc */
678 peer_ssn := 254,
679 sio := '83'O,
680 rctx := 3
681 }
Harald Weltea4ca4462018-02-09 00:17:14 +0100682 };
Pau Espin Pedrol58cf6822019-05-28 18:11:33 +0200683
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +0200684 /* Must match per BTS config in osmo-bsc.cfg */
685 phys_chan_configs phys_chan_config := {
686 "CCCH+SDCCH4+CBCH",
687 "TCH/F",
688 "TCH/F",
689 "TCH/F",
690 "TCH/F",
Vadim Yanitskiy343c9eb2021-07-16 18:36:01 +0600691 "TCH/H",
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +0200692 "PDCH",
693 "PDCH"
694 };
695
Harald Welte47cd0e32020-08-21 12:39:11 +0200696 BSSAP_LE_Configuration mp_bssap_le_cfg := {
697 sccp_service_type := "mtp3_itu",
698 sctp_addr := { 23908, "127.0.0.1", 2905, "127.0.0.1" },
Neels Hofmeyrac086c12020-09-18 23:46:42 +0200699 own_pc := 190, /* 0.23.6 SMLC emulation */
Harald Welte47cd0e32020-08-21 12:39:11 +0200700 own_ssn := 252, /* SMLC side SSN */
701 peer_pc := 187, /* 0.23.3 osmo-bsc */
702 peer_ssn := 250, /* BSC side SSN */
703 sio := '83'O,
704 rctx := 6
705 };
Neels Hofmeyrcfe44062020-10-15 02:28:08 +0200706 boolean mp_enable_lcs_tests := true;
Harald Welte47cd0e32020-08-21 12:39:11 +0200707
Pau Espin Pedrol8f30ccd2019-11-01 17:30:57 +0100708 /* Value set in osmo-bsc.cfg "ms max power" */
709 uint8_t mp_exp_ms_power_level := 7;
Harald Weltea4ca4462018-02-09 00:17:14 +0100710}
711
Neels Hofmeyr9f3e6ac2021-04-08 23:09:24 +0200712friend function f_gen_test_hdlr_pars(integer bssap_idx := 0) return TestHdlrParams {
Philipp Maier48604732018-10-09 15:00:37 +0200713
714 var TestHdlrParams pars := valueof(t_def_TestHdlrPars);
Neels Hofmeyrf246a922020-05-13 02:27:10 +0200715 if (mp_bssap_cfg[bssap_idx].transport == BSSAP_TRANSPORT_AoIP) {
Philipp Maier48604732018-10-09 15:00:37 +0200716 pars.aoip := true;
717 } else {
718 pars.aoip := false;
719 }
Pau Espin Pedrol8f30ccd2019-11-01 17:30:57 +0100720 pars.exp_ms_power_level := mp_exp_ms_power_level;
Neels Hofmeyrf246a922020-05-13 02:27:10 +0200721 pars.mscpool.bssap_idx := bssap_idx;
Neels Hofmeyrbf720202021-10-02 12:58:24 +0200722 pars.expect_tsc := BTS_TSC[0];
Neels Hofmeyrb5b7a6e2021-06-04 19:03:45 +0200723
Philipp Maier48604732018-10-09 15:00:37 +0200724 return pars;
725}
726
Neels Hofmeyr22c3f792020-06-17 02:49:28 +0200727/* Convenience functions for rate counters using g_ctr_msc. */
728
729private function f_ctrs_msc_init(integer mscs_count := NUM_MSC, CounterNameVals counternames := counternames_msc_mscpool) runs on test_CT {
730 g_ctr_msc := f_counter_name_vals_get_n(IPA_CTRL, "msc", mscs_count, counternames);
731 log("initial msc rate counters: ", g_ctr_msc);
732}
733
734private function f_ctrs_msc_add(integer msc_nr, charstring countername, integer val := 1) runs on test_CT {
Neels Hofmeyr9656e922020-06-30 01:27:01 +0200735 f_counter_name_vals_list_add(g_ctr_msc, msc_nr, countername, val);
Neels Hofmeyr22c3f792020-06-17 02:49:28 +0200736}
737
738/* f_ctrs_msc_init();
739 * f_do_thing(on_msc := 0);
740 * f_do_thing(on_msc := 0);
741 * f_do_other(on_msc := 1);
742 * f_ctrs_msc_add(0, "thing", 2);
743 * f_ctrs_msc_add(1, "other");
744 * f_ctrs_msc_verify();
745 */
746private function f_ctrs_msc_verify() runs on test_CT {
747 log("verifying msc rate counters: ", g_ctr_msc);
748 f_counter_name_vals_expect_n(IPA_CTRL, "msc", g_ctr_msc);
749}
750
751/* convenience: f_ctrs_msc_add() and f_ctrs_msc_verify() in one call.
752 * f_ctrs_msc_init();
753 * f_do_thing(on_msc := 0);
754 * f_do_thing(on_msc := 0);
755 * f_do_thing(on_msc := 0);
756 * f_ctrs_msc_expect(0, "thing", 3);
757 */
758private function f_ctrs_msc_expect(integer msc_nr, charstring countername, integer val := 1) runs on test_CT {
759 f_ctrs_msc_add(msc_nr, countername, val);
760 f_ctrs_msc_verify();
761}
762
Neels Hofmeyr12941bd2020-08-29 03:21:26 +0000763/* Convenience functions for rate counters using g_ctr_bts, always also including g_ctr_bsc. */
764
Neels Hofmeyrb7581872021-11-07 14:02:49 +0100765private 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 +0000766 g_ctr_bts := f_counter_name_vals_get_n(IPA_CTRL, "bts", bts_count, counternames);
Neels Hofmeyr4dec8cc2021-11-29 15:59:44 +0100767 log("initial bts rate counters: ", g_ctr_bts);
Neels Hofmeyrb7581872021-11-07 14:02:49 +0100768}
769
770function f_ctrs_bsc_and_bts_init(integer bts_count := NUM_BTS, CounterNameVals counternames := counternames_bsc_bts_handover) runs on test_CT {
771 f_ctrs_bts_init(bts_count, counternames);
Neels Hofmeyr12941bd2020-08-29 03:21:26 +0000772 f_ctrs_bsc_init(counternames);
773}
774
Neels Hofmeyrac432fa2021-11-02 16:45:56 +0100775private function f_ctrs_bsc_and_bts_handover_init(integer bts_count := NUM_BTS) runs on test_CT {
776 var CounterNameVals bts_names := counternames_bsc_bts_handover & counternames_bts_handover;
Neels Hofmeyr4dec8cc2021-11-29 15:59:44 +0100777 f_ctrs_bts_init(bts_count, bts_names);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +0100778 f_ctrs_bsc_init(counternames_bsc_bts_handover);
779}
780
781private function f_ctrs_bts_add(integer bts_nr, charstring countername, integer val := 1) runs on test_CT {
Neels Hofmeyr12941bd2020-08-29 03:21:26 +0000782 f_counter_name_vals_list_add(g_ctr_bts, bts_nr, countername, val);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +0100783}
784
785private function f_ctrs_bsc_and_bts_add(integer bts_nr, charstring countername, integer val := 1) runs on test_CT {
786 f_ctrs_bts_add(bts_nr, countername, val);
Neels Hofmeyr12941bd2020-08-29 03:21:26 +0000787 f_ctrs_bsc_add(countername, val);
788}
789
Neels Hofmeyrb7581872021-11-07 14:02:49 +0100790function f_ctrs_bts_verify() runs on test_CT {
791 f_counter_name_vals_expect_n(IPA_CTRL, "bts", g_ctr_bts);
792}
793
Neels Hofmeyr12941bd2020-08-29 03:21:26 +0000794/* f_ctrs_bsc_and_bts_init();
795 * f_do_thing(on_bts := 0);
796 * f_do_thing(on_bts := 0);
797 * f_do_other(on_bts := 1);
798 * f_ctrs_bsc_and_bts_add(0, "thing", 2);
799 * f_ctrs_bsc_and_bts_add(1, "other");
800 * f_ctrs_bsc_and_bts_verify();
801 */
802private function f_ctrs_bsc_and_bts_verify() runs on test_CT {
Neels Hofmeyrb7581872021-11-07 14:02:49 +0100803 f_ctrs_bts_verify();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +0000804 f_ctrs_bsc_verify();
805}
806
807/* convenience: f_ctrs_bsc_and_bts_add() and f_ctrs_bsc_and_bts_verify() in one call.
808 * f_ctrs_bsc_and_bts_init();
809 * f_do_thing(on_bts := 0);
810 * f_do_thing(on_bts := 0);
811 * f_do_thing(on_bts := 0);
812 * f_ctrs_bsc_and_bts_expect(0, "thing", 3);
813 */
814private function f_ctrs_bsc_and_bts_expect(integer bts_nr, charstring countername, integer val := 1) runs on test_CT {
815 f_ctrs_bsc_and_bts_add(bts_nr, countername, val);
816 f_ctrs_bsc_and_bts_verify();
817}
818
819
820/* Convenience functions for rate counters using g_ctr_bsc. */
821
822private function f_ctrs_bsc_init(CounterNameVals counternames := counternames_bsc_bts_handover) runs on test_CT {
823 g_ctr_bsc := f_counter_name_vals_get_n(IPA_CTRL, "bsc", 1, counternames);
824 log("initial bsc rate counters: ", g_ctr_bsc);
825}
826
827private function f_ctrs_bsc_add(charstring countername, integer val := 1) runs on test_CT {
828 f_counter_name_vals_list_add(g_ctr_bsc, 0, countername, val);
829}
830
831/* f_ctrs_bsc_init();
832 * f_do_thing();
833 * f_do_thing();
834 * f_do_other();
835 * f_ctrs_bsc_add("thing", 2);
836 * f_ctrs_bsc_add("other");
837 * f_ctrs_bsc_verify();
838 */
839private function f_ctrs_bsc_verify() runs on test_CT {
840 f_counter_name_vals_expect_n(IPA_CTRL, "bsc", g_ctr_bsc);
841}
842
843/* convenience: f_ctrs_bsc_add() and f_ctrs_bsc_verify() in one call.
844 * f_ctrs_bsc_init();
845 * f_do_thing();
846 * f_ctrs_bsc_expect("thing", 1);
847 */
848private function f_ctrs_bsc_expect(charstring countername, integer val := 1) runs on test_CT {
849 f_ctrs_bsc_add(countername, val);
850 f_ctrs_bsc_verify();
851}
852
Neels Hofmeyr22c3f792020-06-17 02:49:28 +0200853
Neels Hofmeyr9f3e6ac2021-04-08 23:09:24 +0200854friend function f_shutdown_helper() runs on test_CT {
Daniel Willmann637ef6c2018-07-25 10:49:09 +0200855 all component.stop;
Philipp Maier282ca4b2018-02-27 17:17:00 +0100856 setverdict(pass);
Daniel Willmannafce8662018-07-06 23:11:32 +0200857 mtc.stop;
Philipp Maier282ca4b2018-02-27 17:17:00 +0100858}
859
Neels Hofmeyrf246a922020-05-13 02:27:10 +0200860private function f_legacy_bssap_reset(integer bssap_idx := 0) runs on test_CT {
Harald Weltea4ca4462018-02-09 00:17:14 +0100861 var BSSAP_N_UNITDATA_ind ud_ind;
Pau Espin Pedrol24c05992020-09-01 12:54:12 +0200862 var boolean reset_received := false;
Harald Weltea4ca4462018-02-09 00:17:14 +0100863 timer T := 5.0;
Neels Hofmeyrf246a922020-05-13 02:27:10 +0200864 BSSAP.send(ts_BSSAP_UNITDATA_req(g_bssap[bssap_idx].sccp_addr_peer, g_bssap[bssap_idx].sccp_addr_own,
865 ts_BSSMAP_Reset(0, g_osmux_enabled)));
Harald Weltea4ca4462018-02-09 00:17:14 +0100866 T.start;
867 alt {
Neels Hofmeyrf246a922020-05-13 02:27:10 +0200868 [] BSSAP.receive(tr_BSSAP_UNITDATA_ind(g_bssap[bssap_idx].sccp_addr_own, g_bssap[bssap_idx].sccp_addr_peer,
869 tr_BSSMAP_ResetAck(g_osmux_enabled))) {
Neels Hofmeyr4f5d7be2020-10-16 16:28:16 +0200870 log("BSSMAP: Received RESET-ACK in response to RESET, we're ready to go!");
Harald Weltea4ca4462018-02-09 00:17:14 +0100871 }
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +0200872 [] BSSAP.receive(tr_BSSAP_UNITDATA_ind(?, ?, tr_BSSMAP_Reset(g_osmux_enabled))) -> value ud_ind {
Neels Hofmeyr4f5d7be2020-10-16 16:28:16 +0200873 log("BSSMAP: Respoding to inbound RESET with RESET-ACK");
Harald Weltea4ca4462018-02-09 00:17:14 +0100874 BSSAP.send(ts_BSSAP_UNITDATA_req(ud_ind.callingAddress, ud_ind.calledAddress,
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +0200875 ts_BSSMAP_ResetAck(g_osmux_enabled)));
Pau Espin Pedrol24c05992020-09-01 12:54:12 +0200876 reset_received := true;
Harald Weltea4ca4462018-02-09 00:17:14 +0100877 repeat;
878 }
879 [] BSSAP.receive { repeat; }
Pau Espin Pedrol24c05992020-09-01 12:54:12 +0200880 [] T.timeout {
Neels Hofmeyr4f5d7be2020-10-16 16:28:16 +0200881 log("BSSMAP: Timeout waiting for RESET-ACK after sending RESET");
Pau Espin Pedrol24c05992020-09-01 12:54:12 +0200882 /* If we received a RESET after ours was sent, it
883 may be a race condition where the other peer beacame
884 available after we sent it, but we are in a desired
885 state anyway, so go forward. */
886 if (not reset_received) {
887 setverdict(fail);
888 }
889 }
Harald Weltea4ca4462018-02-09 00:17:14 +0100890 }
Harald Welte28d943e2017-11-25 15:00:50 +0100891}
892
Harald Welteae026692017-12-09 01:03:01 +0100893type record IPA_Client {
Harald Welte21b46bd2017-12-17 19:46:32 +0100894 /* IPA Emulation component reference */
Harald Welteae026692017-12-09 01:03:01 +0100895 IPA_Emulation_CT vc_IPA,
Harald Welte21b46bd2017-12-17 19:46:32 +0100896 /* Unit-ID and other CCM parameters to use for IPA client emulation */
Harald Welteae026692017-12-09 01:03:01 +0100897 IPA_CCM_Parameters ccm_pars,
Harald Welte21b46bd2017-12-17 19:46:32 +0100898 /* String identifier for this IPA Client */
Harald Welte624f9632017-12-16 19:26:04 +0100899 charstring id,
Harald Welte21b46bd2017-12-17 19:46:32 +0100900 /* Associated RSL Emulation Component (if any). Only used in "Handler mode" */
Harald Welte624f9632017-12-16 19:26:04 +0100901 RSL_Emulation_CT vc_RSL optional
Harald Welte28d943e2017-11-25 15:00:50 +0100902}
903
Harald Welte21b46bd2017-12-17 19:46:32 +0100904/*! Start the IPA/RSL related bits for one IPA_Client.
905 * \param clnt IPA_Client for which to establish
906 * \param bsc_host IP address / hostname of the BSC
907 * \param bsc_port TCP port number of the BSC
908 * \param i number identifying this BTS
909 * \param handler_mode Start an RSL_Emulation_CT component (true) or not (false) */
Harald Welte624f9632017-12-16 19:26:04 +0100910function f_ipa_rsl_start(inout IPA_Client clnt, charstring bsc_host, PortNumber bsc_port, integer i,
911 boolean handler_mode := false)
Harald Welte28d943e2017-11-25 15:00:50 +0100912runs on test_CT {
Harald Welteae026692017-12-09 01:03:01 +0100913 timer T := 10.0;
914
Harald Welte96c94412017-12-09 03:12:45 +0100915 clnt.id := "IPA" & int2str(i) & "-RSL";
Harald Welteae026692017-12-09 01:03:01 +0100916 clnt.vc_IPA := IPA_Emulation_CT.create(clnt.id & "-IPA");
917 clnt.ccm_pars := c_IPA_default_ccm_pars;
918 clnt.ccm_pars.name := "Osmocom TTCN-3 BTS Simulator";
919 clnt.ccm_pars.unit_id := int2str(1234+i) & "/0/0";
Harald Welte624f9632017-12-16 19:26:04 +0100920 if (handler_mode) {
921 clnt.vc_RSL := RSL_Emulation_CT.create(clnt.id & "-RSL");
Harald Welte89ab1912018-02-23 18:56:29 +0100922 connect(clnt.vc_RSL:CCHAN_PT, self:RSL_CCHAN[i]);
Harald Welte624f9632017-12-16 19:26:04 +0100923 }
Harald Welteae026692017-12-09 01:03:01 +0100924
925 map(clnt.vc_IPA:IPA_PORT, system:IPA_CODEC_PT);
Harald Welte624f9632017-12-16 19:26:04 +0100926 if (handler_mode) {
927 connect(clnt.vc_IPA:IPA_RSL_PORT, clnt.vc_RSL:IPA_PT);
928 } else {
929 connect(clnt.vc_IPA:IPA_RSL_PORT, self:IPA_RSL[i]);
930 }
Harald Welteae026692017-12-09 01:03:01 +0100931
Harald Welte5d1a2202017-12-13 19:51:29 +0100932 clnt.vc_IPA.start(IPA_Emulation.main_client(bsc_host, bsc_port, "", 10000+i, clnt.ccm_pars));
Harald Welte624f9632017-12-16 19:26:04 +0100933 if (handler_mode) {
934 clnt.vc_RSL.start(RSL_Emulation.main());
935 return;
936 }
Harald Welteae026692017-12-09 01:03:01 +0100937
938 /* wait for IPA RSL link to connect and send ID ACK */
939 T.start;
940 alt {
Vadim Yanitskiya2afacc2020-05-18 21:16:19 +0700941 [] IPA_RSL[i].receive(tr_ASP_IPA_EV(ASP_IPA_EVENT_ID_ACK)) {
Harald Welteae026692017-12-09 01:03:01 +0100942 T.stop;
Vadim Yanitskiy9b4e3562020-05-25 21:40:52 +0700943 IPA_RSL[i].send(ts_ASP_RSL_UD(ts_RSL_PAGING_LOAD_IND(23)));
Harald Welteae026692017-12-09 01:03:01 +0100944 }
Harald Welte60e823a2017-12-10 14:10:59 +0100945 [] IPA_RSL[i].receive(ASP_IPA_Event:?) { repeat }
Harald Welteae026692017-12-09 01:03:01 +0100946 [] IPA_RSL[i].receive { repeat }
947 [] T.timeout {
Harald Welte96c94412017-12-09 03:12:45 +0100948 setverdict(fail, "Timeout RSL waiting for ASP_IPA_EVENT_ID_ACK");
Daniel Willmannafce8662018-07-06 23:11:32 +0200949 mtc.stop;
Harald Welteae026692017-12-09 01:03:01 +0100950 }
951 }
952}
953
Harald Welte12055472018-03-17 20:10:08 +0100954function f_ipa_rsl_stop(inout IPA_Client clnt) runs on test_CT {
955 if (not isbound(clnt) or not isbound(clnt.vc_IPA)) {
956 return;
957 }
958 clnt.vc_IPA.stop;
959 if (isbound(clnt.vc_RSL)) {
960 clnt.vc_RSL.stop;
961 }
962}
963
Harald Welte21b46bd2017-12-17 19:46:32 +0100964/* Wait for the OML connection to be brought up by the external osmo-bts-omldummy */
Harald Weltea5d2ab22017-12-09 14:21:42 +0100965function f_wait_oml(integer bts_nr, charstring status, float secs_max) runs on test_CT {
966 timer T := secs_max;
967 T.start;
968 while (true) {
969 if (f_ctrl_get_bts(IPA_CTRL, bts_nr, "oml-connection-state") == status) {
970 T.stop;
Harald Weltebd868bd2017-12-10 18:28:40 +0100971 /* the 'degraded' state exists from OML connection time, and we have to wait
972 * until all MO's are initialized */
973 T.start(1.0);
974 T.timeout;
Harald Weltea5d2ab22017-12-09 14:21:42 +0100975 return;
976 }
Harald Weltef0d6ac62017-12-17 17:02:21 +0100977 f_sleep(0.1);
Harald Weltea5d2ab22017-12-09 14:21:42 +0100978 if (not T.running) {
Max99253902018-11-16 17:57:39 +0100979 setverdict(fail, "Timeout waiting for BTS" & int2str(bts_nr) & " oml-connection-state ", status);
Daniel Willmannafce8662018-07-06 23:11:32 +0200980 mtc.stop;
Harald Weltea5d2ab22017-12-09 14:21:42 +0100981 }
982 }
983}
984
Harald Welte21b46bd2017-12-17 19:46:32 +0100985/* global altstep for global guard timer; also takes care of responding RESET witH RESET-ACK */
Harald Welteae026692017-12-09 01:03:01 +0100986altstep as_Tguard() runs on test_CT {
Harald Welte60e823a2017-12-10 14:10:59 +0100987 var BSSAP_N_UNITDATA_ind ud_ind;
Neels Hofmeyrcc3f76a2018-03-12 01:43:25 +0100988 [] T_guard.timeout {
989 setverdict(fail, "Timeout of T_guard");
Daniel Willmannafce8662018-07-06 23:11:32 +0200990 mtc.stop;
Neels Hofmeyrcc3f76a2018-03-12 01:43:25 +0100991 }
Harald Welte60e823a2017-12-10 14:10:59 +0100992 /* always respond with RESET ACK to RESET */
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +0200993 [] BSSAP.receive(tr_BSSAP_UNITDATA_ind(?, ?, tr_BSSMAP_Reset(g_osmux_enabled))) -> value ud_ind {
Harald Welte60e823a2017-12-10 14:10:59 +0100994 BSSAP.send(ts_BSSAP_UNITDATA_req(ud_ind.callingAddress, ud_ind.calledAddress,
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +0200995 ts_BSSMAP_ResetAck(g_osmux_enabled)));
Harald Welte69c1c262017-12-13 21:02:08 +0100996 repeat;
Harald Welte60e823a2017-12-10 14:10:59 +0100997 }
Harald Welte28d943e2017-11-25 15:00:50 +0100998}
999
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +01001000altstep no_bssmap_reset() runs on test_CT {
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02001001 [] BSSAP.receive(tr_BSSAP_UNITDATA_ind(?, ?, tr_BSSMAP_Reset(g_osmux_enabled))) {
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +01001002 setverdict(fail, "unexpected BSSMAP Reset");
Daniel Willmannafce8662018-07-06 23:11:32 +02001003 mtc.stop;
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +01001004 }
1005}
1006
Daniel Willmann191e0d92018-01-17 12:44:35 +01001007function f_init_mgcp(charstring id) runs on test_CT {
1008 id := id & "-MGCP";
1009
1010 var MGCPOps ops := {
1011 create_cb := refers(MGCP_Emulation.ExpectedCreateCallback),
1012 unitdata_cb := refers(MGCP_Emulation.DummyUnitdataCallback)
1013 };
1014 var MGCP_conn_parameters mgcp_pars := {
1015 callagent_ip := mp_bsc_ip,
Harald Welte9e4273e2018-01-29 22:01:22 +01001016 callagent_udp_port := -1,
Daniel Willmann191e0d92018-01-17 12:44:35 +01001017 mgw_ip := mp_test_ip,
Pau Espin Pedrol1a026a52019-06-18 17:21:52 +02001018 mgw_udp_port := 2427,
Pau Espin Pedrolfd02ad42019-06-18 17:45:20 +02001019 /* Enable it for SCCPlite, since we have 2 MGCP sockets towards MGW (UDP one +
1020 the on with MGCP over IPA forwarded from MSC one) */
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001021 multi_conn_mode := (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_SCCPlite_SERVER)
Daniel Willmann191e0d92018-01-17 12:44:35 +01001022 };
1023
1024 vc_MGCP := MGCP_Emulation_CT.create(id);
1025 vc_MGCP.start(MGCP_Emulation.main(ops, mgcp_pars, id));
1026}
1027
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02001028/* Enable or disable (current default) Osmux. When enabling, BSSMAP Reset
1029 * contains extra IE (OsmuxSupport) and osmo-bsc will handle AssignReq with
1030 * OsmuxCID IE.
1031 */
1032private function f_vty_allow_osmux(boolean allow) runs on test_CT {
1033 f_vty_enter_cfg_msc(BSCVTY, 0);
1034 if (allow) {
1035 f_vty_transceive(BSCVTY, "osmux on");
1036 } else {
1037 f_vty_transceive(BSCVTY, "osmux off");
1038 }
1039 f_vty_transceive(BSCVTY, "exit");
1040 f_vty_transceive(BSCVTY, "exit");
1041 g_osmux_enabled := allow;
1042}
1043
Max2253c0b2018-11-06 19:28:05 +01001044function f_init_vty(charstring id := "foo") runs on test_CT {
Harald Welte94e0c342018-04-07 11:33:23 +02001045 if (BSCVTY.checkstate("Mapped")) {
1046 /* skip initialization if already executed once */
1047 return;
1048 }
Harald Weltebc03c762018-02-12 18:09:38 +01001049 map(self:BSCVTY, system:BSCVTY);
1050 f_vty_set_prompts(BSCVTY);
1051 f_vty_transceive(BSCVTY, "enable");
Pau Espin Pedrolc675b612020-01-09 19:55:40 +01001052 f_cs7_inst_0_cfg(BSCVTY, {"sccp-timer ias " & int2str(g_bsc_sccp_timer_ias),
1053 "sccp-timer iar " & int2str(g_bsc_sccp_timer_iar)});
Harald Weltebc03c762018-02-12 18:09:38 +01001054}
1055
Neels Hofmeyr9f3e6ac2021-04-08 23:09:24 +02001056friend function f_logp(TELNETasp_PT pt, charstring log_msg)
Neels Hofmeyr4f118412020-06-04 15:25:10 +02001057{
1058 // log on TTCN3 log output
1059 log(log_msg);
1060 // log in stderr log
Neels Hofmeyr767548a2020-08-09 20:26:07 +00001061 f_vty_transceive(pt, "logp lglobal notice TTCN3 f_logp(): " & log_msg);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02001062}
1063
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +02001064private function f_sysinfo_seen(integer rsl_idx, RSL_Message rsl) runs on test_CT
1065{
1066 if (rsl_idx >= lengthof(g_system_information)) {
1067 g_system_information[rsl_idx] := SystemInformationConfig_omit
1068 }
1069 f_sysinfo_dec_raw(g_system_information[rsl_idx], rsl);
1070}
1071
1072altstep as_catch_RSL_sysinfo(integer rsl_idx) runs on test_CT {
1073 var ASP_RSL_Unitdata rx_rsl_ud;
1074
1075 /* For handler_mode := false, receiving the RSL bootstrap messages directly on IPA_RSL */
1076 [] IPA_RSL[rsl_idx].receive(tr_ASP_RSL_UD(tr_RSL_NO_BCCH_INFO)) -> value rx_rsl_ud {
1077 f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
1078 repeat;
1079 }
1080 [] IPA_RSL[rsl_idx].receive(tr_ASP_RSL_UD(tr_RSL_BCCH_INFO)) -> value rx_rsl_ud {
1081 f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
1082 repeat;
1083 }
1084 [] IPA_RSL[rsl_idx].receive(tr_ASP_RSL_UD(tr_RSL_NO_SACCH_FILL)) -> value rx_rsl_ud {
1085 f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
1086 repeat;
1087 }
1088 [] IPA_RSL[rsl_idx].receive(tr_ASP_RSL_UD(tr_RSL_SACCH_FILL)) -> value rx_rsl_ud {
1089 f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
1090 repeat;
1091 }
1092
1093 /* For handler_mode := true, receiving the RSL bootstrap messages via RSL_Emulation */
1094 [] RSL_CCHAN[rsl_idx].receive(tr_ASP_RSL_UD(tr_RSL_NO_BCCH_INFO)) -> value rx_rsl_ud {
1095 f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
1096 repeat;
1097 }
1098 [] RSL_CCHAN[rsl_idx].receive(tr_ASP_RSL_UD(tr_RSL_BCCH_INFO)) -> value rx_rsl_ud {
1099 f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
1100 repeat;
1101 }
1102 [] RSL_CCHAN[rsl_idx].receive(tr_ASP_RSL_UD(tr_RSL_NO_SACCH_FILL)) -> value rx_rsl_ud {
1103 f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
1104 repeat;
1105 }
1106 [] RSL_CCHAN[rsl_idx].receive(tr_ASP_RSL_UD(tr_RSL_SACCH_FILL)) -> value rx_rsl_ud {
1107 f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
1108 repeat;
1109 }
1110}
1111
Neels Hofmeyra460f1f2020-08-09 20:17:03 +00001112/* TODO: use BooleanList from COMMON/src/General_Types.ttcn */
1113private type record of boolean my_BooleanList;
1114
1115private function f_vty_msc_allow_attach(TELNETasp_PT pt, my_BooleanList allow_attach_list)
1116{
Neels Hofmeyr8f576712020-08-12 22:49:53 +00001117 var charstring config := f_vty_transceive_ret(pt, "show running-config");
1118
Neels Hofmeyra460f1f2020-08-09 20:17:03 +00001119 for (var integer msc_nr := 0; msc_nr < sizeof(allow_attach_list); msc_nr := msc_nr+1) {
Neels Hofmeyr8f576712020-08-12 22:49:53 +00001120 if (f_strstr(config, "\nmsc " & int2str(msc_nr) & "\n") < 0) {
1121 /* There is no 'msc N' for this msc_nr in the running config, so don't create an empty msc by
1122 * stepping into that config node. */
1123 log("msc ", msc_nr, " is not configured, skipping");
1124 continue;
1125 }
Neels Hofmeyra460f1f2020-08-09 20:17:03 +00001126 f_vty_enter_cfg_msc(pt, msc_nr);
1127 if (allow_attach_list[msc_nr]) {
1128 /* strict := false: ignore if osmo-bsc does not support this config option (latest build) */
1129 f_vty_transceive(pt, "allow-attach", strict := false);
1130 } else {
1131 f_vty_transceive(pt, "no allow-attach", strict := false);
1132 }
1133 f_vty_transceive(pt, "exit");
1134 f_vty_transceive(pt, "exit");
1135 }
1136}
1137
Harald Welte21b46bd2017-12-17 19:46:32 +01001138/* global initialization function
1139 * \param nr_bts Number of BTSs we should start/bring up
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001140 * \param handler_mode Start an RSL_Emulation_CT component (true) or not (false).
1141 * \param nr_msc Number of virtual MSCs to bring up to connect to osmo-bsc.
1142 */
1143function f_init(integer nr_bts := NUM_BTS, boolean handler_mode := false, boolean allow_osmux := false,
Neels Hofmeyr4fbad7f2020-06-16 00:30:47 +02001144 integer nr_msc := 1, float guard_timeout := 30.0) runs on test_CT {
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001145 var integer bssap_idx;
Harald Welte28d943e2017-11-25 15:00:50 +01001146
Harald Welteae026692017-12-09 01:03:01 +01001147 if (g_initialized) {
1148 return;
Harald Welte28d943e2017-11-25 15:00:50 +01001149 }
Harald Welteae026692017-12-09 01:03:01 +01001150 g_initialized := true;
1151
Neels Hofmeyr4fbad7f2020-06-16 00:30:47 +02001152 T_guard.start(guard_timeout);
Daniel Willmanne68f9272018-11-27 15:15:28 +01001153 activate(as_Tguard());
1154
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02001155 f_init_vty("VirtMSC");
Pau Espin Pedrol23510fb2021-07-20 17:00:38 +02001156 f_vty_allow_osmux(allow_osmux);
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02001157
Neels Hofmeyra460f1f2020-08-09 20:17:03 +00001158 var my_BooleanList allow_attach := { false, false, false };
Daniel Willmannebdecc02020-08-12 15:30:17 +02001159 f_init_statsd("VirtMSC", vc_STATSD, mp_test_ip, mp_bsc_statsd_port);
1160
Neels Hofmeyr9db8e0e2021-08-23 20:45:58 +02001161 /* Make sure each MSC's internal state is "DISCONNECTED" at first */
1162 for (bssap_idx := 0; bssap_idx < NUM_MSC; bssap_idx := bssap_idx+1) {
1163 f_vty_transceive(BSCVTY, "msc " & int2str(bssap_idx) & " bssmap reset", strict := false);
1164 }
1165
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001166 for (bssap_idx := 0; bssap_idx < nr_msc; bssap_idx := bssap_idx+1) {
Neels Hofmeyra460f1f2020-08-09 20:17:03 +00001167 allow_attach[bssap_idx] := true;
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001168 /* Call a function of our 'parent component' RAN_Adapter_CT to start the
1169 * MSC-side BSSAP emulation */
1170 if (handler_mode) {
1171 var RanOps ranops := MSC_RanOps;
1172 ranops.use_osmux := g_osmux_enabled;
1173 f_ran_adapter_init(g_bssap[bssap_idx], mp_bssap_cfg[bssap_idx], "VirtMSC", ranops);
1174 connect(self:SCCPLITE_IPA_CTRL, g_bssap[bssap_idx].vc_RAN:CTRL_CLIENT);
1175 f_ran_adapter_start(g_bssap[bssap_idx]);
1176 } else {
1177 f_ran_adapter_init(g_bssap[bssap_idx], mp_bssap_cfg[bssap_idx], "VirtMSC", omit);
1178 connect(self:BSSAP, g_bssap[bssap_idx].vc_SCCP:SCCP_SP_PORT);
1179 f_ran_adapter_start(g_bssap[bssap_idx]);
1180 f_legacy_bssap_reset();
1181 }
Harald Welte67089ee2018-01-17 22:19:03 +01001182 }
Harald Welted5833a82018-05-27 16:52:56 +02001183
Neels Hofmeyrcfe44062020-10-15 02:28:08 +02001184 if (mp_enable_lcs_tests) {
1185 if (handler_mode) {
1186 f_bssap_le_adapter_init(g_bssap_le, mp_bssap_le_cfg, "VirtSMLC", SMLC_BssapLeOps);
1187 } else {
1188 f_bssap_le_adapter_init(g_bssap_le, mp_bssap_le_cfg, "VirtSMLC", omit);
1189 connect(self:BSSAP_LE, g_bssap_le.vc_SCCP:SCCP_SP_PORT);
1190 }
1191 f_bssap_le_adapter_start(g_bssap_le);
Harald Welte47cd0e32020-08-21 12:39:11 +02001192 }
Harald Welte47cd0e32020-08-21 12:39:11 +02001193
Neels Hofmeyra460f1f2020-08-09 20:17:03 +00001194 /* start the test with exactly all enabled MSCs allowed to attach */
1195 f_vty_msc_allow_attach(BSCVTY, allow_attach);
1196
Pau Espin Pedrol9a5b8ff2021-01-04 19:01:31 +01001197 f_ipa_ctrl_start_client(mp_bsc_ip, mp_bsc_ctrl_port);
Harald Welte28d943e2017-11-25 15:00:50 +01001198
Daniel Willmann191e0d92018-01-17 12:44:35 +01001199 f_init_mgcp("VirtMSC");
1200
Neels Hofmeyr0b7365b2020-07-04 00:52:34 +02001201 for (var integer i := 0; i < nr_bts; i := i+1) {
1202 f_init_bts(i, handler_mode);
Harald Welte696ddb62017-12-08 14:01:43 +01001203 }
Neels Hofmeyr0b7365b2020-07-04 00:52:34 +02001204}
Harald Welte696ddb62017-12-08 14:01:43 +01001205
Neels Hofmeyr0b7365b2020-07-04 00:52:34 +02001206function f_init_bts(integer bts_idx := 0, boolean handler_mode := false)
1207runs on test_CT {
1208 /* wait until osmo-bts-omldummy has respawned */
1209 f_wait_oml(bts_idx, "degraded", 5.0);
1210
1211 /* start RSL connection */
1212 f_ipa_rsl_start(bts[bts_idx].rsl, mp_bsc_ip, mp_bsc_rsl_port, bts_idx, handler_mode);
1213 /* wait until BSC tells us "connected" */
1214 f_wait_oml(bts_idx, "connected", 5.0);
Harald Welte28d943e2017-11-25 15:00:50 +01001215}
1216
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +02001217function f_init_bts_and_check_sysinfo(integer bts_idx := 0, boolean handler_mode := false,
1218 template SystemInformationConfig expect_si)
1219runs on test_CT {
1220 var default sysinfo := activate(as_catch_RSL_sysinfo(bts_idx));
1221
1222 f_init_bts(bts_idx, handler_mode);
1223
1224 /* Give some time to (hopefully/most likely) collect all system informations from RSL startup.
1225 * We could stop as soon as all expected SI are received, but then we might miss SI that we don't expect and
1226 * that might be sent afterwards. So rather give a generous timeout and be quite sure to catch all SI.
1227 */
1228 f_sleep(5.0);
1229 log("RSL ", bts_idx, " SYSTEM INFORMATION: ", g_system_information[bts_idx]);
1230
1231 deactivate(sysinfo);
1232
1233 if (match(g_system_information[bts_idx], expect_si)) {
1234 setverdict(pass);
1235 } else {
1236 log("RSL ", bts_idx, ": EXPECTED SI: ", expect_si);
1237 log("RSL ", bts_idx, ": GOT SI: ", g_system_information[bts_idx]);
1238 setverdict(fail, "received SI does not match expectations");
1239 return;
1240 }
1241}
1242
Maxd4e56962018-10-31 19:08:25 +01001243/* expect to receive a RSL message matching a specified template on a given BTS / stream */
Harald Welte65e419a2020-08-21 12:38:33 +02001244function 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 +01001245runs on test_CT return RSL_Message {
1246 var ASP_RSL_Unitdata rx_rsl_ud;
1247 timer T := t_secs;
1248
1249 T.start;
1250 alt {
Vadim Yanitskiy9b4e3562020-05-25 21:40:52 +07001251 [] IPA_RSL[bts_nr].receive(tr_ASP_RSL_UD(t_rx, sid)) -> value rx_rsl_ud {
Harald Welteae026692017-12-09 01:03:01 +01001252 T.stop;
1253 }
1254 [] IPA_RSL[bts_nr].receive { repeat; }
Harald Welteb2917702017-12-10 15:48:52 +01001255 [] T.timeout {
1256 setverdict(fail, "Timeout expecting ", t_rx);
Daniel Willmannafce8662018-07-06 23:11:32 +02001257 mtc.stop;
Harald Welteb2917702017-12-10 15:48:52 +01001258 }
Harald Welteae026692017-12-09 01:03:01 +01001259 }
1260 return rx_rsl_ud.rsl;
1261}
1262
Harald Welte21b46bd2017-12-17 19:46:32 +01001263/* helper function to transmit RSL on a given BTS/stream */
Harald Welte65e419a2020-08-21 12:38:33 +02001264function 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 +01001265runs on test_CT {
Vadim Yanitskiy9b4e3562020-05-25 21:40:52 +07001266 IPA_RSL[bts_nr].send(ts_ASP_RSL_UD(t_tx, sid));
Harald Welteae026692017-12-09 01:03:01 +01001267}
1268
1269
Harald Welte4003d112017-12-09 22:35:39 +01001270/* verify we get a CHAN_ACT after CHAN RQD */
Harald Welteae026692017-12-09 01:03:01 +01001271testcase TC_chan_act_noreply() runs on test_CT {
1272 var BSSAP_N_UNITDATA_ind ud_ind;
Harald Welte930d0a72018-03-22 22:08:40 +01001273 var RSL_Message rsl_unused;
Harald Welte28d943e2017-11-25 15:00:50 +01001274
Harald Welte89d42e82017-12-17 16:42:41 +01001275 f_init(1);
Harald Welte28d943e2017-11-25 15:00:50 +01001276
Vadim Yanitskiy9b4e3562020-05-25 21:40:52 +07001277 IPA_RSL[0].send(ts_ASP_RSL_UD(ts_RSL_CHAN_RQD('23'O, 23)));
Harald Welte930d0a72018-03-22 22:08:40 +01001278 rsl_unused := f_exp_ipa_rx(0, tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001279 f_shutdown_helper();
Harald Welte28d943e2017-11-25 15:00:50 +01001280}
1281
Neels Hofmeyr734b1a32021-11-29 16:00:17 +01001282const CounterNameVals counternames_bts_chreq := {
1283 { "chreq:total", 0 },
1284 { "chreq:attempted_emerg", 0 },
1285 { "chreq:attempted_call", 0 },
1286 { "chreq:attempted_location_upd", 0 },
1287 { "chreq:attempted_pag", 0 },
1288 { "chreq:attempted_pdch", 0 },
1289 { "chreq:attempted_other", 0 },
1290 { "chreq:attempted_unknown", 0 },
1291 { "chreq:successful", 0 },
1292 { "chreq:successful_emerg", 0 },
1293 { "chreq:successful_call", 0 },
1294 { "chreq:successful_location_upd", 0 },
1295 { "chreq:successful_pag", 0 },
1296 { "chreq:successful_pdch", 0 },
1297 { "chreq:successful_other", 0 },
1298 { "chreq:successful_unknown", 0 },
1299 { "chreq:no_channel", 0 },
1300 { "chreq:max_delay_exceeded", 0 }
1301};
1302
1303/* verify the "chreq:*" counters */
1304private function f_chan_act_counter(OCT1 ra, charstring chreq_ctr_suffix) runs on test_CT
1305{
1306 var GsmFrameNumber fn := 23;
1307
1308 f_logp(BSCVTY, "f_chan_act_counter(" & chreq_ctr_suffix & ")");
1309
1310 var RSL_Message rx_rsl;
1311 f_ipa_tx(0, ts_RSL_CHAN_RQD(ra, fn));
1312 rx_rsl := f_exp_ipa_rx(0, tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
1313 var RslChannelNr chan_nr := rx_rsl.ies[0].body.chan_nr;
1314
1315 f_ctrs_bts_add(0, "chreq:total");
1316 f_ctrs_bts_add(0, "chreq:attempted_" & chreq_ctr_suffix);
1317 f_ctrs_bts_verify();
1318
1319 f_ipa_tx(0, ts_RSL_CHAN_ACT_ACK(chan_nr, fn+10));
1320 rx_rsl := f_exp_ipa_rx(0, tr_RSL_IMM_ASSIGN(0));
1321
1322 f_ctrs_bts_add(0, "chreq:successful");
1323 f_ctrs_bts_add(0, "chreq:successful_" & chreq_ctr_suffix);
1324 f_ctrs_bts_verify();
1325
1326 /* test is done, release RSL Conn Fail Ind to clean up */
1327 f_ipa_tx(0, ts_RSL_CONN_FAIL_IND(chan_nr, RSL_ERR_RADIO_LINK_FAIL));
1328 rx_rsl := f_exp_ipa_rx(0, tr_RSL_MsgTypeD(RSL_MT_RF_CHAN_REL), 10.0);
1329 f_ipa_tx(0, ts_RSL_RF_CHAN_REL_ACK(chan_nr));
1330 f_sleep(1.0);
1331}
1332
Harald Welte4003d112017-12-09 22:35:39 +01001333testcase TC_chan_act_counter() runs on test_CT {
1334 var BSSAP_N_UNITDATA_ind ud_ind;
1335 var integer chreq_total;
Harald Welte930d0a72018-03-22 22:08:40 +01001336 var RSL_Message rsl_unused;
Harald Welte4003d112017-12-09 22:35:39 +01001337
Harald Welte89d42e82017-12-17 16:42:41 +01001338 f_init(1);
Harald Welte4003d112017-12-09 22:35:39 +01001339
Neels Hofmeyr734b1a32021-11-29 16:00:17 +01001340 f_vty_allow_emerg_bts(true, 0);
1341
1342 f_ctrs_bts_init(1, counternames_bts_chreq);
1343
1344 /* emergency call: RA & 0xe0 == 0xa0 --> CHREQ_T_EMERG_CALL */
1345 f_chan_act_counter('a3'O, "emerg");
1346
1347 /* voice TCH/H: RA & 0xf0 == 0x40 --> CHREQ_T_VOICE_CALL_TCH_H */
1348 f_chan_act_counter('43'O, "call");
1349
1350 /* LU: RA & 0xf0 == 0x00 --> CHREQ_T_LOCATION_UPD */
1351 f_chan_act_counter('03'O, "location_upd");
1352
1353 /* Paging: RA & 0xf0 == 0x20 --> CHREQ_T_PAG_R_TCH_F */
1354 f_chan_act_counter('23'O, "pag");
1355 /* Paging: RA & 0xf0 == 0x30 --> CHREQ_T_PAG_R_TCH_FH */
1356 f_chan_act_counter('33'O, "pag");
1357
1358 /* LU: RA & 0xfc == 0x78 --> CHREQ_T_PDCH_TWO_PHASE */
1359 /* no PCU, so PDCH not allowed. Skip this test for now. */
1360 /* f_chan_act_counter('7b'O, "pdch"); */
1361
1362 /* LU: RA & 0xf0 == 0x10 --> CHREQ_T_SDCCH */
1363 f_chan_act_counter('13'O, "other");
Harald Welte4003d112017-12-09 22:35:39 +01001364
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001365 f_shutdown_helper();
Harald Welte4003d112017-12-09 22:35:39 +01001366}
1367
Harald Welteae026692017-12-09 01:03:01 +01001368/* CHAN RQD -> CHAN ACT -> CHAN ACT ACK -> RF CHAN REL */
Philipp Maier9c60a622020-07-09 15:08:46 +02001369private function f_TC_chan_act_ack_noest(OCT1 ra := '23'O) runs on test_CT {
Harald Welteae026692017-12-09 01:03:01 +01001370 var RSL_Message rx_rsl;
1371
Harald Welteae026692017-12-09 01:03:01 +01001372 /* Send CHAN RQD and wait for allocation; acknowledge it */
Philipp Maier9c60a622020-07-09 15:08:46 +02001373 var RslChannelNr chan_nr := f_chreq_act_ack(ra);
Harald Welteae026692017-12-09 01:03:01 +01001374
1375 /* expect BSC to disable the channel again if there's no RLL EST IND */
1376 rx_rsl := f_exp_ipa_rx(0, tr_RSL_MsgTypeD(RSL_MT_RF_CHAN_REL), T3101_MAX);
1377
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001378 f_shutdown_helper();
Harald Welteae026692017-12-09 01:03:01 +01001379}
1380
Philipp Maier9c60a622020-07-09 15:08:46 +02001381/* Normal variant */
1382testcase TC_chan_act_ack_noest() runs on test_CT {
Philipp Maieraf58db22020-08-12 17:24:40 +02001383 f_init(1);
Philipp Maier9c60a622020-07-09 15:08:46 +02001384 f_TC_chan_act_ack_noest();
1385}
1386
1387/* Emergency call variant */
1388testcase TC_chan_act_ack_noest_emerg() runs on test_CT {
1389 /* See also: 3GPP TS 04.08, Table 9.9, ra=101xxxxx */
Philipp Maieraf58db22020-08-12 17:24:40 +02001390 f_init(1);
1391 f_vty_allow_emerg_bts(true, 0);
Philipp Maier9c60a622020-07-09 15:08:46 +02001392 f_TC_chan_act_ack_noest(ra := 'A5'O);
1393}
1394
Philipp Maier606f07d2020-08-12 17:21:58 +02001395/* Emergency call variant, but emergency calls are not allowed */
1396testcase TC_chan_rqd_emerg_deny() runs on test_CT {
1397 /* See also: 3GPP TS 04.08, Table 9.9, ra=101xxxxx */
1398
1399 var RSL_Message rx_rsl;
1400 var GsmRrMessage rr;
1401
1402 f_init(1);
1403 f_vty_allow_emerg_bts(false, 0);
1404
1405 IPA_RSL[0].clear;
1406 f_ipa_tx(0, ts_RSL_CHAN_RQD('A5'O, 23));
1407
1408 rx_rsl := f_exp_ipa_rx(0, tr_RSL_MsgTypeC(RSL_MT_IMMEDIATE_ASSIGN_CMD));
1409 rr := dec_GsmRrMessage(rx_rsl.ies[1].body.full_imm_ass_info.payload);
1410 if (rr.header.message_type == IMMEDIATE_ASSIGNMENT_REJECT) {
1411 setverdict(pass);
1412 } else {
1413 setverdict(fail, "immediate assignment not rejected");
1414 }
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +01001415
1416 f_shutdown_helper();
Philipp Maier606f07d2020-08-12 17:21:58 +02001417}
1418
Harald Welteae026692017-12-09 01:03:01 +01001419/* Test behavior if MSC never answers to CR */
1420testcase TC_chan_act_ack_est_ind_noreply() runs on test_CT {
Harald Weltef77aef62018-01-28 15:35:42 +01001421 var RslLinkId main_dcch := valueof(ts_RslLinkID_DCCH(0));
1422 var IpaStreamId sid := IPAC_PROTO_RSL_TRX0;
Harald Welteae026692017-12-09 01:03:01 +01001423 var RSL_Message rx_rsl;
Harald Weltef77aef62018-01-28 15:35:42 +01001424 var ASP_RSL_Unitdata rx_rsl_ud;
Harald Welteae026692017-12-09 01:03:01 +01001425
Harald Welte89d42e82017-12-17 16:42:41 +01001426 f_init(1);
Harald Welteae026692017-12-09 01:03:01 +01001427
1428 /* Send CHAN RQD and wait for allocation; acknowledge it */
Harald Welted6939652017-12-13 21:02:46 +01001429 var RslChannelNr chan_nr := f_chreq_act_ack();
Harald Welteae026692017-12-09 01:03:01 +01001430
1431 var octetstring l3 := '00010203040506'O
1432 f_ipa_tx(0, ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3));
1433
1434 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3)));
1435
1436 /* expect BSC to disable the channel again if there's no response from MSC */
Harald Weltef77aef62018-01-28 15:35:42 +01001437 /* MS waits 20s (T3210) at LU; 10s (T3230) at CM SERV REQ and 5s (T3220) AT detach */
Neels Hofmeyra5302c82018-11-04 23:09:58 +01001438 f_expect_chan_rel(0, chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001439 f_shutdown_helper();
Harald Welteae026692017-12-09 01:03:01 +01001440}
1441
1442/* Test behavior if MSC answers with CREF to CR */
1443testcase TC_chan_act_ack_est_ind_refused() runs on test_CT {
1444 var BSSAP_N_CONNECT_ind rx_c_ind;
1445 var RSL_Message rx_rsl;
1446
Harald Welte89d42e82017-12-17 16:42:41 +01001447 f_init(1);
Harald Welteae026692017-12-09 01:03:01 +01001448
1449 /* Send CHAN RQD and wait for allocation; acknowledge it */
Harald Welted6939652017-12-13 21:02:46 +01001450 var RslChannelNr chan_nr := f_chreq_act_ack();
Harald Welteae026692017-12-09 01:03:01 +01001451
1452 var octetstring l3 := '00010203040506'O
1453 f_ipa_tx(0, ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3));
1454
1455 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3))) -> value rx_c_ind;
1456 BSSAP.send(ts_BSSAP_DISC_req(rx_c_ind.connectionId, 0));
1457
1458 /* expect BSC to disable the channel */
Neels Hofmeyra5302c82018-11-04 23:09:58 +01001459 f_expect_chan_rel(0, chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001460 f_shutdown_helper();
Harald Welteae026692017-12-09 01:03:01 +01001461}
1462
Harald Welte618ef642017-12-14 14:58:20 +01001463/* CHAN RQD -> CHAN ACT -> CHAN ACT NACK -> RF CHAN REL */
1464testcase TC_chan_act_nack() runs on test_CT {
1465 var RSL_Message rx_rsl;
1466 var integer chact_nack;
1467
Harald Welte89d42e82017-12-17 16:42:41 +01001468 f_init(1);
Harald Welte618ef642017-12-14 14:58:20 +01001469
1470 chact_nack := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", 0, "chan_act:nack");
1471
1472 f_ipa_tx(0, ts_RSL_CHAN_RQD('33'O, 33));
1473 rx_rsl := f_exp_ipa_rx(0, tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
1474 var RslChannelNr chan_nr := rx_rsl.ies[0].body.chan_nr;
1475
1476 f_ipa_tx(0, ts_RSL_CHAN_ACT_NACK(chan_nr, RSL_ERR_EQUIPMENT_FAIL));
1477
1478 /* wait for some time to hope the NACK arrives before the CTRL GET below */
1479 f_sleep(0.5);
1480
1481 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", 0, "chan_act:nack", chact_nack+1);
1482
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001483 f_shutdown_helper();
Harald Welte618ef642017-12-14 14:58:20 +01001484}
1485
Harald Welte799c97b2017-12-14 17:50:30 +01001486/* Test for channel exhaustion due to RACH overload */
1487testcase TC_chan_exhaustion() runs on test_CT {
1488 var ASP_RSL_Unitdata rsl_ud;
1489 var integer i;
1490 var integer chreq_total, chreq_nochan;
1491
Harald Welte89d42e82017-12-17 16:42:41 +01001492 f_init(1);
Harald Welte799c97b2017-12-14 17:50:30 +01001493
1494 chreq_total := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:total");
1495 chreq_nochan := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:no_channel");
1496
Neels Hofmeyr85fa37f2021-10-06 13:50:38 +02001497 /* GSM 44.018 Table 9.1.8.2:
Pau Espin Pedrolfe200d72018-12-10 12:41:04 +01001498 * RA = '33'O -> Establishment cause = 0011xxxx (MS dual rate capable and asks for "TCH/H or TCH/F").
1499 * With current setup, expect 4xSDCCH + 4xTCH/F + 1xTCH/H to succeed */
Philipp Maiercb6cc482018-03-26 13:08:00 +02001500 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 +01001501 var RslChannelNr chan_nr := f_chreq_act_ack('33'O, i);
Harald Welte799c97b2017-12-14 17:50:30 +01001502 }
1503
1504 IPA_RSL[0].clear;
1505
Harald Weltedd8cbf32018-01-28 12:07:52 +01001506 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:total",
Philipp Maiercb6cc482018-03-26 13:08:00 +02001507 chreq_total + NUM_TCHF_PER_BTS + NUM_TCHH_PER_BTS + NUM_SDCCH_PER_BTS);
Harald Welte799c97b2017-12-14 17:50:30 +01001508
1509 /* now expect additional channel activations to fail */
1510 f_ipa_tx(0, ts_RSL_CHAN_RQD('42'O, 42));
1511
1512 alt {
Vadim Yanitskiy9b4e3562020-05-25 21:40:52 +07001513 [] IPA_RSL[0].receive(tr_ASP_RSL_UD(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV))) {
Harald Welte799c97b2017-12-14 17:50:30 +01001514 setverdict(fail, "Received CHAN ACT ACK without resources?!?");
1515 }
Vadim Yanitskiy9b4e3562020-05-25 21:40:52 +07001516 [] IPA_RSL[0].receive(tr_ASP_RSL_UD(tr_RSL_IMM_ASSIGN(?))) -> value rsl_ud {
Harald Welte799c97b2017-12-14 17:50:30 +01001517 var GsmRrMessage rr;
1518 /* match on IMM ASS REJ */
1519 rr := dec_GsmRrMessage(rsl_ud.rsl.ies[1].body.full_imm_ass_info.payload);
1520 if (rr.header.message_type == IMMEDIATE_ASSIGNMENT_REJECT) {
1521 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:total",
Philipp Maiercb6cc482018-03-26 13:08:00 +02001522 chreq_total + NUM_TCHF_PER_BTS + NUM_TCHH_PER_BTS + NUM_SDCCH_PER_BTS+1);
Harald Welte799c97b2017-12-14 17:50:30 +01001523 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:no_channel",
1524 chreq_nochan+1);
1525 setverdict(pass);
1526 } else {
1527 repeat;
1528 }
1529 }
1530 [] IPA_RSL[0].receive { repeat; }
1531 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001532 f_shutdown_helper();
Harald Welte799c97b2017-12-14 17:50:30 +01001533}
1534
Vadim Yanitskiy1ff1fdf2018-11-27 01:32:57 +07001535/* Test channel deactivation due to silence from MS */
1536testcase TC_chan_deact_silence() runs on test_CT {
1537 var RslChannelNr chan_nr;
1538
1539 f_init(1);
1540
1541 /* Request for a dedicated channel */
1542 chan_nr := f_chreq_act_ack('23'O);
1543
1544 /* Wait some time until the channel is released */
1545 f_sleep(2.0);
1546
1547 /* Expect CHANnel RELease */
1548 alt {
Vadim Yanitskiy9b4e3562020-05-25 21:40:52 +07001549 [] IPA_RSL[0].receive(tr_ASP_RSL_UD(tr_RSL_MsgTypeD(RSL_MT_RF_CHAN_REL))) {
Vadim Yanitskiy1ff1fdf2018-11-27 01:32:57 +07001550 log("Received CHANnel RELease");
1551 setverdict(pass);
1552 }
Vadim Yanitskiy9b4e3562020-05-25 21:40:52 +07001553 [] IPA_RSL[0].receive(tr_ASP_RSL_UD(tr_RSL_IMM_ASSIGN(?))) {
Vadim Yanitskiy1ff1fdf2018-11-27 01:32:57 +07001554 /* See OS#3709, OsmoBSC should not send Immediate
1555 * Assignment Reject since a dedicated channel was
1556 * already allocated, and Immediate Assignment was
1557 * already sent. */
1558 setverdict(fail, "Unexpected Immediate Assignment!");
1559 }
1560 [] IPA_RSL[0].receive {
1561 setverdict(fail, "Unexpected RSL message!");
1562 }
1563 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001564 f_shutdown_helper();
Vadim Yanitskiy1ff1fdf2018-11-27 01:32:57 +07001565}
1566
Harald Weltecfe2c962017-12-15 12:09:32 +01001567/***********************************************************************
1568 * Assignment Testing
1569 ***********************************************************************/
1570
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02001571/* Verify that the BSC refuses any BSSAP connection from the MSC (They are all BSC->MSC direction,
1572 * except for the inter-BSC handover, MT side) */
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001573testcase TC_outbound_connect(integer bssap_idx := 0) runs on test_CT {
Harald Welte89d42e82017-12-17 16:42:41 +01001574 f_init(1);
Harald Weltecfe2c962017-12-15 12:09:32 +01001575
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001576 BSSAP.send(ts_BSSAP_CONNECT_req(g_bssap[bssap_idx].sccp_addr_peer, g_bssap[bssap_idx].sccp_addr_own,
1577 2342, ts_BSSMAP_AssignmentReq));
Harald Weltecfe2c962017-12-15 12:09:32 +01001578 BSSAP.receive(tr_BSSAP_DISC_ind(2342, ?, ?));
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001579 f_shutdown_helper();
Harald Weltecfe2c962017-12-15 12:09:32 +01001580}
1581
Harald Welte16a4adf2017-12-14 18:54:01 +01001582/* Test behavior if MSC answers with CREF to CR */
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001583testcase TC_assignment_cic_only(integer bssap_idx := 0) runs on test_CT {
Harald Welte16a4adf2017-12-14 18:54:01 +01001584 var BSSAP_N_CONNECT_ind rx_c_ind;
1585 var RSL_Message rx_rsl;
1586 var DchanTuple dt;
1587
Harald Welte89d42e82017-12-17 16:42:41 +01001588 f_init(1);
Harald Welte16a4adf2017-12-14 18:54:01 +01001589
1590 dt := f_est_dchan('23'O, 23, '00000000'O);
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001591 if (mp_bssap_cfg[bssap_idx].transport == BSSAP_TRANSPORT_AoIP) {
Harald Welte17b27da2018-05-25 20:33:53 +02001592 /* send assignment without AoIP IEs */
1593 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_AssignmentReq(ts_BSSMAP_IE_CIC(0, 1))));
1594 } else {
1595 /* Send assignmetn without CIC in IPA case */
1596 var BSSMAP_IE_AoIP_TransportLayerAddress tla :=
1597 valueof(ts_BSSMAP_IE_AoIP_TLA4('01020304'O, 2342));
1598 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_AssignmentReq(omit, tla)));
1599 }
Harald Welte16a4adf2017-12-14 18:54:01 +01001600 alt {
1601 [] BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_AssignmentComplete)) {
1602 setverdict(fail, "AoIP BSC cannot accept ASSIGNMENT without AoIP Transport IE");
1603 }
Harald Welte235ebf12017-12-15 14:18:16 +01001604 /* TODO: Actually expect GSM0808_CAUSE_REQ_A_IF_TYPE_NOT_SUPP */
Harald Welte16a4adf2017-12-14 18:54:01 +01001605 [] BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_AssignmentFail)) {
1606 setverdict(pass);
1607 }
1608 [] BSSAP.receive { repeat; }
1609 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001610 f_shutdown_helper();
Harald Welte16a4adf2017-12-14 18:54:01 +01001611}
1612
Harald Welteed848512018-05-24 22:27:58 +02001613/* generate an assignment request for either AoIP or SCCPlite */
Pau Espin Pedrol07866632020-09-03 19:10:55 +02001614function 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 +02001615 var PDU_BSSAP ass_cmd;
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02001616 var BSSMAP_IE_Osmo_OsmuxCID osmux_cid := valueof(ts_OsmuxCID(0));
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001617 if (mp_bssap_cfg[bssap_idx].transport == BSSAP_TRANSPORT_AoIP) {
Harald Welteed848512018-05-24 22:27:58 +02001618 var BSSMAP_IE_AoIP_TransportLayerAddress tla :=
Pau Espin Pedrol07866632020-09-03 19:10:55 +02001619 valueof(f_ts_BSSMAP_IE_AoIP_TLA(aoip_tla, 2342));
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02001620 if (osmux_enabled) {
1621 ass_cmd := valueof(ts_BSSMAP_AssignmentReq(omit, tla, osmux_cid));
1622 } else {
1623 ass_cmd := valueof(ts_BSSMAP_AssignmentReq(omit, tla));
1624 }
Harald Welteed848512018-05-24 22:27:58 +02001625 } else {
1626 var BSSMAP_IE_CircuitIdentityCode cic := valueof(ts_BSSMAP_IE_CIC(0,1));
Pau Espin Pedrol096d73d2019-06-06 12:49:17 +02001627 ass_cmd := valueof(ts_BSSMAP_AssignmentReq(cic, omit));
Harald Welteed848512018-05-24 22:27:58 +02001628 }
1629 return ass_cmd;
1630}
1631
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02001632function f_gen_handover_req(integer bssap_idx := 0, charstring aoip_tla := "1.2.3.4",
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02001633 template (omit) BSSMAP_oldToNewBSSIEs oldToNewBSSIEs := omit,
1634 template (omit) TestHdlrEncrParams enc := omit) return PDU_BSSAP {
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01001635 var PDU_BSSAP ho_req;
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02001636
1637 var BSSMAP_IE_EncryptionInformation encryptionInformation :=
1638 valueof(ts_BSSMAP_IE_EncrInfo('0000000000000000'O,'01'O));
1639 var template BSSMAP_IE_ChosenEncryptionAlgorithm chosenEncryptionAlgorithm := omit;
1640 var template BSSMAP_IE_KC128 kc128 := omit;
1641 if (ispresent(enc)) {
1642 var TestHdlrEncrParams v_enc := valueof(enc);
1643 encryptionInformation := valueof(ts_BSSMAP_IE_EncrInfo(v_enc.enc_key, v_enc.enc_alg));
1644 chosenEncryptionAlgorithm := valueof(
1645 ts_BSSMAP_IE_ChosenEncryptionAlgorithm(int2oct(enum2int(
Oliver Smith598e1ed2021-07-09 10:28:40 +02001646 f_cipher_mode_bssmap_to_rsl(v_enc.enc_alg)), 1)));
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02001647 if (ispresent(v_enc.enc_kc128)) {
1648 kc128 := ts_BSSMAP_IE_Kc128(v_enc.enc_kc128);
1649 }
1650 }
1651
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001652 if (mp_bssap_cfg[bssap_idx].transport == BSSAP_TRANSPORT_AoIP) {
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01001653 var BSSMAP_IE_AoIP_TransportLayerAddress tla :=
Pau Espin Pedrol07866632020-09-03 19:10:55 +02001654 valueof(f_ts_BSSMAP_IE_AoIP_TLA(aoip_tla, 2342));
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02001655 ho_req := valueof(ts_BSSMAP_HandoverRequest(omit, tla, oldToNewBSSIEs := oldToNewBSSIEs,
1656 encryptionInformation := encryptionInformation,
1657 chosenEncryptionAlgorithm := chosenEncryptionAlgorithm,
1658 kC128 := kc128));
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01001659 } else {
1660 var BSSMAP_IE_CircuitIdentityCode cic := valueof(ts_BSSMAP_IE_CIC(0,1));
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02001661 ho_req := valueof(ts_BSSMAP_HandoverRequest(cic, omit, oldToNewBSSIEs := oldToNewBSSIEs,
1662 encryptionInformation := encryptionInformation,
1663 chosenEncryptionAlgorithm := chosenEncryptionAlgorithm,
1664 kC128 := kc128));
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01001665 }
1666 return ho_req;
1667}
1668
Harald Welteed848512018-05-24 22:27:58 +02001669/* generate an assignment complete template for either AoIP or SCCPlite */
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001670function f_gen_exp_compl(boolean expect_osmux := false, integer bssap_idx := 0) return template PDU_BSSAP {
Harald Welteed848512018-05-24 22:27:58 +02001671 var template PDU_BSSAP exp_compl;
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02001672 var BSSMAP_IE_Osmo_OsmuxCID osmux_cid := valueof(ts_OsmuxCID(0));
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001673 if (mp_bssap_cfg[bssap_idx].transport == BSSAP_TRANSPORT_AoIP) {
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02001674 if (expect_osmux) {
1675 exp_compl := tr_BSSMAP_AssignmentComplete(omit, ?, osmux_cid);
1676 } else {
1677 exp_compl := tr_BSSMAP_AssignmentComplete(omit, ?, omit);
1678 }
Harald Welteed848512018-05-24 22:27:58 +02001679 } else {
1680 /* CIC is optional "*" as the MSC allocated it */
Pau Espin Pedrol096d73d2019-06-06 12:49:17 +02001681 exp_compl := tr_BSSMAP_AssignmentComplete(*, omit);
Harald Welteed848512018-05-24 22:27:58 +02001682 }
1683 return exp_compl;
1684}
1685
Harald Welte235ebf12017-12-15 14:18:16 +01001686/* Run everything required up to sending a caller-specified assignment command and expect response */
1687function f_assignment_exp(PDU_BSSAP ass_cmd, template PDU_BSSAP exp, charstring fail_text)
1688runs on test_CT {
1689 var BSSAP_N_CONNECT_ind rx_c_ind;
1690 var RSL_Message rx_rsl;
1691 var DchanTuple dt;
1692
Harald Welte89d42e82017-12-17 16:42:41 +01001693 f_init(1);
Harald Welte235ebf12017-12-15 14:18:16 +01001694
1695 dt := f_est_dchan('23'O, 23, '00000000'O);
1696 /* send assignment without AoIP IEs */
1697 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ass_cmd));
1698 alt {
1699 [] BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_AssignmentComplete)) {
1700 if (ischosen(exp.pdu.bssmap.assignmentComplete)) {
1701 setverdict(pass);
1702 } else {
1703 setverdict(fail, fail_text);
1704 }
1705 }
1706 [] BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_AssignmentFail)) {
1707 if (ischosen(exp.pdu.bssmap.assignmentFailure)) {
1708 setverdict(pass);
1709 } else {
1710 setverdict(fail, fail_text);
1711 }
1712 }
1713 [] BSSAP.receive { repeat; }
1714 }
1715}
1716testcase TC_assignment_csd() runs on test_CT {
1717 var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
Harald Welteed848512018-05-24 22:27:58 +02001718 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Harald Welte235ebf12017-12-15 14:18:16 +01001719 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelTypeCSD);
1720 //exp_fail.pdu.bssmap.assignmentFailure.cause.causeValue := int2bit(enum2int(GSM0808_CAUSE_REQ_CODEC_TYPE_OR_CONFIG_UNAVAIL), 7);
1721 f_assignment_exp(ass_cmd, exp_fail, "BSC accepted Assignment for CSD");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001722 f_shutdown_helper();
Harald Welte235ebf12017-12-15 14:18:16 +01001723}
1724
1725testcase TC_assignment_ctm() runs on test_CT {
1726 var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
Harald Welteed848512018-05-24 22:27:58 +02001727 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Harald Welte235ebf12017-12-15 14:18:16 +01001728 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelTypeCTM);
1729 //exp_fail.pdu.bssmap.assignmentFailure.cause.causeValue := int2bit(enum2int(GSM0808_CAUSE_REQ_CODEC_TYPE_OR_CONFIG_UNAVAIL), 7);
1730 f_assignment_exp(ass_cmd, exp_fail, "BSC accepted Assignment for Speech+CTM");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001731 f_shutdown_helper();
Harald Welte235ebf12017-12-15 14:18:16 +01001732}
1733
Harald Welte4003d112017-12-09 22:35:39 +01001734type record DchanTuple {
1735 integer sccp_conn_id,
1736 RslChannelNr rsl_chan_nr
Harald Weltea5d2ab22017-12-09 14:21:42 +01001737}
1738
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +02001739type record of DchanTuple DchanTuples;
1740
Harald Welted6939652017-12-13 21:02:46 +01001741/* Send CHAN RQD and wait for allocation; acknowledge it */
1742private function f_chreq_act_ack(OCT1 ra := '23'O, GsmFrameNumber fn := 23)
1743runs on test_CT return RslChannelNr {
1744 var RSL_Message rx_rsl;
1745 f_ipa_tx(0, ts_RSL_CHAN_RQD(ra, fn));
1746 rx_rsl := f_exp_ipa_rx(0, tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
1747 var RslChannelNr chan_nr := rx_rsl.ies[0].body.chan_nr;
1748 f_ipa_tx(0, ts_RSL_CHAN_ACT_ACK(chan_nr, fn+10));
Daniel Willmannf4ac4ce2018-08-02 14:06:30 +02001749 rx_rsl := f_exp_ipa_rx(0, tr_RSL_IMM_ASSIGN(0));
Harald Welted6939652017-12-13 21:02:46 +01001750 return chan_nr;
1751}
1752
Harald Welte4003d112017-12-09 22:35:39 +01001753/* helper function to establish a dedicated channel via BTS and MSC */
1754function f_est_dchan(OCT1 ra, GsmFrameNumber fn, octetstring l3)
1755runs on test_CT return DchanTuple {
1756 var BSSAP_N_CONNECT_ind rx_c_ind;
Harald Welte4003d112017-12-09 22:35:39 +01001757 var DchanTuple dt;
Harald Weltea5d2ab22017-12-09 14:21:42 +01001758
Harald Welte4003d112017-12-09 22:35:39 +01001759 /* Send CHAN RQD and wait for allocation; acknowledge it */
Harald Welted6939652017-12-13 21:02:46 +01001760 dt.rsl_chan_nr := f_chreq_act_ack(ra, fn);
Harald Welte4003d112017-12-09 22:35:39 +01001761
1762 f_ipa_tx(0, ts_RSL_EST_IND(dt.rsl_chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3));
1763
1764 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3))) -> value rx_c_ind;
1765 dt.sccp_conn_id := rx_c_ind.connectionId;
1766 BSSAP.send(ts_BSSAP_CONNECT_res(dt.sccp_conn_id));
1767
1768 return dt;
Harald Weltea5d2ab22017-12-09 14:21:42 +01001769}
1770
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02001771/* Like f_est_dchan(), but for the first lchan of a dynamic timeslot: first ACK the deactivation of PDCH. */
1772function f_est_dchan_dyn(OCT1 ra, GsmFrameNumber fn, octetstring l3)
1773runs on test_CT return DchanTuple {
1774 var BSSAP_N_CONNECT_ind rx_c_ind;
1775 var DchanTuple dt;
1776
1777 /* Send CHAN RQD */
1778 var RSL_Message rx_rsl;
1779 f_ipa_tx(0, ts_RSL_CHAN_RQD(ra, fn));
1780
1781 /* The dyn TS first deactivates PDCH */
1782 rx_rsl := f_exp_ipa_rx(0, tr_RSL_MsgTypeD(RSL_MT_RF_CHAN_REL), T3101_MAX);
1783 dt.rsl_chan_nr := rx_rsl.ies[0].body.chan_nr;
1784 f_ipa_tx(0, ts_RSL_RF_CHAN_REL_ACK(dt.rsl_chan_nr));
1785
1786 rx_rsl := f_exp_ipa_rx(0, tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
1787 dt.rsl_chan_nr := rx_rsl.ies[0].body.chan_nr;
1788
1789 /* Now activates the signalling channel */
1790 f_ipa_tx(0, ts_RSL_CHAN_ACT_ACK(dt.rsl_chan_nr, fn+10));
1791 rx_rsl := f_exp_ipa_rx(0, tr_RSL_IMM_ASSIGN(0));
1792
1793 f_ipa_tx(0, ts_RSL_EST_IND(dt.rsl_chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3));
1794
1795 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3))) -> value rx_c_ind;
1796 dt.sccp_conn_id := rx_c_ind.connectionId;
1797 BSSAP.send(ts_BSSAP_CONNECT_res(dt.sccp_conn_id));
1798
1799 return dt;
1800}
1801
Harald Welte641fcbe2018-06-14 10:58:35 +02001802/* expect RF CAN REL from BTS, acknowledge it and clear the MSC side */
1803private function f_exp_chan_rel_and_clear(DchanTuple dt, integer bts_nr := 0) runs on test_CT {
1804 var RSL_Message rx_rsl;
1805 /* expect BSC to disable the channel */
1806 rx_rsl := f_exp_ipa_rx(0, tr_RSL_MsgTypeD(RSL_MT_RF_CHAN_REL), T3101_MAX);
1807 /* respond with CHAN REL ACK */
1808 f_ipa_tx(0, ts_RSL_RF_CHAN_REL_ACK(dt.rsl_chan_nr));
1809
1810 /* expect Clear Complete from BSC */
1811 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete));
1812
1813 /* MSC disconnects as instructed. */
1814 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
1815}
1816
Harald Welte4003d112017-12-09 22:35:39 +01001817/* Test behavior of channel release after unilateral RLL REL IND (DISC from MS) */
1818testcase TC_chan_rel_rll_rel_ind() runs on test_CT {
Neels Hofmeyr27f64362018-03-12 01:44:00 +01001819 var BSSAP_N_DATA_ind rx_di;
Harald Welte4003d112017-12-09 22:35:39 +01001820 var DchanTuple dt;
Harald Welte96c94412017-12-09 03:12:45 +01001821
Harald Welte89d42e82017-12-17 16:42:41 +01001822 f_init(1);
Harald Welte96c94412017-12-09 03:12:45 +01001823
Harald Welte4003d112017-12-09 22:35:39 +01001824 dt := f_est_dchan('23'O, 23, '00010203040506'O);
1825
1826 /* simulate RLL REL IND */
1827 f_ipa_tx(0, ts_RSL_REL_IND(dt.rsl_chan_nr, valueof(ts_RslLinkID_DCCH(0))));
1828
Neels Hofmeyr27f64362018-03-12 01:44:00 +01001829 /* expect Clear Request on MSC side */
1830 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearRequest)) -> value rx_di;
1831
1832 /* Instruct BSC to clear channel */
1833 var BssmapCause cause := bit2int(rx_di.userData.pdu.bssmap.clearRequest.cause.causeValue);
1834 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
1835
Harald Welte4003d112017-12-09 22:35:39 +01001836 /* expect BSC to disable the channel */
Harald Welte641fcbe2018-06-14 10:58:35 +02001837 f_exp_chan_rel_and_clear(dt, 0);
Neels Hofmeyr27f64362018-03-12 01:44:00 +01001838
1839 /* wait for SCCP emulation to do its job */
1840 f_sleep(1.0);
Harald Welte4003d112017-12-09 22:35:39 +01001841
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001842 f_shutdown_helper();
Harald Welte4003d112017-12-09 22:35:39 +01001843}
1844
1845/* Test behavior of channel release after CONN FAIL IND from BTS */
1846testcase TC_chan_rel_conn_fail() runs on test_CT {
1847 var BSSAP_N_DATA_ind rx_di;
Harald Welte4003d112017-12-09 22:35:39 +01001848 var DchanTuple dt;
1849
Harald Welte89d42e82017-12-17 16:42:41 +01001850 f_init(1);
Harald Welte4003d112017-12-09 22:35:39 +01001851
1852 dt := f_est_dchan('23'O, 23, '00010203040506'O);
1853
1854 /* simulate CONN FAIL IND */
Harald Weltea8ed9062017-12-14 09:46:01 +01001855 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 +01001856 /* TODO: different cause values? */
1857
Harald Welte4003d112017-12-09 22:35:39 +01001858 /* expect Clear Request from BSC */
1859 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearRequest)) -> value rx_di;
1860
1861 /* Instruct BSC to clear channel */
1862 var BssmapCause cause := bit2int(rx_di.userData.pdu.bssmap.clearRequest.cause.causeValue);
1863 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
1864
Harald Welte6ff76ea2018-01-28 13:08:01 +01001865 /* expect BSC to disable the channel */
Harald Welte641fcbe2018-06-14 10:58:35 +02001866 f_exp_chan_rel_and_clear(dt, 0);
Harald Welte4003d112017-12-09 22:35:39 +01001867
1868 /* wait for SCCP emulation to do its job */
1869 f_sleep(1.0);
1870
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001871 f_shutdown_helper();
Harald Welte4003d112017-12-09 22:35:39 +01001872}
1873
Harald Welte99f3ca02018-06-14 13:40:29 +02001874/* Test behavior of early CONN FAIL IND from BTS (before EST IND!) */
1875/* See also https://www.osmocom.org/issues/3182 */
1876testcase TC_early_conn_fail() runs on test_CT {
1877 var RSL_Message rx_rsl;
1878 var DchanTuple dt;
1879
1880 f_init(1);
1881
1882 /* BTS->BSC: Send CHAN RQD and wait for allocation; acknowledge it */
Harald Weltec46ea3c2020-10-10 18:46:12 +02001883 dt.rsl_chan_nr := f_chreq_act_ack(f_rnd_ra_cs(), 23);
Harald Welte99f3ca02018-06-14 13:40:29 +02001884
1885 /* BTS->BSC: simulate CONN FAIL IND */
1886 f_ipa_tx(0, ts_RSL_CONN_FAIL_IND(dt.rsl_chan_nr, RSL_ERR_RADIO_LINK_FAIL));
1887
1888 /* BTS->BSC: Expect RF channel release from BSC on Abis */
1889 rx_rsl := f_exp_ipa_rx(0, tr_RSL_MsgTypeD(RSL_MT_RF_CHAN_REL), 10.0);
1890
1891 /* BTS<-BSC: respond with CHAN REL ACK */
1892 f_ipa_tx(0, ts_RSL_RF_CHAN_REL_ACK(dt.rsl_chan_nr));
1893
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001894 f_shutdown_helper();
Harald Welte99f3ca02018-06-14 13:40:29 +02001895}
1896
1897/* Test behavior of late CONN FAIL IND from BTS (ater REL IND!) */
1898/* See also https://www.osmocom.org/issues/3182 */
1899testcase TC_late_conn_fail() runs on test_CT {
1900 var RSL_Message rx_rsl;
1901 var DchanTuple dt;
1902
1903 f_init(1);
1904
1905 dt := f_est_dchan('23'O, 23, '00010203040506'O);
1906
1907 /* BSC<-MSC: Instruct BSC to clear connection */
1908 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(0)));
1909
1910 /* BTS->BSC: expect BSC to deactivate SACCH */
1911 rx_rsl := f_exp_ipa_rx(0, tr_RSL_DEACT_SACCH(dt.rsl_chan_nr));
1912
1913 /* BTS->BSC: simulate a late CONN FAIL IND from BTS */
1914 f_ipa_tx(0, ts_RSL_CONN_FAIL_IND(dt.rsl_chan_nr, RSL_ERR_RADIO_LINK_FAIL));
1915
1916 /* BTS<-BSC: Expect RF channel release from BSC on Abis */
1917 rx_rsl := f_exp_ipa_rx(0, tr_RSL_MsgTypeD(RSL_MT_RF_CHAN_REL), 10.0);
1918 /* BTS->BSC: respond with CHAN REL ACK */
1919 f_ipa_tx(0, ts_RSL_RF_CHAN_REL_ACK(dt.rsl_chan_nr));
1920
1921 /* BSC->MSC: expect Clear Complete from BSC */
1922 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete));
1923
1924 /* BSC<-MSC: MSC disconnects as requested. */
1925 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
1926
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001927 f_shutdown_helper();
Harald Welte99f3ca02018-06-14 13:40:29 +02001928}
1929
Oliver Smithaf03bef2021-08-24 15:34:51 +02001930private function f_TC_stats_conn_fail(charstring id) runs on MSC_ConnHdlr {
1931 var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
1932 var PDU_BSSAP ass_cmd := f_gen_ass_req();
1933
1934 f_statsd_reset();
1935
1936 /* Establish SDCCH */
1937 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelTypeCSD);
1938 f_establish_fully(ass_cmd, exp_fail);
1939
1940 /* Expect stats to be 0 */
1941 var StatsDExpects expect := {
1942 {name := "TTCN3.bts.0.chan.rf_fail", mtype := "c", min := 0, max := 0},
1943 {name := "TTCN3.bts.0.chan.rf_fail_sdcch", mtype := "c", min := 0, max := 0}
1944 };
1945 f_statsd_expect(expect);
1946
1947 /* Simulate CONN FAIL IND on SDCCH */
1948 RSL.send(ts_ASP_RSL_UD(
1949 ts_RSL_CONN_FAIL_IND(g_chan_nr, RSL_ERR_RADIO_LINK_FAIL),
1950 IPAC_PROTO_RSL_TRX0));
1951
Neels Hofmeyr58be48a2021-09-07 18:39:21 +02001952 f_sleep(1.0);
1953
Oliver Smithaf03bef2021-08-24 15:34:51 +02001954 /* Expect stats to be 1 */
1955 expect := {
1956 {name := "TTCN3.bts.0.chan.rf_fail", mtype := "c", min := 1, max := 1},
1957 {name := "TTCN3.bts.0.chan.rf_fail_sdcch", mtype := "c", min := 1, max := 1}
1958 };
1959 f_statsd_expect(expect);
1960}
1961testcase TC_stats_conn_fail() runs on test_CT {
1962 var TestHdlrParams pars := f_gen_test_hdlr_pars();
1963 var MSC_ConnHdlr vc_conn;
1964
1965 f_init(1, true);
1966 f_sleep(1.0);
1967
1968 vc_conn := f_start_handler(refers(f_TC_stats_conn_fail), pars);
1969 vc_conn.done;
1970
1971 f_shutdown_helper();
1972}
1973
Neels Hofmeyrf44ccd12018-11-05 19:15:23 +01001974function f_expect_chan_rel(integer bts_nr, RslChannelNr rsl_chan_nr,
Neels Hofmeyra5302c82018-11-04 23:09:58 +01001975 boolean expect_deact_sacch := true,
1976 boolean expect_rr_chan_rel := true,
1977 boolean expect_rll_rel_req := true,
Harald Welte99787102019-02-04 10:41:36 +01001978 boolean handle_rll_rel := true,
Pau Espin Pedrol36bd4fa2021-04-15 13:00:24 +02001979 template CellSelIndValue expect_cells := omit,
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02001980 template RR_Cause expect_rr_cause := ?
Neels Hofmeyra5302c82018-11-04 23:09:58 +01001981 ) runs on test_CT {
Harald Welte91d54a52018-01-28 15:35:07 +01001982
1983 var RslLinkId main_dcch := valueof(ts_RslLinkID_DCCH(0));
Neels Hofmeyra5302c82018-11-04 23:09:58 +01001984 var boolean got_deact_sacch := false;
1985 var boolean got_rr_chan_rel := false;
1986 var boolean got_rll_rel_req := false;
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02001987 var ASP_RSL_Unitdata ud;
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02001988 var RSL_IE_Body l3_ie;
1989 var PDU_ML3_NW_MS l3;
1990 var RR_Cause got_cause;
Neels Hofmeyra5302c82018-11-04 23:09:58 +01001991 log("f_expect_chan_rel() expecting: expect_deact_sacch=", expect_deact_sacch, " expect_rr_chan_rel=", expect_rr_chan_rel,
1992 " expect_rll_rel_req=", expect_rll_rel_req);
Harald Welte91d54a52018-01-28 15:35:07 +01001993 alt {
Vadim Yanitskiy9b4e3562020-05-25 21:40:52 +07001994 [] IPA_RSL[bts_nr].receive(tr_ASP_RSL_UD(tr_RSL_DEACT_SACCH(rsl_chan_nr))) {
Neels Hofmeyra5302c82018-11-04 23:09:58 +01001995 got_deact_sacch := true;
Harald Welte91d54a52018-01-28 15:35:07 +01001996 repeat;
1997 }
Pau Espin Pedrol841b90d2021-04-15 16:42:52 +02001998 [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 +01001999 got_rr_chan_rel := true;
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002000
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002001 if (f_rsl_find_ie(ud.rsl, RSL_IE_L3_INFO, l3_ie) == false) {
2002 setverdict(fail, "cannot find L3");
2003 mtc.stop;
2004 }
2005 l3 := dec_PDU_ML3_NW_MS(l3_ie.l3_info.payload);
2006
Pau Espin Pedrol36bd4fa2021-04-15 13:00:24 +02002007 if (not istemplatekind(expect_cells, "omit")) {
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002008 var CellSelIndValue cells := dec_CellSelIndValue(
2009 l3.msgs.rrm.channelRelease.cellSelectionIndicator.cellSelectionIndicatorValue);
2010
Pau Espin Pedrol36bd4fa2021-04-15 13:00:24 +02002011 log("GOT RR CHANNEL RELEASE WITH CELLS: ", cells);
2012 if (match(cells, expect_cells)) {
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002013 setverdict(pass);
2014 } else {
Pau Espin Pedrol36bd4fa2021-04-15 13:00:24 +02002015 log("EXPECTED CELLS: ", expect_cells);
2016 setverdict(fail, "Received cells list on RR Channel Release does not match expectations");
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002017 }
2018 }
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002019
2020 if (not istemplatekind(expect_rr_cause, "omit")) {
2021 int2enum(oct2int(l3.msgs.rrm.channelRelease.rRCause.valuePart), got_cause);
2022 log("GOT CAUSE CODE: ", l3.msgs.rrm.channelRelease.rRCause.valuePart, " = ", got_cause);
2023 if (match(got_cause, expect_rr_cause)) {
2024 setverdict(pass);
2025 } else {
2026 log("EXPECTED CAUSE CODE: ", expect_rr_cause);
2027 setverdict(fail, "Received RR Channel Release Cause code does not match expectations");
2028 }
2029 }
Harald Welte99787102019-02-04 10:41:36 +01002030 repeat;
2031 }
Pau Espin Pedrol841b90d2021-04-15 16:42:52 +02002032 [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 +01002033 got_rr_chan_rel := true;
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002034
2035 if (not istemplatekind(expect_rr_cause, "omit")) {
2036 if (f_rsl_find_ie(ud.rsl, RSL_IE_L3_INFO, l3_ie) == false) {
2037 setverdict(fail, "cannot find L3");
2038 mtc.stop;
2039 }
2040 l3 := dec_PDU_ML3_NW_MS(l3_ie.l3_info.payload);
2041
2042 int2enum(oct2int(l3.msgs.rrm.channelRelease.rRCause.valuePart), got_cause);
2043 log("GOT CAUSE CODE: ", l3.msgs.rrm.channelRelease.rRCause.valuePart, " = ", got_cause);
2044 if (match(got_cause, expect_rr_cause)) {
2045 setverdict(pass);
2046 } else {
2047 log("EXPECTED CAUSE CODE: ", expect_rr_cause);
2048 setverdict(fail, "Received RR Channel Release Cause code does not match expectations");
2049 }
2050 }
Neels Hofmeyr211169d2018-11-07 00:37:29 +01002051 repeat;
2052 }
Vadim Yanitskiy9b4e3562020-05-25 21:40:52 +07002053 [] IPA_RSL[bts_nr].receive(tr_ASP_RSL_UD(tr_RSL_REL_REQ(rsl_chan_nr, ?))) {
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002054 got_rll_rel_req := true;
Harald Welte91d54a52018-01-28 15:35:07 +01002055 /* FIXME: Why are we getting this for LinkID SACCH? */
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002056 if (handle_rll_rel) {
2057 f_ipa_tx(0, ts_RSL_REL_CONF(rsl_chan_nr, main_dcch));
2058 }
Harald Welte91d54a52018-01-28 15:35:07 +01002059 repeat;
2060 }
Vadim Yanitskiy9b4e3562020-05-25 21:40:52 +07002061 [] IPA_RSL[bts_nr].receive(tr_ASP_RSL_UD(tr_RSL_MsgTypeD(RSL_MT_RF_CHAN_REL))) {
Harald Welte91d54a52018-01-28 15:35:07 +01002062 /* respond with CHAN REL ACK */
2063 f_ipa_tx(0, ts_RSL_RF_CHAN_REL_ACK(rsl_chan_nr));
2064 }
2065 /* ignore any user data */
Vadim Yanitskiy9b4e3562020-05-25 21:40:52 +07002066 [] IPA_RSL[bts_nr].receive(tr_ASP_RSL_UD(tr_RSL_MsgTypeR(?))) {
Harald Welte91d54a52018-01-28 15:35:07 +01002067 repeat;
2068 }
2069 }
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002070
2071 log("f_expect_chan_rel() summary: got_deact_sacch=", got_deact_sacch, " got_rr_chan_rel=", got_rr_chan_rel,
2072 " got_rll_rel_req=", got_rll_rel_req);
2073
2074 if (expect_deact_sacch != got_deact_sacch) {
2075 setverdict(fail, "f_expect_chan_rel(): expect_deact_sacch=", expect_deact_sacch, " got_deact_sacch=", got_deact_sacch);
2076 }
2077 if (expect_rr_chan_rel != got_rr_chan_rel) {
2078 setverdict(fail, "f_expect_chan_rel(): expect_rr_chan_rel=", expect_rr_chan_rel, " got_rr_chan_rel=", got_rr_chan_rel);
2079 }
2080 if (expect_rll_rel_req != got_rll_rel_req) {
2081 setverdict(fail, "f_expect_chan_rel(): expect_rll_rel_req=", expect_rll_rel_req, " got_rll_rel_req=", got_rll_rel_req);
2082 }
Harald Welte91d54a52018-01-28 15:35:07 +01002083}
2084
Harald Welte4003d112017-12-09 22:35:39 +01002085/* Test behavior of channel release after hard Clear Command from MSC */
2086testcase TC_chan_rel_hard_clear() runs on test_CT {
2087 var BSSAP_N_DATA_ind rx_di;
Harald Welte4003d112017-12-09 22:35:39 +01002088 var DchanTuple dt;
Harald Welte4003d112017-12-09 22:35:39 +01002089
Harald Welte89d42e82017-12-17 16:42:41 +01002090 f_init(1);
Harald Welte4003d112017-12-09 22:35:39 +01002091
2092 dt := f_est_dchan('23'O, 23, '00010203040506'O);
2093
2094 /* Instruct BSC to clear channel */
2095 var BssmapCause cause := 0;
2096 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
2097
2098 /* expect Clear Complete from BSC on A */
2099 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete)) {
2100 /* release the SCCP connection */
2101 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2102 }
2103
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002104 f_expect_chan_rel(0, dt.rsl_chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002105 f_shutdown_helper();
Harald Welte4003d112017-12-09 22:35:39 +01002106}
2107
Pau Espin Pedrol841b90d2021-04-15 16:42:52 +02002108function f_TC_chan_rel_last_eutran_plmn_hard_clear(boolean tx_csfb_ind) runs on test_CT {
2109 var BSSAP_N_DATA_ind rx_di;
2110 var DchanTuple dt;
2111
2112 f_init(1);
2113
2114 dt := f_est_dchan('23'O, 23, '00010203040506'O);
2115 /* Send CommonID with some random PLMN (BSC doesn't take it into account
2116 /* yet when generating the EUTRAN neigh list in RR CHannel Release) */
2117 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_CommonId('001019876543210'H, '323454'O)));
2118
2119 /* Instruct BSC to clear channel */
2120 var BssmapCause cause := 0;
2121 if (tx_csfb_ind) {
2122 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommandCSFB(cause)));
2123 } else {
2124 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
2125 }
2126
2127 /* expect Clear Complete from BSC on A */
2128 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete)) {
2129 /* release the SCCP connection */
2130 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2131 }
2132
2133 /* 1 neighbor is added by default in osmo-bts.cfg and
2134 SystemInformationConfig_default, use that: */
2135 var template CellSelIndValue exp_cells := f_tr_rr_chan_rel_earfcns(1);
2136
2137 f_expect_chan_rel(0, dt.rsl_chan_nr, expect_rll_rel_req := false, expect_cells := exp_cells);
2138 f_shutdown_helper();
2139}
2140
2141/* Test behavior of RR Channel rRelease after Clear Command without CSFB indicator
2142 from MSC, previously receiving any CommonID containing the "Last Used E-UTRAN
2143 PLMN Id". According to spec (3GPP TS 48.008 sec 3.1.30) that's the bit requesting
2144 EUTRAN neighbor list sent later on by BSC in RR Channel, so receiving CSFB
2145 Indicator or not shouldn't matter at all. */
2146testcase TC_chan_rel_last_eutran_plmn_hard_clear_no_csfb() runs on test_CT {
2147 f_TC_chan_rel_last_eutran_plmn_hard_clear(false);
2148}
2149
2150/* Test behavior of RR Channel rRelease after Clear Command with CSFB indicator from
2151 MSC, previously receiving any CommonID containing the "Last Used E-UTRAN PLMN
2152 Id". According to spec (3GPP TS 48.008 sec 3.1.30) that's the bit requesting
2153 EUTRAN neighbor list sent later on by BSC in RR Channel. */
2154testcase TC_chan_rel_last_eutran_plmn_hard_clear_csfb() runs on test_CT {
2155 f_TC_chan_rel_last_eutran_plmn_hard_clear(true);
2156}
2157
2158/* Test behavior of RR Channel Release after Clear Command with CSFB indicator from
2159 MSC, without receiving any CommonID containing the "Last Used E-UTRAN PLMN
2160 Id". According to spec (TS 48.008 version 16.0.0 Release 16 "3.2.1.21") the
2161 CSFB Indicator should not be used anymore, and hence, there should be no
2162 EUTRAN neighbor list sent by BSC in RR Channel release since no CommonId with
2163 Last Used E-UTRAN PLMN Id" IE was sent for this conn. */
Harald Welte99787102019-02-04 10:41:36 +01002164testcase TC_chan_rel_hard_clear_csfb() runs on test_CT {
2165 var BSSAP_N_DATA_ind rx_di;
2166 var DchanTuple dt;
2167
2168 f_init(1);
2169
2170 dt := f_est_dchan('23'O, 23, '00010203040506'O);
2171
2172 /* Instruct BSC to clear channel */
2173 var BssmapCause cause := 0;
2174 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommandCSFB(cause)));
2175
2176 /* expect Clear Complete from BSC on A */
2177 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete)) {
2178 /* release the SCCP connection */
2179 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2180 }
2181
Pau Espin Pedrol841b90d2021-04-15 16:42:52 +02002182 f_expect_chan_rel(0, dt.rsl_chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002183 f_shutdown_helper();
Harald Welte99787102019-02-04 10:41:36 +01002184}
2185
Harald Welted8c36cd2017-12-09 23:05:31 +01002186/* Test behavior of channel release after hard RLSD from MSC */
2187testcase TC_chan_rel_hard_rlsd() runs on test_CT {
Harald Welted8c36cd2017-12-09 23:05:31 +01002188 var DchanTuple dt;
Harald Welted8c36cd2017-12-09 23:05:31 +01002189
Harald Welte89d42e82017-12-17 16:42:41 +01002190 f_init(1);
Harald Welted8c36cd2017-12-09 23:05:31 +01002191
2192 dt := f_est_dchan('23'O, 23, '00010203040506'O);
2193
2194 /* release the SCCP connection */
2195 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2196
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002197 f_expect_chan_rel(0, dt.rsl_chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002198 f_shutdown_helper();
Harald Welted8c36cd2017-12-09 23:05:31 +01002199}
2200
Harald Welte550daf92018-06-11 19:22:13 +02002201/* Test behavior of channel release after hard RLSD from MSC and MS is not responding to RLL REL REQ */
2202testcase TC_chan_rel_hard_rlsd_ms_dead() runs on test_CT {
2203 var DchanTuple dt;
2204
2205 f_init(1);
2206
2207 dt := f_est_dchan('23'O, 23, '00010203040506'O);
2208
2209 /* release the SCCP connection */
2210 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2211
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002212 f_expect_chan_rel(0, dt.rsl_chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002213 f_shutdown_helper();
Harald Welte550daf92018-06-11 19:22:13 +02002214}
2215
Harald Welte85804d42017-12-10 14:11:58 +01002216/* Test behavior of channel release after BSSMAP RESET from MSC */
2217testcase TC_chan_rel_a_reset() runs on test_CT {
Harald Welte85804d42017-12-10 14:11:58 +01002218 var DchanTuple dt;
Harald Welte85804d42017-12-10 14:11:58 +01002219
Harald Welte89d42e82017-12-17 16:42:41 +01002220 f_init(1);
Harald Welte85804d42017-12-10 14:11:58 +01002221
2222 dt := f_est_dchan('23'O, 23, '00010203040506'O);
2223
2224 /* Clear the queue, it might still contain stuff like IMMEDIATE ASSIGN */
2225 IPA_RSL[0].clear;
2226
2227 /* perform BSSAP RESET, expect RESET ACK and DISC.ind on connection */
Neels Hofmeyrf246a922020-05-13 02:27:10 +02002228 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 +01002229 interleave {
Neels Hofmeyrf246a922020-05-13 02:27:10 +02002230 [] 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 +01002231 [] BSSAP.receive(tr_BSSAP_DISC_ind(dt.sccp_conn_id, ?, ?)) { }
2232 }
2233
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002234 f_expect_chan_rel(0, dt.rsl_chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002235 f_shutdown_helper();
Harald Welte85804d42017-12-10 14:11:58 +01002236}
2237
Pau Espin Pedrolc675b612020-01-09 19:55:40 +01002238/* Verify T(iar) triggers and releases the channel */
2239testcase TC_chan_rel_sccp_tiar_timeout() runs on test_CT {
2240 var DchanTuple dt;
2241
2242 /* Set T(iar) in BSC low enough that it will trigger before other side
2243 has time to keep alive with a T(ias). Keep recommended ratio of
2244 T(iar) >= T(ias)*2 */
2245 g_bsc_sccp_timer_ias := 2;
2246 g_bsc_sccp_timer_iar := 5;
2247
2248 f_init(1);
2249
2250 dt := f_est_dchan('23'O, 23, '00010203040506'O);
2251 f_expect_chan_rel(0, dt.rsl_chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002252 f_shutdown_helper();
Pau Espin Pedrolc675b612020-01-09 19:55:40 +01002253}
2254
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002255private function f_tc_chan_rel_rr_cause(myBSSMAP_Cause clear_cmd_cause, template RR_Cause expect_rr_cause)
2256runs on test_CT
2257{
2258 var DchanTuple dt;
2259
2260 dt := f_est_dchan('23'O, 23, '00010203040506'O);
2261 var BssmapCause cause := 0;
2262 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(enum2int(clear_cmd_cause))));
2263 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete)) {
2264 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2265 }
2266
2267 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 +02002268}
2269
2270/* Test that Clear Command cause codes affect the RR Channel Release cause code */
2271testcase TC_chan_rel_rr_cause() runs on test_CT {
2272 f_init(1);
2273
2274 f_tc_chan_rel_rr_cause(GSM0808_CAUSE_CALL_CONTROL, GSM48_RR_CAUSE_NORMAL);
2275 f_tc_chan_rel_rr_cause(GSM0808_CAUSE_HANDOVER_SUCCESSFUL, GSM48_RR_CAUSE_NORMAL);
2276 f_tc_chan_rel_rr_cause(GSM0808_CAUSE_PREEMPTION, GSM48_RR_CAUSE_PREMPTIVE_REL);
2277 f_tc_chan_rel_rr_cause(GSM0808_CAUSE_RADIO_INTERFACE_MESSAGE_FAILURE, GSM48_RR_CAUSE_PROT_ERROR_UNSPC);
2278 f_tc_chan_rel_rr_cause(GSM0808_CAUSE_RADIO_INTERFACE_FAILURE, GSM48_RR_CAUSE_ABNORMAL_UNSPEC);
2279 f_tc_chan_rel_rr_cause(GSM0808_CAUSE_EQUIPMENT_FAILURE, GSM48_RR_CAUSE_ABNORMAL_UNSPEC);
Vadim Yanitskiye18aebb2021-01-03 13:10:43 +01002280
2281 f_shutdown_helper();
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002282}
2283
Harald Welte5cd20ed2017-12-13 21:03:20 +01002284/* Test behavior if RSL EST IND for non-active channel */
2285testcase TC_rll_est_ind_inact_lchan() runs on test_CT {
2286 timer T := 2.0;
2287
Harald Welte89d42e82017-12-17 16:42:41 +01002288 f_init(1);
Harald Welte5cd20ed2017-12-13 21:03:20 +01002289
2290 var octetstring l3 := '00010203040506'O;
2291 var RslChannelNr chan_nr := valueof(t_RslChanNr_Bm(6));
2292 f_ipa_tx(0, ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3));
2293
2294 T.start;
2295 alt {
2296 [] BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3))) {
2297 setverdict(fail, "MSC received COMPL L3 for non-active lchan");
2298 }
2299 [] BSSAP.receive {}
2300 [] IPA_RSL[0].receive {}
2301 [] T.timeout {}
2302 }
2303
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002304 f_shutdown_helper();
Harald Welte5cd20ed2017-12-13 21:03:20 +01002305}
2306
2307/* Test behavior if RSL EST IND for invalid SAPI */
2308testcase TC_rll_est_ind_inval_sapi1() runs on test_CT {
2309 var RslChannelNr chan_nr;
2310
Harald Welte89d42e82017-12-17 16:42:41 +01002311 f_init(1);
Harald Welte5cd20ed2017-12-13 21:03:20 +01002312
2313 chan_nr := f_chreq_act_ack()
2314
2315 var octetstring l3 := '00010203040506'O;
2316 f_ipa_tx(0, ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(1)), l3));
2317
2318 timer T := 2.0;
2319 T.start;
2320 alt {
2321 [] BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3))) {
2322 setverdict(fail, "MSC received COMPL L3 for invalid SAPI 1");
2323 }
2324 [] BSSAP.receive { repeat; }
2325 [] IPA_RSL[0].receive { repeat; }
2326 [] T.timeout {}
2327 }
2328
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002329 f_shutdown_helper();
Harald Welte5cd20ed2017-12-13 21:03:20 +01002330}
2331
2332/* Test behavior if RSL EST IND for invalid SAPI */
2333testcase TC_rll_est_ind_inval_sapi3() runs on test_CT {
2334 timer T := 2.0;
2335
Harald Welte89d42e82017-12-17 16:42:41 +01002336 f_init(1);
Harald Welte5cd20ed2017-12-13 21:03:20 +01002337
2338 var RslChannelNr chan_nr := f_chreq_act_ack();
2339
2340 var octetstring l3 := '00010203040506'O;
2341 f_ipa_tx(0, ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(3)), l3));
2342
2343 T.start;
2344 alt {
2345 [] BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3))) {
2346 setverdict(fail, "MSC received COMPL L3 for invalid SAPI 3");
2347 }
2348 [] BSSAP.receive { repeat; }
2349 [] IPA_RSL[0].receive { repeat; }
2350 [] T.timeout {}
2351 }
2352
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002353 f_shutdown_helper();
Harald Welte5cd20ed2017-12-13 21:03:20 +01002354}
2355
2356/* Test behavior if RSL EST IND for invalid SACCH */
2357testcase TC_rll_est_ind_inval_sacch() runs on test_CT {
2358 timer T := 2.0;
2359
Harald Welte89d42e82017-12-17 16:42:41 +01002360 f_init(1);
Harald Welte5cd20ed2017-12-13 21:03:20 +01002361
2362 var RslChannelNr chan_nr := f_chreq_act_ack();
2363
2364 var octetstring l3 := '00010203040506'O;
2365 f_ipa_tx(0, ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_SACCH(0)), l3));
2366
2367 T.start;
2368 alt {
2369 [] BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3))) {
2370 setverdict(fail, "MSC received COMPL L3 for invalid Link SACCH");
2371 }
2372 [] BSSAP.receive { repeat; }
2373 [] IPA_RSL[0].receive { repeat; }
2374 [] T.timeout {}
2375 }
2376
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002377 f_shutdown_helper();
Harald Welte5cd20ed2017-12-13 21:03:20 +01002378}
2379
Vadim Yanitskiy61f784a2020-10-01 21:12:19 +07002380/* Verify DLCI / RSL Link ID conversion for MO/MT messages on SAPI0/SAPI3 */
2381private function f_TC_tch_dlci_link_id_sapi(charstring id) runs on MSC_ConnHdlr {
2382 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
2383 var PDU_BSSAP ass_cmd := f_gen_ass_req();
2384
2385 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
2386 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
2387
2388 f_establish_fully(ass_cmd, exp_compl);
2389
2390 /* SAPI0 has already been established by f_establish_fully(), establish SAPI3 */
2391 RSL.send(ts_RSL_EST_IND(g_chan_nr, ts_RslLinkID_SACCH(3), '0904'O));
2392 /* Expect BSSAP/DTAP on SAPI3 (DLCI IE) */
2393 BSSAP.receive(PDU_BSSAP:{
2394 discriminator := '1'B,
2395 spare := '0000000'B,
2396 dlci := 'C3'O,
2397 lengthIndicator := ?,
2398 pdu := { dtap := '0904'O }
2399 });
2400
2401 /* Send messages on DCCH/SAPI0 and ACCH/SAPI3 */
2402 for (var integer i := 0; i < 32; i := i + 1) {
2403 var octetstring l3 := '09'O & f_rnd_octstring(14);
2404 var template (value) RslLinkId link_id;
2405 var template (value) OCT1 dlci;
2406
2407 if (i mod 2 == 0) {
2408 /* SAPI0 on FACCH or SDCCH */
2409 link_id := ts_RslLinkID_DCCH(0);
2410 dlci := '80'O;
2411 } else {
2412 /* SAPI3 on SACCH */
2413 link_id := ts_RslLinkID_SACCH(3);
2414 dlci := 'C3'O;
2415 }
2416
2417 /* Send MO message: RSL -> BSSAP */
Neels Hofmeyr0aa719b2020-10-12 18:43:09 +00002418 f_mo_l3_transceive(RSL, link_id, dlci, l3);
Vadim Yanitskiy61f784a2020-10-01 21:12:19 +07002419 /* Send MT message: BSSAP -> RSL */
Neels Hofmeyr0aa719b2020-10-12 18:43:09 +00002420 f_mt_l3_transceive(RSL, link_id, dlci, l3);
Vadim Yanitskiy61f784a2020-10-01 21:12:19 +07002421 }
2422}
2423testcase TC_tch_dlci_link_id_sapi() runs on test_CT {
2424 var TestHdlrParams pars := f_gen_test_hdlr_pars();
2425 var MSC_ConnHdlr vc_conn;
2426
2427 f_init(1, true);
2428 f_sleep(1.0);
2429
2430 vc_conn := f_start_handler(refers(f_TC_tch_dlci_link_id_sapi), pars);
2431 vc_conn.done;
2432
2433 f_shutdown_helper();
2434}
2435
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002436private function f_exp_sapi_n_reject(template (present) GsmSapi sapi := ?,
2437 template myBSSMAP_Cause cause := ?,
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +07002438 template (present) BIT2 cc := ?,
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002439 float T_val := 2.0)
2440runs on test_CT {
2441 var BSSAP_N_DATA_ind rx_di;
2442 timer T;
2443
2444 var template BSSMAP_IE_Cause tr_cause := tr_BSSMAP_IE_Cause(cause);
2445 var template PDU_BSSAP tr_pdu := tr_BSSMAP_SAPInReject(sapi);
2446
2447 T.start(T_val);
2448 alt {
2449 [] BSSAP.receive(tr_BSSAP_DATA_ind(?, tr_pdu)) -> value rx_di {
2450 var BSSMAP_IE_Cause rx_cause := rx_di.userData.pdu.bssmap.sAPInReject.cause;
2451 if (not match(rx_cause, tr_cause)) {
2452 setverdict(fail, "Rx unexpected Cause IE: ",
2453 rx_cause, " vs expected ", tr_cause);
2454 }
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +07002455
2456 /* Who ever on the earth decided to define this field as two separate bits?!? */
2457 var BIT2 rx_cc := rx_di.userData.pdu.bssmap.sAPInReject.dLCI.c2
2458 & rx_di.userData.pdu.bssmap.sAPInReject.dLCI.c1;
2459 if (not match(rx_cc, cc)) {
2460 setverdict(fail, "Rx unexpected Control Channel type: ",
2461 rx_cc, " vs expected ", cc);
2462 }
2463
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002464 setverdict(pass);
2465 }
2466 [] BSSAP.receive(BSSAP_N_DATA_ind:?) -> value rx_di {
2467 setverdict(fail, "Rx unexpected BSSAP PDU: ", rx_di);
2468 }
2469 [] T.timeout {
2470 setverdict(fail, "Timeout waiting for BSSMAP SAPI N Reject");
2471 }
2472 }
2473}
2474
2475/* Check if we get SAPI N Reject on receipt of unexpected RLL RELease INDication */
2476testcase TC_rll_rel_ind_sapi_n_reject() runs on test_CT {
2477 var octetstring rnd_data := f_rnd_octstring(16);
2478 var RSL_Message rx_rsl;
2479 var DchanTuple dt;
2480
2481 f_init(1);
2482
2483 /* MS establishes a SAPI=0 link on DCCH */
2484 dt := f_est_dchan(f_rnd_ra_cs(), 23, rnd_data);
2485
2486 /* MSC sends some data on (not yet established) SAPI=3 link */
2487 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSAP_DTAP(rnd_data, '03'O)));
2488 /* BSC attempts to establish a SAPI=3 link on DCCH */
2489 rx_rsl := f_exp_ipa_rx(0, tr_RSL_EST_REQ(dt.rsl_chan_nr, tr_RslLinkID_DCCH(3)));
2490
2491 /* MS sends unexpected RELease INDication on SAPI=3 */
2492 f_ipa_tx(0, ts_RSL_REL_IND(dt.rsl_chan_nr, ts_RslLinkID_DCCH(3)));
2493 /* We expect to receive BSSMAP SAPI N Reject message from the BSC */
2494 f_exp_sapi_n_reject(3, GSM0808_CAUSE_MS_NOT_EQUIPPED);
2495
2496 /* Clean up the connection */
2497 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2498 f_expect_chan_rel(0, dt.rsl_chan_nr, expect_rll_rel_req := false);
2499
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002500 f_shutdown_helper();
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002501}
2502
2503/* Check if we get SAPI N Reject on receipt of unexpected RLL ERROR INDication */
2504testcase TC_rll_err_ind_sapi_n_reject() runs on test_CT {
2505 var octetstring rnd_data := f_rnd_octstring(16);
2506 var RSL_Message rx_rsl;
2507 var DchanTuple dt;
2508
2509 f_init(1);
2510
2511 /* MS establishes a SAPI=0 link on DCCH */
2512 dt := f_est_dchan(f_rnd_ra_cs(), 23, rnd_data);
2513
2514 /* MSC sends some data on (not yet established) SAPI=3 link */
2515 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSAP_DTAP(rnd_data, '03'O)));
2516 /* BSC attempts to establish a SAPI=3 link on DCCH */
2517 rx_rsl := f_exp_ipa_rx(0, tr_RSL_EST_REQ(dt.rsl_chan_nr, tr_RslLinkID_DCCH(3)));
2518
2519 /* BTS sends unexpected ERROR INDication on SAPI=3 */
2520 f_ipa_tx(0, ts_RSL_ERROR_IND(dt.rsl_chan_nr, ts_RslLinkID_DCCH(3), ''O));
2521 /* We expect to receive BSSMAP SAPI N Reject message from the BSC */
2522 f_exp_sapi_n_reject(3, GSM0808_CAUSE_BSS_NOT_EQUIPPED);
2523
2524 /* Clean up the connection */
2525 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2526 f_expect_chan_rel(0, dt.rsl_chan_nr, expect_rll_rel_req := false);
2527
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002528 f_shutdown_helper();
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002529}
2530
2531/* Check if we get SAPI N Reject due to a SAPI=3 link establishment timeout */
2532testcase TC_rll_timeout_sapi_n_reject() runs on test_CT {
2533 var octetstring rnd_data := f_rnd_octstring(16);
2534 var RSL_Message rx_rsl;
2535 var DchanTuple dt;
2536
2537 f_init(1);
2538
2539 /* MS establishes a SAPI=0 link on DCCH */
2540 dt := f_est_dchan(f_rnd_ra_cs(), 23, rnd_data);
2541
2542 /* MSC sends some data on (not yet established) SAPI=3 link */
2543 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSAP_DTAP(rnd_data, '03'O)));
2544 /* BSC attempts to establish a SAPI=3 link on DCCH */
2545 rx_rsl := f_exp_ipa_rx(0, tr_RSL_EST_REQ(dt.rsl_chan_nr, tr_RslLinkID_DCCH(3)));
2546
2547 /* MS does not respond, so the link establishment timeout triggers SAPI N Reject */
2548 f_exp_sapi_n_reject(3, GSM0808_CAUSE_BSS_NOT_EQUIPPED, T_val := 8.0);
2549
2550 /* Clean up the connection */
2551 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2552 f_expect_chan_rel(0, dt.rsl_chan_nr, expect_rll_rel_req := false);
2553
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002554 f_shutdown_helper();
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002555}
2556
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +07002557/* Check DLCI CC (Control Channel type) bits in SAPI N Reject */
2558testcase TC_rll_sapi_n_reject_dlci_cc() runs on test_CT {
2559 var octetstring rnd_data := f_rnd_octstring(16);
2560 var RSL_Message rx_rsl;
2561 var DchanTuple dt;
2562
2563 f_init(1);
2564
2565 /* MS establishes a SAPI=0 link on DCCH */
2566 dt := f_est_dchan(f_rnd_ra_cs(), 23, rnd_data);
2567
2568 /* MSC sends some data on (not yet established) SAPI=3 link */
2569 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSAP_DTAP(rnd_data, '03'O)));
2570 /* BSC attempts to establish a SAPI=3 link on DCCH */
2571 rx_rsl := f_exp_ipa_rx(0, tr_RSL_EST_REQ(dt.rsl_chan_nr, tr_RslLinkID_DCCH(3)));
2572
2573 /* MS sends unexpected ERROR INDication on DCCH/ACCH SAPI=3 */
2574 f_ipa_tx(0, ts_RSL_ERROR_IND(dt.rsl_chan_nr, ts_RslLinkID_DCCH(3), ''O));
2575 f_exp_sapi_n_reject(3, GSM0808_CAUSE_MS_NOT_EQUIPPED, '10'B);
2576
2577 /* Clean up the connection */
2578 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2579 f_expect_chan_rel(0, dt.rsl_chan_nr, expect_rll_rel_req := false);
2580
2581 f_shutdown_helper();
2582}
2583
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +02002584testcase TC_si_default() runs on test_CT {
2585 f_init(0);
2586 f_init_bts_and_check_sysinfo(0, expect_si := SystemInformationConfig_default);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002587 f_shutdown_helper();
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +02002588}
Harald Welte4003d112017-12-09 22:35:39 +01002589
Neels Hofmeyr56f24782020-07-09 00:50:49 +02002590/* We're testing SI2quater with lists of EARFCNs. Instead of just incrementing EARFCNs, also pick some from the edges of
2591 * the entire value range. This function provides the same EARFCN numbers for the same earfcn_index */
2592private function f_test_si2quater_earfcn_by_idx(integer earfcn_index) return uint16_t
2593{
2594 select (earfcn_index) {
2595 case (0) {
2596 /* E-ARFCN 111 is already added in the osmo-bsc.cfg */
2597 return 111;
2598 }
2599 case (1) {
2600 return 1;
2601 }
2602 case (2) {
2603 return 0;
2604 }
2605 case (3) {
2606 return 65535;
2607 }
2608 case else {
2609 return 23 * (earfcn_index - 3);
2610 }
2611 }
2612}
2613
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002614function f_test_si2quater(integer total_earfcns, template SystemInformationConfig expect_si,
2615 template CellSelIndValue expect_cells := omit) runs on test_CT {
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002616
2617 f_init(0);
2618
2619 /* E-ARFCN 111 is already added in the osmo-bsc.cfg, so only add more arfcns if total_earfcns > 1 */
2620 for (var integer i := 1; i < total_earfcns; i := i + 1) {
Neels Hofmeyr56f24782020-07-09 00:50:49 +02002621 f_bts_0_cfg(BSCVTY, {"si2quater neighbor-list add earfcn " & int2str(f_test_si2quater_earfcn_by_idx(i))
2622 & " thresh-hi 20 thresh-lo 10 prio 3 qrxlv 22 meas 3"});
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002623 }
2624
2625 f_init_bts_and_check_sysinfo(0, expect_si := expect_si);
2626
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002627 if (not istemplatekind(expect_cells, "omit")) {
2628 /* Also check that RR Channel Release contains these EARFCNs.
2629 * (copied code from TC_chan_rel_hard_clear_csfb) */
2630 var BSSAP_N_DATA_ind rx_di;
2631 var DchanTuple dt;
2632
2633 dt := f_est_dchan('23'O, 23, '00010203040506'O);
Pau Espin Pedrold0046312021-04-19 16:35:58 +02002634 /* Send CommonID with some random PLMN (BSC doesn't take it into account
2635 * yet when generating the EUTRAN neigh list in RR CHannel Release) */
2636 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_CommonId('001019876543210'H, '323454'O)));
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002637
2638 /* Instruct BSC to clear channel */
2639 var BssmapCause cause := 0;
2640 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommandCSFB(cause)));
2641
2642 /* expect Clear Complete from BSC on A */
2643 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete)) {
2644 /* release the SCCP connection */
2645 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2646 }
2647
Pau Espin Pedrol841b90d2021-04-15 16:42:52 +02002648 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 +02002649 }
2650
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002651 for (var integer i := 1; i < total_earfcns; i := i + 1) {
Neels Hofmeyr56f24782020-07-09 00:50:49 +02002652 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 +02002653 }
2654}
2655
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002656private function f_tr_si2quater_earfcns(integer count) return template SI2quaterRestOctetsList
2657{
2658 var template SI2quaterRestOctetsList si2quater := {};
2659 var integer si2quater_count := (count + 2) / 3;
2660
2661 for (var integer i := 0; i < count; i := i + 1) {
Neels Hofmeyr56f24782020-07-09 00:50:49 +02002662 var integer earfcn := f_test_si2quater_earfcn_by_idx(i);
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002663 var integer index := i / 3;
2664 var integer earfcn_index := i mod 3;
2665 if (index >= lengthof(si2quater)) {
2666 si2quater[index] := tr_SI2quaterRestOctets_EUTRAN(index := index, count := si2quater_count - 1);
2667 }
2668 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);
2669 }
2670
2671 return si2quater;
2672}
2673
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002674private function f_tr_rr_chan_rel_earfcns(integer count) return template CellSelIndValue
2675{
2676 var template CellSelIndValue_EUTRAN_Descrs cells := {};
2677
Alexander Couzensf74b5cb2020-09-10 22:28:40 +02002678 /* the lte neighbors must match the config & vty to pass this test */
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002679 for (var integer i := 0; i < count; i := i + 1) {
2680 var integer earfcn := f_test_si2quater_earfcn_by_idx(i);
Alexander Couzensf74b5cb2020-09-10 22:28:40 +02002681 cells[i] := tr_CellSelIndValue_EUTRAN_Descr(earfcn, '1'B, 3);
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002682 }
2683
2684 return tr_CellSelIndValue_EUTRAN(cells);
2685}
2686
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002687private function f_tc_si2quater_n_earfcns(integer n) runs on test_CT
2688{
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002689 var template SystemInformationConfig sic := SystemInformationConfig_default;
Pau Espin Pedrol8ab62e42020-12-18 16:19:11 +01002690 sic.si2quater := f_tr_si2quater_earfcns(n);
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002691 var template CellSelIndValue cells := f_tr_rr_chan_rel_earfcns(n);
2692 f_test_si2quater(n, sic, cells);
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002693}
2694
2695testcase TC_si2quater_2_earfcns() runs on test_CT {
2696 f_tc_si2quater_n_earfcns(2);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002697 f_shutdown_helper();
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002698}
2699
2700testcase TC_si2quater_3_earfcns() runs on test_CT {
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002701 f_tc_si2quater_n_earfcns(3);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002702 f_shutdown_helper();
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002703}
2704
2705testcase TC_si2quater_4_earfcns() runs on test_CT {
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002706 f_tc_si2quater_n_earfcns(4);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002707 f_shutdown_helper();
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002708}
2709
2710testcase TC_si2quater_5_earfcns() runs on test_CT {
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002711 f_tc_si2quater_n_earfcns(5);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002712 f_shutdown_helper();
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002713}
2714
2715testcase TC_si2quater_6_earfcns() runs on test_CT {
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002716 f_tc_si2quater_n_earfcns(6);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002717 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002718}
2719
2720testcase TC_si2quater_12_earfcns() runs on test_CT {
2721 f_tc_si2quater_n_earfcns(12);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002722 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002723}
2724
2725testcase TC_si2quater_23_earfcns() runs on test_CT {
2726 f_tc_si2quater_n_earfcns(23);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002727 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002728}
2729
2730testcase TC_si2quater_32_earfcns() runs on test_CT {
2731 f_tc_si2quater_n_earfcns(32);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002732 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002733}
2734
2735testcase TC_si2quater_33_earfcns() runs on test_CT {
2736 f_tc_si2quater_n_earfcns(33);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002737 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002738}
2739
2740testcase TC_si2quater_42_earfcns() runs on test_CT {
2741 f_tc_si2quater_n_earfcns(42);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002742 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002743}
2744
2745testcase TC_si2quater_48_earfcns() runs on test_CT {
2746 f_tc_si2quater_n_earfcns(48);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002747 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002748}
2749
2750/* verify the VTY error response when adding too many EARFCNs, and showing that osmo-bsc still sends 16 SI2quater with
2751 * 48 EARFCNs. */
2752testcase TC_si2quater_49_earfcns() runs on test_CT {
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002753 var template SystemInformationConfig sic := SystemInformationConfig_default;
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002754 sic.si2quater := f_tr_si2quater_earfcns(48); /* 48, not 49! */
2755 f_init(0);
2756
2757 for (var integer i := 1; i < 48; i := i + 1) {
Neels Hofmeyr56f24782020-07-09 00:50:49 +02002758 f_bts_0_cfg(BSCVTY, {"si2quater neighbor-list add earfcn " & int2str(f_test_si2quater_earfcn_by_idx(i))
2759 & " thresh-hi 20 thresh-lo 10 prio 3 qrxlv 22 meas 3"});
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002760 }
2761
2762 /* The 49th EARFCN no longer fits, expect VTY error */
2763 f_vty_enter_cfg_bts(BSCVTY, 0);
2764 var charstring vty_error;
2765 vty_error := f_vty_transceive_ret(BSCVTY,
2766 "si2quater neighbor-list add earfcn 70 thresh-hi 20 thresh-lo 10 prio 3 qrxlv 22 meas 3")
2767 f_vty_transceive(BSCVTY, "end");
2768
2769 if (f_strstr(vty_error, "Unable to add ARFCN 70") >= 0) {
2770 log("Got expected VTY error: ", vty_error);
2771 setverdict(pass);
2772 } else {
2773 setverdict(fail, "Expected the 49th EUTRAN ARFCN to be rejected by vty config, got: ", vty_error);
2774 }
2775
2776 f_init_bts_and_check_sysinfo(0, expect_si := sic);
2777
2778 for (var integer i := 1; i < 48; i := i + 1) {
Neels Hofmeyr56f24782020-07-09 00:50:49 +02002779 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 +02002780 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002781 f_shutdown_helper();
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002782}
2783
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02002784private function f_acc09_count_allowed(AccessControlClass acc) return uint8_t
2785{
2786 var uint8_t count := 0;
2787 for (var integer i := 5; i < 16; i := i + 1) {
2788 if (acc[i] == '0'B) { /* the list marks barred, we count allowed */
2789 count := count + 1;
2790 }
2791 }
2792 return count;
2793}
2794
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02002795private function f_recv_next_si1(integer rsl_idx := 0) runs on test_CT return SystemInformationType1
2796{
2797 var ASP_RSL_Unitdata rx_rsl_ud;
2798 var SystemInformationType1 last_si1;
2799
2800 timer T := 30.0;
2801 T.start;
2802 alt {
2803 [] IPA_RSL[rsl_idx].receive(tr_ASP_RSL_UD((tr_RSL_NO_BCCH_INFO,
2804 tr_RSL_BCCH_INFO,
2805 tr_RSL_NO_SACCH_FILL,
2806 tr_RSL_SACCH_FILL))
2807 ) -> value rx_rsl_ud {
2808 f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
2809 if (g_system_information[rsl_idx].si1 == omit) {
2810 repeat;
2811 }
2812 last_si1 := g_system_information[rsl_idx].si1;
2813 g_system_information[rsl_idx].si1 := omit;
2814 T.stop;
2815 }
Vadim Yanitskiy79ebd5e2021-01-04 00:12:55 +01002816 [] IPA_RSL[rsl_idx].receive { repeat; }
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02002817 [] T.timeout { setverdict(fail, "Timeout receiving next SI1"); }
2818 }
2819 return last_si1;
2820}
2821
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02002822/* verify ACC rotate feature */
2823testcase TC_si_acc_rotate() runs on test_CT {
2824 var template SystemInformationConfig sic := SystemInformationConfig_default;
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02002825 var SystemInformationType1 last_si1;
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02002826 var AccessControlClass acc;
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02002827 var uint8_t count;
2828 var integer times_allowed[10] := { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
2829
2830 f_init(0, guard_timeout := 60.0);
2831
2832 f_bts_0_cfg(BSCVTY, {"rach access-control-class 5 barred",
2833 "access-control-class-rotate 3",
2834 "access-control-class-rotate-quantum 1"});
2835
2836 /* Init and get first sysinfo */
2837 f_init_bts_and_check_sysinfo(0, expect_si := ?);
2838
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02002839 for (var integer i:= 0; i < 20; i := i + 1) {
2840 last_si1 := f_recv_next_si1(0);
2841 acc := last_si1.rach_control.acc;
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02002842 count := f_acc09_count_allowed(acc);
2843 log("RSL: GOT SI1 ACC len=", count, ": ", acc);
2844
2845 if (count != 3) {
2846 log("RSL: EXPECTED SI ACC len=3");
2847 setverdict(fail, "received SI does not match expectations");
2848 break;
2849 }
2850
2851 for (var integer j := 0; j < 10; j := j + 1) {
2852 if (acc[16 - 1 - j] == '0'B) { /* the list marks barred, we count allowed */
2853 times_allowed[j] := times_allowed[j] + 1;
2854 }
2855 }
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02002856 }
2857
2858 for (var integer j := 0; j < 10; j := j + 1) {
2859 log("ACC", j, " allowed ", times_allowed[j], " times" );
2860 if (j != 5 and times_allowed[j] < 3) {
2861 setverdict(fail, "ACC", j, " ERROR: allowed ", times_allowed[j], " < 1 times");
2862 } else if (j == 5 and times_allowed[j] > 0) {
2863 setverdict(fail, "ACC", j, " ERROR: allowed ", times_allowed[j], " > 0 times");
2864 }
2865 }
2866
2867 f_bts_0_cfg(BSCVTY, {"access-control-class-rotate 10",
2868 "rach access-control-class 5 allowed"});
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002869 f_shutdown_helper();
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02002870}
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002871
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02002872/* verify ACC startup ramp+rotate feature */
2873testcase TC_si_acc_ramp_rotate() runs on test_CT {
2874 var template SystemInformationConfig sic := SystemInformationConfig_default;
2875 var SystemInformationType1 last_si1;
2876 var AccessControlClass acc;
2877 var ASP_RSL_Unitdata rx_rsl_ud;
2878 var uint8_t count;
2879 var uint8_t prev_count;
2880 var integer times_allowed[10] := { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
2881
2882 f_init(0, guard_timeout := 80.0);
2883
2884 f_bts_0_cfg(BSCVTY, {"rach access-control-class 4 barred",
2885 "access-control-class-rotate 0",
2886 "access-control-class-rotate-quantum 1",
2887 "access-control-class-ramping",
2888 "access-control-class-ramping-step-interval 5",
2889 "access-control-class-ramping-step-size 5"});
2890
2891 /* Init and get first sysinfo */
2892 f_init_bts_and_check_sysinfo(0, expect_si := ?);
2893 last_si1 := g_system_information[0].si1;
2894 acc := last_si1.rach_control.acc;
2895 count := f_acc09_count_allowed(acc);
2896 /* Adm subset size was set to 0 above, so wait until all ACC are barred */
2897 while (count > 0) {
2898 last_si1 := f_recv_next_si1(0);
2899 acc := last_si1.rach_control.acc;
2900 count := f_acc09_count_allowed(acc);
2901 log("RSL: wait len()=0: GOT SI1 ACC len=", count, ": ", acc);
2902 }
2903
2904 /* Increase adm subset size, we should see ramping start up */
2905 f_bts_0_cfg(BSCVTY, {"access-control-class-rotate 10"});
2906 prev_count := 0;
2907 while (true) {
2908 last_si1 := f_recv_next_si1(0);
2909 acc := last_si1.rach_control.acc;
2910 count := f_acc09_count_allowed(acc);
2911 log("RSL: GOT SI1 ACC len=", count, ": ", acc);
2912
2913 if (prev_count > count) {
2914 setverdict(fail, "ACC allowed count dropped while expecting grow: ", prev_count, " -> ", count);
2915 break;
2916 }
2917
2918 if (count == 9) {
2919 break; /* Maximum reached (10 - 1 perm barred), done here */
2920 }
2921
2922 prev_count := count;
2923 }
2924
2925 setverdict(pass);
2926
2927 f_bts_0_cfg(BSCVTY, {"access-control-class-rotate 10",
2928 "rach access-control-class 4 allowed",
2929 "no access-control-class-ramping"});
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002930 f_shutdown_helper();
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02002931}
2932
Harald Welte4003d112017-12-09 22:35:39 +01002933testcase TC_ctrl_msc_connection_status() runs on test_CT {
2934 var charstring ctrl_resp;
2935
Harald Welte89d42e82017-12-17 16:42:41 +01002936 f_init(1);
Harald Welte4003d112017-12-09 22:35:39 +01002937
2938 /* See https://osmocom.org/issues/2729 */
2939 f_ctrl_get_exp(IPA_CTRL, "msc_connection_status", "connected");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002940 f_shutdown_helper();
Harald Welte4003d112017-12-09 22:35:39 +01002941}
2942
Stefan Sperlingb041b3d2018-01-03 17:14:55 +01002943testcase TC_ctrl_msc0_connection_status() runs on test_CT {
2944 var charstring ctrl_resp;
2945
2946 f_init(1);
Stefan Sperlingb041b3d2018-01-03 17:14:55 +01002947
2948 f_ctrl_get_exp(IPA_CTRL, "msc.0.connection_status", "connected");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002949 f_shutdown_helper();
Stefan Sperlingb041b3d2018-01-03 17:14:55 +01002950}
2951
Neels Hofmeyr0bc470d2021-08-21 13:37:13 +02002952/* Verify correct stats on the number of configured and connected MSCs */
2953private function f_tc_stat_num_msc_connected_msc_connhdlr(integer expect_num_msc_connected) runs on MSC_ConnHdlr {
2954 g_pars := f_gen_test_hdlr_pars();
2955 var StatsDExpects expect := {
2956 { name := "TTCN3.bsc.0.num_msc.connected", mtype := "g", min := expect_num_msc_connected, max := expect_num_msc_connected },
2957 { name := "TTCN3.bsc.0.num_msc.total", mtype := "g", min := NUM_MSC, max := NUM_MSC }
2958 };
2959 f_statsd_expect(expect);
2960}
2961
2962private function f_tc_stat_num_msc_connected_test_ct(void_fn tc_fn, integer nr_msc) runs on test_CT
2963{
2964 var MSC_ConnHdlr vc_conn;
2965
2966 f_init(nr_bts := 1, handler_mode := true, nr_msc := nr_msc);
2967 f_sleep(1.0);
2968 vc_conn := f_start_handler(tc_fn);
2969 vc_conn.done;
2970
2971 /* Also verify stat exposed on CTRL interface */
2972 f_ctrl_get_exp(IPA_CTRL, "stat_item.last.bsc.0.num_msc:connected", int2str(nr_msc));
2973 f_ctrl_get_exp(IPA_CTRL, "stat_item.last.bsc.0.num_msc:total", int2str(NUM_MSC));
2974
2975 f_shutdown_helper();
2976}
2977
2978/* Verify that when 1 MSC is active, that num_msc:connected reports 1. */
2979private function f_tc_stat_num_msc_connected_1(charstring id) runs on MSC_ConnHdlr {
2980 f_tc_stat_num_msc_connected_msc_connhdlr(1);
2981}
2982testcase TC_stat_num_msc_connected_1() runs on test_CT {
2983 f_tc_stat_num_msc_connected_test_ct(refers(f_tc_stat_num_msc_connected_1), 1);
2984}
2985
2986/* Verify that when 2 MSCs are active, that num_msc:connected reports 2. */
2987private function f_tc_stat_num_msc_connected_2(charstring id) runs on MSC_ConnHdlr {
2988 f_tc_stat_num_msc_connected_msc_connhdlr(2);
2989}
2990testcase TC_stat_num_msc_connected_2() runs on test_CT {
2991 f_tc_stat_num_msc_connected_test_ct(refers(f_tc_stat_num_msc_connected_2), 2);
2992}
2993
2994/* Verify that when 3 MSCs are active, that num_msc:connected reports 3. */
2995private function f_tc_stat_num_msc_connected_3(charstring id) runs on MSC_ConnHdlr {
2996 f_tc_stat_num_msc_connected_msc_connhdlr(3);
2997}
2998testcase TC_stat_num_msc_connected_3() runs on test_CT {
2999 f_tc_stat_num_msc_connected_test_ct(refers(f_tc_stat_num_msc_connected_3), 3);
3000}
3001
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +02003002/* Verify correct stats on the number of configured and connected MSCs */
3003private function f_tc_stat_num_bts_connected_msc_connhdlr(integer expect_num_bts_connected) runs on MSC_ConnHdlr {
3004 g_pars := f_gen_test_hdlr_pars();
3005 var StatsDExpects expect := {
3006 { name := "TTCN3.bsc.0.num_bts.oml_connected", mtype := "g", min := expect_num_bts_connected, max := NUM_BTS_CFG },
3007 { name := "TTCN3.bsc.0.num_bts.all_trx_rsl_connected", mtype := "g", min := expect_num_bts_connected, max := expect_num_bts_connected },
3008 { name := "TTCN3.bsc.0.num_bts.total", mtype := "g", min := NUM_BTS_CFG, max := NUM_BTS_CFG },
3009 { name := "TTCN3.bsc.0.num_trx.rsl_connected", mtype := "g", min := expect_num_bts_connected, max := expect_num_bts_connected },
3010 { name := "TTCN3.bsc.0.num_trx.total", mtype := "g", min := NUM_BTS_CFG, max := NUM_BTS_CFG }
3011 };
3012 f_statsd_expect(expect);
3013}
3014
3015private function f_tc_stat_num_bts_connected_test_ct(void_fn tc_fn, integer nr_bts) runs on test_CT {
3016 var MSC_ConnHdlr vc_conn;
3017
3018 f_init(nr_bts := nr_bts, handler_mode := true, nr_msc := 1);
3019 f_sleep(1.0);
3020 vc_conn := f_start_handler(tc_fn);
3021 vc_conn.done;
3022
3023 /* Also verify stat exposed on CTRL interface */
3024 f_ctrl_get_exp(IPA_CTRL, "stat_item.last.bsc.0.num_bts:all_trx_rsl_connected", int2str(nr_bts));
3025 f_ctrl_get_exp(IPA_CTRL, "stat_item.last.bsc.0.num_bts:total", int2str(NUM_BTS_CFG));
3026 f_ctrl_get_exp(IPA_CTRL, "stat_item.last.bsc.0.num_trx:rsl_connected", int2str(nr_bts));
3027 f_ctrl_get_exp(IPA_CTRL, "stat_item.last.bsc.0.num_trx:total", int2str(NUM_BTS_CFG));
3028
Neels Hofmeyra41ae302021-09-06 22:06:02 +02003029 /* Verify rf_states exposed on CTRL interface */
3030 var charstring expect_net_rf_states := "";
3031 for (var integer i := 0; i < NUM_BTS_CFG; i := i + 1) {
3032 var charstring expect_bts_rf_states := int2str(i) & ",0,";
3033 if (i < NUM_BTS) {
3034 /* In these tests, OML for the first NUM_BTS are always connected via osmo-bts-omldummy */
3035 expect_bts_rf_states := expect_bts_rf_states & "operational,unlocked,";
3036 } else {
3037 /* For remaining i < NUM_BTS_CFG, OML is not connected, i.e. inoperational */
3038 expect_bts_rf_states := expect_bts_rf_states & "inoperational,locked,";
3039 }
3040 /* The RF policy is still global in osmo-bsc, i.e. always "on" */
3041 expect_bts_rf_states := expect_bts_rf_states & "on,";
3042 if (i < nr_bts) {
3043 /* For BTS where RSL is connected, the RSL state will be "up" */
3044 expect_bts_rf_states := expect_bts_rf_states & "rsl-up;";
3045 } else {
3046 expect_bts_rf_states := expect_bts_rf_states & "rsl-down;";
3047 }
3048
3049 f_ctrl_get_exp(IPA_CTRL, "bts." & int2str(i) & ".rf_states", expect_bts_rf_states);
3050 expect_net_rf_states := expect_net_rf_states & expect_bts_rf_states;
3051 }
3052 f_ctrl_get_exp(IPA_CTRL, "rf_states", expect_net_rf_states);
3053
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +02003054 f_shutdown_helper();
3055}
3056
3057/* Verify that when 1 BTS is connected, that num_{bts,trx}:*_connected reports 1. */
3058private function f_tc_stat_num_bts_connected_1(charstring id) runs on MSC_ConnHdlr {
3059 f_tc_stat_num_bts_connected_msc_connhdlr(1);
3060}
3061testcase TC_stat_num_bts_connected_1() runs on test_CT {
3062 f_tc_stat_num_bts_connected_test_ct(refers(f_tc_stat_num_bts_connected_1), 1);
3063}
3064
3065/* Verify that when 2 BTS is connected, that num_{bts,trx}:*_connected reports 2. */
3066private function f_tc_stat_num_bts_connected_2(charstring id) runs on MSC_ConnHdlr {
3067 f_tc_stat_num_bts_connected_msc_connhdlr(2);
3068}
3069testcase TC_stat_num_bts_connected_2() runs on test_CT {
3070 f_tc_stat_num_bts_connected_test_ct(refers(f_tc_stat_num_bts_connected_2), 2);
3071}
3072
3073/* Verify that when 3 BTS is connected, that num_{bts,trx}:*_connected reports 3. */
3074private function f_tc_stat_num_bts_connected_3(charstring id) runs on MSC_ConnHdlr {
3075 f_tc_stat_num_bts_connected_msc_connhdlr(3);
3076}
3077testcase TC_stat_num_bts_connected_3() runs on test_CT {
3078 f_tc_stat_num_bts_connected_test_ct(refers(f_tc_stat_num_bts_connected_3), 3);
3079}
3080
Harald Welte4003d112017-12-09 22:35:39 +01003081testcase TC_ctrl() runs on test_CT {
3082 var charstring ctrl_resp;
3083
Harald Welte89d42e82017-12-17 16:42:41 +01003084 f_init(1);
Harald Welte4003d112017-12-09 22:35:39 +01003085
3086 /* all below values must match the osmo-bsc.cfg config file used */
3087
Harald Welte6a129692018-03-17 17:30:14 +01003088 f_ctrl_get_exp(IPA_CTRL, "mcc", "001");
3089 f_ctrl_get_exp(IPA_CTRL, "mnc", "01");
Oliver Smith75aa0202019-08-19 14:17:50 +02003090 f_ctrl_get_exp(IPA_CTRL, "number-of-bts", "4");
Harald Welte4003d112017-12-09 22:35:39 +01003091
3092 var integer bts_nr := 0;
3093 f_ctrl_get_exp_bts(IPA_CTRL, bts_nr, "location-area-code", "1");
3094 f_ctrl_get_exp_bts(IPA_CTRL, bts_nr, "cell-identity", "0");
3095 f_ctrl_get_exp_bts(IPA_CTRL, bts_nr, "oml-connection-state", "connected");
3096 f_ctrl_get_exp_bts(IPA_CTRL, bts_nr, "gprs-mode", "gprs");
3097 f_ctrl_get_exp_bts(IPA_CTRL, bts_nr, "rf_state", "operational,unlocked,on");
3098 f_ctrl_get_exp_trx(IPA_CTRL, bts_nr, 0, "arfcn", "871");
3099 f_ctrl_get_exp_trx(IPA_CTRL, bts_nr, 0, "max-power-reduction", "20");
3100
3101 var integer uptime := str2int(f_ctrl_get_bts(IPA_CTRL, bts_nr, "oml-uptime"));
3102 f_sleep(2.0);
3103 if (str2int(f_ctrl_get_bts(IPA_CTRL, bts_nr, "oml-uptime")) < uptime+1) {
3104 setverdict(fail, "oml-uptime not incrementing as expected");
3105 }
3106 /* TODO: Disconnect RSL, imply that OML is disconnected and check for uptime zero? */
3107
3108 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bsc", 0, "paging:attempted", 0);
3109
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003110 f_shutdown_helper();
Harald Welte96c94412017-12-09 03:12:45 +01003111}
3112
Pau Espin Pedrol5a2d7432019-06-07 19:43:45 +02003113/* Verify that Upon receival of SET "location", BSC forwards a TRAP
3114 "location-state" over the SCCPlite IPA conn */
3115testcase TC_ctrl_location() runs on test_CT {
3116 var MSC_ConnHdlr vc_conn;
3117 var integer bts_nr := 0;
3118
3119 f_init(1, true);
3120 f_sleep(1.0);
3121
3122 f_ctrl_set_bts(IPA_CTRL, bts_nr, "location", "1234567,fix3d,0.340000,0.560000,0.780000");
3123 f_ctrl_exp_trap(SCCPLITE_IPA_CTRL, "bts." & int2str(bts_nr) & ".location-state",
3124 "1234567,fix3d,0.340000,0.560000,0.780000,operational,unlocked,on,001,01");
3125
3126 f_ctrl_set(SCCPLITE_IPA_CTRL, "rf_locked", "1");
3127 f_sleep(2.0);
3128
3129 f_ctrl_set_bts(IPA_CTRL, bts_nr, "location", "1234888,fix3d,0.350000,0.570000,0.790000");
3130 f_ctrl_exp_trap(SCCPLITE_IPA_CTRL, "bts." & int2str(bts_nr) & ".location-state",
3131 "1234888,fix3d,0.350000,0.570000,0.790000,operational,locked,off,001,01");
3132
3133 /* should match the one from config */
3134 f_ctrl_set(SCCPLITE_IPA_CTRL, "rf_locked", "0");
3135
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003136 f_shutdown_helper();
Pau Espin Pedrol5a2d7432019-06-07 19:43:45 +02003137}
3138
Harald Welte6f521d82017-12-11 19:52:02 +01003139
3140/***********************************************************************
3141 * Paging Testing
3142 ***********************************************************************/
3143
3144type record Cell_Identity {
3145 GsmMcc mcc,
3146 GsmMnc mnc,
3147 GsmLac lac,
3148 GsmCellId ci
3149};
Harald Welte24135bd2018-03-17 19:27:53 +01003150private const Cell_Identity cid := { '001'H, '01'H, 1, 0 };
Stefan Sperling049a86e2018-03-20 15:51:00 +01003151private const Cell_Identity unknown_cid := { '678'H, 'f90'H, 1, 0 };
Harald Welte6f521d82017-12-11 19:52:02 +01003152
Harald Welte5d1a2202017-12-13 19:51:29 +01003153type set of integer BtsIdList;
3154
3155private function f_bts_in_list(integer bts_id, BtsIdList bts_ids) return boolean {
3156 for (var integer j := 0; j < sizeof(bts_ids); j := j + 1) {
3157 if (bts_id == bts_ids[j]) {
3158 return true;
3159 }
3160 }
3161 return false;
3162}
Harald Welte6f521d82017-12-11 19:52:02 +01003163
3164/* core paging test helper function; used by most paging test cases */
3165private function f_pageing_helper(hexstring imsi,
3166 template BSSMAP_FIELD_CellIdentificationList cid_list,
Harald Welte5d1a2202017-12-13 19:51:29 +01003167 BtsIdList bts_ids := { 0 },
Harald Welte6f521d82017-12-11 19:52:02 +01003168 template RSL_ChanNeeded rsl_chneed := omit,
Vadim Yanitskiycc4623d2020-03-28 06:14:06 +07003169 template (omit) OCT4 tmsi := omit) runs on test_CT
Harald Welte6f521d82017-12-11 19:52:02 +01003170{
3171 var template BSSMAP_IE_ChannelNeeded bssmap_chneed;
Vadim Yanitskiycc4623d2020-03-28 06:14:06 +07003172 var template MobileIdentityV mi;
Harald Welte6f521d82017-12-11 19:52:02 +01003173 var RSL_Message rx_rsl;
3174 var integer paging_group := hex2int(imsi[lengthof(imsi)-1]);
Harald Welte5d1a2202017-12-13 19:51:29 +01003175 var integer i;
Harald Welte6f521d82017-12-11 19:52:02 +01003176
3177 f_init();
Harald Welte6f521d82017-12-11 19:52:02 +01003178
3179 /* Clear the queue, it might still contain stuff like BCCH FILLING */
Harald Weltec3068592018-03-17 19:55:31 +01003180 for (i := 0; i < NUM_BTS; i := i + 1) {
3181 IPA_RSL[i].clear;
Harald Welte5d1a2202017-12-13 19:51:29 +01003182 }
Harald Welte6f521d82017-12-11 19:52:02 +01003183
3184 if (isvalue(rsl_chneed)) {
3185 /* The values of 08.08 3.2.2.36 and 08.58 9.3.40 are luckily identical */
3186 bssmap_chneed := ts_BSSMAP_IE_ChanNeeded(int2bit(enum2int(valueof(rsl_chneed)),2));
3187 } else {
3188 bssmap_chneed := omit;
3189 }
3190
Neels Hofmeyrf246a922020-05-13 02:27:10 +02003191 BSSAP.send(ts_BSSAP_UNITDATA_req(g_bssap[0].sccp_addr_peer, g_bssap[0].sccp_addr_own,
3192 ts_BSSMAP_Paging(imsi, cid_list, tmsi, bssmap_chneed)));
Harald Welte6f521d82017-12-11 19:52:02 +01003193
Vadim Yanitskiycc4623d2020-03-28 06:14:06 +07003194 if (not istemplatekind(tmsi, "omit")) {
3195 mi := t_MI_TMSI(tmsi);
Harald Welte6f521d82017-12-11 19:52:02 +01003196 } else {
Vadim Yanitskiycc4623d2020-03-28 06:14:06 +07003197 mi := tr_MI_IMSI(imsi);
Harald Welte6f521d82017-12-11 19:52:02 +01003198 }
Vadim Yanitskiycc4623d2020-03-28 06:14:06 +07003199
Harald Welte5d1a2202017-12-13 19:51:29 +01003200 for (i := 0; i < sizeof(bts_ids); i := i + 1) {
Vadim Yanitskiycc4623d2020-03-28 06:14:06 +07003201 rx_rsl := f_exp_ipa_rx(bts_ids[i], tr_RSL_PAGING_CMD(mi));
Harald Welte5d1a2202017-12-13 19:51:29 +01003202 /* check channel type, paging group */
3203 if (rx_rsl.ies[1].body.paging_group != paging_group) {
3204 setverdict(fail, "Paging for wrong paging group");
3205 }
3206 if (ispresent(rsl_chneed) and
3207 rx_rsl.ies[3].body.chan_needed.chan_needed != valueof(rsl_chneed)) {
3208 setverdict(fail, "RSL Channel Needed != BSSMAP Channel Needed");
3209 }
Harald Welte6f521d82017-12-11 19:52:02 +01003210 }
Harald Welte2fccd982018-01-31 15:48:19 +01003211 f_sleep(2.0);
Harald Welte5d1a2202017-12-13 19:51:29 +01003212 /* do a quick check on all not-included BTSs if they received paging */
3213 for (i := 0; i < NUM_BTS; i := i + 1) {
3214 timer T := 0.1;
3215 if (f_bts_in_list(i, bts_ids)) {
3216 continue;
3217 }
3218 T.start;
3219 alt {
Vadim Yanitskiy9b4e3562020-05-25 21:40:52 +07003220 [] IPA_RSL[i].receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD(mi))) {
Harald Welte5d1a2202017-12-13 19:51:29 +01003221 setverdict(fail, "Paging on BTS ", i, " which is not part of ", bts_ids);
3222 }
3223 [] IPA_RSL[i].receive { repeat; }
3224 [] T.timeout { }
3225 }
Harald Welte6f521d82017-12-11 19:52:02 +01003226 }
3227
3228 setverdict(pass);
3229}
3230
Harald Welte5d1a2202017-12-13 19:51:29 +01003231const BtsIdList c_BtsId_all := { 0, 1, 2 };
Harald Welte751d3eb2018-01-31 15:51:06 +01003232const BtsIdList c_BtsId_none := { };
Harald Welte5d1a2202017-12-13 19:51:29 +01003233const BtsIdList c_BtsId_LAC1 := { 0, 1 };
3234const BtsIdList c_BtsId_LAC2 := { 2 };
3235
Harald Welte6f521d82017-12-11 19:52:02 +01003236/* PAGING by IMSI + TMSI */
3237testcase TC_paging_imsi_nochan() runs on test_CT {
3238 var BSSMAP_FIELD_CellIdentificationList cid_list;
3239 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Philipp Maier8c04b0a2018-02-23 13:48:48 +01003240 f_pageing_helper('001010100000001'H, cid_list, c_BtsId_all, omit, omit);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003241 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003242}
3243
3244/* PAGING by IMSI + TMSI */
3245testcase TC_paging_tmsi_nochan() runs on test_CT {
3246 var BSSMAP_FIELD_CellIdentificationList cid_list;
3247 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003248 f_pageing_helper('001010100000001'H, cid_list, c_BtsId_all, omit, 'A1B2C301'O);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003249 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003250}
3251
3252/* Paging with different "channel needed' values */
3253testcase TC_paging_tmsi_any() runs on test_CT {
3254 var BSSMAP_FIELD_CellIdentificationList cid_list;
3255 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003256 f_pageing_helper('001010100000002'H, cid_list, c_BtsId_all, RSL_CHANNEED_ANY, 'A1B2C302'O);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003257 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003258}
3259testcase TC_paging_tmsi_sdcch() runs on test_CT {
3260 var BSSMAP_FIELD_CellIdentificationList cid_list;
3261 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003262 f_pageing_helper('001010100000003'H, cid_list, c_BtsId_all, RSL_CHANNEED_SDCCH, 'A1B2C303'O);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003263 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003264}
3265testcase TC_paging_tmsi_tch_f() runs on test_CT {
3266 var BSSMAP_FIELD_CellIdentificationList cid_list;
3267 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003268 f_pageing_helper('001010000000004'H, cid_list, c_BtsId_all, RSL_CHANNEED_TCH_F, 'A1B2C304'O);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003269 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003270}
3271testcase TC_paging_tmsi_tch_hf() runs on test_CT {
3272 var BSSMAP_FIELD_CellIdentificationList cid_list;
3273 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003274 f_pageing_helper('001010000000005'H, cid_list, c_BtsId_all, RSL_CHANNEED_TCH_ForH, 'A1B2C305'O);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003275 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003276}
3277
3278/* Paging by CGI */
3279testcase TC_paging_imsi_nochan_cgi() runs on test_CT {
3280 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3281 cid_list := { cIl_CGI := { ts_BSSMAP_CI_CGI(cid.mcc, cid.mnc, cid.lac, cid.ci) } };
Harald Welte5d1a2202017-12-13 19:51:29 +01003282 f_pageing_helper('001010000000006'H, cid_list, { 0 });
Philipp Maier282ca4b2018-02-27 17:17:00 +01003283 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003284}
3285
3286/* Paging by LAC+CI */
3287testcase TC_paging_imsi_nochan_lac_ci() runs on test_CT {
3288 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3289 cid_list := { cIl_LAC_CI := { ts_BSSMAP_CI_LAC_CI(cid.lac, cid.ci) } };
Harald Welte5d1a2202017-12-13 19:51:29 +01003290 f_pageing_helper('001010000000007'H, cid_list, { 0 });
Philipp Maier282ca4b2018-02-27 17:17:00 +01003291 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003292}
3293
3294/* Paging by CI */
3295testcase TC_paging_imsi_nochan_ci() runs on test_CT {
3296 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3297 cid_list := { cIl_CI := { ts_BSSMAP_CI_CI(cid.ci) } };
Harald Welte5d1a2202017-12-13 19:51:29 +01003298 f_pageing_helper('001010000000008'H, cid_list, { 0 });
Philipp Maier282ca4b2018-02-27 17:17:00 +01003299 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003300}
3301
3302/* Paging by LAI */
3303testcase TC_paging_imsi_nochan_lai() runs on test_CT {
3304 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3305 cid_list := { cIl_LAI := { ts_BSSMAP_CI_LAI(cid.mcc, cid.mnc, cid.lac) } };
Harald Welte5d1a2202017-12-13 19:51:29 +01003306 f_pageing_helper('001010000000009'H, cid_list, c_BtsId_LAC1);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003307 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003308}
3309
3310/* Paging by LAC */
3311testcase TC_paging_imsi_nochan_lac() runs on test_CT {
3312 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3313 cid_list := { cIl_LAC := { ts_BSSMAP_CI_LAC(cid.lac) } };
Harald Welte5d1a2202017-12-13 19:51:29 +01003314 f_pageing_helper('001010000000010'H, cid_list, c_BtsId_LAC1);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003315 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003316}
3317
3318/* Paging by "all in BSS" */
3319testcase TC_paging_imsi_nochan_all() runs on test_CT {
3320 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3321 cid_list := { cIl_allInBSS := ''O };
Harald Welte5d1a2202017-12-13 19:51:29 +01003322 f_pageing_helper('001010000000011'H, cid_list, c_BtsId_all);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003323 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003324}
3325
Stefan Sperling7b5e1782018-03-20 19:32:43 +01003326/* Paging by PLMN+LAC+RNC; We do not implement this; Verify nothing is paged */
Harald Welte751d3eb2018-01-31 15:51:06 +01003327testcase TC_paging_imsi_nochan_plmn_lac_rnc() runs on test_CT {
3328 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3329 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 +01003330 f_pageing_helper('001010000000012'H, cid_list, c_BtsId_none);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003331 f_shutdown_helper();
Harald Welte751d3eb2018-01-31 15:51:06 +01003332}
Harald Welte6f521d82017-12-11 19:52:02 +01003333
Stefan Sperling7b5e1782018-03-20 19:32:43 +01003334/* Paging by RNC; We do not implement this; Verify nothing is paged */
Harald Welte751d3eb2018-01-31 15:51:06 +01003335testcase TC_paging_imsi_nochan_rnc() runs on test_CT {
3336 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3337 cid_list := { cIl_RNC := { int2oct(13, 2) } };
Stefan Sperling7b5e1782018-03-20 19:32:43 +01003338 f_pageing_helper('001010000000013'H, cid_list, c_BtsId_none);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003339 f_shutdown_helper();
Harald Welte751d3eb2018-01-31 15:51:06 +01003340}
3341
Stefan Sperling7b5e1782018-03-20 19:32:43 +01003342/* Paging by LAC+RNC; We do not implement; Verify nothing is paged */
Harald Welte751d3eb2018-01-31 15:51:06 +01003343testcase TC_paging_imsi_nochan_lac_rnc() runs on test_CT {
3344 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3345 cid_list := { cIl_LAC_RNC := { ts_BSSMAP_CI_LAC_RNC(cid.lac, 14) } };
Stefan Sperling7b5e1782018-03-20 19:32:43 +01003346 f_pageing_helper('001010000000014'H, cid_list, c_BtsId_none);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003347 f_shutdown_helper();
Harald Welte751d3eb2018-01-31 15:51:06 +01003348}
3349
Harald Welte6f521d82017-12-11 19:52:02 +01003350/* Paging on multiple cells (multiple entries in list): Verify all of them page */
Harald Welte751d3eb2018-01-31 15:51:06 +01003351testcase TC_paging_imsi_nochan_lacs() runs on test_CT {
3352 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3353 cid_list := { cIl_LAC := { ts_BSSMAP_CI_LAC(1), ts_BSSMAP_CI_LAC(2) } };
3354 f_pageing_helper('001010000000015'H, cid_list, c_BtsId_all);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003355 f_shutdown_helper();
Harald Welte751d3eb2018-01-31 15:51:06 +01003356}
3357
3358/* Paging on empty list: Verify none of them page */
3359testcase TC_paging_imsi_nochan_lacs_empty() runs on test_CT {
3360 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3361 cid_list := { cIl_LAC := { } };
3362 f_pageing_helper('001010000000016'H, cid_list, c_BtsId_none);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003363 f_shutdown_helper();
Harald Welte751d3eb2018-01-31 15:51:06 +01003364}
3365
Stefan Sperling049a86e2018-03-20 15:51:00 +01003366/* Paging by CGI with unknown MCC/MNC: Verify nothing is paged. */
3367testcase TC_paging_imsi_nochan_cgi_unknown_cid() runs on test_CT {
3368 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3369 cid_list := { cIl_CGI := { ts_BSSMAP_CI_CGI(unknown_cid.mcc, unknown_cid.mnc, unknown_cid.lac, unknown_cid.ci) } };
3370 f_pageing_helper('001010000000006'H, cid_list, c_BtsId_none);
3371 f_shutdown_helper();
3372}
3373
Harald Welte6f521d82017-12-11 19:52:02 +01003374/* Verify paging retransmission interval + count */
3375/* Verify paging stops after channel establishment */
Harald Welte6f521d82017-12-11 19:52:02 +01003376/* Test behavior under paging overload */
Harald Welteae026692017-12-09 01:03:01 +01003377
Harald Weltee65d40e2017-12-13 00:09:06 +01003378/* Verify PCH load */
3379testcase TC_paging_imsi_load() runs on test_CT {
3380 var BSSMAP_FIELD_CellIdentificationList cid_list;
3381 timer T := 4.0;
Harald Welte2caa1062018-03-17 18:19:05 +01003382 timer T_retrans := 1.0;
Harald Weltee65d40e2017-12-13 00:09:06 +01003383 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003384 f_pageing_helper('001010123456789'H, cid_list, c_BtsId_all);
Harald Weltee65d40e2017-12-13 00:09:06 +01003385
3386 /* tell BSC there is no paging space anymore */
3387 f_ipa_tx(0, ts_RSL_PAGING_LOAD_IND(0));
Harald Welte3b57ab52018-03-17 18:01:10 +01003388 f_sleep(0.2);
3389 IPA_RSL[0].clear;
Harald Weltee65d40e2017-12-13 00:09:06 +01003390
3391 /* Wait for 4 seconds if any more PAGING CMD are received on RSL. Normally,
3392 * there would be 8 retransmissions during 4 seconds */
3393 T.start;
Harald Welte2caa1062018-03-17 18:19:05 +01003394 T_retrans.start;
Harald Weltee65d40e2017-12-13 00:09:06 +01003395 alt {
Vadim Yanitskiy9b4e3562020-05-25 21:40:52 +07003396 [] IPA_RSL[0].receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD(?))) {
Harald Weltee65d40e2017-12-13 00:09:06 +01003397 setverdict(fail, "Received PAGING after LOAD_IND(0)");
Daniel Willmannafce8662018-07-06 23:11:32 +02003398 mtc.stop;
Harald Weltee65d40e2017-12-13 00:09:06 +01003399 }
Harald Welte2caa1062018-03-17 18:19:05 +01003400 [] T_retrans.timeout {
3401 /* re-trnsmit the zero-space LOAD IND to avoid BSC 'auto credit' */
3402 f_ipa_tx(0, ts_RSL_PAGING_LOAD_IND(0));
3403 T_retrans.start;
3404 repeat;
3405 }
Harald Weltee65d40e2017-12-13 00:09:06 +01003406 [] T.timeout {
3407 setverdict(pass);
3408 }
3409 }
Philipp Maier282ca4b2018-02-27 17:17:00 +01003410
3411 f_shutdown_helper();
Harald Weltee65d40e2017-12-13 00:09:06 +01003412}
3413
Harald Welte235ebf12017-12-15 14:18:16 +01003414/* Verify Paging Counter */
Harald Welte1ff69992017-12-14 12:31:17 +01003415testcase TC_paging_counter() runs on test_CT {
3416 var BSSMAP_FIELD_CellIdentificationList cid_list;
3417 timer T := 4.0;
3418 var integer i;
3419 var integer paging_attempted_bsc;
3420 var integer paging_attempted_bts[NUM_BTS];
Oliver Smith8b343d32021-11-26 13:01:42 +01003421 var integer paging_expired_bsc;
Harald Welte1ff69992017-12-14 12:31:17 +01003422 var integer paging_expired_bts[NUM_BTS];
3423 cid_list := valueof(ts_BSSMAP_CIL_noCell);
3424
3425 f_init();
3426
3427 /* read counters before paging */
3428 paging_attempted_bsc := f_ctrl_get_ratectr_abs(IPA_CTRL, "bsc", 0, "paging:attempted");
Oliver Smith8b343d32021-11-26 13:01:42 +01003429 if (Misc_Helpers.f_osmo_repo_is("nightly")) { /* osmo-bsc > 1.8.0 */
3430 paging_expired_bsc := f_ctrl_get_ratectr_abs(IPA_CTRL, "bsc", 0, "paging:expired");
3431 }
Harald Welte1ff69992017-12-14 12:31:17 +01003432 for (i := 0; i < NUM_BTS; i := i+1) {
3433 paging_attempted_bts[i] := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", i, "paging:attempted");
3434 paging_expired_bts[i] := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", i, "paging:expired");
3435 }
3436
3437 f_pageing_helper('001230000000001'H, cid_list, c_BtsId_all);
3438
3439 /* expect the attempted pages on BSC and each BTSs to have incremented by one */
3440 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bsc", 0, "paging:attempted", paging_attempted_bsc+1);
3441 for (i := 0; i < NUM_BTS; i := i+1) {
3442 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", i, "paging:attempted",
3443 paging_attempted_bts[i]+1);
3444 }
3445
3446 /* assume that 12s later the paging on all BTSs have expired and hence incremented by 1 */
3447 f_sleep(12.0);
Oliver Smith8b343d32021-11-26 13:01:42 +01003448 if (Misc_Helpers.f_osmo_repo_is("nightly")) { /* osmo-bsc > 1.8.0 */
3449 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bsc", 0, "paging:expired", paging_expired_bsc+1);
3450 }
Harald Welte1ff69992017-12-14 12:31:17 +01003451 for (i := 0; i < NUM_BTS; i := i+1) {
3452 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", i, "paging:expired",
3453 paging_expired_bts[i]+1);
3454 }
Harald Welte1ff69992017-12-14 12:31:17 +01003455
Philipp Maier282ca4b2018-02-27 17:17:00 +01003456 f_shutdown_helper();
Harald Welte1ff69992017-12-14 12:31:17 +01003457}
3458
3459
Harald Welte10985002017-12-12 09:29:15 +01003460/* Verify paging stops after A-RESET */
3461testcase TC_paging_imsi_a_reset() runs on test_CT {
3462 var BSSMAP_FIELD_CellIdentificationList cid_list;
3463 timer T := 3.0;
3464 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003465 f_pageing_helper('001010123456789'H, cid_list, c_BtsId_all);
Harald Welte10985002017-12-12 09:29:15 +01003466
3467 /* Perform a BSSMAP Reset and wait for ACK */
Neels Hofmeyrf246a922020-05-13 02:27:10 +02003468 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 +01003469 alt {
Neels Hofmeyrf246a922020-05-13 02:27:10 +02003470 [] 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 +01003471 [] BSSAP.receive { repeat; }
3472 }
3473
Daniel Willmanncbef3982018-07-30 09:22:40 +02003474 /* Wait to avoid a possible race condition if a paging message is
3475 * received right before the reset ACK. */
3476 f_sleep(0.2);
3477
Harald Welte10985002017-12-12 09:29:15 +01003478 /* Clear the queue, it might still contain stuff like BCCH FILLING */
Philipp Maier1e6b4422018-02-23 14:02:13 +01003479 for (var integer i := 0; i < sizeof(IPA_RSL); i := i+1) {
3480 IPA_RSL[i].clear;
3481 }
Harald Welte10985002017-12-12 09:29:15 +01003482
3483 /* Wait for 3 seconds if any more PAGING CMD are received on RSL */
3484 T.start;
3485 alt {
Vadim Yanitskiy9b4e3562020-05-25 21:40:52 +07003486 [] IPA_RSL[0].receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD(?))) {
Harald Welte10985002017-12-12 09:29:15 +01003487 setverdict(fail, "Received PAGING after A-RESET");
Daniel Willmannafce8662018-07-06 23:11:32 +02003488 mtc.stop;
Harald Welte10985002017-12-12 09:29:15 +01003489 }
Vadim Yanitskiy9b4e3562020-05-25 21:40:52 +07003490 [] IPA_RSL[1].receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD(?))) {
Harald Welte5d1a2202017-12-13 19:51:29 +01003491 setverdict(fail, "Received PAGING after A-RESET");
Daniel Willmannafce8662018-07-06 23:11:32 +02003492 mtc.stop;
Harald Welte5d1a2202017-12-13 19:51:29 +01003493 }
Vadim Yanitskiy9b4e3562020-05-25 21:40:52 +07003494 [] IPA_RSL[2].receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD(?))) {
Harald Welte5d1a2202017-12-13 19:51:29 +01003495 setverdict(fail, "Received PAGING after A-RESET");
Daniel Willmannafce8662018-07-06 23:11:32 +02003496 mtc.stop;
Harald Welte5d1a2202017-12-13 19:51:29 +01003497 }
Harald Welte10985002017-12-12 09:29:15 +01003498 [] T.timeout {
3499 setverdict(pass);
3500 }
3501 }
Philipp Maier282ca4b2018-02-27 17:17:00 +01003502
3503 f_shutdown_helper();
Harald Welte10985002017-12-12 09:29:15 +01003504}
Harald Welteae026692017-12-09 01:03:01 +01003505
Philipp Maierf45824a2019-08-14 14:44:10 +02003506/* Verify how we handle unsolicited Paging Response. In case of an unsolicit
3507 * paging response we can not know which MSC is in charge, so we will blindly
3508 * pick the first configured MSC. This behavior is required in order to make
3509 * MT-CSFB calls working because in those cases the BSC can not know that the
3510 * MSC has already paged the subscriver via SGs. So any MT-CSFB call will look
3511 * like an unsolicited Paging Response to the MSC.
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +01003512 */
3513testcase TC_paging_resp_unsol() runs on test_CT {
3514
3515 f_init(1);
Philipp Maierf45824a2019-08-14 14:44:10 +02003516 timer T := 5.0;
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +01003517
3518 var BSSAP_N_CONNECT_ind rx_c_ind;
3519 var DchanTuple dt;
3520 var PDU_ML3_MS_NW l3 := valueof(ts_PAG_RESP(valueof(ts_MI_IMSI_LV('001010008880018'H))));
Philipp Maierf45824a2019-08-14 14:44:10 +02003521 var octetstring rr_pag_resp := enc_PDU_ML3_MS_NW(l3);
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +01003522
3523 /* Send CHAN RQD and wait for allocation; acknowledge it */
3524 dt.rsl_chan_nr := f_chreq_act_ack();
3525
3526 /* Send unsolicited Paging response (no matching Paging CMD stored in BSC) */
3527 f_ipa_tx(0, ts_RSL_EST_IND(dt.rsl_chan_nr, valueof(ts_RslLinkID_DCCH(0)), enc_PDU_ML3_MS_NW(l3)));
3528
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +01003529
Philipp Maierf45824a2019-08-14 14:44:10 +02003530 /* Expevct a CR with a matching Paging response on the A-Interface */
3531 T.start;
3532 alt {
3533 [] BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(rr_pag_resp))) {
3534 setverdict(pass);
3535 }
3536 [] BSSAP.receive {
3537 setverdict(fail, "Received unexpected message on A-Interface!");
3538 }
3539 [] T.timeout {
3540 setverdict(fail, "Received nothing on A-Interface!");
3541 }
3542 }
3543
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003544 f_shutdown_helper();
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +01003545}
3546
Harald Welte4e9b9cc2017-12-14 18:31:02 +01003547/* Test RSL link drop causes counter increment */
3548testcase TC_rsl_drop_counter() runs on test_CT {
3549 var integer rsl_fail;
3550
Harald Welte89d42e82017-12-17 16:42:41 +01003551 f_init(1);
Harald Welte4e9b9cc2017-12-14 18:31:02 +01003552
3553 rsl_fail := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", 0, "rsl_fail");
3554
3555 bts[0].rsl.vc_IPA.stop;
3556
3557 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", 0, "rsl_fail", rsl_fail+1);
3558
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003559 f_shutdown_helper();
Harald Welte4e9b9cc2017-12-14 18:31:02 +01003560}
3561
3562/* TODO: Test OML link drop causes counter increment */
3563
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003564/* The body of TC_rsl_unknown_unit_id() and TC_oml_unknown_unit_id() tests. */
3565function f_ipa_unknown_unit_id(integer mp_bsc_ipa_port) runs on test_CT return boolean {
3566 timer T := 10.0;
3567
3568 bts[0].rsl.id := "IPA-0-RSL";
3569 bts[0].rsl.vc_IPA := IPA_Emulation_CT.create(bts[0].rsl.id & "-IPA");
3570 bts[0].rsl.ccm_pars := c_IPA_default_ccm_pars;
3571 bts[0].rsl.ccm_pars.name := "Osmocom TTCN-3 BTS Simulator";
Oliver Smith92c2bdb2019-08-20 15:11:24 +02003572 bts[0].rsl.ccm_pars.unit_id := "99/0/0"; /* value which is unknown at BTS */
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003573
Pau Espin Pedrol9a5b8ff2021-01-04 19:01:31 +01003574 f_ipa_ctrl_start_client(mp_bsc_ip, mp_bsc_ctrl_port);
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003575
3576 f_init_mgcp("VirtMSC");
3577
3578 /* start RSL/OML connection (XXX re-uses RSL port/protocol definitions for OML) */
3579 map(bts[0].rsl.vc_IPA:IPA_PORT, system:IPA);
3580 connect(bts[0].rsl.vc_IPA:IPA_RSL_PORT, self:IPA_RSL[0]);
3581 bts[0].rsl.vc_IPA.start(IPA_Emulation.main_client(mp_bsc_ip, mp_bsc_ipa_port, "", 10000, bts[0].rsl.ccm_pars));
3582
3583 /* wait for IPA OML link to connect and then disconnect */
3584 T.start;
3585 alt {
Vadim Yanitskiya2afacc2020-05-18 21:16:19 +07003586 [] IPA_RSL[0].receive(tr_ASP_IPA_EV(ASP_IPA_EVENT_DOWN)) {
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003587 T.stop;
3588 return true;
3589 }
3590 [] IPA_RSL[0].receive { repeat }
3591 [] T.timeout {
Daniel Willmannafce8662018-07-06 23:11:32 +02003592 return false;
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003593 }
3594 }
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003595 return false;
3596}
3597
3598/* BSC should close an RSL connection from a BTS with unknown unit ID (OS#2714). */
3599testcase TC_rsl_unknown_unit_id() runs on test_CT {
3600 if (f_ipa_unknown_unit_id(mp_bsc_rsl_port)) {
3601 setverdict(pass);
3602 } else {
3603 setverdict(fail, "Timeout RSL waiting for connection to close");
3604 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003605 f_shutdown_helper();
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003606}
3607
3608
3609/* BSC should close an RSL connection from a BTS with unknown unit ID (OS#2714). */
3610testcase TC_oml_unknown_unit_id() runs on test_CT {
3611 if (f_ipa_unknown_unit_id(mp_bsc_oml_port)) {
3612 setverdict(pass);
3613 } else {
3614 setverdict(fail, "Timeout OML waiting for connection to close");
3615 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003616 f_shutdown_helper();
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003617}
3618
3619
Harald Weltec1a2fff2017-12-17 11:06:19 +01003620/***********************************************************************
Harald Welte6811d102019-04-14 22:23:14 +02003621 * "New world" test cases using RSL_Emulation + RAN_Emulation
Harald Weltec1a2fff2017-12-17 11:06:19 +01003622 ***********************************************************************/
3623
Harald Welte6811d102019-04-14 22:23:14 +02003624import from RAN_Emulation all;
Harald Welte47cd0e32020-08-21 12:39:11 +02003625import from BSSAP_LE_Emulation all;
Harald Weltec1a2fff2017-12-17 11:06:19 +01003626import from RSL_Emulation all;
3627import from MSC_ConnectionHandler all;
3628
3629type function void_fn(charstring id) runs on MSC_ConnHdlr;
3630
Harald Welte336820c2018-05-31 20:34:52 +02003631/* helper function to create and connect a MSC_ConnHdlr component */
Neels Hofmeyrf246a922020-05-13 02:27:10 +02003632private function f_connect_handler(inout MSC_ConnHdlr vc_conn, integer bssap_idx := 0) runs on test_CT {
3633 connect(vc_conn:RAN, g_bssap[bssap_idx].vc_RAN:PROC);
Daniel Willmann191e0d92018-01-17 12:44:35 +01003634 connect(vc_conn:MGCP_PROC, vc_MGCP:MGCP_PROC);
Harald Weltec1a2fff2017-12-17 11:06:19 +01003635 connect(vc_conn:RSL, bts[0].rsl.vc_RSL:CLIENT_PT);
Harald Weltef70df652018-01-29 22:00:23 +01003636 connect(vc_conn:RSL_PROC, bts[0].rsl.vc_RSL:RSL_PROC);
Philipp Maier88f4ae82018-03-01 14:00:58 +01003637 if (isvalue(bts[1])) {
Philipp Maier956a92f2018-02-16 10:58:07 +01003638 connect(vc_conn:RSL1, bts[1].rsl.vc_RSL:CLIENT_PT);
3639 connect(vc_conn:RSL1_PROC, bts[1].rsl.vc_RSL:RSL_PROC);
3640 }
Neels Hofmeyr91401012019-07-11 00:42:35 +02003641 if (isvalue(bts[2])) {
3642 connect(vc_conn:RSL2, bts[2].rsl.vc_RSL:CLIENT_PT);
3643 connect(vc_conn:RSL2_PROC, bts[2].rsl.vc_RSL:RSL_PROC);
3644 }
Neels Hofmeyrf246a922020-05-13 02:27:10 +02003645 connect(vc_conn:BSSAP, g_bssap[bssap_idx].vc_RAN:CLIENT);
Neels Hofmeyrcfe44062020-10-15 02:28:08 +02003646 if (mp_enable_lcs_tests) {
3647 connect(vc_conn:BSSAP_LE, g_bssap_le.vc_BSSAP_LE:CLIENT);
3648 connect(vc_conn:BSSAP_LE_PROC, g_bssap_le.vc_BSSAP_LE:PROC);
3649 }
Daniel Willmann191e0d92018-01-17 12:44:35 +01003650 connect(vc_conn:MGCP, vc_MGCP:MGCP_CLIENT);
Pau Espin Pedrolfd02ad42019-06-18 17:45:20 +02003651 connect(vc_conn:MGCP_MULTI, vc_MGCP:MGCP_CLIENT_MULTI);
Daniel Willmannebdecc02020-08-12 15:30:17 +02003652 connect(vc_conn:STATSD_PROC, vc_STATSD:STATSD_PROC);
Harald Welte336820c2018-05-31 20:34:52 +02003653}
3654
Neels Hofmeyrda436782021-07-20 22:09:06 +02003655function f_start_handler_create(template (omit) TestHdlrParams pars := omit)
Harald Welte336820c2018-05-31 20:34:52 +02003656runs on test_CT return MSC_ConnHdlr {
3657 var charstring id := testcasename();
3658 var MSC_ConnHdlr vc_conn;
Neels Hofmeyrf246a922020-05-13 02:27:10 +02003659 var integer bssap_idx := 0;
3660 if (isvalue(pars)) {
3661 bssap_idx := valueof(pars).mscpool.bssap_idx;
3662 }
Harald Welte336820c2018-05-31 20:34:52 +02003663 vc_conn := MSC_ConnHdlr.create(id);
Neels Hofmeyrf246a922020-05-13 02:27:10 +02003664 f_connect_handler(vc_conn, bssap_idx);
Neels Hofmeyrda436782021-07-20 22:09:06 +02003665 return vc_conn;
3666}
3667
3668function f_start_handler_run(MSC_ConnHdlr vc_conn, void_fn fn, template (omit) TestHdlrParams pars := omit)
3669runs on test_CT return MSC_ConnHdlr {
3670 var charstring id := testcasename();
Neels Hofmeyr1708d1b2020-10-10 16:56:48 +02003671 /* Emit a marker to appear in the SUT's own logging output */
Neels Hofmeyrda436782021-07-20 22:09:06 +02003672 f_logp(BSCVTY, id & "() start");
Harald Weltea0630032018-03-20 21:09:55 +01003673 vc_conn.start(f_handler_init(fn, id, pars));
Harald Weltec1a2fff2017-12-17 11:06:19 +01003674 return vc_conn;
3675}
3676
Neels Hofmeyrda436782021-07-20 22:09:06 +02003677function f_start_handler(void_fn fn, template (omit) TestHdlrParams pars := omit)
3678runs on test_CT return MSC_ConnHdlr {
3679 return f_start_handler_run(f_start_handler_create(pars), fn, pars);
3680}
3681
Harald Weltea0630032018-03-20 21:09:55 +01003682/* first function inside ConnHdlr component; sets g_pars + starts function */
3683private function f_handler_init(void_fn fn, charstring id, template (omit) TestHdlrParams pars := omit)
3684runs on MSC_ConnHdlr {
3685 if (isvalue(pars)) {
3686 g_pars := valueof(pars);
3687 }
3688 fn.apply(id);
3689}
3690
Oliver Smith26a3db72021-07-09 13:51:29 +02003691private function f_vty_encryption_a5(charstring options) runs on test_CT {
3692 f_vty_transceive(BSCVTY, "configure terminal");
3693 f_vty_transceive(BSCVTY, "network");
3694 f_vty_transceive(BSCVTY, "encryption a5 " & options);
3695 f_vty_transceive(BSCVTY, "exit");
3696 f_vty_transceive(BSCVTY, "exit");
3697}
3698
3699private function f_vty_encryption_a5_reset() runs on test_CT {
3700 /* keep in sync with docker-playground.git ttcn3-bsc-test/osmo-bsc.cfg */
3701 f_vty_encryption_a5("0 1 3");
3702}
3703
Harald Welte3c86ea02018-05-10 22:28:05 +02003704/* Establish signalling channel (non-assignment case) followed by cipher mode */
3705private function f_tc_ciph_mode_a5(charstring id) runs on MSC_ConnHdlr {
Harald Welteed848512018-05-24 22:27:58 +02003706 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
3707 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Harald Welte3c86ea02018-05-10 22:28:05 +02003708 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelTypeSIGNAL);
Philipp Maier23000732018-05-18 11:25:37 +02003709 ass_cmd.pdu.bssmap.assignmentRequest.circuitIdentityCode := omit;
3710 ass_cmd.pdu.bssmap.assignmentRequest.aoIPTransportLayer := omit;
3711 exp_compl.pdu.bssmap.assignmentComplete.circuitIdentityCode := omit;
3712 exp_compl.pdu.bssmap.assignmentComplete.aoIPTransportLayer := omit;
Harald Welte3c86ea02018-05-10 22:28:05 +02003713
Philipp Maier23000732018-05-18 11:25:37 +02003714 f_establish_fully(ass_cmd, exp_compl);
Harald Welte3c86ea02018-05-10 22:28:05 +02003715}
3716testcase TC_ciph_mode_a5_0() runs on test_CT {
3717 var MSC_ConnHdlr vc_conn;
Philipp Maier48604732018-10-09 15:00:37 +02003718 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte3c86ea02018-05-10 22:28:05 +02003719 pars.encr := valueof(t_EncrParams('01'O, f_rnd_octstring(8)));
3720
3721 f_init(1, true);
3722 f_sleep(1.0);
3723 vc_conn := f_start_handler(refers(f_tc_ciph_mode_a5), pars);
3724 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003725 f_shutdown_helper();
Harald Welte3c86ea02018-05-10 22:28:05 +02003726}
3727testcase TC_ciph_mode_a5_1() runs on test_CT {
3728 var MSC_ConnHdlr vc_conn;
Philipp Maier48604732018-10-09 15:00:37 +02003729 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte3c86ea02018-05-10 22:28:05 +02003730 pars.encr := valueof(t_EncrParams('02'O, f_rnd_octstring(8)));
3731
3732 f_init(1, true);
3733 f_sleep(1.0);
3734 vc_conn := f_start_handler(refers(f_tc_ciph_mode_a5), pars);
3735 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003736 f_shutdown_helper();
Harald Welte3c86ea02018-05-10 22:28:05 +02003737}
Oliver Smith50b98122021-07-09 15:00:28 +02003738/* OS#4975: verify that A5/2 is preferred over A5/0 */
3739testcase TC_ciph_mode_a5_2_0() runs on test_CT {
3740 var MSC_ConnHdlr vc_conn;
3741 var TestHdlrParams pars := f_gen_test_hdlr_pars();
3742
3743 pars.encr := valueof(t_EncrParams('05'O, f_rnd_octstring(8))); /* A5/0 and A5/2 (0x01|0x04)*/
3744 pars.encr_exp_enc_alg := '04'O; /* A5/2 */
3745
3746 f_init(1, true);
3747 f_vty_encryption_a5("0 1 2 3");
3748 f_sleep(1.0);
3749 vc_conn := f_start_handler(refers(f_tc_ciph_mode_a5), pars);
3750 vc_conn.done;
3751 f_vty_encryption_a5_reset();
3752 f_shutdown_helper();
3753}
Oliver Smith1dff88d2021-07-09 08:45:51 +02003754/* OS#4975: verify that A5/1 is preferred over A5/2 */
3755testcase TC_ciph_mode_a5_2_1() runs on test_CT {
3756 var MSC_ConnHdlr vc_conn;
3757 var TestHdlrParams pars := f_gen_test_hdlr_pars();
3758
3759 pars.encr := valueof(t_EncrParams('06'O, f_rnd_octstring(8))); /* A5/1 and A5/2 (0x02|0x04)*/
3760 pars.encr_exp_enc_alg := '02'O; /* A5/1 */
3761
3762 f_init(1, true);
3763 f_vty_encryption_a5("1 2");
3764 f_sleep(1.0);
3765 vc_conn := f_start_handler(refers(f_tc_ciph_mode_a5), pars);
3766 vc_conn.done;
3767 f_vty_encryption_a5_reset();
3768 f_shutdown_helper();
3769}
Harald Welte3c86ea02018-05-10 22:28:05 +02003770testcase TC_ciph_mode_a5_3() runs on test_CT {
3771 var MSC_ConnHdlr vc_conn;
Philipp Maier48604732018-10-09 15:00:37 +02003772 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte3c86ea02018-05-10 22:28:05 +02003773 pars.encr := valueof(t_EncrParams('08'O, f_rnd_octstring(8)));
3774
3775 f_init(1, true);
3776 f_sleep(1.0);
3777 vc_conn := f_start_handler(refers(f_tc_ciph_mode_a5), pars);
3778 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003779 f_shutdown_helper();
Harald Welte3c86ea02018-05-10 22:28:05 +02003780}
Neels Hofmeyr81ad27f2021-06-11 00:09:40 +02003781/* Establish a Signalling channel with A5/4 encryption. */
3782testcase TC_ciph_mode_a5_4() runs on test_CT {
3783 var MSC_ConnHdlr vc_conn;
3784 var TestHdlrParams pars := f_gen_test_hdlr_pars();
3785 pars.encr := valueof(t_EncrParams('10'O, f_rnd_octstring(8), f_rnd_octstring(16)));
Harald Welte3c86ea02018-05-10 22:28:05 +02003786
Neels Hofmeyr81ad27f2021-06-11 00:09:40 +02003787 f_init(1, true);
Oliver Smith26a3db72021-07-09 13:51:29 +02003788 f_vty_encryption_a5("0 1 3 4");
Neels Hofmeyr81ad27f2021-06-11 00:09:40 +02003789 f_sleep(1.0);
3790 vc_conn := f_start_handler(refers(f_tc_ciph_mode_a5), pars);
3791 vc_conn.done;
Oliver Smith26a3db72021-07-09 13:51:29 +02003792 f_vty_encryption_a5_reset();
Neels Hofmeyr81ad27f2021-06-11 00:09:40 +02003793 f_shutdown_helper();
3794}
Pau Espin Pedrol07866632020-09-03 19:10:55 +02003795/* establish initial channel, enable ciphering followed by assignment to ciphered channel */
3796private function f_tc_assignment_aoip_tla_v6(charstring id) runs on MSC_ConnHdlr {
3797 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
3798 var PDU_BSSAP ass_cmd := f_gen_ass_req(aoip_tla := "::3");
3799 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
3800 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
3801
3802 f_establish_fully(ass_cmd, exp_compl);
3803}
3804testcase TC_assignment_aoip_tla_v6() runs on test_CT {
3805 var MSC_ConnHdlr vc_conn;
3806 var TestHdlrParams pars := f_gen_test_hdlr_pars();
3807
3808 f_init(1, true);
3809 f_sleep(1.0);
3810 vc_conn := f_start_handler(refers(f_tc_assignment_aoip_tla_v6), pars);
3811 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003812 f_shutdown_helper();
Pau Espin Pedrol07866632020-09-03 19:10:55 +02003813}
3814
Harald Welte3c86ea02018-05-10 22:28:05 +02003815
3816/* establish initial channel, enable ciphering followed by assignment to ciphered channel */
Harald Welte651fcdc2018-05-10 20:23:16 +02003817private function f_tc_assignment_fr_a5(charstring id) runs on MSC_ConnHdlr {
Harald Welteed848512018-05-24 22:27:58 +02003818 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
3819 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Harald Weltec1a2fff2017-12-17 11:06:19 +01003820
Harald Welte552620d2017-12-16 23:21:36 +01003821 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
3822 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
Harald Welte73cd2712017-12-17 00:44:52 +01003823
Harald Weltea0630032018-03-20 21:09:55 +01003824 f_establish_fully(ass_cmd, exp_compl);
Harald Welte552620d2017-12-16 23:21:36 +01003825}
Harald Welte552620d2017-12-16 23:21:36 +01003826testcase TC_assignment_fr_a5_0() runs on test_CT {
3827 var MSC_ConnHdlr vc_conn;
Philipp Maier48604732018-10-09 15:00:37 +02003828 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte651fcdc2018-05-10 20:23:16 +02003829 pars.encr := valueof(t_EncrParams('01'O, f_rnd_octstring(8)));
Harald Welte552620d2017-12-16 23:21:36 +01003830
Harald Welte89d42e82017-12-17 16:42:41 +01003831 f_init(1, true);
Harald Welte552620d2017-12-16 23:21:36 +01003832 f_sleep(1.0);
Harald Welte651fcdc2018-05-10 20:23:16 +02003833 vc_conn := f_start_handler(refers(f_tc_assignment_fr_a5), pars);
Harald Welte552620d2017-12-16 23:21:36 +01003834 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003835 f_shutdown_helper();
Harald Welte552620d2017-12-16 23:21:36 +01003836}
Harald Welte552620d2017-12-16 23:21:36 +01003837testcase TC_assignment_fr_a5_1() runs on test_CT {
Harald Weltec1a2fff2017-12-17 11:06:19 +01003838 var MSC_ConnHdlr vc_conn;
Philipp Maier48604732018-10-09 15:00:37 +02003839 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte651fcdc2018-05-10 20:23:16 +02003840 pars.encr := valueof(t_EncrParams('02'O, f_rnd_octstring(8)));
Harald Weltec1a2fff2017-12-17 11:06:19 +01003841
Harald Welte89d42e82017-12-17 16:42:41 +01003842 f_init(1, true);
Harald Weltec1a2fff2017-12-17 11:06:19 +01003843 f_sleep(1.0);
Harald Welte651fcdc2018-05-10 20:23:16 +02003844 vc_conn := f_start_handler(refers(f_tc_assignment_fr_a5), pars);
3845 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003846 f_shutdown_helper();
Harald Welte651fcdc2018-05-10 20:23:16 +02003847}
3848testcase TC_assignment_fr_a5_3() runs on test_CT {
3849 var MSC_ConnHdlr vc_conn;
Philipp Maier48604732018-10-09 15:00:37 +02003850 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte651fcdc2018-05-10 20:23:16 +02003851 pars.encr := valueof(t_EncrParams('08'O, f_rnd_octstring(8)));
Harald Weltec1a2fff2017-12-17 11:06:19 +01003852
Harald Welte651fcdc2018-05-10 20:23:16 +02003853 f_init(1, true);
3854 f_sleep(1.0);
3855 vc_conn := f_start_handler(refers(f_tc_assignment_fr_a5), pars);
Harald Weltec1a2fff2017-12-17 11:06:19 +01003856 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003857 f_shutdown_helper();
Harald Weltec1a2fff2017-12-17 11:06:19 +01003858}
Neels Hofmeyr0d8ec532021-06-11 00:09:48 +02003859/* Establish a Signalling channel and re-assign to TCH/F with A5/4 encryption. */
3860testcase TC_assignment_fr_a5_4() runs on test_CT {
3861 var MSC_ConnHdlr vc_conn;
3862 var TestHdlrParams pars := f_gen_test_hdlr_pars();
3863 pars.encr := valueof(t_EncrParams('10'O, f_rnd_octstring(8), f_rnd_octstring(16)));
3864
3865 f_init(1, true);
Oliver Smith7eabd312021-07-12 14:18:56 +02003866 f_vty_encryption_a5("0 1 3 4");
Neels Hofmeyr0d8ec532021-06-11 00:09:48 +02003867 f_sleep(1.0);
3868 vc_conn := f_start_handler(refers(f_tc_assignment_fr_a5), pars);
3869 vc_conn.done;
Oliver Smith7eabd312021-07-12 14:18:56 +02003870 f_vty_encryption_a5_reset();
Neels Hofmeyr0d8ec532021-06-11 00:09:48 +02003871 f_shutdown_helper();
3872}
Harald Weltec1a2fff2017-12-17 11:06:19 +01003873
Neels Hofmeyr0faeb7a2021-06-10 23:59:35 +02003874/* Allow only A5/4, but omit the Kc128 IE from MSC's msg. Expect Cipher Mode Reject. */
3875testcase TC_assignment_fr_a5_4_fail() runs on test_CT {
3876 var TestHdlrParams pars := f_gen_test_hdlr_pars();
3877 var MSC_ConnHdlr vc_conn;
3878
3879 f_init(1, true);
3880 f_sleep(1.0);
3881
3882 pars.encr := valueof(t_EncrParams('10'O, f_rnd_octstring(8))); // A5/4 support, but Kc128 missing!
3883 vc_conn := f_start_handler(refers(f_TC_assignment_a5_not_sup), pars);
3884 vc_conn.done;
3885 f_shutdown_helper();
3886}
3887
Harald Welte552620d2017-12-16 23:21:36 +01003888/* Expect ASSIGNMENT FAIL if mandatory IE is missing */
3889private function f_tc_assignment_fr_a5_1_codec_missing(charstring id) runs on MSC_ConnHdlr {
Philipp Maier48604732018-10-09 15:00:37 +02003890 g_pars := f_gen_test_hdlr_pars();
Harald Welte552620d2017-12-16 23:21:36 +01003891 var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
Harald Welteed848512018-05-24 22:27:58 +02003892 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Harald Welte552620d2017-12-16 23:21:36 +01003893
3894 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02003895 /* Omit: ass_cmd.pdu.bssmap.assignmentRequest.codecList */
3896
Harald Weltea0630032018-03-20 21:09:55 +01003897 f_establish_fully(ass_cmd, exp_fail);
Harald Welte552620d2017-12-16 23:21:36 +01003898}
Harald Welte552620d2017-12-16 23:21:36 +01003899testcase TC_assignment_fr_a5_1_codec_missing() runs on test_CT {
3900 var MSC_ConnHdlr vc_conn;
3901
Harald Welte89d42e82017-12-17 16:42:41 +01003902 f_init(1, true);
Harald Welte552620d2017-12-16 23:21:36 +01003903 f_sleep(1.0);
3904
Harald Welte8863fa12018-05-10 20:15:27 +02003905 vc_conn := f_start_handler(refers(f_tc_assignment_fr_a5_1_codec_missing));
Harald Welte552620d2017-12-16 23:21:36 +01003906 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003907 f_shutdown_helper();
Harald Welte552620d2017-12-16 23:21:36 +01003908}
3909
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +02003910private function f_TC_assignment_a5_not_sup(charstring id) runs on MSC_ConnHdlr {
3911 var template PDU_BSSAP exp_ass_cpl := f_gen_exp_compl();
3912 var PDU_BSSAP exp_ass_req := f_gen_ass_req();
Harald Welte552620d2017-12-16 23:21:36 +01003913
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +02003914 exp_ass_req.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
3915 exp_ass_req.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
3916
3917 /* this is like the beginning of f_establish_fully(), but only up to ciphering reject */
3918
3919 var BSSMAP_FIELD_CodecType codecType;
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +02003920
3921 codecType := exp_ass_req.pdu.bssmap.assignmentRequest.codecList.codecElements[0].codecType;
3922 f_MscConnHdlr_init(g_pars.media_nr, host_bts, host_mgw_mgcp, codecType);
3923
3924 f_create_chan_and_exp();
3925 /* we should now have a COMPL_L3 at the MSC */
3926
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +02003927 /* Start ciphering, expect Cipher Mode Reject */
Neels Hofmeyr6c388f22021-06-11 02:36:56 +02003928 f_cipher_mode(g_pars.encr, exp_fail := true);
Harald Welte552620d2017-12-16 23:21:36 +01003929}
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +02003930testcase TC_assignment_fr_a5_not_sup() runs on test_CT {
3931 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte552620d2017-12-16 23:21:36 +01003932 var MSC_ConnHdlr vc_conn;
3933
Harald Welte89d42e82017-12-17 16:42:41 +01003934 f_init(1, true);
Harald Welte552620d2017-12-16 23:21:36 +01003935 f_sleep(1.0);
3936
Neels Hofmeyr0588cad2021-06-11 01:38:18 +02003937 pars.encr := valueof(t_EncrParams('20'O, f_rnd_octstring(8), f_rnd_octstring(16)));
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +02003938 vc_conn := f_start_handler(refers(f_TC_assignment_a5_not_sup), pars);
Harald Welte552620d2017-12-16 23:21:36 +01003939 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003940 f_shutdown_helper();
Harald Welte552620d2017-12-16 23:21:36 +01003941}
3942
3943
Harald Welte4532e0a2017-12-23 02:05:44 +01003944private function f_tc_assignment_sign(charstring id) runs on MSC_ConnHdlr {
Philipp Maier48604732018-10-09 15:00:37 +02003945 g_pars := f_gen_test_hdlr_pars();
Harald Welte4532e0a2017-12-23 02:05:44 +01003946 var template PDU_BSSAP exp_compl := tr_BSSMAP_AssignmentComplete(omit, omit);
Philipp Maier48604732018-10-09 15:00:37 +02003947 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Harald Welte4532e0a2017-12-23 02:05:44 +01003948 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelTypeSIGNAL);
Daniel Willmannebdecc02020-08-12 15:30:17 +02003949
3950 f_statsd_reset();
Harald Weltea0630032018-03-20 21:09:55 +01003951 f_establish_fully(ass_cmd, exp_compl);
Daniel Willmannebdecc02020-08-12 15:30:17 +02003952
3953 var StatsDExpects expect := {
Daniel Willmannc5398f72020-09-21 10:41:35 +02003954 { name := "TTCN3.bts.0.chreq.total", mtype := "c", min := 1, max := 1},
3955 { name := "TTCN3.bts.0.chreq.successful", mtype := "c", min := 1, max := 1},
Daniel Willmannebdecc02020-08-12 15:30:17 +02003956 { name := "TTCN3.bsc.0.assignment.attempted", mtype := "c", min := 1, max := 1},
3957 { name := "TTCN3.bsc.0.assignment.completed", mtype := "c", min := 1, max := 1}
3958 };
3959 f_statsd_expect(expect);
Harald Welte4532e0a2017-12-23 02:05:44 +01003960}
3961
3962testcase TC_assignment_sign() runs on test_CT {
3963 var MSC_ConnHdlr vc_conn;
3964
3965 f_init(1, true);
3966 f_sleep(1.0);
3967
Harald Welte8863fa12018-05-10 20:15:27 +02003968 vc_conn := f_start_handler(refers(f_tc_assignment_sign));
Harald Welte4532e0a2017-12-23 02:05:44 +01003969 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003970 f_shutdown_helper();
Harald Welte4532e0a2017-12-23 02:05:44 +01003971}
3972
Harald Welte60aa5762018-03-21 19:33:13 +01003973/***********************************************************************
3974 * Codec (list) testing
3975 ***********************************************************************/
3976
3977/* check if the given rsl_mode is compatible with the a_elem */
3978private function f_match_codec(BSSMAP_FIELD_CodecElement a_elem, RSL_IE_ChannelMode rsl_mode)
3979return boolean {
3980 select (a_elem.codecType) {
3981 case (GSM_FR) {
3982 if (match(rsl_mode, tr_RSL_ChanMode(RSL_CHRT_TCH_F, RSL_CMOD_SP_GSM1))) {
3983 return true;
3984 }
3985 }
3986 case (GSM_HR) {
3987 if (match(rsl_mode, tr_RSL_ChanMode(RSL_CHRT_TCH_H, RSL_CMOD_SP_GSM1))) {
3988 return true;
3989 }
3990 }
3991 case (GSM_EFR) {
3992 if (match(rsl_mode, tr_RSL_ChanMode(RSL_CHRT_TCH_F, RSL_CMOD_SP_GSM2))) {
3993 return true;
3994 }
3995 }
3996 case (FR_AMR) {
3997 if (match(rsl_mode, tr_RSL_ChanMode(RSL_CHRT_TCH_F, RSL_CMOD_SP_GSM3))) {
3998 return true;
3999 }
4000 }
4001 case (HR_AMR) {
4002 if (match(rsl_mode, tr_RSL_ChanMode(RSL_CHRT_TCH_H, RSL_CMOD_SP_GSM3))) {
4003 return true;
4004 }
4005 }
4006 case else { }
4007 }
4008 return false;
4009}
4010
4011/* check if the given rsl_mode is compatible with the a_list */
4012private function f_match_codecs(BSSMAP_IE_SpeechCodecList a_list, RSL_IE_ChannelMode rsl_mode)
4013return boolean {
4014 for (var integer i := 0; i < sizeof(a_list); i := i+1) {
4015 if (f_match_codec(a_list.codecElements[i], rsl_mode)) {
4016 return true;
4017 }
4018 }
4019 return false;
4020}
4021
4022/* determine BSSMAP_IE_ChannelType from *first* element of BSSMAP_FIELD_CodecElement */
Philipp Maier61f6b572018-07-06 14:03:38 +02004023function f_BSSMAP_chtype_from_codec(BSSMAP_FIELD_CodecElement a_elem)
Harald Welte60aa5762018-03-21 19:33:13 +01004024return BSSMAP_IE_ChannelType {
4025 /* FIXME: actually look at all elements of BSSMAP_IE_SpeechCodecList */
4026 var BSSMAP_IE_ChannelType ret := valueof(ts_BSSMAP_IE_ChannelType);
4027 select (a_elem.codecType) {
4028 case (GSM_FR) {
4029 ret.channelRateAndType := ChRate_TCHF;
4030 ret.speechId_DataIndicator := Spdi_TCHF_FR;
4031 }
4032 case (GSM_HR) {
4033 ret.channelRateAndType := ChRate_TCHH;
4034 ret.speechId_DataIndicator := Spdi_TCHH_HR;
4035 }
4036 case (GSM_EFR) {
4037 ret.channelRateAndType := ChRate_TCHF;
4038 ret.speechId_DataIndicator := Spdi_TCHF_EFR;
4039 }
4040 case (FR_AMR) {
4041 ret.channelRateAndType := ChRate_TCHF;
4042 ret.speechId_DataIndicator := Spdi_TCHF_AMR;
4043 }
4044 case (HR_AMR) {
4045 ret.channelRateAndType := ChRate_TCHH;
4046 ret.speechId_DataIndicator := Spdi_TCHH_AMR;
4047 }
4048 case else {
4049 setverdict(fail, "Unsupported codec ", a_elem);
Daniel Willmannafce8662018-07-06 23:11:32 +02004050 mtc.stop;
Harald Welte60aa5762018-03-21 19:33:13 +01004051 }
4052 }
4053 return ret;
4054}
4055
Harald Weltea63b9102018-03-22 20:36:16 +01004056private function f_rsl_chmod_tmpl_from_codec(BSSMAP_FIELD_CodecElement a_elem)
4057return template RSL_IE_Body {
4058 var template RSL_IE_Body mode_ie := {
4059 chan_mode := {
4060 len := ?,
4061 reserved := ?,
4062 dtx_d := ?,
4063 dtx_u := ?,
4064 spd_ind := RSL_SPDI_SPEECH,
4065 ch_rate_type := -,
4066 coding_alg_rate := -
4067 }
4068 }
4069
4070 select (a_elem.codecType) {
4071 case (GSM_FR) {
4072 mode_ie.chan_mode.ch_rate_type := RSL_CHRT_TCH_F;
4073 mode_ie.chan_mode.coding_alg_rate := RSL_CMOD_SP_GSM1;
4074 }
4075 case (GSM_HR) {
4076 mode_ie.chan_mode.ch_rate_type := RSL_CHRT_TCH_H;
4077 mode_ie.chan_mode.coding_alg_rate := RSL_CMOD_SP_GSM1;
4078 }
4079 case (GSM_EFR) {
4080 mode_ie.chan_mode.ch_rate_type := RSL_CHRT_TCH_F;
4081 mode_ie.chan_mode.coding_alg_rate := RSL_CMOD_SP_GSM2;
4082 }
4083 case (FR_AMR) {
4084 mode_ie.chan_mode.ch_rate_type := RSL_CHRT_TCH_F;
4085 mode_ie.chan_mode.coding_alg_rate := RSL_CMOD_SP_GSM3;
4086 }
4087 case (HR_AMR) {
4088 mode_ie.chan_mode.ch_rate_type := RSL_CHRT_TCH_H;
4089 mode_ie.chan_mode.coding_alg_rate := RSL_CMOD_SP_GSM3;
4090 }
4091 }
4092 return mode_ie;
4093}
4094
Harald Welte60aa5762018-03-21 19:33:13 +01004095type record CodecListTest {
4096 BSSMAP_IE_SpeechCodecList codec_list,
4097 charstring id
4098}
4099type record of CodecListTest CodecListTests
4100
4101private function f_TC_assignment_codec(charstring id) runs on MSC_ConnHdlr {
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02004102 var PDU_BSSAP ass_cmd := f_gen_ass_req(g_pars.use_osmux);
4103 var template PDU_BSSAP exp_compl := f_gen_exp_compl(g_pars.use_osmux);
Harald Welte60aa5762018-03-21 19:33:13 +01004104
4105 /* puzzle together the ASSIGNMENT REQ for given codec[s] */
Neels Hofmeyrf246a922020-05-13 02:27:10 +02004106 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
Harald Welte79f3f542018-05-25 20:02:37 +02004107 ass_cmd.pdu.bssmap.assignmentRequest.codecList := g_pars.ass_codec_list;
4108 exp_compl.pdu.bssmap.assignmentComplete.speechCodec.codecElements[0] :=
4109 g_pars.ass_codec_list.codecElements[0];
Philipp Maierd0e64b02019-03-13 14:15:23 +01004110 if (isvalue(g_pars.expect_mr_s0_s7)) {
4111 exp_compl.pdu.bssmap.assignmentComplete.speechCodec.codecElements[0].s0_7 :=
4112 g_pars.expect_mr_s0_s7;
4113 }
Harald Welte79f3f542018-05-25 20:02:37 +02004114 }
Harald Welte60aa5762018-03-21 19:33:13 +01004115 ass_cmd.pdu.bssmap.assignmentRequest.channelType :=
4116 f_BSSMAP_chtype_from_codec(g_pars.ass_codec_list.codecElements[0]);
Harald Welte60aa5762018-03-21 19:33:13 +01004117 log("expecting ASS COMPL like this: ", exp_compl);
4118
4119 f_establish_fully(ass_cmd, exp_compl);
Harald Weltea63b9102018-03-22 20:36:16 +01004120
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004121 if (not g_pars.expect_channel_mode_modify) {
4122 /* Verify that the RSL-side activation actually matches our expectations */
4123 var RSL_Message rsl := f_rslem_get_last_act(RSL_PROC, 0, g_chan_nr);
Harald Weltea63b9102018-03-22 20:36:16 +01004124
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004125 var RSL_IE_Body mode_ie;
4126 if (f_rsl_find_ie(rsl, RSL_IE_CHAN_MODE, mode_ie) == false) {
4127 setverdict(fail, "Couldn't find CHAN_MODE IE");
Daniel Willmannafce8662018-07-06 23:11:32 +02004128 mtc.stop;
Neels Hofmeyrbcf62bc2018-07-04 00:24:33 +02004129 }
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004130 var template RSL_IE_Body t_mode_ie := f_rsl_chmod_tmpl_from_codec(g_pars.ass_codec_list.codecElements[0]);
4131 if (not match(mode_ie, t_mode_ie)) {
4132 log("mode_ie ", mode_ie, " != t_mode_ie ", t_mode_ie);
4133 setverdict(fail, "RSL Channel Mode IE doesn't match expectation");
Neels Hofmeyrbcf62bc2018-07-04 00:24:33 +02004134 }
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004135
4136 var RSL_IE_Body mr_conf;
4137 if (g_pars.expect_mr_conf_ie != omit) {
4138 if (f_rsl_find_ie(rsl, RSL_IE_MR_CONFIG, mr_conf) == false) {
4139 setverdict(fail, "Missing MR CONFIG IE in RSL Chan Activ");
4140 mtc.stop;
4141 }
Neels Hofmeyrbcf62bc2018-07-04 00:24:33 +02004142 log("found RSL MR CONFIG IE: ", mr_conf);
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004143
4144 if (not match(mr_conf, g_pars.expect_mr_conf_ie)) {
4145 setverdict(fail, "RSL MR CONFIG IE does not match expectation. Expected: ",
4146 g_pars.expect_mr_conf_ie);
4147 }
4148 } else {
4149 if (f_rsl_find_ie(rsl, RSL_IE_MR_CONFIG, mr_conf) == true) {
4150 log("found RSL MR CONFIG IE: ", mr_conf);
4151 setverdict(fail, "Found MR CONFIG IE in RSL Chan Activ, expecting omit");
4152 mtc.stop;
4153 }
Neels Hofmeyrbcf62bc2018-07-04 00:24:33 +02004154 }
4155 }
Harald Welte60aa5762018-03-21 19:33:13 +01004156}
4157
Philipp Maierd0e64b02019-03-13 14:15:23 +01004158private function f_TC_assignment_codec_fail(charstring id) runs on MSC_ConnHdlr {
4159
4160 var PDU_BSSAP ass_cmd := f_gen_ass_req();
4161 var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
4162
4163 /* puzzle together the ASSIGNMENT REQ for given codec[s] */
Neels Hofmeyrf246a922020-05-13 02:27:10 +02004164 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
Philipp Maierd0e64b02019-03-13 14:15:23 +01004165 ass_cmd.pdu.bssmap.assignmentRequest.codecList := g_pars.ass_codec_list;
4166 }
4167 ass_cmd.pdu.bssmap.assignmentRequest.channelType :=
4168 f_BSSMAP_chtype_from_codec(g_pars.ass_codec_list.codecElements[0]);
4169 log("expecting ASS FAIL like this: ", exp_fail);
4170
4171 f_establish_fully(ass_cmd, exp_fail);
4172}
4173
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004174const CounterNameVals counternames_bsc_bts_assignment := {
4175 { "assignment:attempted", 0 },
4176 { "assignment:completed", 0 },
4177 { "assignment:stopped", 0 },
4178 { "assignment:no_channel", 0 },
4179 { "assignment:timeout", 0 },
4180 { "assignment:failed", 0 },
4181 { "assignment:error", 0 }
4182};
4183
4184const CounterNameVals counternames_bts_assignment := {
4185 { "assignment:attempted_sign", 0 },
4186 { "assignment:attempted_speech", 0 },
4187 { "assignment:completed_sign", 0 },
4188 { "assignment:completed_speech", 0 },
4189 { "assignment:stopped_sign", 0 },
4190 { "assignment:stopped_speech", 0 },
4191 { "assignment:no_channel_sign", 0 },
4192 { "assignment:no_channel_speech", 0 },
4193 { "assignment:timeout_sign", 0 },
4194 { "assignment:timeout_speech", 0 },
4195 { "assignment:failed_sign", 0 },
4196 { "assignment:failed_speech", 0 },
4197 { "assignment:error_sign", 0 },
4198 { "assignment:error_speech", 0 }
4199};
4200
4201function f_ctrs_bsc_and_bts_assignment_init(integer bts_count := NUM_BTS) runs on test_CT {
4202 var CounterNameVals bts_names := counternames_bsc_bts_assignment & counternames_bts_assignment;
4203 f_ctrs_bts_init(bts_count, bts_names);
4204 f_ctrs_bsc_init(counternames_bsc_bts_assignment);
4205}
4206
Harald Welte60aa5762018-03-21 19:33:13 +01004207testcase TC_assignment_codec_fr() runs on test_CT {
Philipp Maier48604732018-10-09 15:00:37 +02004208 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte60aa5762018-03-21 19:33:13 +01004209 var MSC_ConnHdlr vc_conn;
4210
4211 f_init(1, true);
4212 f_sleep(1.0);
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004213 f_ctrs_bsc_and_bts_assignment_init(1);
Harald Welte60aa5762018-03-21 19:33:13 +01004214
4215 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
Harald Welte8863fa12018-05-10 20:15:27 +02004216 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
Harald Welte60aa5762018-03-21 19:33:13 +01004217 vc_conn.done;
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004218
4219 f_ctrs_bsc_and_bts_add(0, "assignment:attempted", 1);
4220 f_ctrs_bts_add(0, "assignment:attempted_speech", 1);
4221 f_ctrs_bsc_and_bts_add(0, "assignment:completed", 1);
4222 f_ctrs_bts_add(0, "assignment:completed_speech", 1);
4223 f_ctrs_bts_verify();
4224
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004225 f_shutdown_helper();
Harald Welte60aa5762018-03-21 19:33:13 +01004226}
4227
4228testcase TC_assignment_codec_hr() runs on test_CT {
Philipp Maier48604732018-10-09 15:00:37 +02004229 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte60aa5762018-03-21 19:33:13 +01004230 var MSC_ConnHdlr vc_conn;
4231
4232 f_init(1, true);
4233 f_sleep(1.0);
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004234 f_ctrs_bsc_and_bts_assignment_init(1);
Harald Welte60aa5762018-03-21 19:33:13 +01004235
4236 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR}));
Harald Welte8863fa12018-05-10 20:15:27 +02004237 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
Harald Welte60aa5762018-03-21 19:33:13 +01004238 vc_conn.done;
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004239
4240 f_ctrs_bsc_and_bts_add(0, "assignment:attempted", 1);
4241 f_ctrs_bts_add(0, "assignment:attempted_speech", 1);
4242 f_ctrs_bsc_and_bts_add(0, "assignment:completed", 1);
4243 f_ctrs_bts_add(0, "assignment:completed_speech", 1);
4244 f_ctrs_bts_verify();
4245
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004246 f_shutdown_helper();
Harald Welte60aa5762018-03-21 19:33:13 +01004247}
4248
4249testcase TC_assignment_codec_efr() runs on test_CT {
Philipp Maier48604732018-10-09 15:00:37 +02004250 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte60aa5762018-03-21 19:33:13 +01004251 var MSC_ConnHdlr vc_conn;
4252
4253 f_init(1, true);
4254 f_sleep(1.0);
4255
4256 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecEFR}));
Harald Welte8863fa12018-05-10 20:15:27 +02004257 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
Harald Welte60aa5762018-03-21 19:33:13 +01004258 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004259 f_shutdown_helper();
Harald Welte60aa5762018-03-21 19:33:13 +01004260}
4261
Philipp Maierd0e64b02019-03-13 14:15:23 +01004262/* Allow 5,90k only (current default config) */
4263private function f_allow_amr_rate_5_90k() runs on test_CT {
Neels Hofmeyr2a5670b2020-11-25 23:39:57 +00004264 f_vty_cfg_msc(BSCVTY, 0, {
4265 "amr-config 12_2k forbidden",
4266 "amr-config 10_2k forbidden",
4267 "amr-config 7_95k forbidden",
4268 "amr-config 7_40k forbidden",
4269 "amr-config 6_70k forbidden",
4270 "amr-config 5_90k allowed",
4271 "amr-config 5_15k forbidden",
4272 "amr-config 4_75k forbidden"
4273 });
Philipp Maierd0e64b02019-03-13 14:15:23 +01004274}
4275
4276/* Allow 4,75k, 5,90k, 4,70k and 12,2k, which are the most common rates
4277 * ("Config-NB-Code = 1") */
4278private function f_allow_amr_rate_4_75k_5_90k_7_40k_12_20k() runs on test_CT {
Neels Hofmeyr2a5670b2020-11-25 23:39:57 +00004279 f_vty_cfg_msc(BSCVTY, 0, {
4280 "amr-config 12_2k allowed",
4281 "amr-config 10_2k forbidden",
4282 "amr-config 7_95k forbidden",
4283 "amr-config 7_40k allowed",
4284 "amr-config 6_70k forbidden",
4285 "amr-config 5_90k allowed",
4286 "amr-config 5_15k forbidden",
4287 "amr-config 4_75k allowed"
4288 });
Philipp Maierd0e64b02019-03-13 14:15:23 +01004289}
4290
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004291private function f_vty_amr_start_mode_set(boolean fr, charstring startmode) runs on test_CT {
4292 var charstring tch;
4293 if (fr) {
4294 tch := "tch-f";
4295 } else {
4296 tch := "tch-h";
4297 }
4298 f_vty_cfg_bts(BSCVTY, 0, { "amr " & tch & " start-mode " & startmode });
4299}
4300
4301/* Set the AMR start-mode for this TCH back to the default configuration. */
4302private function f_vty_amr_start_mode_restore(boolean fr) runs on test_CT {
4303 f_vty_amr_start_mode_set(fr, "auto");
4304}
4305
Harald Welte60aa5762018-03-21 19:33:13 +01004306testcase TC_assignment_codec_amr_f() runs on test_CT {
Philipp Maier48604732018-10-09 15:00:37 +02004307 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte60aa5762018-03-21 19:33:13 +01004308 var MSC_ConnHdlr vc_conn;
Philipp Maier7695a0d2018-09-27 17:52:14 +02004309
4310 /* Note: This setups the codec configuration. The parameter payload in
4311 * mr_conf must be consistant with the parameter codecElements in pars
4312 * and also must match the amr-config in osmo-bsc.cfg! */
Neels Hofmeyrbcf62bc2018-07-04 00:24:33 +02004313 var RSL_IE_Body mr_conf := {
4314 other := {
4315 len := 2,
4316 payload := '2804'O
4317 }
4318 };
Harald Welte60aa5762018-03-21 19:33:13 +01004319
Philipp Maier7695a0d2018-09-27 17:52:14 +02004320 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_F}));
Philipp Maier806f8f12019-03-12 12:13:41 +01004321 pars.ass_codec_list.codecElements[0].s0_7 := '00000100'B; /* 5,90k */
Philipp Maier7695a0d2018-09-27 17:52:14 +02004322 pars.ass_codec_list.codecElements[0].s8_15 := '01010111'B;
4323 pars.expect_mr_conf_ie := mr_conf;
4324
Harald Welte60aa5762018-03-21 19:33:13 +01004325 f_init(1, true);
4326 f_sleep(1.0);
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004327 f_vty_amr_start_mode_set(true, "1");
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004328 f_ctrs_bsc_and_bts_assignment_init(1);
Harald Welte60aa5762018-03-21 19:33:13 +01004329
Harald Welte8863fa12018-05-10 20:15:27 +02004330 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
Harald Welte60aa5762018-03-21 19:33:13 +01004331 vc_conn.done;
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004332
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004333 f_ctrs_bsc_and_bts_add(0, "assignment:attempted", 1);
4334 f_ctrs_bts_add(0, "assignment:attempted_speech", 1);
4335 f_ctrs_bsc_and_bts_add(0, "assignment:completed", 1);
4336 f_ctrs_bts_add(0, "assignment:completed_speech", 1);
4337 f_ctrs_bts_verify();
4338
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004339 f_vty_amr_start_mode_restore(true);
Vadim Yanitskiy292e5962021-01-03 14:18:47 +01004340 f_shutdown_helper();
Harald Welte60aa5762018-03-21 19:33:13 +01004341}
4342
4343testcase TC_assignment_codec_amr_h() runs on test_CT {
Philipp Maier48604732018-10-09 15:00:37 +02004344 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte60aa5762018-03-21 19:33:13 +01004345 var MSC_ConnHdlr vc_conn;
Philipp Maier7695a0d2018-09-27 17:52:14 +02004346
4347 /* See note above */
Neels Hofmeyrbcf62bc2018-07-04 00:24:33 +02004348 var RSL_IE_Body mr_conf := {
4349 other := {
4350 len := 2,
4351 payload := '2804'O
4352 }
4353 };
Harald Welte60aa5762018-03-21 19:33:13 +01004354
Philipp Maier7695a0d2018-09-27 17:52:14 +02004355 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_H}));
Philipp Maier806f8f12019-03-12 12:13:41 +01004356 pars.ass_codec_list.codecElements[0].s0_7 := '00000100'B; /* 5,90k */
Philipp Maier7695a0d2018-09-27 17:52:14 +02004357 pars.ass_codec_list.codecElements[0].s8_15 := '00000111'B;
4358 pars.expect_mr_conf_ie := mr_conf;
4359
Harald Welte60aa5762018-03-21 19:33:13 +01004360 f_init(1, true);
4361 f_sleep(1.0);
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004362 f_vty_amr_start_mode_set(false, "1");
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004363 f_ctrs_bsc_and_bts_assignment_init(1);
Harald Welte60aa5762018-03-21 19:33:13 +01004364
Harald Welte8863fa12018-05-10 20:15:27 +02004365 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
Harald Welte60aa5762018-03-21 19:33:13 +01004366 vc_conn.done;
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004367
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004368 f_ctrs_bsc_and_bts_add(0, "assignment:attempted", 1);
4369 f_ctrs_bts_add(0, "assignment:attempted_speech", 1);
4370 f_ctrs_bsc_and_bts_add(0, "assignment:completed", 1);
4371 f_ctrs_bts_add(0, "assignment:completed_speech", 1);
4372 f_ctrs_bts_verify();
4373
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004374 f_vty_amr_start_mode_restore(false);
Vadim Yanitskiy292e5962021-01-03 14:18:47 +01004375 f_shutdown_helper();
Harald Welte60aa5762018-03-21 19:33:13 +01004376}
4377
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004378/* Establish signalling on a TCH/F lchan, and then switch to speech mode without a new Assignment. */
4379testcase TC_assignment_codec_fr_by_mode_modify() runs on test_CT {
4380 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4381 var MSC_ConnHdlr vc_conn;
4382
4383 f_init(1, true);
4384 f_sleep(1.0);
4385
4386 /* By disabling all SDCCH, the MS should be given a TCH/F for signalling. Then activating an FR codec should
4387 * merely do a Channel Mode Modify, and not assign to a new lchan. f_establish_fully() already accounts for
4388 * expecting a Channel Mode Modify if the channel type is compatible. */
4389 f_disable_all_sdcch();
4390 f_disable_all_tch_h();
4391
4392 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
4393 pars.expect_channel_mode_modify := true;
4394 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
4395 vc_conn.done;
4396
4397 f_enable_all_sdcch();
4398 f_enable_all_tch();
4399 f_shutdown_helper();
4400}
4401
Neels Hofmeyr454d7922020-11-26 02:24:57 +00004402/* 'amr start-mode auto' should not keep the (unused) 'smod' bits from previous configuration */
4403testcase TC_assignment_codec_amr_startmode_cruft() runs on test_CT {
4404 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4405 var MSC_ConnHdlr vc_conn;
4406
4407 var RSL_IE_Body mr_conf := {
4408 other := {
4409 len := 2,
4410 payload := '2004'O /* <- expect ICMI=0, smod=00 */
4411 }
4412 };
4413
4414 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_F}));
4415 pars.ass_codec_list.codecElements[0].s0_7 := '00000100'B; /* 5,90k */
4416 pars.ass_codec_list.codecElements[0].s8_15 := '01010111'B;
4417 pars.expect_mr_conf_ie := mr_conf;
4418
4419 f_init(1, true);
4420 f_sleep(1.0);
4421
4422 /* First set nonzero start mode bits */
4423 f_vty_amr_start_mode_set(true, "4");
4424 /* Now set to auto, and expect the startmode bits to be zero in the message, i.e. ensure that osmo-bsc does not
4425 * let the startmode bits stick around and has deterministic MultiRate config for 'start-mode auto'; that is
4426 * ensured by above '2004'O, where 'x0xx'O indicates ICMI = 0, spare = 0, smod = 00. */
4427 f_vty_amr_start_mode_set(true, "auto");
4428
4429 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
4430 vc_conn.done;
Neels Hofmeyr454d7922020-11-26 02:24:57 +00004431
4432 /* Clear the startmode bits to not affect subsequent tests, in case the bits should indeed stick around. */
4433 f_vty_amr_start_mode_set(true, "1");
4434 f_vty_amr_start_mode_restore(true);
Vadim Yanitskiy292e5962021-01-03 14:18:47 +01004435 f_shutdown_helper();
Neels Hofmeyr454d7922020-11-26 02:24:57 +00004436}
4437
Neels Hofmeyr21863562020-11-26 00:34:33 +00004438function f_TC_assignment_codec_amr(boolean fr, octetstring mrconf, bitstring s8_s0, bitstring exp_s8_s0,
4439 charstring start_mode := "1")
Philipp Maierd0e64b02019-03-13 14:15:23 +01004440runs on test_CT {
4441
4442 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4443 var MSC_ConnHdlr vc_conn;
4444
4445 /* See note above */
4446 var RSL_IE_Body mr_conf := {
4447 other := {
4448 len := lengthof(mrconf),
4449 payload := mrconf
4450 }
4451 };
4452
4453 if (fr) {
4454 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_F}));
4455 } else {
4456 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_H}));
4457 }
4458 pars.ass_codec_list.codecElements[0].s0_7 := s8_s0;
4459 pars.ass_codec_list.codecElements[0].s8_15 := '00000111'B;
4460 pars.expect_mr_conf_ie := mr_conf;
4461 pars.expect_mr_s0_s7 := exp_s8_s0;
4462
4463 f_init(1, true);
4464 f_allow_amr_rate_4_75k_5_90k_7_40k_12_20k();
Neels Hofmeyr21863562020-11-26 00:34:33 +00004465 f_vty_amr_start_mode_set(fr, start_mode);
Philipp Maierd0e64b02019-03-13 14:15:23 +01004466 f_sleep(1.0);
4467
4468 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
4469 vc_conn.done;
4470 f_allow_amr_rate_5_90k();
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004471 f_vty_amr_start_mode_restore(fr);
Philipp Maierd0e64b02019-03-13 14:15:23 +01004472}
4473
4474function f_TC_assignment_codec_amr_fail(boolean fr, bitstring s8_s0)
4475runs on test_CT {
4476
4477 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4478 var MSC_ConnHdlr vc_conn;
4479
4480 if (fr) {
4481 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_F}));
4482 } else {
4483 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_H}));
4484 }
4485 pars.ass_codec_list.codecElements[0].s0_7 := s8_s0;
4486 pars.ass_codec_list.codecElements[0].s8_15 := '00000111'B;
4487
4488 f_init(1, true);
4489 f_allow_amr_rate_4_75k_5_90k_7_40k_12_20k();
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004490 f_vty_amr_start_mode_set(fr, "1");
Philipp Maierd0e64b02019-03-13 14:15:23 +01004491 f_sleep(1.0);
4492
4493 vc_conn := f_start_handler(refers(f_TC_assignment_codec_fail), pars);
4494 vc_conn.done;
4495 f_allow_amr_rate_5_90k();
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004496 f_vty_amr_start_mode_restore(fr);
Philipp Maierd0e64b02019-03-13 14:15:23 +01004497}
4498
4499
4500/* Set S1, we expect an AMR multirate configuration IE with all four rates
4501 * set. */
4502testcase TC_assignment_codec_amr_f_S1() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004503 f_TC_assignment_codec_amr(true, '289520882208'O, '00000010'B, '00000010'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004504 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004505}
4506
4507/* Set S1, we expect an AMR multirate configuration IE with the lower three
4508 * rates set. */
4509testcase TC_assignment_codec_amr_h_S1() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004510 f_TC_assignment_codec_amr(false, '2815208820'O, '00000010'B, '00000010'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004511 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004512}
4513
4514/* Set S1 and two other rates, we expect an AMR MULTIRATE CONFIGURATION IE with
4515 * all four rates (and only S1 set in the ASSIGNMENT COMPLETE) */
4516testcase TC_assignment_codec_amr_f_S124() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004517 f_TC_assignment_codec_amr(true, '289520882208'O, '00010110'B, '00000010'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004518 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004519}
4520
4521/* Set S1 and two other rates, we expect an AMR MULTIRATE CONFIGURATION IE with
4522 * all four rates (and only S1 set in the ASSIGNMENT COMPLETE) */
4523testcase TC_assignment_codec_amr_h_S124() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004524 f_TC_assignment_codec_amr(false, '2815208820'O, '00010110'B, '00000010'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004525 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004526}
4527
4528/* The following block of tests selects more and more rates until all four
4529 * possible rates are in the active set (full rate) */
4530testcase TC_assignment_codec_amr_f_S0() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004531 f_TC_assignment_codec_amr(true, '2801'O, '00000001'B, '00000001'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004532 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004533}
4534
4535testcase TC_assignment_codec_amr_f_S02() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004536 f_TC_assignment_codec_amr(true, '28052080'O, '00000101'B, '00000101'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004537 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004538}
4539
4540testcase TC_assignment_codec_amr_f_S024() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004541 f_TC_assignment_codec_amr(true, '2815208820'O, '00010101'B, '00010101'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004542 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004543}
4544
4545testcase TC_assignment_codec_amr_f_S0247() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004546 f_TC_assignment_codec_amr(true, '289520882208'O, '10010101'B, '10010101'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004547 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004548}
4549
4550/* The following block of tests selects more and more rates until all three
4551 * possible rates are in the active set (half rate) */
4552testcase TC_assignment_codec_amr_h_S0() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004553 f_TC_assignment_codec_amr(false, '2801'O, '00000001'B, '00000001'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004554 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004555}
4556
4557testcase TC_assignment_codec_amr_h_S02() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004558 f_TC_assignment_codec_amr(false, '28052080'O, '00000101'B, '00000101'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004559 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004560}
4561
4562testcase TC_assignment_codec_amr_h_S024() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004563 f_TC_assignment_codec_amr(false, '2815208820'O, '00010101'B, '00010101'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004564 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004565}
4566
4567/* The following block tests what happens when the MSC does offer rate
4568 * configurations that are not supported by the BSC. Normally such situations
4569 * should not happen because the MSC gets informed by the BSC in advance via
4570 * the L3 COMPLETE message which rates are applicable. The MSC should not try
4571 * to offer rates that are not applicable anyway. */
4572
4573testcase TC_assignment_codec_amr_h_S0247() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004574 /* Try to include 12,2k in into the active set even though the channel
4575 * is half rate only. The BSC is expected to remove the 12,0k */
4576 f_TC_assignment_codec_amr(false, '2815208820'O, '10010101'B, '00010101'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004577 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004578}
4579
4580testcase TC_assignment_codec_amr_f_S01234567() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004581 /* See what happens when all rates are selected at once. Since then
4582 * Also S1 is selected, this setting will be prefered and we should
4583 * get 12.2k, 7,40k, 5,90k, and 4,75k in the active set. */
4584 f_TC_assignment_codec_amr(true, '289520882208'O, '11111111'B, '00000010'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004585 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004586}
4587
4588testcase TC_assignment_codec_amr_f_S0234567() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004589 /* Same as above, but with S1 missing, the MSC is then expected to
4590 * select the currently supported rates, which are also 12.2k, 7,40k,
4591 * 5,90k, and 4,75k, into the active set. */
4592 f_TC_assignment_codec_amr(true, '289520882208'O, '11111101'B, '10010101'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_zero() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004597 /* Try to select no rates at all */
4598 f_TC_assignment_codec_amr_fail(true, '00000000'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004599 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004600}
4601
4602testcase TC_assignment_codec_amr_f_unsupp() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004603 /* Try to select only unsupported rates */
4604 f_TC_assignment_codec_amr_fail(true, '01101000'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_S7() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004609 /* Try to select 12,2k for half rate */
4610 f_TC_assignment_codec_amr_fail(false, '10000000'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004611 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004612}
4613
Neels Hofmeyr21863562020-11-26 00:34:33 +00004614testcase TC_assignment_codec_amr_f_start_mode_auto() runs on test_CT {
4615 f_TC_assignment_codec_amr(true, '209520882208'O, '11111111'B, '00000010'B,
4616 start_mode := "auto");
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +01004617 f_shutdown_helper();
Neels Hofmeyr21863562020-11-26 00:34:33 +00004618}
4619
4620testcase TC_assignment_codec_amr_h_start_mode_auto() runs on test_CT {
4621 f_TC_assignment_codec_amr(false, '2015208820'O, '10010101'B, '00010101'B,
4622 start_mode := "auto");
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +01004623 f_shutdown_helper();
Neels Hofmeyr21863562020-11-26 00:34:33 +00004624}
4625
Neels Hofmeyr3eb94562020-11-26 02:40:26 +00004626testcase TC_assignment_codec_amr_f_start_mode_4() runs on test_CT {
Vadim Yanitskiy7815f482021-01-03 17:07:37 +01004627 /* "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 +00004628 f_TC_assignment_codec_amr(true, '2b9520882208'O, '11111111'B, '00000010'B,
4629 start_mode := "4");
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +01004630 f_shutdown_helper();
Neels Hofmeyr3eb94562020-11-26 02:40:26 +00004631}
4632
4633testcase TC_assignment_codec_amr_h_start_mode_4() runs on test_CT {
Vadim Yanitskiy7815f482021-01-03 17:07:37 +01004634 /* "amr tch-h modes 0 2 4" => total 3 modes and start mode 4 => '10'B on the wire */
4635 f_TC_assignment_codec_amr(false, '2a15208820'O, '10010101'B, '00010101'B,
Neels Hofmeyr3eb94562020-11-26 02:40:26 +00004636 start_mode := "4");
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +01004637 f_shutdown_helper();
Neels Hofmeyr3eb94562020-11-26 02:40:26 +00004638}
4639
Philipp Maierac09bfc2019-01-08 13:41:39 +01004640private function f_disable_all_tch_f() runs on test_CT {
Philipp Maierc704a882019-01-29 15:58:52 +01004641 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 1 sub-slot 0 borken");
4642 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 2 sub-slot 0 borken");
4643 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 3 sub-slot 0 borken");
4644 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 4 sub-slot 0 borken");
Philipp Maierac09bfc2019-01-08 13:41:39 +01004645}
4646
4647private function f_disable_all_tch_h() runs on test_CT {
Philipp Maierc704a882019-01-29 15:58:52 +01004648 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 5 sub-slot 0 borken");
4649 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 5 sub-slot 1 borken");
Philipp Maierac09bfc2019-01-08 13:41:39 +01004650}
4651
4652private function f_enable_all_tch() runs on test_CT {
Philipp Maierc704a882019-01-29 15:58:52 +01004653 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 1 sub-slot 0 unused");
4654 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 2 sub-slot 0 unused");
4655 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 3 sub-slot 0 unused");
4656 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 4 sub-slot 0 unused");
4657 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 5 sub-slot 0 unused");
4658 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 5 sub-slot 1 unused");
Philipp Maierac09bfc2019-01-08 13:41:39 +01004659}
4660
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004661private function f_disable_all_sdcch() runs on test_CT {
4662 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 0 borken");
4663 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 1 borken");
4664 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 2 borken");
4665 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 3 borken");
4666}
4667
4668private function f_enable_all_sdcch() runs on test_CT {
4669 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 0 unused");
4670 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 1 unused");
4671 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 2 unused");
4672 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 3 unused");
4673}
4674
Philipp Maierac09bfc2019-01-08 13:41:39 +01004675/* Allow HR only */
4676private function f_TC_assignment_codec_xr_exhausted_req_hr(charstring id) runs on MSC_ConnHdlr {
4677 g_pars := f_gen_test_hdlr_pars();
4678 var PDU_BSSAP ass_cmd := f_gen_ass_req();
4679 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
4680 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
4681 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '09'O;
4682 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '05'O;
4683 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR}));
4684 f_establish_fully(ass_cmd, exp_compl);
4685}
4686
4687/* Allow FR only */
4688private function f_TC_assignment_codec_xr_exhausted_req_fr(charstring id) runs on MSC_ConnHdlr {
4689 g_pars := f_gen_test_hdlr_pars();
4690 var PDU_BSSAP ass_cmd := f_gen_ass_req();
4691 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
4692 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
4693 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '08'O;
4694 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '01'O;
4695 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
4696 f_establish_fully(ass_cmd, exp_compl);
4697}
4698
4699/* Allow HR only (expect assignment failure) */
4700private function f_TC_assignment_codec_xr_exhausted_req_hr_fail(charstring id) runs on MSC_ConnHdlr {
4701 g_pars := f_gen_test_hdlr_pars();
4702 var PDU_BSSAP ass_cmd := f_gen_ass_req();
4703 var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
4704 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
4705 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '09'O;
4706 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '05'O;
4707 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR}));
4708 f_establish_fully(ass_cmd, exp_fail);
4709}
4710
4711/* Allow FR only (expect assignment failure) */
4712private function f_TC_assignment_codec_xr_exhausted_req_fr_fail(charstring id) runs on MSC_ConnHdlr {
4713 g_pars := f_gen_test_hdlr_pars();
4714 var PDU_BSSAP ass_cmd := f_gen_ass_req();
4715 var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
4716 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
4717 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '08'O;
4718 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '01'O;
4719 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
4720 f_establish_fully(ass_cmd, exp_fail);
4721}
4722
4723/* Allow FR and HR, but prefer FR */
4724private function f_TC_assignment_codec_fr_exhausted_req_fr_hr(charstring id) runs on MSC_ConnHdlr {
4725 g_pars := f_gen_test_hdlr_pars();
4726 var PDU_BSSAP ass_cmd := f_gen_ass_req();
4727 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
4728 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
4729 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '0A'O; /* Prefer FR */
4730 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '8105'O;
4731 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR, ts_CodecHR}));
4732 exp_compl.pdu.bssmap.assignmentComplete.speechVersion.speechVersionIdentifier := '0000101'B; /* Expect HR */
4733 f_establish_fully(ass_cmd, exp_compl);
4734}
4735
4736/* Allow FR and HR, but prefer HR */
4737private function f_TC_assignment_codec_fr_exhausted_req_hr_fr(charstring id) runs on MSC_ConnHdlr {
4738 g_pars := f_gen_test_hdlr_pars();
4739 var PDU_BSSAP ass_cmd := f_gen_ass_req();
4740 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
4741 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
4742 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '0B'O; /* Prefer HR */
4743 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '8501'O;
4744 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR, ts_CodecFR}));
4745 exp_compl.pdu.bssmap.assignmentComplete.speechVersion.speechVersionIdentifier := '0000101'B; /* Expect HR */
4746 f_establish_fully(ass_cmd, exp_compl);
4747}
4748
4749/* Allow FR and HR, but prefer FR */
4750private function f_TC_assignment_codec_hr_exhausted_req_fr_hr(charstring id) runs on MSC_ConnHdlr {
4751 g_pars := f_gen_test_hdlr_pars();
4752 var PDU_BSSAP ass_cmd := f_gen_ass_req();
4753 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
4754 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
4755 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '0A'O; /* Prefer FR */
4756 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '8105'O;
4757 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR, ts_CodecHR}));
4758 exp_compl.pdu.bssmap.assignmentComplete.speechVersion.speechVersionIdentifier := '0000001'B; /* Expect FR */
4759 f_establish_fully(ass_cmd, exp_compl);
4760}
4761
4762/* Allow FR and HR, but prefer HR */
4763private function f_TC_assignment_codec_hr_exhausted_req_hr_fr(charstring id) runs on MSC_ConnHdlr {
4764 g_pars := f_gen_test_hdlr_pars();
4765 var PDU_BSSAP ass_cmd := f_gen_ass_req();
4766 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
4767 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
4768 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '0B'O; /* Prefer HR */
4769 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '8501'O;
4770 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR, ts_CodecFR}));
4771 exp_compl.pdu.bssmap.assignmentComplete.speechVersion.speechVersionIdentifier := '0000001'B; /* Expect FR */
4772 f_establish_fully(ass_cmd, exp_compl);
4773}
4774
4775/* Request a HR channel while all FR channels are exhausted, this is expected
4776 * to work without conflicts */
4777testcase TC_assignment_codec_fr_exhausted_req_hr() runs on test_CT {
4778 var MSC_ConnHdlr vc_conn;
4779 f_init(1, true);
4780 f_sleep(1.0);
4781 f_enable_all_tch();
4782 f_disable_all_tch_f();
4783 vc_conn := f_start_handler(refers(f_TC_assignment_codec_xr_exhausted_req_hr));
4784 vc_conn.done;
4785 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004786 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01004787}
4788
4789/* Request a FR channel while all FR channels are exhausted, this is expected
4790 * to fail. */
4791testcase TC_assignment_codec_fr_exhausted_req_fr() runs on test_CT {
4792 var MSC_ConnHdlr vc_conn;
4793 f_init(1, true);
4794 f_sleep(1.0);
4795 f_enable_all_tch();
4796 f_disable_all_tch_f();
4797 vc_conn := f_start_handler(refers(f_TC_assignment_codec_xr_exhausted_req_fr_fail));
4798 vc_conn.done;
4799 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004800 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01004801}
4802
4803/* Request a FR (prefered) or alternatively a HR channel while all FR channels
4804 * are exhausted, this is expected to be resolved by selecting a HR channel. */
4805testcase TC_assignment_codec_fr_exhausted_req_fr_hr() runs on test_CT {
4806 var MSC_ConnHdlr vc_conn;
4807 f_init(1, true);
4808 f_sleep(1.0);
4809 f_enable_all_tch();
4810 f_disable_all_tch_f();
4811 vc_conn := f_start_handler(refers(f_TC_assignment_codec_fr_exhausted_req_fr_hr));
4812 vc_conn.done;
4813 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004814 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01004815}
4816
4817/* Request a HR (prefered) or alternatively a FR channel while all FR channels
4818 * are exhausted, this is expected to work without conflicts. */
4819testcase TC_assignment_codec_fr_exhausted_req_hr_fr() runs on test_CT {
4820 var MSC_ConnHdlr vc_conn;
4821 f_init(1, true);
4822 f_sleep(1.0);
4823 f_enable_all_tch();
4824 f_disable_all_tch_f();
4825 vc_conn := f_start_handler(refers(f_TC_assignment_codec_fr_exhausted_req_hr_fr));
4826 vc_conn.done;
4827 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004828 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01004829}
4830
4831/* Request a FR channel while all HR channels are exhausted, this is expected
4832 * to work without conflicts */
4833testcase TC_assignment_codec_hr_exhausted_req_fr() runs on test_CT {
4834 var MSC_ConnHdlr vc_conn;
4835 f_init(1, true);
4836 f_sleep(1.0);
4837 f_enable_all_tch();
4838 f_disable_all_tch_h();
4839 vc_conn := f_start_handler(refers(f_TC_assignment_codec_xr_exhausted_req_fr));
4840 vc_conn.done;
4841 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004842 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01004843}
4844
4845/* Request a HR channel while all HR channels are exhausted, this is expected
4846 * to fail. */
4847testcase TC_assignment_codec_hr_exhausted_req_hr() runs on test_CT {
4848 var MSC_ConnHdlr vc_conn;
4849 f_init(1, true);
4850 f_sleep(1.0);
4851 f_enable_all_tch();
4852 f_disable_all_tch_h();
4853 vc_conn := f_start_handler(refers(f_TC_assignment_codec_xr_exhausted_req_hr_fail));
4854 vc_conn.done;
4855 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004856 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01004857}
4858
4859/* Request a HR (prefered) or alternatively a FR channel while all HR channels
4860 * are exhausted, this is expected to be resolved by selecting a FR channel. */
4861testcase TC_assignment_codec_hr_exhausted_req_hr_fr() runs on test_CT {
4862 var MSC_ConnHdlr vc_conn;
4863 f_init(1, true);
4864 f_sleep(1.0);
4865 f_enable_all_tch();
4866 f_disable_all_tch_h();
4867 vc_conn := f_start_handler(refers(f_TC_assignment_codec_hr_exhausted_req_hr_fr));
4868 vc_conn.done;
4869 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004870 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01004871}
4872
4873/* Request a FR (prefered) or alternatively a HR channel while all HR channels
4874 * are exhausted, this is expected to work without conflicts. */
4875testcase TC_assignment_codec_hr_exhausted_req_fr_hr() runs on test_CT {
4876 var MSC_ConnHdlr vc_conn;
4877 f_init(1, true);
4878 f_sleep(1.0);
4879 f_enable_all_tch();
4880 f_disable_all_tch_h();
4881 vc_conn := f_start_handler(refers(f_TC_assignment_codec_hr_exhausted_req_fr_hr));
4882 vc_conn.done;
4883 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004884 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01004885}
4886
4887/* Allow FR and HR, but prefer HR */
4888private function f_TC_assignment_codec_req_hr_fr(charstring id) runs on MSC_ConnHdlr {
4889 g_pars := f_gen_test_hdlr_pars();
4890 var PDU_BSSAP ass_cmd := f_gen_ass_req();
4891 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
4892 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
4893 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '0B'O; /* Prefer HR */
4894 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '8501'O;
4895 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR, ts_CodecFR}));
4896 exp_compl.pdu.bssmap.assignmentComplete.speechVersion.speechVersionIdentifier := '0000101'B; /* Expect HR */
4897 f_establish_fully(ass_cmd, exp_compl);
4898}
4899
4900/* Allow FR and HR, but prefer FR */
4901private function f_TC_assignment_codec_req_fr_hr(charstring id) runs on MSC_ConnHdlr {
4902 g_pars := f_gen_test_hdlr_pars();
4903 var PDU_BSSAP ass_cmd := f_gen_ass_req();
4904 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
4905 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
4906 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '0A'O; /* Prefer FR */
4907 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '8105'O;
4908 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR, ts_CodecHR}));
4909 exp_compl.pdu.bssmap.assignmentComplete.speechVersion.speechVersionIdentifier := '0000001'B; /* Expect FR */
4910 f_establish_fully(ass_cmd, exp_compl);
4911}
4912
4913/* Request a HR (prefered) or alternatively a FR channel, it is expected that
4914 * HR, which is the prefered type, is selected. */
4915testcase TC_assignment_codec_req_hr_fr() runs on test_CT {
4916 var MSC_ConnHdlr vc_conn;
4917 f_init(1, true);
4918 f_sleep(1.0);
4919 f_enable_all_tch();
4920 vc_conn := f_start_handler(refers(f_TC_assignment_codec_req_hr_fr));
4921 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004922 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01004923}
4924
4925/* Request a FR (prefered) or alternatively a HR channel, it is expected that
4926 * FR, which is the prefered type, is selected. */
4927testcase TC_assignment_codec_req_fr_hr() runs on test_CT {
4928 var MSC_ConnHdlr vc_conn;
4929 f_init(1, true);
4930 f_sleep(1.0);
4931 f_enable_all_tch();
4932 vc_conn := f_start_handler(refers(f_TC_assignment_codec_req_fr_hr));
4933 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004934 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01004935}
4936
Pau Espin Pedrol14475352021-07-22 15:48:16 +02004937/* request a signalling channel with all SDCCH exhausted, it is expected that a TCH will be selected */
4938private function f_TC_assignment_sdcch_exhausted_req_signalling(charstring id) runs on MSC_ConnHdlr {
4939 g_pars := f_gen_test_hdlr_pars();
4940 g_pars.ra := '02'O; /* RA containing reason=LU */
4941
4942 var MobileIdentityLV mi := valueof(ts_MI_IMSI_LV(g_pars.imsi));
4943 var PDU_ML3_MS_NW l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, mi));
4944 var octetstring l3_enc := enc_PDU_ML3_MS_NW(l3_info);
4945 var template uint3_t tsc := ?;
4946
4947 f_MscConnHdlr_init(g_pars.media_nr, host_bts, host_mgw_mgcp, FR_AMR);
4948 f_create_bssmap_exp(l3_enc);
4949 /* call helper function for CHAN_RQD -> IMM ASS ->EST_IND */
4950 RSL_Emulation.f_chan_est(g_pars.ra, l3_enc, g_pars.link_id, g_pars.fn, tsc);
4951
4952 /* we should now have a COMPL_L3 at the MSC */
4953 timer T := 10.0;
4954 T.start;
4955 alt {
4956 [] BSSAP.receive(tr_BSSMAP_ComplL3);
4957 [] T.timeout {
4958 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout waiting for COMPLETE LAYER 3 INFORMATION");
4959 }
4960 }
4961}
4962testcase TC_assignment_sdcch_exhausted_req_signalling() runs on test_CT {
4963 var MSC_ConnHdlr vc_conn;
4964 f_init(1, true);
4965 f_sleep(1.0);
4966 f_disable_all_sdcch();
4967 vc_conn := f_start_handler(refers(f_TC_assignment_sdcch_exhausted_req_signalling));
4968 vc_conn.done;
4969 f_enable_all_sdcch();
4970 f_shutdown_helper();
4971}
4972
4973/* Request a signalling channel with all SDCCH exhausted, it is
4974 expected that no TCH will be selected for signalling and assigment will fail
4975 because it's dictated by VTY config */
4976testcase TC_assignment_sdcch_exhausted_req_signalling_tch_forbidden() runs on test_CT {
4977 var RSL_Message rsl_unused, rsl_msg;
4978 var GsmRrMessage rr;
4979 f_init(1, false);
4980 f_sleep(1.0);
4981 f_vty_allow_tch_for_signalling(false, 0);
4982 f_disable_all_sdcch();
4983
4984 /* RA containing reason=LU */
4985 f_ipa_tx(0, ts_RSL_CHAN_RQD('02'O, 2342));
4986 rsl_msg := f_exp_ipa_rx(0, tr_RSL_IMM_ASSIGN(0));
4987 rr := dec_GsmRrMessage(rsl_msg.ies[1].body.full_imm_ass_info.payload);
4988 if (rr.header.message_type != IMMEDIATE_ASSIGNMENT_REJECT) {
4989 setverdict(fail, "Expected reject");
4990 }
4991
4992 f_vty_allow_tch_for_signalling(true, 0);
4993 f_enable_all_sdcch();
4994 f_shutdown_helper();
4995}
4996
4997/* Request a voice channel with all SDCCH exhausted, it is
4998 * expected that TCH channel will be allocated since the VTY option is only
4999 * aimed at signalling requests */
5000private function f_TC_assignment_sdcch_exhausted_req_voice_tch_forbidden(charstring id) runs on MSC_ConnHdlr {
5001 g_pars := f_gen_test_hdlr_pars();
5002 g_pars.ra := '43'O; /* RA containing reason=originating speech call*/
5003
5004 var MobileIdentityLV mi := valueof(ts_MI_IMSI_LV(g_pars.imsi));
5005 var PDU_ML3_MS_NW l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, mi));
5006 var octetstring l3_enc := enc_PDU_ML3_MS_NW(l3_info);
5007 var template uint3_t tsc := ?;
5008
5009 f_MscConnHdlr_init(g_pars.media_nr, host_bts, host_mgw_mgcp, FR_AMR);
5010 f_create_bssmap_exp(l3_enc);
5011 /* call helper function for CHAN_RQD -> IMM ASS ->EST_IND */
5012 RSL_Emulation.f_chan_est(g_pars.ra, l3_enc, g_pars.link_id, g_pars.fn, tsc);
5013
5014 /* we should now have a COMPL_L3 at the MSC */
5015 timer T := 10.0;
5016 T.start;
5017 alt {
5018 [] BSSAP.receive(tr_BSSMAP_ComplL3);
5019 [] T.timeout {
5020 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout waiting for COMPLETE LAYER 3 INFORMATION");
5021 }
5022 }
5023}
5024testcase TC_assignment_sdcch_exhausted_req_voice_tch_forbidden() runs on test_CT {
5025 var MSC_ConnHdlr vc_conn;
5026 f_init(1, true);
5027 f_sleep(1.0);
5028 f_vty_allow_tch_for_signalling(false, 0);
5029 f_disable_all_sdcch();
5030
5031 vc_conn := f_start_handler(refers(f_TC_assignment_sdcch_exhausted_req_voice_tch_forbidden));
5032 vc_conn.done;
5033
5034 f_vty_allow_tch_for_signalling(true, 0);
5035 f_enable_all_sdcch();
5036 f_shutdown_helper();
5037}
5038
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02005039testcase TC_assignment_osmux() runs on test_CT {
5040 var TestHdlrParams pars := f_gen_test_hdlr_pars();
5041 var MSC_ConnHdlr vc_conn;
5042
5043 /* See note above */
5044 var RSL_IE_Body mr_conf := {
5045 other := {
5046 len := 2,
5047 payload := '2804'O
5048 }
5049 };
5050
5051 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_H}));
5052 pars.ass_codec_list.codecElements[0].s0_7 := '00000100'B; /* 5,90k */
5053 pars.ass_codec_list.codecElements[0].s8_15 := '00000111'B;
5054 pars.expect_mr_conf_ie := mr_conf;
5055 pars.use_osmux := true;
5056
5057 f_init(1, true, true);
5058 f_sleep(1.0);
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00005059 f_vty_amr_start_mode_set(false, "1");
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02005060
5061 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
5062 vc_conn.done;
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00005063
5064 f_vty_amr_start_mode_restore(false);
Vadim Yanitskiy292e5962021-01-03 14:18:47 +01005065 f_shutdown_helper();
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02005066}
5067
Neels Hofmeyr92b12b72018-09-18 14:30:23 +02005068/* test the procedure of the MSC requesting a Classmark Update:
5069 * a) BSSMAP Classmark Request should result in RR CLASSMARK ENQUIRY,
5070 * b) L3 RR CLASSMARK CHANGE should result in BSSMAP CLASSMARK UPDATE */
Harald Welte898113b2018-01-31 18:32:21 +01005071private function f_tc_classmark(charstring id) runs on MSC_ConnHdlr {
Philipp Maier48604732018-10-09 15:00:37 +02005072 g_pars := f_gen_test_hdlr_pars();
5073
Harald Weltea0630032018-03-20 21:09:55 +01005074 f_create_chan_and_exp();
Harald Welte898113b2018-01-31 18:32:21 +01005075 /* we should now have a COMPL_L3 at the MSC */
Harald Welte898113b2018-01-31 18:32:21 +01005076
Neels Hofmeyr92b12b72018-09-18 14:30:23 +02005077 BSSAP.send(ts_BSSMAP_ClassmarkRequest);
5078 RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_CM_ENQUIRY));
5079
Harald Welte898113b2018-01-31 18:32:21 +01005080 f_rsl_send_l3(ts_RRM_CM_CHG(valueof(ts_CM2)));
5081 BSSAP.receive(tr_BSSMAP_ClassmarkUpd(?, omit));
5082 setverdict(pass);
5083}
5084testcase TC_classmark() runs on test_CT {
5085 var MSC_ConnHdlr vc_conn;
5086 f_init(1, true);
5087 f_sleep(1.0);
Harald Welte8863fa12018-05-10 20:15:27 +02005088 vc_conn := f_start_handler(refers(f_tc_classmark));
Harald Welte898113b2018-01-31 18:32:21 +01005089 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005090 f_shutdown_helper();
Harald Welte898113b2018-01-31 18:32:21 +01005091}
5092
Harald Welteeddf0e92020-06-21 19:42:15 +02005093/* Send a CommonID from the simulated MSC and verify that the information is used to
5094 * fill BSC-internal data structures (specifically, bsc_subscr associated with subscr_conn) */
5095private function f_tc_common_id(charstring id) runs on MSC_ConnHdlr {
5096 g_pars := f_gen_test_hdlr_pars();
5097 f_MscConnHdlr_init_vty();
5098
5099 f_create_chan_and_exp();
5100 /* we should now have a COMPL_L3 at the MSC */
Harald Welteeddf0e92020-06-21 19:42:15 +02005101
5102 /* Send CommonID */
5103 BSSAP.send(ts_BSSMAP_CommonId(g_pars.imsi));
5104
5105 /* Use VTY to verify that the IMSI of the subscr_conn is set */
5106 var charstring regex := "*(IMSI: " & hex2str(g_pars.imsi) & ")*";
5107 f_vty_transceive_match_regexp_retry(BSCVTY, "show conns", regex, 0, 4, 1.0);
5108
5109 setverdict(pass);
5110}
5111testcase TC_common_id() runs on test_CT {
5112 var MSC_ConnHdlr vc_conn;
5113 f_init(1, true);
5114 f_sleep(1.0);
5115 vc_conn := f_start_handler(refers(f_tc_common_id));
5116 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005117 f_shutdown_helper();
Harald Welteeddf0e92020-06-21 19:42:15 +02005118}
5119
Harald Weltee3bd6582018-01-31 22:51:25 +01005120private function f_est_single_l3(template PDU_ML3_MS_NW l3) runs on MSC_ConnHdlr {
Philipp Maier48604732018-10-09 15:00:37 +02005121 g_pars := f_gen_test_hdlr_pars();
Harald Weltea0630032018-03-20 21:09:55 +01005122 f_create_chan_and_exp();
Harald Welte898113b2018-01-31 18:32:21 +01005123 /* we should now have a COMPL_L3 at the MSC */
Harald Welte898113b2018-01-31 18:32:21 +01005124
Harald Weltee3bd6582018-01-31 22:51:25 +01005125 /* send the single message we want to send */
5126 f_rsl_send_l3(l3);
5127}
5128
5129private function f_bssap_expect_nothing(float sec := 5.00) runs on MSC_ConnHdlr {
5130 timer T := sec;
5131 var PDU_BSSAP bssap;
Harald Welte898113b2018-01-31 18:32:21 +01005132 T.start;
5133 alt {
Harald Weltee3bd6582018-01-31 22:51:25 +01005134 [] BSSAP.receive(PDU_BSSAP:?) -> value bssap {
5135 setverdict(fail, "Unexpected BSSMAP ", bssap);
Daniel Willmannafce8662018-07-06 23:11:32 +02005136 mtc.stop;
Harald Welte898113b2018-01-31 18:32:21 +01005137 }
5138 [] T.timeout {
5139 setverdict(pass);
5140 }
5141 }
5142}
5143
Harald Weltee3bd6582018-01-31 22:51:25 +01005144/* unsolicited ASSIGNMENT FAIL (without ASSIGN) from MS shouldn't bring BSC down */
5145private function f_tc_unsol_ass_fail(charstring id) runs on MSC_ConnHdlr {
5146 f_est_single_l3(ts_RRM_AssignmentFailure('00'O));
5147 f_bssap_expect_nothing();
5148}
Harald Welte898113b2018-01-31 18:32:21 +01005149testcase TC_unsol_ass_fail() runs on test_CT {
5150 var MSC_ConnHdlr vc_conn;
5151 f_init(1, true);
5152 f_sleep(1.0);
Harald Welte8863fa12018-05-10 20:15:27 +02005153 vc_conn := f_start_handler(refers(f_tc_unsol_ass_fail));
Harald Welte898113b2018-01-31 18:32:21 +01005154 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005155 f_shutdown_helper();
Harald Welte898113b2018-01-31 18:32:21 +01005156}
Harald Welte552620d2017-12-16 23:21:36 +01005157
Harald Welteea99a002018-01-31 20:46:43 +01005158
5159/* unsolicited ASSIGNMENT COMPLETE (without ASSIGN) from MS shouldn't bring BSC down */
5160private function f_tc_unsol_ass_compl(charstring id) runs on MSC_ConnHdlr {
Harald Weltee3bd6582018-01-31 22:51:25 +01005161 f_est_single_l3(ts_RRM_AssignmentComplete('00'O));
5162 f_bssap_expect_nothing();
Harald Welteea99a002018-01-31 20:46:43 +01005163}
5164testcase TC_unsol_ass_compl() runs on test_CT {
5165 var MSC_ConnHdlr vc_conn;
5166 f_init(1, true);
5167 f_sleep(1.0);
Harald Welte8863fa12018-05-10 20:15:27 +02005168 vc_conn := f_start_handler(refers(f_tc_unsol_ass_compl));
Harald Welteea99a002018-01-31 20:46:43 +01005169 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005170 f_shutdown_helper();
Harald Welteea99a002018-01-31 20:46:43 +01005171}
5172
5173
Harald Weltefbf9b5e2018-01-31 20:41:23 +01005174/* unsolicited HANDOVER FAIL (without ASSIGN) from MS shouldn't bring BSC down */
5175private function f_tc_unsol_ho_fail(charstring id) runs on MSC_ConnHdlr {
Harald Weltee3bd6582018-01-31 22:51:25 +01005176 f_est_single_l3(ts_RRM_HandoverFailure('00'O));
5177 f_bssap_expect_nothing();
Harald Weltefbf9b5e2018-01-31 20:41:23 +01005178}
Harald Weltefbf9b5e2018-01-31 20:41:23 +01005179testcase TC_unsol_ho_fail() runs on test_CT {
5180 var MSC_ConnHdlr vc_conn;
5181 f_init(1, true);
5182 f_sleep(1.0);
Harald Welte8863fa12018-05-10 20:15:27 +02005183 vc_conn := f_start_handler(refers(f_tc_unsol_ho_fail));
Harald Weltefbf9b5e2018-01-31 20:41:23 +01005184 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005185 f_shutdown_helper();
Harald Weltefbf9b5e2018-01-31 20:41:23 +01005186}
5187
5188
Harald Weltee3bd6582018-01-31 22:51:25 +01005189/* short message from MS should be ignored */
5190private function f_tc_err_82_short_msg(charstring id) runs on MSC_ConnHdlr {
Philipp Maier48604732018-10-09 15:00:37 +02005191 g_pars := f_gen_test_hdlr_pars();
Harald Weltea0630032018-03-20 21:09:55 +01005192 f_create_chan_and_exp();
Harald Weltee3bd6582018-01-31 22:51:25 +01005193 /* we should now have a COMPL_L3 at the MSC */
Harald Weltee3bd6582018-01-31 22:51:25 +01005194
5195 /* send short message */
5196 RSL.send(ts_RSL_DATA_IND(g_chan_nr, valueof(ts_RslLinkID_DCCH(0)), ''O));
5197 f_bssap_expect_nothing();
5198}
5199testcase TC_err_82_short_msg() runs on test_CT {
5200 var MSC_ConnHdlr vc_conn;
5201 f_init(1, true);
5202 f_sleep(1.0);
Harald Welte8863fa12018-05-10 20:15:27 +02005203 vc_conn := f_start_handler(refers(f_tc_err_82_short_msg));
Harald Weltee3bd6582018-01-31 22:51:25 +01005204 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005205 f_shutdown_helper();
Harald Weltee3bd6582018-01-31 22:51:25 +01005206}
5207
5208
Harald Weltee9e02e42018-01-31 23:36:25 +01005209/* 24.008 8.4 Unknown message must trigger RR STATUS */
5210private function f_tc_err_84_unknown_msg(charstring id) runs on MSC_ConnHdlr {
5211 f_est_single_l3(ts_RRM_UL_REL('00'O));
5212 timer T := 3.0
5213 alt {
5214 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_STATUS)) {
5215 setverdict(pass);
5216 }
5217 [] BSSAP.receive { setverdict(fail, "unexpected BSSAP"); }
Harald Welte458fd372018-03-21 11:26:23 +01005218 [] T.timeout { setverdict(fail, "Timeout waiting for RR STATUS"); }
Harald Weltee9e02e42018-01-31 23:36:25 +01005219 }
5220}
5221testcase TC_err_84_unknown_msg() runs on test_CT {
5222 var MSC_ConnHdlr vc_conn;
5223 f_init(1, true);
5224 f_sleep(1.0);
Harald Welte8863fa12018-05-10 20:15:27 +02005225 vc_conn := f_start_handler(refers(f_tc_err_84_unknown_msg));
Harald Weltee9e02e42018-01-31 23:36:25 +01005226 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005227 f_shutdown_helper();
Harald Weltee9e02e42018-01-31 23:36:25 +01005228}
5229
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01005230/***********************************************************************
5231 * Handover
5232 ***********************************************************************/
5233
Harald Welte94e0c342018-04-07 11:33:23 +02005234/* execute a "bts <0-255> trx <0-255> timeslot <0-7> " command on given Dchan */
5235private function f_vty_ts_action(charstring suffix, integer bts_nr, integer trx_nr, integer ts_nr)
5236runs on test_CT {
5237 var charstring cmd := "bts "&int2str(bts_nr)&" trx "&int2str(trx_nr)&
5238 " timeslot "&int2str(ts_nr)&" ";
5239 f_vty_transceive(BSCVTY, cmd & suffix);
5240}
5241
Harald Welte261af4b2018-02-12 21:20:39 +01005242/* 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 +07005243private function f_vty_ss_action(TELNETasp_PT pt, charstring suffix,
5244 uint8_t bts_nr, uint8_t trx_nr,
5245 in RslChannelNr chan_nr)
5246{
Harald Welte261af4b2018-02-12 21:20:39 +01005247 /* FIXME: resolve those from component-global state */
5248 var integer ts_nr := chan_nr.tn;
5249 var integer ss_nr;
5250 if (ischosen(chan_nr.u.ch0)) {
5251 ss_nr := 0;
5252 } else if (ischosen(chan_nr.u.lm)) {
5253 ss_nr := chan_nr.u.lm.sub_chan;
5254 } else if (ischosen(chan_nr.u.sdcch4)) {
5255 ss_nr := chan_nr.u.sdcch4.sub_chan;
5256 } else if (ischosen(chan_nr.u.sdcch8)) {
5257 ss_nr := chan_nr.u.sdcch8.sub_chan;
5258 } else {
5259 setverdict(fail, "Invalid ChanNr ", chan_nr);
Daniel Willmannafce8662018-07-06 23:11:32 +02005260 mtc.stop;
Harald Welte261af4b2018-02-12 21:20:39 +01005261 }
5262
5263 var charstring cmd := "bts "&int2str(bts_nr)&" trx "&int2str(trx_nr)&
5264 " timeslot "&int2str(ts_nr)&" sub-slot "&int2str(ss_nr)&" ";
Vadim Yanitskiy00070722020-09-02 17:27:57 +07005265 f_vty_transceive(pt, cmd & suffix);
Harald Welte261af4b2018-02-12 21:20:39 +01005266}
5267
Neels Hofmeyr91401012019-07-11 00:42:35 +02005268/* Even though the VTY command to trigger handover takes a new BTS number as argument, behind the scenes osmo-bsc always
5269 * translates that to a target ARFCN+BSIC first. See bsc_vty.c trigger_ho_or_as(), which puts the selected BTS' neighbor
5270 * ident key (ARFCN + BSIC) in the struct passed on to handover_request(). handover_start() then resolves that to a
5271 * viable actual neighbor cell. So from the internal osmo-bsc perspective, we always request handover to an ARFCN + BSIC
5272 * pair, not really to a specific BTS number. */
Vadim Yanitskiy00070722020-09-02 17:27:57 +07005273private function f_vty_handover(TELNETasp_PT pt, uint8_t bts_nr, uint8_t trx_nr,
5274 in RslChannelNr chan_nr, uint8_t new_bts_nr)
5275{
5276 f_vty_ss_action(pt, "handover " & int2str(new_bts_nr), bts_nr, trx_nr, chan_nr);
Harald Welte261af4b2018-02-12 21:20:39 +01005277}
5278
5279/* intra-BSC hand-over between BTS0 and BTS1 */
5280private function f_tc_ho_int(charstring id) runs on MSC_ConnHdlr {
Harald Welteed848512018-05-24 22:27:58 +02005281 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5282 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Harald Welte261af4b2018-02-12 21:20:39 +01005283
5284 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5285 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
5286
Harald Weltea0630032018-03-20 21:09:55 +01005287 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr666f0432020-07-04 00:53:07 +02005288 f_bts_0_cfg(BSCVTY, {"neighbor bts 1"});
Harald Welte261af4b2018-02-12 21:20:39 +01005289
5290 var HandoverState hs := {
5291 rr_ho_cmpl_seen := false,
5292 handover_done := false,
Neels Hofmeyrc741fcb2021-10-02 14:52:28 +02005293 old_chan_nr := -,
5294 expect_target_tsc := BTS_TSC[1]
Harald Welte261af4b2018-02-12 21:20:39 +01005295 };
Neels Hofmeyrc2cf4542021-10-02 12:26:38 +02005296 /* issue hand-over command on VTY, from BTS 0 to BTS 1 */
Vadim Yanitskiy00070722020-09-02 17:27:57 +07005297 f_vty_handover(BSCVTY, 0, 0, g_chan_nr, 1);
Harald Welte261af4b2018-02-12 21:20:39 +01005298 /* temporarily suspend DChan processing on BTS1 to avoid race with RSLEM_register */
5299 f_rslem_suspend(RSL1_PROC);
Philipp Maier3e2af5d2018-07-11 17:01:05 +02005300
5301 /* From the MGW perspective, a handover is is characterized by
5302 * performing one MDCX operation with the MGW. So we expect to see
5303 * one more MDCX during handover. */
5304 g_media.mgcp_conn[0].mdcx_seen_exp := g_media.mgcp_conn[0].crcx_seen_exp + 1;
5305
Harald Welte261af4b2018-02-12 21:20:39 +01005306 alt {
5307 [] as_handover(hs);
Harald Welte261af4b2018-02-12 21:20:39 +01005308 }
Philipp Maier3e2af5d2018-07-11 17:01:05 +02005309
Philipp Maier4dae0652018-11-12 12:03:26 +01005310 /* Since this is an internal handover we expect the BSC to inform the
5311 * MSC about the event */
5312 BSSAP.receive(tr_BSSMAP_HandoverPerformed);
5313
Philipp Maier3e2af5d2018-07-11 17:01:05 +02005314 /* Check the amount of MGCP transactions is still consistant with the
5315 * test expectation */
5316 f_check_mgcp_expectations()
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005317
Neels Hofmeyrc2cf4542021-10-02 12:26:38 +02005318 var RSL_Message chan_act := f_rslem_get_last_act(RSL1_PROC, 0, g_chan_nr);
5319
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005320 /* Ensure the Channel Activation for the new channel contained the right encryption params. as_handover() set
5321 * 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 +02005322 f_verify_encr_info(chan_act);
5323
5324 f_chan_act_verify_tsc(chan_act, BTS_TSC[1]);
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005325
Neels Hofmeyr861a4c12018-11-07 01:23:17 +01005326 f_sleep(0.5);
Harald Welte261af4b2018-02-12 21:20:39 +01005327}
5328
5329testcase TC_ho_int() runs on test_CT {
Neels Hofmeyr5f7a9df2021-06-21 01:30:43 +02005330 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte261af4b2018-02-12 21:20:39 +01005331 var MSC_ConnHdlr vc_conn;
5332 f_init(2, true);
5333 f_sleep(1.0);
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00005334
Neels Hofmeyrc2cf4542021-10-02 12:26:38 +02005335 pars.expect_tsc := BTS_TSC[0];
5336
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01005337 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00005338
Neels Hofmeyr5f7a9df2021-06-21 01:30:43 +02005339 vc_conn := f_start_handler(refers(f_tc_ho_int), pars);
Harald Welte261af4b2018-02-12 21:20:39 +01005340 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00005341
5342 /* from f_establish_fully() */
5343 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
5344 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
5345 /* from handover */
5346 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
5347 f_ctrs_bsc_and_bts_add(0, "handover:completed");
5348 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
5349 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:completed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01005350 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:attempted");
5351 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:completed");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00005352 f_ctrs_bsc_and_bts_verify();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005353 f_shutdown_helper();
Harald Welte261af4b2018-02-12 21:20:39 +01005354}
Harald Weltee9e02e42018-01-31 23:36:25 +01005355
Oliver Smith7eabd312021-07-12 14:18:56 +02005356function 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 +02005357 var MSC_ConnHdlr vc_conn;
5358 var TestHdlrParams pars := f_gen_test_hdlr_pars();
5359 pars.encr := valueof(t_EncrParams(encr_alg, f_rnd_octstring(8), f_rnd_octstring(16)));
5360
5361 f_init(2, true);
Oliver Smith7eabd312021-07-12 14:18:56 +02005362 f_vty_encryption_a5(enc_a5);
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005363 f_sleep(1.0);
5364
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01005365 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005366
5367 vc_conn := f_start_handler(refers(f_tc_ho_int), pars);
5368 vc_conn.done;
5369
5370 /* from f_establish_fully() */
5371 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
5372 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
5373 /* from handover */
5374 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
5375 f_ctrs_bsc_and_bts_add(0, "handover:completed");
5376 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
5377 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:completed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01005378 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:attempted");
5379 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:completed");
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005380 f_ctrs_bsc_and_bts_verify();
Oliver Smith7eabd312021-07-12 14:18:56 +02005381 f_vty_encryption_a5_reset();
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005382 f_shutdown_helper();
5383}
5384
5385testcase TC_ho_int_a5_0() runs on test_CT {
5386 f_tc_ho_int_a5('01'O);
5387}
5388
5389testcase TC_ho_int_a5_1() runs on test_CT {
5390 f_tc_ho_int_a5('02'O);
5391}
5392
5393testcase TC_ho_int_a5_3() runs on test_CT {
5394 f_tc_ho_int_a5('08'O);
5395}
5396
5397testcase TC_ho_int_a5_4() runs on test_CT {
Oliver Smith7eabd312021-07-12 14:18:56 +02005398 f_tc_ho_int_a5('10'O, "0 1 3 4");
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005399}
5400
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005401/* intra-BSC hand-over with CONNection FAILure and cause Radio Link Failure: check RR release cause */
5402private function f_tc_ho_int_radio_link_failure(charstring id) runs on MSC_ConnHdlr {
5403 g_pars := f_gen_test_hdlr_pars();
5404 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5405 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005406
5407 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5408 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
5409
5410 f_establish_fully(ass_cmd, exp_compl);
5411 f_bts_0_cfg(BSCVTY, {"neighbor bts 1"});
5412
5413 var HandoverState hs := {
5414 rr_ho_cmpl_seen := false,
5415 handover_done := false,
Neels Hofmeyrc741fcb2021-10-02 14:52:28 +02005416 old_chan_nr := -,
5417 expect_target_tsc := BTS_TSC[1]
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005418 };
5419 /* issue hand-over command on VTY */
5420 f_vty_handover(BSCVTY, 0, 0, g_chan_nr, 1);
5421 /* temporarily suspend DChan processing on BTS1 to avoid race with RSLEM_register */
5422 f_rslem_suspend(RSL1_PROC);
5423
5424 /* From the MGW perspective, a handover is is characterized by
5425 * performing one MDCX operation with the MGW. So we expect to see
5426 * one more MDCX during handover. */
5427 g_media.mgcp_conn[0].mdcx_seen_exp := g_media.mgcp_conn[0].crcx_seen_exp + 1;
5428
5429 var RSL_Message rsl;
5430 var PDU_ML3_NW_MS l3;
5431 var RslChannelNr new_chan_nr;
5432 var GsmArfcn arfcn;
5433 RSL.receive(tr_RSL_DATA_REQ(g_chan_nr)) -> value rsl {
5434 l3 := dec_PDU_ML3_NW_MS(rsl.ies[2].body.l3_info.payload);
5435 if (not ischosen(l3.msgs.rrm.handoverCommand)) {
5436 setverdict(fail, "Expected handoverCommand");
5437 mtc.stop;
5438 }
5439 }
5440 f_ChDesc2RslChanNr(l3.msgs.rrm.handoverCommand.channelDescription2,
5441 new_chan_nr, arfcn);
5442
5443 f_rslem_register(0, new_chan_nr, RSL1_PROC);
5444
5445 /* resume processing of RSL DChan messages, which was temporarily suspended
5446 * before performing a hand-over */
5447 f_rslem_resume(RSL1_PROC);
5448 RSL1.receive(tr_RSL_IPA_CRCX(new_chan_nr));
5449
5450 f_sleep(1.0);
5451
5452 /* Handover fails because no HANDO DET appears on the new lchan,
5453 * and the old lchan reports a Radio Link Failure. */
5454 RSL.send(ts_RSL_CONN_FAIL_IND(g_chan_nr, RSL_ERR_RADIO_LINK_FAIL));
5455
5456 var PDU_BSSAP rx_clear_request;
5457 BSSAP.receive(tr_BSSMAP_ClearRequest) -> value rx_clear_request;
5458 var BssmapCause cause := bit2int(rx_clear_request.pdu.bssmap.clearRequest.cause.causeValue);
5459 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
5460
5461 var RR_Cause rr_cause := GSM48_RR_CAUSE_ABNORMAL_UNSPEC;
5462
5463 var MgcpCommand mgcp;
5464 interleave {
5465 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_RELEASE(int2oct(enum2int(rr_cause), 1)))) {}
5466 [] RSL.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {}
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +02005467 [] RSL.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005468 RSL.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
Neels Hofmeyre680b012021-07-22 19:19:09 +02005469 f_rslem_unregister(0, g_chan_nr);
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005470 }
5471 [] RSL1.receive(tr_RSL_DEACT_SACCH(new_chan_nr)) {}
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +02005472 [] RSL1.receive(tr_RSL_RF_CHAN_REL(new_chan_nr)) {
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005473 RSL1.send(ts_RSL_RF_CHAN_REL_ACK(new_chan_nr));
Neels Hofmeyre680b012021-07-22 19:19:09 +02005474 f_rslem_unregister(0, g_chan_nr, PT := RSL1_PROC);
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005475 }
5476 [] BSSAP.receive(tr_BSSMAP_ClearComplete) {}
5477 }
5478
5479 f_sleep(0.5);
5480 setverdict(pass);
5481}
5482testcase TC_ho_int_radio_link_failure() runs on test_CT {
5483 var MSC_ConnHdlr vc_conn;
5484 f_init(2, true);
5485 f_sleep(1.0);
5486
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01005487 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005488
5489 vc_conn := f_start_handler(refers(f_tc_ho_int_radio_link_failure));
5490 vc_conn.done;
5491
5492 /* from f_establish_fully() */
5493 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
5494 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
5495 /* from handover */
5496 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
5497 f_ctrs_bsc_and_bts_add(0, "handover:stopped");
5498 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
5499 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:stopped");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01005500 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:attempted");
5501 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:stopped");
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005502 f_ctrs_bsc_and_bts_verify();
5503 f_shutdown_helper();
5504}
5505
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005506/* Expecting MGCP to DLCX the endpoint's two connections: towards BTS and towards MSC */
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02005507private function f_expect_dlcx_conns() runs on MSC_ConnHdlr {
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005508 var MgcpCommand mgcp;
Pau Espin Pedrolfd02ad42019-06-18 17:45:20 +02005509 var template MgcpResponse mgcp_resp;
5510 var MGCP_RecvFrom mrf;
5511 var template MgcpMessage msg_resp;
5512 var template MgcpMessage msg_dlcx := {
5513 command := tr_DLCX()
5514 }
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005515
Pau Espin Pedrolfd02ad42019-06-18 17:45:20 +02005516 if (g_pars.aoip) {
5517 MGCP.receive(tr_DLCX()) -> value mgcp {
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005518 log("Got first DLCX: ", mgcp);
5519 MGCP.send(ts_DLCX_ACK2(mgcp.line.trans_id));
Pau Espin Pedrolfd02ad42019-06-18 17:45:20 +02005520 };
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005521
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005522 MGCP.receive(tr_DLCX()) -> value mgcp {
5523 log("Got second DLCX: ", mgcp);
5524 MGCP.send(ts_DLCX_ACK2(mgcp.line.trans_id));
5525 };
Pau Espin Pedrolfd02ad42019-06-18 17:45:20 +02005526 } else {
5527 /* For SCCPLite, BSC doesn't handle the MSC-side */
5528 MGCP_MULTI.receive(tr_MGCP_RecvFrom_any(msg_dlcx)) -> value mrf {
5529 log("Got first DLCX: ", mrf.msg.command);
5530 msg_resp := {
5531 response := ts_DLCX_ACK2(mrf.msg.command.line.trans_id)
5532 }
5533 MGCP_MULTI.send(t_MGCP_SendToMrf(mrf, msg_resp));
5534 };
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005535 }
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005536}
5537
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02005538private 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 +01005539
Neels Hofmeyrafe2ea52021-11-24 15:16:12 +01005540 var NcellReports neighbor_rep := {
5541 { rxlev := 20, bcch_freq := 0, bsic := 11 }
5542 };
5543 var octetstring l3_mr := enc_GsmRrL3Message(valueof(ts_MEAS_REP(true, 8, 8, reps := neighbor_rep)));
5544 RSL.send(ts_RSL_MEAS_RES(g_chan_nr, 0, ts_RSL_IE_UplinkMeas, ts_RSL_IE_BS_Power(0), ts_RSL_IE_L1Info,
5545 l3_mr, 0));
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01005546
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02005547 BSSAP.receive(tr_BSSMAP_HandoverRequired(exp_oldToNewBSSIEs));
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01005548
5549 f_sleep(0.5);
5550 /* The MSC negotiates Handover Request and Handover Request Ack with
5551 * the other BSS and comes back with a BSSMAP Handover Command
5552 * containing an RR Handover Command coming from the target BSS... */
5553
5554 var PDU_ML3_NW_MS rr_ho_cmd := valueof(ts_RR_HandoverCommand);
5555 log("Remote cell's RR Handover Command passed through as L3 Info: ", rr_ho_cmd);
5556 var octetstring rr_ho_cmd_enc := enc_PDU_ML3_NW_MS(rr_ho_cmd);
5557 log("Remote cell's RR Handover Command passed through as L3 Info, encoded: ", rr_ho_cmd_enc);
5558 BSSAP.send(ts_BSSMAP_HandoverCommand(rr_ho_cmd_enc));
5559
5560 /* expect the Handover Command to go out on RR */
5561 var RSL_Message rsl_ho_cmd
5562 RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, ?)) -> value rsl_ho_cmd;
5563 log("RSL Data Req went out to first BTS: ", rsl_ho_cmd);
5564 var RSL_IE_Body rsl_ho_cmd_l3;
5565 if (not f_rsl_find_ie(rsl_ho_cmd, RSL_IE_L3_INFO, rsl_ho_cmd_l3)) {
5566 log("RSL message contains no L3 Info IE, expected RR Handover Command");
5567 setverdict(fail);
5568 } else {
5569 log("Found L3 Info: ", rsl_ho_cmd_l3);
5570 if (rsl_ho_cmd_l3.l3_info.payload != rr_ho_cmd_enc) {
5571 log("FAIL: the BSC sent out a different L3 Info, not matching the RR Handover Command the other BSS forwarded.");
5572 setverdict(fail);
5573 } else {
5574 log("Success: the BSC sent out the same RR Handover Command the other BSS forwarded.");
5575 setverdict(pass);
5576 }
5577 }
5578
5579 /* When the other BSS has reported a completed handover, this side is
5580 * torn down. */
5581
5582 var myBSSMAP_Cause cause_val := GSM0808_CAUSE_HANDOVER_SUCCESSFUL;
5583 var BssmapCause cause := enum2int(cause_val);
5584 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
5585
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02005586 f_expect_dlcx_conns();
Pau Espin Pedrol06199952021-06-15 11:30:00 +02005587
5588 interleave {
5589 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_RELEASE));
5590 [] RSL.receive(tr_RSL_DEACT_SACCH(g_chan_nr));
5591 [] RSL.receive(tr_RSL_RF_CHAN_REL(g_chan_nr));
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02005592 [] BSSAP.receive(tr_BSSMAP_ClearComplete);
Pau Espin Pedrol06199952021-06-15 11:30:00 +02005593 }
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01005594 setverdict(pass);
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02005595}
5596
5597private function f_tc_ho_out_of_this_bsc(charstring id) runs on MSC_ConnHdlr {
5598 g_pars := f_gen_test_hdlr_pars();
5599 var PDU_BSSAP ass_req := f_gen_ass_req();
5600 ass_req.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5601 ass_req.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
5602 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5603 f_establish_fully(ass_req, exp_compl);
5604
5605 f_ho_out_of_this_bsc();
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01005606}
5607testcase TC_ho_out_of_this_bsc() runs on test_CT {
5608 var MSC_ConnHdlr vc_conn;
5609
Neels Hofmeyrafe2ea52021-11-24 15:16:12 +01005610 f_init_vty();
5611 f_bts_0_cfg(BSCVTY,
5612 {"neighbor-list mode automatic",
5613 "handover 1",
5614 "handover algorithm 2",
5615 "handover2 window rxlev averaging 1",
5616 "neighbor lac 99 arfcn 123 bsic any"});
5617 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
5618
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01005619 f_init(1, true);
5620 f_sleep(1.0);
5621
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01005622 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00005623
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01005624 vc_conn := f_start_handler(refers(f_tc_ho_out_of_this_bsc));
5625 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00005626
5627 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
5628 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
5629 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
5630 f_ctrs_bsc_and_bts_add(0, "handover:completed");
5631 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
5632 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:completed");
5633 f_ctrs_bsc_and_bts_verify();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005634 f_shutdown_helper();
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01005635}
5636
Neels Hofmeyr0aa719b2020-10-12 18:43:09 +00005637private function f_mo_l3_transceive(RSL_DCHAN_PT rsl := RSL,
5638 template (value) RslLinkId link_id := ts_RslLinkID_DCCH(0),
Vadim Yanitskiy2ef6a2f2020-10-08 23:17:32 +07005639 template (present) OCT1 dlci := ?,
Vadim Yanitskiyb93aa432020-10-01 14:23:11 +07005640 octetstring l3 := '0123456789'O)
5641runs on MSC_ConnHdlr {
Neels Hofmeyr43654812020-09-25 01:35:35 +02005642 /* The old lchan and conn should still be active. See that arbitrary L3
5643 * is still going through. */
Neels Hofmeyr0aa719b2020-10-12 18:43:09 +00005644 rsl.send(ts_RSL_DATA_IND(g_chan_nr, link_id, l3));
Neels Hofmeyr43654812020-09-25 01:35:35 +02005645 var template PDU_BSSAP exp_data := {
5646 discriminator := '1'B,
5647 spare := '0000000'B,
Vadim Yanitskiyb93aa432020-10-01 14:23:11 +07005648 dlci := dlci,
5649 lengthIndicator := lengthof(l3),
Neels Hofmeyr43654812020-09-25 01:35:35 +02005650 pdu := {
5651 dtap := l3
5652 }
5653 };
5654 BSSAP.receive(exp_data);
5655 setverdict(pass);
5656}
5657
Neels Hofmeyr0aa719b2020-10-12 18:43:09 +00005658private function f_mt_l3_transceive(RSL_DCHAN_PT rsl := RSL,
5659 template (present) RslLinkId link_id := tr_RslLinkID_DCCH(0),
Vadim Yanitskiy0033a3b2020-10-01 22:21:16 +07005660 template (value) OCT1 dlci := '00'O,
5661 octetstring l3 := '0123456789'O)
5662runs on MSC_ConnHdlr {
5663 BSSAP.send(PDU_BSSAP:{
5664 discriminator := '1'B,
5665 spare := '0000000'B,
5666 dlci := dlci,
5667 lengthIndicator := lengthof(l3),
5668 pdu := {
5669 dtap := l3
5670 }
5671 });
Neels Hofmeyr0aa719b2020-10-12 18:43:09 +00005672 rsl.receive(tr_RSL_DATA_REQ(g_chan_nr, link_id, l3));
Vadim Yanitskiy0033a3b2020-10-01 22:21:16 +07005673 setverdict(pass);
5674}
5675
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02005676/* BSC asks for inter-BSC HO, but the MSC decides that it won't happen and
5677 * simply never sends a BSSMAP Handover Command. */
5678private function f_tc_ho_out_fail_no_msc_response(charstring id) runs on MSC_ConnHdlr {
Daniel Willmann3b59eb52018-10-29 15:40:55 +01005679 g_pars := f_gen_test_hdlr_pars();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02005680
5681 var PDU_BSSAP ass_req := f_gen_ass_req();
5682 ass_req.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5683 ass_req.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
5684 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5685 f_establish_fully(ass_req, exp_compl);
5686
Neels Hofmeyr666f0432020-07-04 00:53:07 +02005687 f_bts_0_cfg(BSCVTY, {"neighbor lac 99 arfcn 123 bsic any"});
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02005688 f_vty_transceive(BSCVTY, "handover any to arfcn 123 bsic any");
5689
5690 BSSAP.receive(tr_BSSMAP_HandoverRequired);
5691
5692 /* osmo-bsc should time out 10 seconds after the handover started.
5693 * Let's give it a bit extra. */
5694 f_sleep(15.0);
5695
Vadim Yanitskiy74ae5eb2020-10-01 22:13:29 +07005696 f_mo_l3_transceive();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02005697 f_sleep(1.0);
5698}
5699testcase TC_ho_out_fail_no_msc_response() runs on test_CT {
5700 var MSC_ConnHdlr vc_conn;
5701
5702 f_init(1, true);
5703 f_sleep(1.0);
5704
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01005705 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00005706
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02005707 vc_conn := f_start_handler(refers(f_tc_ho_out_fail_no_msc_response));
5708 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00005709
5710 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
5711 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
5712 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
5713 f_ctrs_bsc_and_bts_add(0, "handover:timeout");
5714 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
5715 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:timeout");
5716 f_ctrs_bsc_and_bts_verify();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005717 f_shutdown_helper();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02005718}
5719
5720/* BSC asks for inter-BSC HO, receives BSSMAP Handover Command, but MS reports
5721 * RR Handover Failure. */
5722private function f_tc_ho_out_fail_rr_ho_failure(charstring id) runs on MSC_ConnHdlr {
Daniel Willmann3b59eb52018-10-29 15:40:55 +01005723 g_pars := f_gen_test_hdlr_pars();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02005724
5725 var PDU_BSSAP ass_req := f_gen_ass_req();
5726 ass_req.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5727 ass_req.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
5728 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5729 f_establish_fully(ass_req, exp_compl);
5730
Neels Hofmeyr666f0432020-07-04 00:53:07 +02005731 f_bts_0_cfg(BSCVTY, {"neighbor lac 99 arfcn 123 bsic any"});
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02005732 f_vty_transceive(BSCVTY, "handover any to arfcn 123 bsic any");
5733
5734 BSSAP.receive(tr_BSSMAP_HandoverRequired);
5735
5736 f_sleep(0.5);
5737 /* The MSC negotiates Handover Request and Handover Request Ack with
5738 * the other BSS and comes back with a BSSMAP Handover Command
5739 * containing an RR Handover Command coming from the target BSS... */
5740
5741 var PDU_ML3_NW_MS rr_ho_cmd := valueof(ts_RR_HandoverCommand);
5742 log("Remote cell's RR Handover Command passed through as L3 Info: ", rr_ho_cmd);
5743 var octetstring rr_ho_cmd_enc := enc_PDU_ML3_NW_MS(rr_ho_cmd);
5744 log("Remote cell's RR Handover Command passed through as L3 Info, encoded: ", rr_ho_cmd_enc);
5745 BSSAP.send(ts_BSSMAP_HandoverCommand(rr_ho_cmd_enc));
5746
5747 /* expect the Handover Command to go out on RR */
5748 var RSL_Message rsl_ho_cmd
5749 RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, ?)) -> value rsl_ho_cmd;
5750 log("RSL Data Req went out to first BTS: ", rsl_ho_cmd);
5751 var RSL_IE_Body rsl_ho_cmd_l3;
5752 if (not f_rsl_find_ie(rsl_ho_cmd, RSL_IE_L3_INFO, rsl_ho_cmd_l3)) {
5753 log("RSL message contains no L3 Info IE, expected RR Handover Command");
5754 setverdict(fail);
5755 } else {
5756 log("Found L3 Info: ", rsl_ho_cmd_l3);
5757 if (rsl_ho_cmd_l3.l3_info.payload != rr_ho_cmd_enc) {
5758 log("FAIL: the BSC sent out a different L3 Info, not matching the RR Handover Command the other BSS forwarded.");
5759 setverdict(fail);
5760 } else {
5761 log("Success: the BSC sent out the same RR Handover Command the other BSS forwarded.");
5762 setverdict(pass);
5763 }
5764 }
5765
5766 f_sleep(0.2);
5767 f_rsl_send_l3(ts_RRM_HandoverFailure('00'O));
5768
5769 /* Should tell the MSC about the failure */
5770 BSSAP.receive(tr_BSSMAP_HandoverFailure);
5771
5772 f_sleep(1.0);
5773
Vadim Yanitskiy74ae5eb2020-10-01 22:13:29 +07005774 f_mo_l3_transceive();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02005775 f_sleep(1.0);
5776
5777 setverdict(pass);
5778 f_sleep(1.0);
5779}
5780testcase TC_ho_out_fail_rr_ho_failure() 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_rr_ho_failure));
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:failed");
5795 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
5796 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:failed");
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
Neels Hofmeyr10f2bfa2019-07-09 19:33:29 +02005801/* BSC asks for inter-BSC-out HO, receives BSSMAP Handover Command, but then no reply is received about HO outcome
5802 * (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 +02005803 * and the lchan is released. */
5804private function f_tc_ho_out_fail_no_result_after_ho_cmd(charstring id) runs on MSC_ConnHdlr {
Daniel Willmann3b59eb52018-10-29 15:40:55 +01005805 g_pars := f_gen_test_hdlr_pars();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02005806
5807 var PDU_BSSAP ass_req := f_gen_ass_req();
5808 ass_req.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5809 ass_req.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
5810 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5811 f_establish_fully(ass_req, exp_compl);
5812
Neels Hofmeyr666f0432020-07-04 00:53:07 +02005813 f_bts_0_cfg(BSCVTY, {"neighbor lac 99 arfcn 123 bsic any"});
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02005814 f_vty_transceive(BSCVTY, "handover any to arfcn 123 bsic any");
5815
5816 BSSAP.receive(tr_BSSMAP_HandoverRequired);
5817
5818 f_sleep(0.5);
5819 /* The MSC negotiates Handover Request and Handover Request Ack with
5820 * the other BSS and comes back with a BSSMAP Handover Command
5821 * containing an RR Handover Command coming from the target BSS... */
5822
5823 var PDU_ML3_NW_MS rr_ho_cmd := valueof(ts_RR_HandoverCommand);
5824 log("Remote cell's RR Handover Command passed through as L3 Info: ", rr_ho_cmd);
5825 var octetstring rr_ho_cmd_enc := enc_PDU_ML3_NW_MS(rr_ho_cmd);
5826 log("Remote cell's RR Handover Command passed through as L3 Info, encoded: ", rr_ho_cmd_enc);
5827 BSSAP.send(ts_BSSMAP_HandoverCommand(rr_ho_cmd_enc));
5828
5829 /* expect the Handover Command to go out on RR */
5830 var RSL_Message rsl_ho_cmd
5831 RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, ?)) -> value rsl_ho_cmd;
5832 log("RSL Data Req went out to first BTS: ", rsl_ho_cmd);
5833 var RSL_IE_Body rsl_ho_cmd_l3;
5834 if (not f_rsl_find_ie(rsl_ho_cmd, RSL_IE_L3_INFO, rsl_ho_cmd_l3)) {
5835 log("RSL message contains no L3 Info IE, expected RR Handover Command");
5836 setverdict(fail);
5837 } else {
5838 log("Found L3 Info: ", rsl_ho_cmd_l3);
5839 if (rsl_ho_cmd_l3.l3_info.payload != rr_ho_cmd_enc) {
5840 log("FAIL: the BSC sent out a different L3 Info, not matching the RR Handover Command the other BSS forwarded.");
5841 setverdict(fail);
5842 } else {
5843 log("Success: the BSC sent out the same RR Handover Command the other BSS forwarded.");
5844 setverdict(pass);
5845 }
5846 }
5847
Neels Hofmeyr10f2bfa2019-07-09 19:33:29 +02005848 /* We get neither success nor failure report from the remote BSS. Eventually T8 times out and we run into 3GPP
5849 * TS 48.008 3.1.5.3.3 "Abnormal Conditions": Clear Request should go to the MSC, and RR should be released
5850 * after Clear Command */
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02005851
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02005852 var PDU_BSSAP rx_clear_request;
Neels Hofmeyre1797aa2019-07-09 19:34:04 +02005853 BSSAP.receive(tr_BSSMAP_ClearRequest) -> value rx_clear_request;
5854 log("Got BSSMAP Clear Request");
5855 /* Instruct BSC to clear channel */
5856 var BssmapCause cause := bit2int(rx_clear_request.pdu.bssmap.clearRequest.cause.causeValue);
5857 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
5858
5859 var MgcpCommand mgcp;
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02005860 interleave {
Neels Hofmeyr861a4c12018-11-07 01:23:17 +01005861 [] RSL.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {
5862 log("Got Deact SACCH");
5863 }
Harald Welte924b6ea2019-02-04 01:05:34 +01005864 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_RELEASE)) {
Neels Hofmeyr211169d2018-11-07 00:37:29 +01005865 log("Got RR Release");
5866 }
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +02005867 [] RSL.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02005868 log("Got RF Chan Rel");
5869 RSL.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
Neels Hofmeyre680b012021-07-22 19:19:09 +02005870 f_rslem_unregister(0, g_chan_nr);
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02005871 }
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02005872 }
5873
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02005874 f_expect_dlcx_conns();
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02005875 BSSAP.receive(tr_BSSMAP_ClearComplete);
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005876
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02005877 setverdict(pass);
5878 f_sleep(1.0);
5879}
Neels Hofmeyrd8a602c2019-07-09 19:46:01 +02005880testcase TC_ho_out_fail_no_result_after_ho_cmd() runs on test_CT {
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02005881 var MSC_ConnHdlr vc_conn;
5882
5883 f_init(1, true);
5884 f_sleep(1.0);
5885
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01005886 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00005887
Neels Hofmeyrd8a602c2019-07-09 19:46:01 +02005888 vc_conn := f_start_handler(refers(f_tc_ho_out_fail_no_result_after_ho_cmd));
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02005889 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00005890
5891 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
5892 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
5893 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
5894 f_ctrs_bsc_and_bts_add(0, "handover:timeout");
5895 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
5896 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:timeout");
5897 f_ctrs_bsc_and_bts_verify();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005898 f_shutdown_helper();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02005899}
5900
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02005901private 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 +01005902 /* Hack: the proper way would be to wait for the BSSMAP Handover Request ACK and extract the
5903 * actual assigned chan_nr from its L3 (RR Handover Command) message. But osmo-bsc starts acting
5904 * on the lchan even before we get a chance to evaluate the BSSMAP Handover Request ACK. So we
5905 * need to assume that osmo-bsc will activate TS 1 and already set up this lchan's RSL emulation
5906 * before we get started. */
5907 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
5908 f_rslem_register(0, new_chan_nr);
5909 g_chan_nr := new_chan_nr;
Neels Hofmeyr34174bd2021-10-02 14:52:57 +02005910 var uint3_t expect_target_tsc := BTS_TSC[0];
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01005911 f_sleep(1.0);
5912
5913 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
5914 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
5915 activate(as_Media());
5916
Neels Hofmeyr90f80962020-06-12 16:16:55 +02005917 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02005918 f_gen_handover_req(aoip_tla := g_pars.host_aoip_tla,
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02005919 oldToNewBSSIEs := oldToNewBSSIEs,
5920 enc := g_pars.encr)));
Harald Welte6811d102019-04-14 22:23:14 +02005921 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01005922
5923 /* The RSL Emulation magically accepts the Chan Activ behind the scenes. */
5924
5925 var PDU_BSSAP rx_bssap;
5926 var octetstring ho_command_str;
5927
5928 BSSAP.receive(tr_BSSMAP_HandoverRequestAcknowledge(?)) -> value rx_bssap;
Pau Espin Pedrol76ba5412019-06-10 11:00:33 +02005929
Neels Hofmeyr34174bd2021-10-02 14:52:57 +02005930 /* we're sure that the channel activation is done now, verify the parameters in it */
5931 var RSL_Message chan_act := f_rslem_get_last_act(RSL_PROC, 0, g_chan_nr);
5932 f_verify_encr_info(chan_act);
5933 f_chan_act_verify_tsc(chan_act, expect_target_tsc);
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02005934
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01005935 ho_command_str := rx_bssap.pdu.bssmap.handoverRequestAck.layer3Information.layer3info;
5936 log("Received L3 Info in HO Request Ack: ", ho_command_str);
5937 var PDU_ML3_NW_MS ho_command := dec_PDU_ML3_NW_MS(ho_command_str);
5938 log("L3 Info in HO Request Ack is ", ho_command);
5939
5940 var GsmArfcn arfcn;
5941 var RslChannelNr actual_new_chan_nr;
5942 f_ChDesc2RslChanNr(ho_command.msgs.rrm.handoverCommand.channelDescription2,
5943 actual_new_chan_nr, arfcn);
5944
5945 if (actual_new_chan_nr != new_chan_nr) {
5946 log("ERROR: osmo-bsc assigned a different lchan than we assumed above -- this test will fail now.",
5947 " Assumed: ", new_chan_nr, " Assigned: ", actual_new_chan_nr);
5948 setverdict(fail);
5949 return;
5950 }
5951 log("Handover Command chan_nr is", actual_new_chan_nr);
5952
Neels Hofmeyr34174bd2021-10-02 14:52:57 +02005953 var uint3_t got_tsc := rr_chan_desc_tsc(ho_command.msgs.rrm.handoverCommand.channelDescription2);
5954 if (not match(got_tsc, expect_target_tsc)) {
5955 setverdict(fail, "RR Handover Command: unexpected TSC in Channel Description: expected ",
5956 expect_target_tsc, " got ", got_tsc);
5957 mtc.stop;
5958 } else {
5959 log("handoverCommand: verified TSC = ", got_tsc);
5960 }
5961
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01005962 /* Now the MSC forwards the RR Handover Command to the other BSC, which
5963 * tells the MS to handover to the new lchan. Here comes the new MS on
5964 * the new lchan with a Handover RACH: */
5965
5966 /* send handover detect */
5967
5968 RSL.send(ts_RSL_HANDO_DET(new_chan_nr));
5969
5970 BSSAP.receive(tr_BSSMAP_HandoverDetect);
5971
5972 /* send handover complete over the new channel */
5973
5974 var PDU_ML3_MS_NW l3_tx := valueof(ts_RRM_HandoverComplete('00'O));
5975 RSL.send(ts_RSL_EST_IND(new_chan_nr, valueof(ts_RslLinkID_DCCH(0)),
5976 enc_PDU_ML3_MS_NW(l3_tx)));
5977
5978 BSSAP.receive(tr_BSSMAP_HandoverComplete);
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02005979 setverdict(pass);
5980}
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02005981
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02005982private function f_tc_ho_into_this_bsc(charstring id) runs on MSC_ConnHdlr {
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02005983 var template PDU_ML3_NW_MS exp_rr_rel_tmpl;
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02005984 var template (omit) BSSMAP_oldToNewBSSIEs oldToNewBSSIEs := omit;
5985 if (not istemplatekind(g_pars.last_used_eutran_plmn, "omit")) {
5986 oldToNewBSSIEs := f_ts_BSSMAP_oldToNewBSSIEs(ts_BSSMAP_LastUsedEUTRANPLMNId(g_pars.last_used_eutran_plmn));
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02005987 }
5988 if (g_pars.exp_fast_return) {
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02005989 exp_rr_rel_tmpl := tr_RRM_RR_RELEASE_CellSelectInd;
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02005990 } else {
5991 exp_rr_rel_tmpl := tr_RRM_RR_RELEASE;
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02005992 }
5993 f_ho_into_this_bsc(id, oldToNewBSSIEs);
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02005994 f_perform_clear(exp_rr_rel_tmpl := exp_rr_rel_tmpl);
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01005995 setverdict(pass);
5996}
Pau Espin Pedrol07866632020-09-03 19:10:55 +02005997function f_tc_ho_into_this_bsc_main(TestHdlrParams pars) runs on test_CT {
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01005998 var MSC_ConnHdlr vc_conn;
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01005999
6000 f_init(1, true);
6001 f_sleep(1.0);
6002
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006003 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006004
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006005 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
6006 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006007
6008 vc_conn := f_start_handler(refers(f_tc_ho_into_this_bsc), pars);
6009 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006010
6011 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6012 f_ctrs_bsc_and_bts_add(0, "handover:completed");
6013 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:attempted");
6014 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:completed");
6015 f_ctrs_bsc_and_bts_verify();
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006016}
6017
Pau Espin Pedrol07866632020-09-03 19:10:55 +02006018testcase TC_ho_into_this_bsc() runs on test_CT {
6019 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6020 f_tc_ho_into_this_bsc_main(pars);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02006021 f_shutdown_helper();
Pau Espin Pedrol07866632020-09-03 19:10:55 +02006022}
6023
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02006024function f_tc_ho_into_this_bsc_a5(OCT1 encr_alg) runs on test_CT {
6025 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6026 pars.encr := valueof(t_EncrParams(encr_alg, f_rnd_octstring(8), f_rnd_octstring(16)));
6027 f_tc_ho_into_this_bsc_main(pars);
6028 f_shutdown_helper();
6029}
6030
6031testcase TC_ho_into_this_bsc_a5_0() runs on test_CT {
6032 f_tc_ho_into_this_bsc_a5('01'O);
6033}
6034
6035testcase TC_ho_into_this_bsc_a5_1() runs on test_CT {
6036 f_tc_ho_into_this_bsc_a5('02'O);
6037}
6038
6039testcase TC_ho_into_this_bsc_a5_3() runs on test_CT {
6040 f_tc_ho_into_this_bsc_a5('08'O);
6041}
6042
6043testcase TC_ho_into_this_bsc_a5_4() runs on test_CT {
6044 f_tc_ho_into_this_bsc_a5('10'O);
6045}
6046
Pau Espin Pedrol07866632020-09-03 19:10:55 +02006047testcase TC_ho_into_this_bsc_tla_v6() runs on test_CT {
6048 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6049 pars.host_aoip_tla := "::6";
6050 f_tc_ho_into_this_bsc_main(pars);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02006051 f_shutdown_helper();
Pau Espin Pedrol07866632020-09-03 19:10:55 +02006052}
6053
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02006054/* Similar to TC_ho_into_this_bsc, but when in SRVCC, HO Req contains "Old BSS
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006055 to New BSS Information" IE with "Last Used E-UTRAN PLMN Id", which, when the
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02006056 channel is later released (RR CHannel Release), should trigger inclusion of
6057 IE "Cell Selection Indicator after Release of all TCH and SDCCH" with E-UTRAN
6058 neighbors. */
6059testcase TC_srvcc_eutran_to_geran() runs on test_CT {
6060 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6061 pars.last_used_eutran_plmn := '323454'O;
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006062 pars.exp_fast_return := true;
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02006063 f_tc_ho_into_this_bsc_main(pars);
Pau Espin Pedrol211a7142021-06-15 16:43:03 +02006064
6065 f_ctrs_bsc_and_bts_add(0, "srvcc:attempted");
6066 f_ctrs_bsc_and_bts_add(0, "srvcc:completed");
6067 f_ctrs_bsc_and_bts_verify();
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02006068 f_shutdown_helper();
6069}
6070
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006071/* Same as TC_srvcc_eutran_to_geran, but test explicitly forbiding fast return
6072 on the BTS. As a result, RR Release shouldn't contain the EUTRAN neighbor
6073 list when the channel is released. */
6074testcase TC_srvcc_eutran_to_geran_forbid_fast_return() runs on test_CT {
6075 f_init_vty();
6076 f_vty_allow_srvcc_fast_return(true, 0)
6077
6078 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6079 pars.last_used_eutran_plmn := '323454'O;
6080 pars.exp_fast_return := false;
6081 f_tc_ho_into_this_bsc_main(pars);
6082 f_vty_allow_srvcc_fast_return(false, 0);
6083 f_shutdown_helper();
6084}
6085
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006086private function f_tc_srvcc_eutran_to_geran_ho_out(charstring id) runs on MSC_ConnHdlr {
6087 var template (omit) BSSMAP_oldToNewBSSIEs oldToNewBSSIEs;
6088 oldToNewBSSIEs := f_ts_BSSMAP_oldToNewBSSIEs(ts_BSSMAP_LastUsedEUTRANPLMNId(g_pars.last_used_eutran_plmn));
6089 f_ho_into_this_bsc(id, oldToNewBSSIEs);
6090 f_ho_out_of_this_bsc(oldToNewBSSIEs);
6091 setverdict(pass);
6092}
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006093
6094private function f_tc_srvcc_eutran_to_geran_ho_out_main(boolean disable_fast_return)
6095 runs on test_CT {
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006096 var MSC_ConnHdlr vc_conn;
6097 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6098
6099 f_init(1, true);
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006100 if (disable_fast_return) {
6101 f_vty_allow_srvcc_fast_return(true, 0);
6102 }
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006103 f_sleep(1.0);
6104
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006105 f_ctrs_bsc_and_bts_handover_init();
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006106
6107 pars.last_used_eutran_plmn := '323454'O;
6108 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
6109 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
6110
6111 vc_conn := f_start_handler(refers(f_tc_srvcc_eutran_to_geran_ho_out), pars);
6112 vc_conn.done;
6113
6114 f_ctrs_bsc_and_bts_add(0, "handover:attempted", 2);
6115 f_ctrs_bsc_and_bts_add(0, "handover:completed", 2);
6116 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:attempted", 1);
6117 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:completed", 1);
6118 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted", 1);
6119 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:completed", 1);
Pau Espin Pedrol211a7142021-06-15 16:43:03 +02006120
6121 f_ctrs_bsc_and_bts_add(0, "srvcc:attempted", 1);
6122 f_ctrs_bsc_and_bts_add(0, "srvcc:completed", 1);
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006123 f_ctrs_bsc_and_bts_verify();
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006124
6125 if (disable_fast_return) {
6126 f_vty_allow_srvcc_fast_return(false, 0);
6127 }
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006128 f_shutdown_helper();
6129}
6130
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006131/* First, HO into BSC from EUTRAN (SRVCC): HO Request contains "Old BSS to New
6132 BSS Information" IE with "Last Used E-UTRAN PLMN Id".
6133 Second, HO to another BSC: HO Required contains "Old BSS to New BSS Information"
6134 IE with "Last Used E-UTRAN PLMN Id" from first step. */
6135testcase TC_srvcc_eutran_to_geran_ho_out() runs on test_CT {
6136 f_tc_srvcc_eutran_to_geran_ho_out_main(false);
6137}
6138/* Validate subsequent intra-GSM-HO works the same (with OldBSSToNewBSSInfo IE)
6139 * independently of fast-reture allowed/forbidden in local BTS */
6140testcase TC_srvcc_eutran_to_geran_ho_out_forbid_fast_return() runs on test_CT {
6141 f_tc_srvcc_eutran_to_geran_ho_out_main(true);
6142}
6143
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006144private function f_tc_ho_in_fail_msc_clears(charstring id) runs on MSC_ConnHdlr {
6145 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
6146 f_rslem_register(0, new_chan_nr);
6147 g_chan_nr := new_chan_nr;
6148 f_sleep(1.0);
6149
6150 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
6151 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
6152 activate(as_Media());
6153
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006154 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006155 f_gen_handover_req()));
Harald Welte6811d102019-04-14 22:23:14 +02006156 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006157
6158 /* The RSL Emulation magically accepts the Chan Activ behind the scenes. */
6159
6160 var PDU_BSSAP rx_bssap;
6161 var octetstring ho_command_str;
6162
6163 BSSAP.receive(tr_BSSMAP_HandoverRequestAcknowledge(?)) -> value rx_bssap;
6164
6165 ho_command_str := rx_bssap.pdu.bssmap.handoverRequestAck.layer3Information.layer3info;
6166 log("Received L3 Info in HO Request Ack: ", ho_command_str);
6167 var PDU_ML3_NW_MS ho_command := dec_PDU_ML3_NW_MS(ho_command_str);
6168 log("L3 Info in HO Request Ack is ", ho_command);
6169
6170 var GsmArfcn arfcn;
6171 var RslChannelNr actual_new_chan_nr;
6172 f_ChDesc2RslChanNr(ho_command.msgs.rrm.handoverCommand.channelDescription2,
6173 actual_new_chan_nr, arfcn);
6174
6175 if (actual_new_chan_nr != new_chan_nr) {
6176 log("ERROR: osmo-bsc assigned a different lchan than we assumed above -- this test will fail now.",
6177 " Assumed: ", new_chan_nr, " Assigned: ", actual_new_chan_nr);
6178 setverdict(fail);
6179 return;
6180 }
6181 log("Handover Command chan_nr is", actual_new_chan_nr);
6182
Neels Hofmeyr61ca08d2019-05-06 23:52:22 +02006183 /* For deterministic test results, give some time for the MGW endpoint to be configured */
6184 f_sleep(1.0);
6185
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006186 /* Now the MSC forwards the RR Handover Command to the other BSC, which
6187 * tells the MS to handover to the new lchan. In this case, the MS
6188 * reports a Handover Failure to the old BSS, which forwards a BSSMAP
6189 * Handover Failure to the MSC. The procedure according to 3GPP TS
6190 * 48.008 3.1.5.3.2 "Handover Failure" is then that the MSC sends a
6191 * BSSMAP Clear Command: */
6192
6193 var myBSSMAP_Cause cause_val := GSM0808_CAUSE_RADIO_INTERFACE_FAILURE_REVERSION;
6194 var BssmapCause cause := enum2int(cause_val);
6195 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
6196
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02006197 f_expect_dlcx_conns();
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02006198 BSSAP.receive(tr_BSSMAP_ClearComplete);
6199
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006200 setverdict(pass);
6201 f_sleep(1.0);
6202
6203 setverdict(pass);
6204}
6205testcase TC_ho_in_fail_msc_clears() runs on test_CT {
6206 var MSC_ConnHdlr vc_conn;
6207 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6208
6209 f_init(1, true);
6210 f_sleep(1.0);
6211
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006212 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006213
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006214 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
6215 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006216
6217 vc_conn := f_start_handler(refers(f_tc_ho_in_fail_msc_clears), pars);
6218 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006219
6220 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6221 f_ctrs_bsc_and_bts_add(0, "handover:stopped");
6222 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:attempted");
6223 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:stopped");
6224 f_ctrs_bsc_and_bts_verify();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02006225 f_shutdown_helper();
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006226}
6227
6228private function f_tc_ho_in_fail_msc_clears_after_ho_detect(charstring id) runs on MSC_ConnHdlr {
6229 /* Hack: the proper way would be to wait for the BSSMAP Handover Request ACK and extract the
6230 * actual assigned chan_nr from its L3 (RR Handover Command) message. But osmo-bsc starts acting
6231 * on the lchan even before we get a chance to evaluate the BSSMAP Handover Request ACK. So we
6232 * need to assume that osmo-bsc will activate TS 1 and already set up this lchan's RSL emulation
6233 * before we get started. */
6234 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
6235 f_rslem_register(0, new_chan_nr);
6236 g_chan_nr := new_chan_nr;
6237 f_sleep(1.0);
6238
6239 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
6240 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
6241 activate(as_Media());
6242
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006243 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006244 f_gen_handover_req()));
Harald Welte6811d102019-04-14 22:23:14 +02006245 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006246
6247 /* The RSL Emulation magically accepts the Chan Activ behind the scenes. */
6248
6249 var PDU_BSSAP rx_bssap;
6250 var octetstring ho_command_str;
6251
6252 BSSAP.receive(tr_BSSMAP_HandoverRequestAcknowledge(?)) -> value rx_bssap;
6253
6254 ho_command_str := rx_bssap.pdu.bssmap.handoverRequestAck.layer3Information.layer3info;
6255 log("Received L3 Info in HO Request Ack: ", ho_command_str);
6256 var PDU_ML3_NW_MS ho_command := dec_PDU_ML3_NW_MS(ho_command_str);
6257 log("L3 Info in HO Request Ack is ", ho_command);
6258
6259 var GsmArfcn arfcn;
6260 var RslChannelNr actual_new_chan_nr;
6261 f_ChDesc2RslChanNr(ho_command.msgs.rrm.handoverCommand.channelDescription2,
6262 actual_new_chan_nr, arfcn);
6263
6264 if (actual_new_chan_nr != new_chan_nr) {
6265 log("ERROR: osmo-bsc assigned a different lchan than we assumed above -- this test will fail now.",
6266 " Assumed: ", new_chan_nr, " Assigned: ", actual_new_chan_nr);
6267 setverdict(fail);
6268 return;
6269 }
6270 log("Handover Command chan_nr is", actual_new_chan_nr);
6271
6272 /* Now the MSC forwards the RR Handover Command to the other BSC, which
6273 * tells the MS to handover to the new lchan. Here comes the new MS on
6274 * the new lchan with a Handover RACH: */
6275
6276 /* send handover detect */
6277
6278 RSL.send(ts_RSL_HANDO_DET(new_chan_nr));
6279
6280 BSSAP.receive(tr_BSSMAP_HandoverDetect);
6281
6282 /* The MSC chooses to clear the connection now, maybe we got the
6283 * Handover RACH on the new cell but the MS still signaled Handover
6284 * Failure to the old BSS? */
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);
6292
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006293 f_sleep(1.0);
6294}
6295testcase TC_ho_in_fail_msc_clears_after_ho_detect() runs on test_CT {
6296 var MSC_ConnHdlr vc_conn;
6297 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6298
6299 f_init(1, true);
6300 f_sleep(1.0);
6301
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006302 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006303
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006304 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
6305 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006306
6307 vc_conn := f_start_handler(refers(f_tc_ho_in_fail_msc_clears_after_ho_detect), pars);
6308 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006309
6310 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6311 f_ctrs_bsc_and_bts_add(0, "handover:stopped");
6312 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:attempted");
6313 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:stopped");
6314 f_ctrs_bsc_and_bts_verify();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02006315 f_shutdown_helper();
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006316}
6317
6318/* The new BSS's lchan times out before the MSC decides that handover failed. */
6319private function f_tc_ho_in_fail_no_detect(charstring id) runs on MSC_ConnHdlr {
6320 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
6321 f_rslem_register(0, new_chan_nr);
6322 g_chan_nr := new_chan_nr;
6323 f_sleep(1.0);
6324
6325 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
6326 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
6327 activate(as_Media());
6328
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006329 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006330 f_gen_handover_req()));
Harald Welte6811d102019-04-14 22:23:14 +02006331 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006332
6333 /* The RSL Emulation magically accepts the Chan Activ behind the scenes. */
6334
6335 var PDU_BSSAP rx_bssap;
6336 var octetstring ho_command_str;
6337
6338 BSSAP.receive(tr_BSSMAP_HandoverRequestAcknowledge(?)) -> value rx_bssap;
6339
6340 ho_command_str := rx_bssap.pdu.bssmap.handoverRequestAck.layer3Information.layer3info;
6341 log("Received L3 Info in HO Request Ack: ", ho_command_str);
6342 var PDU_ML3_NW_MS ho_command := dec_PDU_ML3_NW_MS(ho_command_str);
6343 log("L3 Info in HO Request Ack is ", ho_command);
6344
6345 var GsmArfcn arfcn;
6346 var RslChannelNr actual_new_chan_nr;
6347 f_ChDesc2RslChanNr(ho_command.msgs.rrm.handoverCommand.channelDescription2,
6348 actual_new_chan_nr, arfcn);
6349
6350 if (actual_new_chan_nr != new_chan_nr) {
6351 log("ERROR: osmo-bsc assigned a different lchan than we assumed above -- this test will fail now.",
6352 " Assumed: ", new_chan_nr, " Assigned: ", actual_new_chan_nr);
6353 setverdict(fail);
6354 return;
6355 }
6356 log("Handover Command chan_nr is", actual_new_chan_nr);
6357
6358 /* Now the MSC forwards the RR Handover Command to the other BSC, which
6359 * tells the MS to handover to the new lchan. But the MS never shows up
6360 * on the new lchan. */
6361
6362 BSSAP.receive(tr_BSSMAP_HandoverFailure);
6363
6364 /* Did osmo-bsc also send a Clear Request? */
6365 timer T := 0.5;
6366 T.start;
6367 alt {
6368 [] BSSAP.receive(tr_BSSMAP_ClearRequest);
6369 [] T.timeout { }
6370 }
6371
6372 /* MSC plays along with a Clear Command (no matter whether osmo-bsc
6373 * asked for it, this is a Handover Failure after all). */
6374
6375 var myBSSMAP_Cause cause_val := GSM0808_CAUSE_RADIO_INTERFACE_FAILURE_REVERSION;
6376 var BssmapCause cause := enum2int(cause_val);
6377 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
6378
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02006379 f_expect_dlcx_conns();
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02006380 BSSAP.receive(tr_BSSMAP_ClearComplete);
6381
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006382 f_sleep(1.0);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006383}
6384testcase TC_ho_in_fail_no_detect() runs on test_CT {
6385 var MSC_ConnHdlr vc_conn;
6386 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6387
6388 f_init(1, true);
6389 f_sleep(1.0);
6390
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006391 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006392
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006393 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
6394 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006395
6396 vc_conn := f_start_handler(refers(f_tc_ho_in_fail_no_detect), pars);
6397 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006398
6399 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6400 f_ctrs_bsc_and_bts_add(0, "handover:error");
6401 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:attempted");
6402 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:error");
6403 f_ctrs_bsc_and_bts_verify();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02006404 f_shutdown_helper();
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006405}
6406
6407/* Same as f_tc_ho_in_fail_no_detect, but MSC fails to send a Clear Command */
6408private function f_tc_ho_in_fail_no_detect2(charstring id) runs on MSC_ConnHdlr {
6409 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
6410 f_rslem_register(0, new_chan_nr);
6411 g_chan_nr := new_chan_nr;
6412 f_sleep(1.0);
6413
6414 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
6415 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
6416 activate(as_Media());
6417
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006418 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006419 f_gen_handover_req()));
Harald Welte6811d102019-04-14 22:23:14 +02006420 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006421
6422 /* The RSL Emulation magically accepts the Chan Activ behind the scenes. */
6423
6424 var PDU_BSSAP rx_bssap;
6425 var octetstring ho_command_str;
6426
6427 BSSAP.receive(tr_BSSMAP_HandoverRequestAcknowledge(?)) -> value rx_bssap;
6428
6429 ho_command_str := rx_bssap.pdu.bssmap.handoverRequestAck.layer3Information.layer3info;
6430 log("Received L3 Info in HO Request Ack: ", ho_command_str);
6431 var PDU_ML3_NW_MS ho_command := dec_PDU_ML3_NW_MS(ho_command_str);
6432 log("L3 Info in HO Request Ack is ", ho_command);
6433
6434 var GsmArfcn arfcn;
6435 var RslChannelNr actual_new_chan_nr;
6436 f_ChDesc2RslChanNr(ho_command.msgs.rrm.handoverCommand.channelDescription2,
6437 actual_new_chan_nr, arfcn);
6438
6439 if (actual_new_chan_nr != new_chan_nr) {
6440 log("ERROR: osmo-bsc assigned a different lchan than we assumed above -- this test will fail now.",
6441 " Assumed: ", new_chan_nr, " Assigned: ", actual_new_chan_nr);
6442 setverdict(fail);
6443 return;
6444 }
6445 log("Handover Command chan_nr is", actual_new_chan_nr);
6446
6447 /* Now the MSC forwards the RR Handover Command to the other BSC, which
6448 * tells the MS to handover to the new lchan. But the MS never shows up
6449 * on the new lchan. */
6450
6451 BSSAP.receive(tr_BSSMAP_HandoverFailure);
6452
6453 /* MSC plays dumb and sends no Clear Command */
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006454 var PDU_BSSAP rx_clear_request;
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02006455
6456 BSSAP.receive(tr_BSSMAP_ClearRequest) -> value rx_clear_request {
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006457 var BssmapCause cause := bit2int(rx_clear_request.pdu.bssmap.clearRequest.cause.causeValue);
6458 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
6459 };
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02006460 f_expect_dlcx_conns();
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02006461 BSSAP.receive(tr_BSSMAP_ClearComplete);
6462
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006463 f_sleep(1.0);
6464}
6465testcase TC_ho_in_fail_no_detect2() runs on test_CT {
6466 var MSC_ConnHdlr vc_conn;
6467 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6468
6469 f_init(1, true);
6470 f_sleep(1.0);
6471
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006472 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006473
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006474 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
6475 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006476
6477 vc_conn := f_start_handler(refers(f_tc_ho_in_fail_no_detect2), pars);
6478 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006479
6480 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6481 f_ctrs_bsc_and_bts_add(0, "handover:error");
6482 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:attempted");
6483 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:error");
6484 f_ctrs_bsc_and_bts_verify();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02006485 f_shutdown_helper();
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006486}
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006487
Neels Hofmeyr91401012019-07-11 00:42:35 +02006488type record of charstring Commands;
6489
Neels Hofmeyr666f0432020-07-04 00:53:07 +02006490private function f_bts_0_cfg(TELNETasp_PT pt, Commands cmds := {})
Neels Hofmeyr91401012019-07-11 00:42:35 +02006491{
Neels Hofmeyr666f0432020-07-04 00:53:07 +02006492 f_vty_enter_cfg_bts(pt, 0);
Neels Hofmeyr91401012019-07-11 00:42:35 +02006493 for (var integer i := 0; i < sizeof(cmds); i := i+1) {
Neels Hofmeyr666f0432020-07-04 00:53:07 +02006494 f_vty_transceive(pt, cmds[i]);
Neels Hofmeyr91401012019-07-11 00:42:35 +02006495 }
Neels Hofmeyr666f0432020-07-04 00:53:07 +02006496 f_vty_transceive(pt, "end");
Neels Hofmeyr91401012019-07-11 00:42:35 +02006497}
6498
Pau Espin Pedrolc675b612020-01-09 19:55:40 +01006499private function f_cs7_inst_0_cfg(TELNETasp_PT pt, Commands cmds := {})
6500{
6501 f_vty_enter_cfg_cs7_inst(pt, 0);
6502 for (var integer i := 0; i < sizeof(cmds); i := i+1) {
6503 f_vty_transceive(pt, cmds[i]);
6504 }
6505 f_vty_transceive(pt, "end");
6506}
6507
Neels Hofmeyr91401012019-07-11 00:42:35 +02006508private function f_probe_for_handover(charstring log_label,
6509 charstring log_descr,
6510 charstring handover_vty_cmd,
6511 boolean expect_handover,
Neels Hofmeyr6a955cc2021-10-02 14:53:48 +02006512 boolean is_inter_bsc_handover := false,
6513 template uint3_t expect_target_tsc := ?)
Neels Hofmeyr91401012019-07-11 00:42:35 +02006514runs on MSC_ConnHdlr
6515{
Neels Hofmeyrb3fc8982020-05-11 00:16:42 +02006516 /* We're going to thwart any and all handover attempts, just be ready to handle (and ignore) handover target
6517 * lchans to be established on bts 1 or bts 2. */
6518 f_rslem_suspend(RSL1_PROC);
6519 f_rslem_suspend(RSL2_PROC);
6520
Neels Hofmeyr91401012019-07-11 00:42:35 +02006521 var RSL_Message rsl;
6522
6523 var charstring log_msg := " (expecting handover)"
6524 if (not expect_handover) {
6525 log_msg := " (expecting NO handover)";
6526 }
6527 log("f_probe_for_handover starting: " & log_label & ": " & log_descr & log_msg);
6528 f_vty_transceive(BSCVTY, handover_vty_cmd);
6529
Neels Hofmeyr91401012019-07-11 00:42:35 +02006530 timer T := 2.0;
6531 T.start;
6532
6533 alt {
6534 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr)) -> value rsl {
6535 var PDU_ML3_NW_MS l3 := dec_PDU_ML3_NW_MS(rsl.ies[2].body.l3_info.payload);
6536 log("Rx L3 from net: ", l3);
6537 if (ischosen(l3.msgs.rrm.handoverCommand)) {
6538 var RslChannelNr new_chan_nr;
6539 var GsmArfcn arfcn;
6540 f_ChDesc2RslChanNr(l3.msgs.rrm.handoverCommand.channelDescription2,
6541 new_chan_nr, arfcn);
6542 log("Handover to new chan ", new_chan_nr, " on ARFCN ", arfcn);
6543 log(l3.msgs.rrm.handoverCommand);
6544
Neels Hofmeyr6a955cc2021-10-02 14:53:48 +02006545 /* Verify correct TSC in handoverCommand */
6546 var uint3_t got_tsc := rr_chan_desc_tsc(l3.msgs.rrm.handoverCommand.channelDescription2);
6547 if (not match(got_tsc, expect_target_tsc)) {
6548 setverdict(fail, "RR Handover Command: unexpected TSC in Channel Description: expected ",
6549 expect_target_tsc, " got ", got_tsc);
6550 mtc.stop;
6551 } else {
6552 log("handoverCommand: verified TSC = ", got_tsc, " (matches ",
6553 expect_target_tsc, ")");
6554 }
6555
Neels Hofmeyr91401012019-07-11 00:42:35 +02006556 /* Need to register for new lchan on new BTS -- it's either bts 1 or bts 2. It doesn't really
6557 * matter on which BTS it really is, we're not going to follow through an entire handover
6558 * anyway. */
6559 f_rslem_register(0, new_chan_nr, RSL1_PROC);
6560 f_rslem_resume(RSL1_PROC);
6561 f_rslem_register(0, new_chan_nr, RSL2_PROC);
6562 f_rslem_resume(RSL2_PROC);
6563
6564 if (expect_handover and not is_inter_bsc_handover) {
6565 setverdict(pass);
6566 log("f_probe_for_handover(" & log_label & "): Got RSL Handover Command as expected.");
6567 } else {
6568 setverdict(fail, "f_probe_for_handover(" & log_label & "): Expected none, but got RSL Handover Command. "
6569 & log_label & ": " & log_descr);
6570 }
6571
6572 log("f_probe_for_handover(" & log_label & "): Ending the test: Handover Failure stops the procedure.");
6573 /* osmo-bsc has triggered Handover. That's all we need to know for this test, reply with
6574 * Handover Failure. */
6575 f_rsl_send_l3(ts_RRM_HandoverFailure('00'O));
6576
6577 /* target BTS is told to release lchan again; don't care which BTS nor what messages. */
6578 f_sleep(0.5);
6579 RSL1.clear;
6580 RSL2.clear;
6581 log("f_probe_for_handover(" & log_label & "): done (got RSL Handover Command)");
6582 break;
6583 } else {
6584 repeat;
6585 }
6586 }
6587 [] BSSAP.receive(tr_BSSMAP_HandoverRequired) {
6588 if (expect_handover and is_inter_bsc_handover) {
6589 setverdict(pass);
6590 log("f_probe_for_handover(" & log_label & "): Got BSSMAP Handover Required as expected.");
6591 } else {
6592 setverdict(fail, "f_probe_for_handover(" & log_label & "): Expected none, but got BSSMAP Handover Required. "
6593 & log_label & ": " & log_descr);
6594 }
6595
6596 log("f_probe_for_handover(" & log_label & "): done (got BSSMAP Handover Required)");
6597
6598 /* Note: f_tc_ho_neighbor_config_start() sets T7, the timeout for BSSMAP Handover Required, to
6599 * 1 second. There is no legal way to quickly abort a handover after a BSSMAP Handover Required,
6600 * setting a short timeout and waiting is the only way. */
6601 log("f_probe_for_handover(" & log_label & "): waiting for inter-BSC HO to time out...");
6602 f_sleep(1.5);
6603 log("f_probe_for_handover(" & log_label & "): ...done");
6604
6605 break;
6606 }
6607 [] T.timeout {
6608 if (expect_handover) {
6609 setverdict(fail, "f_probe_for_handover(" & log_label & "): Expected Handover, but got none. "
6610 & log_label & ": " & log_descr);
6611 } else {
6612 setverdict(pass);
6613 log("f_probe_for_handover(" & log_label & "): Got no Handover, as expected.");
6614 }
6615 log("f_probe_for_handover(" & log_label & "): done (got no Handover)");
6616 break;
6617 }
6618 }
6619
6620 f_rslem_resume(RSL1_PROC);
6621 f_rslem_resume(RSL2_PROC);
6622 f_sleep(3.0);
6623 RSL.clear;
6624
6625 log("f_probe_for_handover(" & log_label & "): done clearing");
6626}
6627
6628/* Test the effect of various neighbor configuration scenarios:
6629 *
6630 * To avoid complexity, block off any actual handover operation, and always remain on the lchan at bts 0.
6631 * Reconfigure the neighbors for bts 0, trigger a Handover, and probe whether osmo-bsc does or doesn't start HO.
6632 */
6633private function f_tc_ho_neighbor_config_start() runs on MSC_ConnHdlr {
6634 g_pars := f_gen_test_hdlr_pars();
6635 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
6636 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Neels Hofmeyr91401012019-07-11 00:42:35 +02006637
6638 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
6639 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
6640
6641 /* Establish lchan at bts 0 */
6642 f_establish_fully(ass_cmd, exp_compl);
6643
6644 /* Shorten the inter-BSC Handover timeout, to not wait so long for inter-BSC Handovers */
6645 f_vty_enter_cfg_network(BSCVTY);
6646 f_vty_transceive(BSCVTY, "timer T7 1");
6647 f_vty_transceive(BSCVTY, "end");
6648}
6649
6650private function f_tc_ho_neighbor_config_1(charstring id) runs on MSC_ConnHdlr {
6651 f_tc_ho_neighbor_config_start();
6652
6653 /*
6654 * bts 0 ARFCN 871 BSIC 10
6655 * bts 1 ARFCN 871 BSIC 11
6656 * bts 2 ARFCN 871 BSIC 12
6657 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
6658 */
6659
6660 log("f_tc_ho_neighbor_config: 1. No 'neighbor' config");
Neels Hofmeyr666f0432020-07-04 00:53:07 +02006661 f_bts_0_cfg(BSCVTY, {"no neighbors"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02006662 f_probe_for_handover("1.a", "HO to bts 1 works, implicitly listed as neighbor (legacy behavior when none are configured)",
6663 "handover any to arfcn 871 bsic 11",
Neels Hofmeyr6a955cc2021-10-02 14:53:48 +02006664 true, expect_target_tsc := BTS_TSC[1]);
Neels Hofmeyr91401012019-07-11 00:42:35 +02006665
6666 f_probe_for_handover("1.b", "HO to unknown cell does not start",
6667 "handover any to arfcn 13 bsic 39",
6668 false);
6669
6670 f_probe_for_handover("1.c", "HO to 871-12 is ambiguous = error",
6671 "handover any to arfcn 871 bsic 12",
6672 false);
6673
6674 f_probe_for_handover("1.d", "HO to 871-11 still works (verify that this test properly cleans up)",
6675 "handover any to arfcn 871 bsic 11",
Neels Hofmeyr6a955cc2021-10-02 14:53:48 +02006676 true, expect_target_tsc := BTS_TSC[1]);
Neels Hofmeyr91401012019-07-11 00:42:35 +02006677}
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006678testcase TC_ho_neighbor_config_1() runs on test_CT {
6679 var MSC_ConnHdlr vc_conn;
6680 f_init(3, true, guard_timeout := 60.0);
6681 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006682 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006683 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_1));
6684 vc_conn.done;
6685
6686 /* f_tc_ho_neighbor_config_start() */
6687 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
6688 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
6689
6690 /* 1.a */
6691 /* "failed" means a handover was triggered and started (which is all this test aims for) and the test ended the
6692 * handover quickly by sending a Handover Failure message. */
6693 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6694 f_ctrs_bsc_and_bts_add(0, "handover:failed");
6695 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
6696 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:failed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006697 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:attempted");
6698 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:failed");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006699
6700 /* 1.b */
6701 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6702 f_ctrs_bsc_and_bts_add(0, "handover:error");
6703
6704 /* 1.c */
6705 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6706 f_ctrs_bsc_and_bts_add(0, "handover:error");
6707
6708 /* 1.d */
6709 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6710 f_ctrs_bsc_and_bts_add(0, "handover:failed");
6711 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
6712 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:failed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006713 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:attempted");
6714 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:failed");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006715
6716 f_ctrs_bsc_and_bts_verify();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02006717 f_shutdown_helper();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006718}
6719
Neels Hofmeyr91401012019-07-11 00:42:35 +02006720private function f_tc_ho_neighbor_config_2(charstring id) runs on MSC_ConnHdlr {
6721 f_tc_ho_neighbor_config_start();
6722
6723 /*
6724 * bts 0 ARFCN 871 BSIC 10
6725 * bts 1 ARFCN 871 BSIC 11
6726 * bts 2 ARFCN 871 BSIC 12
6727 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
6728 */
6729
6730 log("f_tc_ho_neighbor_config: 2. explicit local neighbor: 'neighbor bts 1'");
Neels Hofmeyr666f0432020-07-04 00:53:07 +02006731 f_bts_0_cfg(BSCVTY, {"neighbor bts 1"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02006732 f_sleep(0.5);
6733
6734 f_probe_for_handover("2.a", "HO to bts 1 works, explicitly listed as neighbor",
6735 "handover any to arfcn 871 bsic 11",
Neels Hofmeyr6a955cc2021-10-02 14:53:48 +02006736 true, expect_target_tsc := BTS_TSC[1]);
Neels Hofmeyr91401012019-07-11 00:42:35 +02006737
6738 f_probe_for_handover("2.b", "HO to bts 2 doesn't work, not listed as neighbor",
6739 "handover any to arfcn 871 bsic 12",
6740 false);
6741}
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006742testcase TC_ho_neighbor_config_2() runs on test_CT {
6743 var MSC_ConnHdlr vc_conn;
6744 f_init(3, true, guard_timeout := 50.0);
6745 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006746 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006747 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_2));
6748 vc_conn.done;
6749
6750 /* f_tc_ho_neighbor_config_start() */
6751 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
6752 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
6753
6754 /* 2.a */
6755 /* "failed" means a handover was triggered and started (which is all this test aims for) and the test ended the
6756 * handover quickly by sending a Handover Failure message. */
6757 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6758 f_ctrs_bsc_and_bts_add(0, "handover:failed");
6759 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
6760 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:failed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006761 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:attempted");
6762 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:failed");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006763
6764 /* 2.b */
6765 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6766 f_ctrs_bsc_and_bts_add(0, "handover:error");
6767
6768 f_ctrs_bsc_and_bts_verify();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02006769 f_shutdown_helper();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006770}
6771
Neels Hofmeyr91401012019-07-11 00:42:35 +02006772private function f_tc_ho_neighbor_config_3(charstring id) runs on MSC_ConnHdlr {
6773 f_tc_ho_neighbor_config_start();
6774
6775 /*
6776 * bts 0 ARFCN 871 BSIC 10
6777 * bts 1 ARFCN 871 BSIC 11
6778 * bts 2 ARFCN 871 BSIC 12
6779 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
6780 */
6781
6782 log("f_tc_ho_neighbor_config: 3. explicit local neighbor: 'neighbor bts 2'");
Neels Hofmeyr666f0432020-07-04 00:53:07 +02006783 f_bts_0_cfg(BSCVTY, {"no neighbors", "neighbor bts 2"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02006784 f_sleep(0.5);
6785
6786 f_probe_for_handover("3.a", "HO to bts 1 doesn't work, not listed as neighbor",
6787 "handover any to arfcn 871 bsic 11",
6788 false);
6789 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",
6790 "handover any to arfcn 871 bsic 12",
Neels Hofmeyr6a955cc2021-10-02 14:53:48 +02006791 true, expect_target_tsc := BTS_TSC[2]);
Neels Hofmeyr91401012019-07-11 00:42:35 +02006792}
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006793testcase TC_ho_neighbor_config_3() runs on test_CT {
6794 var MSC_ConnHdlr vc_conn;
6795 f_init(3, true, guard_timeout := 50.0);
6796 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006797 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006798 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_3));
6799 vc_conn.done;
6800
6801 /* f_tc_ho_neighbor_config_start() */
6802 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
6803 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
6804
6805 /* 3.a */
6806 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6807 f_ctrs_bsc_and_bts_add(0, "handover:error");
6808
6809 /* 3.b */
6810 /* "failed" means a handover was triggered and started (which is all this test aims for) and the test ended the
6811 * handover quickly by sending a Handover Failure message. */
6812 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6813 f_ctrs_bsc_and_bts_add(0, "handover:failed");
6814 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
6815 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:failed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006816 f_ctrs_bts_add(2, "incoming_intra_bsc_ho:attempted");
6817 f_ctrs_bts_add(2, "incoming_intra_bsc_ho:failed");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006818
6819 f_ctrs_bsc_and_bts_verify();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02006820 f_shutdown_helper();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006821}
6822
Neels Hofmeyr91401012019-07-11 00:42:35 +02006823private function f_tc_ho_neighbor_config_4(charstring id) runs on MSC_ConnHdlr {
6824 f_tc_ho_neighbor_config_start();
6825
6826 /*
6827 * bts 0 ARFCN 871 BSIC 10
6828 * bts 1 ARFCN 871 BSIC 11
6829 * bts 2 ARFCN 871 BSIC 12
6830 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
6831 */
6832
6833 log("f_tc_ho_neighbor_config: 4. explicit remote neighbor: 'neighbor lac 99 arfcn 123 bsic 45'");
Neels Hofmeyr666f0432020-07-04 00:53:07 +02006834 f_bts_0_cfg(BSCVTY, {"no neighbors", "neighbor lac 99 arfcn 123 bsic 45"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02006835 f_sleep(0.5);
6836
6837 f_probe_for_handover("4.a", "HO to bts 1 doesn't work, not listed as neighbor",
6838 "handover any to arfcn 871 bsic 11",
6839 false);
6840 f_probe_for_handover("4.b", "HO to bts 2 doesn't work, not listed as neighbor",
6841 "handover any to arfcn 871 bsic 12",
6842 false);
6843 f_probe_for_handover("4.c", "HO to 123-45 triggers inter-BSC HO",
6844 "handover any to arfcn 123 bsic 45",
6845 true, true);
6846}
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006847testcase TC_ho_neighbor_config_4() runs on test_CT {
6848 var MSC_ConnHdlr vc_conn;
6849 f_init(3, true, guard_timeout := 50.0);
6850 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006851 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006852 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_4));
6853 vc_conn.done;
6854
6855 /* f_tc_ho_neighbor_config_start() */
6856 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
6857 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
6858
6859 /* 4.a */
6860 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6861 f_ctrs_bsc_and_bts_add(0, "handover:error");
6862
6863 /* 4.b */
6864 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6865 f_ctrs_bsc_and_bts_add(0, "handover:error");
6866
6867 /* 4.c */
6868 /* "timeout" means a handover was triggered and started (which is all this test aims for) and the test ended the
6869 * handover quickly by timing out after the Handover Required message */
6870 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6871 f_ctrs_bsc_and_bts_add(0, "handover:timeout");
6872 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
6873 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:timeout");
6874
6875 f_ctrs_bsc_and_bts_verify();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02006876 f_shutdown_helper();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006877}
6878
Neels Hofmeyr91401012019-07-11 00:42:35 +02006879private function f_tc_ho_neighbor_config_5(charstring id) runs on MSC_ConnHdlr {
6880 f_tc_ho_neighbor_config_start();
6881
6882 /*
6883 * bts 0 ARFCN 871 BSIC 10
6884 * bts 1 ARFCN 871 BSIC 11
6885 * bts 2 ARFCN 871 BSIC 12
6886 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
6887 */
6888
6889 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 +02006890 f_bts_0_cfg(BSCVTY, {"no neighbors", "neighbor lac 99 arfcn 871 bsic 12"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02006891 f_sleep(0.5);
6892
6893 f_probe_for_handover("5.a", "HO to 871-12 triggers inter-BSC HO (ignoring local cells with same ARFCN+BSIC)",
6894 "handover any to arfcn 871 bsic 12",
6895 true, true);
6896}
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006897testcase TC_ho_neighbor_config_5() runs on test_CT {
6898 var MSC_ConnHdlr vc_conn;
6899 f_init(3, true);
6900 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006901 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006902 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_5));
6903 vc_conn.done;
6904
6905 /* f_tc_ho_neighbor_config_start() */
6906 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
6907 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
6908
6909 /* 5 */
6910 /* "timeout" means a handover was triggered and started (which is all this test aims for) and the test ended the
6911 * handover quickly by timing out after the Handover Required message */
6912 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6913 f_ctrs_bsc_and_bts_add(0, "handover:timeout");
6914 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
6915 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:timeout");
6916
6917 f_ctrs_bsc_and_bts_verify();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02006918 f_shutdown_helper();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006919}
6920
Neels Hofmeyr91401012019-07-11 00:42:35 +02006921private function f_tc_ho_neighbor_config_6(charstring id) runs on MSC_ConnHdlr {
6922 f_tc_ho_neighbor_config_start();
6923
6924 /*
6925 * bts 0 ARFCN 871 BSIC 10
6926 * bts 1 ARFCN 871 BSIC 11
6927 * bts 2 ARFCN 871 BSIC 12
6928 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
6929 */
6930
6931 log("f_tc_ho_neighbor_config: 6. config error: explicit local and remote neighbors with ambiguous ARFCN+BSIC:"
6932 & " 'neighbor bts 2; neighbor lac 99 arfcn 871 bsic 12'");
Neels Hofmeyr666f0432020-07-04 00:53:07 +02006933 f_bts_0_cfg(BSCVTY, {"no neighbors", "neighbor bts 2", "neighbor lac 99 arfcn 871 bsic 12"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02006934 f_sleep(0.5);
6935
6936 f_probe_for_handover("6.a", "HO to 871-12 is ambiguous = error",
6937 "handover any to arfcn 871 bsic 12",
6938 false);
6939}
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006940testcase TC_ho_neighbor_config_6() runs on test_CT {
6941 var MSC_ConnHdlr vc_conn;
6942 f_init(3, true);
6943 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006944 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006945 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_6));
6946 vc_conn.done;
6947
6948 /* f_tc_ho_neighbor_config_start() */
6949 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
6950 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
6951
6952 /* 6.a */
6953 /* "timeout" means a handover was triggered and started (which is all this test aims for) and the test ended the
6954 * handover quickly by timing out after the Handover Required message */
6955 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6956 f_ctrs_bsc_and_bts_add(0, "handover:error");
6957
6958 f_ctrs_bsc_and_bts_verify();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02006959 f_shutdown_helper();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006960}
6961
Neels Hofmeyr91401012019-07-11 00:42:35 +02006962private function f_tc_ho_neighbor_config_7(charstring id) runs on MSC_ConnHdlr {
6963 f_tc_ho_neighbor_config_start();
6964
6965 /*
6966 * bts 0 ARFCN 871 BSIC 10
6967 * bts 1 ARFCN 871 BSIC 11
6968 * bts 2 ARFCN 871 BSIC 12
6969 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
6970 */
6971
6972 log("f_tc_ho_neighbor_config: 7. explicit local and remote neighbors:"
6973 & " 'neighbor bts 2; neighbor lac 99 arfcn 123 bsic 45'");
Neels Hofmeyr666f0432020-07-04 00:53:07 +02006974 f_bts_0_cfg(BSCVTY, {"no neighbors", "neighbor bts 2", "neighbor lac 99 arfcn 123 bsic 45"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02006975 f_sleep(0.5);
6976
6977 f_probe_for_handover("7.a", "HO to 871-12 does HO to bts 2",
6978 "handover any to arfcn 871 bsic 12",
Neels Hofmeyr6a955cc2021-10-02 14:53:48 +02006979 true, expect_target_tsc := BTS_TSC[2]);
Neels Hofmeyr91401012019-07-11 00:42:35 +02006980 f_probe_for_handover("7.b", "HO to 123-45 triggers inter-BSC HO",
6981 "handover any to arfcn 123 bsic 45",
6982 true, true);
6983}
Neels Hofmeyr91401012019-07-11 00:42:35 +02006984testcase TC_ho_neighbor_config_7() runs on test_CT {
6985 var MSC_ConnHdlr vc_conn;
Neels Hofmeyrf2b88032020-06-16 00:35:04 +02006986 f_init(3, true, guard_timeout := 50.0);
Neels Hofmeyr91401012019-07-11 00:42:35 +02006987 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006988 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr91401012019-07-11 00:42:35 +02006989 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_7));
6990 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006991
6992 /* f_tc_ho_neighbor_config_start() */
6993 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
6994 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
6995
6996 /* 7.a */
6997 /* "failed" means a handover was triggered and started (which is all this test aims for) and the test ended the
6998 * handover quickly by sending a Handover Failure message. */
6999 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7000 f_ctrs_bsc_and_bts_add(0, "handover:failed");
7001 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
7002 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:failed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007003 f_ctrs_bts_add(2, "incoming_intra_bsc_ho:attempted");
7004 f_ctrs_bts_add(2, "incoming_intra_bsc_ho:failed");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007005
7006 /* 7.b */
7007 /* "timeout" means a handover was triggered and started (which is all this test aims for) and the test ended the
7008 * handover quickly by timing out after the Handover Required message */
7009 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7010 f_ctrs_bsc_and_bts_add(0, "handover:timeout");
7011 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
7012 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:timeout");
7013
7014 f_ctrs_bsc_and_bts_verify();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02007015 f_shutdown_helper();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007016}
7017
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +01007018/* OS#3041: Open and close N connections in a normal fashion, and expect no
7019 * BSSMAP Reset just because of that. */
7020testcase TC_bssap_rlsd_does_not_cause_bssmap_reset() runs on test_CT {
7021 var default d;
7022 var integer i;
7023 var DchanTuple dt;
7024
7025 f_init();
7026
7027 /* Wait for initial BSSMAP Reset to pass */
7028 f_sleep(4.0);
7029
7030 d := activate(no_bssmap_reset());
7031
7032 /* Setup up a number of connections and RLSD them again from the MSC
7033 * side. In the buggy behavior, the fourth one triggers BSSMAP Reset.
7034 * Let's do it some more times for good measure. */
Harald Weltec3260d92018-06-11 17:48:16 +02007035 for (i := 0; i < 4; i := i+1) {
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +01007036 /* Since we're doing a lot of runs, give each one a fresh
7037 * T_guard from the top. */
7038 T_guard.start;
7039
7040 /* Setup a BSSAP connection and clear it right away. This is
7041 * the MSC telling the BSC about a planned release, it's not an
7042 * erratic loss of a connection. */
Harald Weltea1897182018-06-11 13:53:09 +02007043 dt := f_est_dchan(int2oct(i,1), 23+i, '00010203040506'O);
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +01007044
7045 /* MSC disconnects (RLSD). */
7046 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
7047 }
7048
7049 /* In the buggy behavior, a timeout of 2 seconds happens between above
7050 * trigger (logs "SIGTRAN connection down, reconnecting...") and the
7051 * actual BSSMAP Reset. Wait a bit longer just to make sure. */
7052 f_sleep(4.0);
7053
7054 deactivate(d);
7055 f_shutdown_helper();
7056}
Harald Welte552620d2017-12-16 23:21:36 +01007057
Neels Hofmeyr4ff93282018-03-12 04:25:35 +01007058/* OS#3041: Open and close N connections in a normal fashion, and expect no
7059 * BSSMAP Reset just because of that. Invoke the release by a BSSMAP Clear from
7060 * the MSC. */
7061testcase TC_bssmap_clear_does_not_cause_bssmap_reset() runs on test_CT {
7062 var default d;
7063 var integer i;
7064 var DchanTuple dt;
7065 var BSSAP_N_DATA_ind rx_di;
Neels Hofmeyr4ff93282018-03-12 04:25:35 +01007066 var myBSSMAP_Cause cause_val := GSM0808_CAUSE_CALL_CONTROL;
7067 var BssmapCause cause := enum2int(cause_val);
7068
7069 f_init();
7070
7071 /* Wait for initial BSSMAP Reset to pass */
7072 f_sleep(4.0);
7073
7074 d := activate(no_bssmap_reset());
7075
7076 /* Setup up a number of connections and RLSD them again from the MSC
7077 * side. In the buggy behavior, the fourth one triggers BSSMAP Reset.
7078 * Let's do it some more times for good measure. */
7079 for (i := 0; i < 8; i := i+1) {
7080 /* Since we're doing a lot of runs, give each one a fresh
7081 * T_guard from the top. */
7082 T_guard.start;
7083
7084 /* Setup a BSSAP connection and clear it right away. This is
7085 * the MSC telling the BSC about a planned release, it's not an
7086 * erratic loss of a connection. */
Harald Weltea1897182018-06-11 13:53:09 +02007087 dt := f_est_dchan(int2oct(i,1), 23+i, '00010203040506'O);
Neels Hofmeyr4ff93282018-03-12 04:25:35 +01007088
7089 /* Instruct BSC to clear channel */
7090 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
7091
7092 /* expect BSC to disable the channel */
Harald Welte641fcbe2018-06-14 10:58:35 +02007093 f_exp_chan_rel_and_clear(dt, 0);
Neels Hofmeyr4ff93282018-03-12 04:25:35 +01007094 }
7095
7096 /* In the buggy behavior, a timeout of 2 seconds happens between above
7097 * trigger (logs "SIGTRAN connection down, reconnecting...") and the
7098 * actual BSSMAP Reset. Wait a bit longer just to make sure. */
7099 f_sleep(4.0);
7100
7101 deactivate(d);
7102 f_shutdown_helper();
7103}
7104
Neels Hofmeyrfd445c32018-03-09 15:39:31 +01007105/* OS#3041: Open and close N connections in a normal fashion, and expect no
7106 * BSSMAP Reset just because of that. Close connections from the MS side with a
7107 * Release Ind on RSL. */
7108testcase TC_ms_rel_ind_does_not_cause_bssmap_reset() runs on test_CT {
7109 var default d;
7110 var integer i;
7111 var DchanTuple dt;
7112 var BSSAP_N_DATA_ind rx_di;
Neels Hofmeyrfd445c32018-03-09 15:39:31 +01007113 var integer j;
7114
7115 f_init();
7116
7117 /* Wait for initial BSSMAP Reset to pass */
7118 f_sleep(4.0);
7119
7120 d := activate(no_bssmap_reset());
7121
7122 /* Setup up a number of connections and RLSD them again from the MSC
7123 * side. In the buggy behavior, the fourth one triggers BSSMAP Reset.
7124 * Let's do it some more times for good measure. */
7125 for (i := 0; i < 8; i := i+1) {
7126 /* Since we're doing a lot of runs, give each one a fresh
7127 * T_guard from the top. */
7128 T_guard.start;
7129
7130 /* Setup a BSSAP connection and clear it right away. This is
7131 * the MSC telling the BSC about a planned release, it's not an
7132 * erratic loss of a connection. */
7133 dt := f_est_dchan('23'O, 23, '00010203040506'O);
7134
7135 /* simulate RLL REL IND */
7136 f_ipa_tx(0, ts_RSL_REL_IND(dt.rsl_chan_nr, valueof(ts_RslLinkID_DCCH(0))));
7137
7138 /* expect Clear Request on MSC side */
7139 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearRequest)) -> value rx_di;
7140
7141 /* Instruct BSC to clear channel */
7142 var BssmapCause cause := bit2int(rx_di.userData.pdu.bssmap.clearRequest.cause.causeValue);
7143 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
7144
7145 /* expect BSC to disable the channel */
Harald Welte641fcbe2018-06-14 10:58:35 +02007146 f_exp_chan_rel_and_clear(dt, 0);
Neels Hofmeyrfd445c32018-03-09 15:39:31 +01007147 }
7148
7149 /* In the buggy behavior, a timeout of 2 seconds happens between above
7150 * trigger (logs "SIGTRAN connection down, reconnecting...") and the
7151 * actual BSSMAP Reset. Wait a bit longer just to make sure. */
7152 f_sleep(4.0);
7153
7154 deactivate(d);
7155 f_shutdown_helper();
7156}
7157
Harald Welte94e0c342018-04-07 11:33:23 +02007158/***********************************************************************
7159 * IPA style dynamic PDCH
7160 ***********************************************************************/
7161
7162private function f_dyn_ipa_pdch_act(integer bts_nr, integer trx_nr, integer ts_nr,
7163 template (omit) RSL_Cause nack := omit)
7164runs on test_CT {
7165 var RslChannelNr chan_nr := valueof(t_RslChanNr_Bm(ts_nr));
7166 var RSL_Message rsl_unused;
7167 /* ask BSC via VTY to activate a given IPA style chan as PDCH */
7168 f_vty_ts_action("pdch activate", bts_nr, trx_nr, ts_nr);
7169 /* expect the BSC to issue the related RSL command */
7170 rsl_unused := f_exp_ipa_rx(0, tr_RSL_IPA_PDCH_ACT(chan_nr));
7171 if (istemplatekind(nack, "omit")) {
7172 /* respond with a related acknowledgement */
7173 f_ipa_tx(0, ts_RSL_IPA_PDCH_ACT_ACK(chan_nr, ts_RSL_IE_FrameNumber(2342)));
7174 } else {
7175 f_ipa_tx(0, ts_RSL_IPA_PDCH_ACT_NACK(chan_nr, valueof(nack)));
7176 }
7177}
7178
7179private function f_dyn_ipa_pdch_deact(integer bts_nr, integer trx_nr, integer ts_nr,
7180 template (omit) RSL_Cause nack := omit)
7181runs on test_CT {
7182 var RslChannelNr chan_nr := valueof(t_RslChanNr_Bm(ts_nr));
7183 var RSL_Message rsl_unused;
7184 /* ask BSC via VTY to activate a given IPA style chan as PDCH */
7185 f_vty_ts_action("pdch deactivate", bts_nr, trx_nr, ts_nr);
7186 /* expect the BSC to issue the related RSL command */
7187 rsl_unused := f_exp_ipa_rx(0, tr_RSL_IPA_PDCH_DEACT(chan_nr));
7188 if (istemplatekind(nack, "omit")) {
7189 /* respond with a related acknowledgement */
7190 f_ipa_tx(0, ts_RSL_IPA_PDCH_DEACT_ACK(chan_nr));
7191 } else {
7192 f_ipa_tx(0, ts_RSL_IPA_PDCH_DEACT_NACK(chan_nr, valueof(nack)));
7193 }
7194}
7195
7196private function f_ts_dyn_mode_get(integer bts_nr, integer trx_nr, integer ts_nr)
7197runs on test_CT return charstring {
7198 var charstring cmd, resp;
7199 cmd := "show timeslot "&int2str(bts_nr)&" "&int2str(trx_nr)&" "&int2str(ts_nr);
Stefan Sperlingcff13562018-11-13 15:24:06 +01007200 return f_vty_transceive_match_regexp_retry(BSCVTY, cmd, "*\((*)\)*", 0, 4, 1.0);
Harald Welte94e0c342018-04-07 11:33:23 +02007201}
7202
7203private function f_ts_dyn_mode_assert(integer bts_nr, integer trx_nr, integer ts_nr,
7204 template charstring exp)
7205runs on test_CT {
7206 var charstring mode := f_ts_dyn_mode_get(bts_nr, trx_nr, ts_nr);
7207 if (not match(mode, exp)) {
7208 setverdict(fail, "Unexpected TS Mode: ", mode);
Daniel Willmannafce8662018-07-06 23:11:32 +02007209 mtc.stop;
Harald Welte94e0c342018-04-07 11:33:23 +02007210 }
7211}
7212
7213private function f_ts_set_chcomb(integer bts_nr, integer trx_nr, integer ts_nr, charstring chcomb)
7214runs on test_CT {
7215 f_vty_enter_cfg_ts(BSCVTY, bts_nr, trx_nr, ts_nr);
7216 f_vty_transceive(BSCVTY, "phys_chan_config " & chcomb);
7217 f_vty_transceive(BSCVTY, "end");
7218}
7219
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02007220
7221private function f_ts_reset_chcomb(integer bts_nr) runs on test_CT {
7222 var integer i;
7223 for (i := 0; i < 8; i := i + 1) {
7224 f_ts_set_chcomb(bts_nr, 0, i, phys_chan_config[i]);
7225 }
7226}
7227
Harald Welte94e0c342018-04-07 11:33:23 +02007228private const charstring TCHF_MODE := "TCH/F mode";
7229private const charstring TCHH_MODE := "TCH/H mode";
7230private const charstring PDCH_MODE := "PDCH mode";
7231private const charstring NONE_MODE := "NONE mode";
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02007232private const charstring SDCCH8_MODE := "SDCCH8 mode";
Harald Welte94e0c342018-04-07 11:33:23 +02007233
7234/* Test IPA PDCH activation / deactivation triggered by VTY */
7235testcase TC_dyn_pdch_ipa_act_deact() runs on test_CT {
7236 var RSL_Message rsl_unused;
7237
7238 /* change Timeslot 6 before f_init() starts RSL */
7239 f_init_vty();
7240 f_ts_set_chcomb(0, 0, 6, "TCH/F_PDCH");
7241 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
7242
7243 f_init(1, false);
7244 f_sleep(1.0);
7245
7246 var RslChannelNr chan_nr := valueof(t_RslChanNr_Bm(6));
7247
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02007248 log("TCH/F_PDCH pchan starts out in TCH/F mode:");
Harald Welte94e0c342018-04-07 11:33:23 +02007249 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, TCHF_MODE);
7250 /* The BSC will activate the dynamic PDCH by default, so confirm that */
7251 rsl_unused := f_exp_ipa_rx(0, tr_RSL_IPA_PDCH_ACT(chan_nr));
7252 f_ipa_tx(0, ts_RSL_IPA_PDCH_ACT_ACK(chan_nr, ts_RSL_IE_FrameNumber(2342)));
7253 f_sleep(1.0);
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02007254 log("TCH/F_PDCH pchan, PDCH ACT was ACKed, so now in PDCH mode:");
Harald Welte94e0c342018-04-07 11:33:23 +02007255 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, PDCH_MODE);
7256
7257 /* De-activate it via VTY */
7258 f_dyn_ipa_pdch_deact(0, 0, chan_nr.tn);
7259 f_sleep(1.0);
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02007260 log("TCH/F_PDCH pchan, PDCH DEACT via VTY, so now back in TCH/F mode:");
Harald Welte94e0c342018-04-07 11:33:23 +02007261 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, TCHF_MODE);
7262
7263 /* re-activate it via VTY */
7264 f_dyn_ipa_pdch_act(0, 0, chan_nr.tn);
7265 f_sleep(1.0);
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02007266 log("TCH/F_PDCH pchan, PDCH ACT via VTY, so now in PDCH mode:");
Harald Welte94e0c342018-04-07 11:33:23 +02007267 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, PDCH_MODE);
7268
7269 /* and finally de-activate it again */
7270 f_dyn_ipa_pdch_deact(0, 0, chan_nr.tn);
7271 f_sleep(1.0);
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02007272 log("TCH/F_PDCH pchan, PDCH DEACT via VTY, so now back in TCH/F mode:");
Harald Welte94e0c342018-04-07 11:33:23 +02007273 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, TCHF_MODE);
7274
Neels Hofmeyr887e8f12018-06-27 01:01:55 +02007275 /* clean up config */
7276 f_ts_set_chcomb(0, 0, 6, "PDCH");
7277
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02007278 f_shutdown_helper();
Harald Welte94e0c342018-04-07 11:33:23 +02007279}
7280
7281/* Test IPA PDCH activation NACK */
7282testcase TC_dyn_pdch_ipa_act_nack() runs on test_CT {
7283 var RSL_Message rsl_unused;
7284
7285 /* change Timeslot 6 before f_init() starts RSL */
7286 f_init_vty();
7287 f_ts_set_chcomb(0, 0, 6, "TCH/F_PDCH");
7288 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
7289
7290 f_init(1, false);
7291 f_sleep(1.0);
7292
7293 var RslChannelNr chan_nr := valueof(t_RslChanNr_Bm(6));
7294
7295 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, TCHF_MODE);
7296 /* The BSC will activate the dynamic PDCH by default, so confirm that */
7297 rsl_unused := f_exp_ipa_rx(0, tr_RSL_IPA_PDCH_ACT(chan_nr));
7298 f_ipa_tx(0, ts_RSL_IPA_PDCH_ACT_ACK(chan_nr, ts_RSL_IE_FrameNumber(2342)));
7299 f_sleep(1.0);
7300 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, PDCH_MODE);
7301
7302 /* De-activate it via VTY */
7303 f_dyn_ipa_pdch_deact(0, 0, chan_nr.tn);
7304 f_sleep(1.0);
7305 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, TCHF_MODE);
7306
7307 /* re-activate it via VTY, but fail that; check BSC still assumes TCH/F mode */
7308 f_dyn_ipa_pdch_act(0, 0, chan_nr.tn, RSL_ERR_EQUIPMENT_FAIL);
7309 f_sleep(1.0);
7310 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, TCHF_MODE);
7311
Neels Hofmeyr887e8f12018-06-27 01:01:55 +02007312 /* clean up config */
7313 f_ts_set_chcomb(0, 0, 6, "PDCH");
7314
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02007315 f_shutdown_helper();
Harald Welte94e0c342018-04-07 11:33:23 +02007316}
7317
7318
7319/***********************************************************************
7320 * Osmocom style dynamic PDCH
7321 ***********************************************************************/
7322
7323private function f_dyn_osmo_pdch_act(integer bts_nr, integer trx_nr, integer ts_nr,
7324 template (omit) RSL_Cause nack := omit)
7325runs on test_CT {
7326 var RslChannelNr chan_nr := valueof(t_RslChanNr_PDCH(ts_nr));
7327 var RSL_Message rsl_unused;
Pau Espin Pedrol64adf372021-06-28 16:25:47 +02007328 /* ask BSC via VTY to activate a given OSMO style chan as PDCH */
Harald Welte94e0c342018-04-07 11:33:23 +02007329 /* FIXME: no VTY command to activate Osmocom PDCH !! */
7330 /* expect the BSC to issue the related RSL command */
7331 rsl_unused := f_exp_ipa_rx(0, tr_RSL_CHAN_ACT(chan_nr, ?));
7332 if (istemplatekind(nack, "omit")) {
7333 /* respond with a related acknowledgement */
7334 f_ipa_tx(0, ts_RSL_CHAN_ACT_ACK(chan_nr, 2342));
7335 } else {
7336 f_ipa_tx(0, ts_RSL_CHAN_ACT_NACK(chan_nr, valueof(nack)));
7337 }
7338}
7339
7340private function f_dyn_osmo_pdch_deact(integer bts_nr, integer trx_nr, integer ts_nr,
7341 template (omit) RSL_Cause nack := omit)
7342runs on test_CT {
7343 var RslChannelNr chan_nr := valueof(t_RslChanNr_PDCH(ts_nr));
7344 var RSL_Message rsl_unused;
Pau Espin Pedrol64adf372021-06-28 16:25:47 +02007345 /* ask BSC via VTY to activate a given OSMO style chan as PDCH */
Harald Welte94e0c342018-04-07 11:33:23 +02007346 /* FIXME: no VTY command to activate Osmocom PDCH !! */
7347 /* expect the BSC to issue the related RSL command */
7348 rsl_unused := f_exp_ipa_rx(0, tr_RSL_RF_CHAN_REL(chan_nr));
7349 if (istemplatekind(nack, "omit")) {
7350 /* respond with a related acknowledgement */
7351 f_ipa_tx(0, ts_RSL_RF_CHAN_REL_ACK(chan_nr));
7352 } else {
7353 //f_ipa_tx(0, ts_RSL_RF_CHAN_REL_NACK(chan_nr, valueof(nack)));
7354 }
7355}
7356
7357/* Test Osmocom dyn PDCH activation / deactivation triggered by VTY */
7358testcase TC_dyn_pdch_osmo_act_deact() runs on test_CT {
7359 var RSL_Message rsl_unused;
7360
7361 /* change Timeslot 6 before f_init() starts RSL */
7362 f_init_vty();
7363 f_ts_set_chcomb(0, 0, 6, "TCH/F_TCH/H_PDCH");
7364 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
7365
7366 f_init(1, false);
7367 f_sleep(1.0);
7368
7369 var RslChannelNr chan_nr := valueof(t_RslChanNr_PDCH(6));
7370
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02007371 log("TCH/F_TCH/H_PDCH pchan starts out in disabled mode:");
Harald Welte94e0c342018-04-07 11:33:23 +02007372 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, NONE_MODE);
7373 /* The BSC will activate the dynamic PDCH by default, so confirm that */
7374 rsl_unused := f_exp_ipa_rx(0, tr_RSL_CHAN_ACT_PDCH(chan_nr, ?));
7375
7376 f_ipa_tx(0, ts_RSL_CHAN_ACT_ACK(chan_nr, 2342));
7377 f_sleep(1.0);
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02007378 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 +02007379 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, PDCH_MODE);
7380
Neels Hofmeyr887e8f12018-06-27 01:01:55 +02007381 /* clean up config */
7382 f_ts_set_chcomb(0, 0, 6, "PDCH");
7383
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02007384 f_shutdown_helper();
Harald Welte94e0c342018-04-07 11:33:23 +02007385}
7386
7387/* Test Osmocom dyn PDCH activation NACK behavior */
7388testcase TC_dyn_pdch_osmo_act_nack() runs on test_CT {
7389 var RSL_Message rsl_unused;
7390
7391 /* change Timeslot 6 before f_init() starts RSL */
7392 f_init_vty();
7393 f_ts_set_chcomb(0, 0, 6, "TCH/F_TCH/H_PDCH");
7394 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
7395
7396 f_init(1, false);
7397 f_sleep(1.0);
7398
7399 var RslChannelNr chan_nr := valueof(t_RslChanNr_PDCH(6));
7400
7401 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, NONE_MODE);
7402 /* The BSC will activate the dynamic PDCH by default, so confirm that */
7403 rsl_unused := f_exp_ipa_rx(0, tr_RSL_CHAN_ACT_PDCH(chan_nr, ?));
7404
7405 /* NACK this activation and expect the "show timeslot" mode still to be NONE */
7406 f_ipa_tx(0, ts_RSL_CHAN_ACT_NACK(chan_nr, RSL_ERR_EQUIPMENT_FAIL));
7407 f_sleep(1.0);
7408 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, NONE_MODE);
7409
Neels Hofmeyr887e8f12018-06-27 01:01:55 +02007410 /* clean up config */
7411 f_ts_set_chcomb(0, 0, 6, "PDCH");
7412
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02007413 f_shutdown_helper();
Harald Welte94e0c342018-04-07 11:33:23 +02007414}
7415
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02007416/* Test Osmocom dyn TS SDCCH8 activation / deactivation */
7417testcase TC_dyn_ts_sdcch8_act_deact() runs on test_CT {
7418 var RSL_Message rsl_unused, rsl_msg;
7419 var DchanTuple dt;
7420 var BSSAP_N_CONNECT_ind rx_c_ind;
7421
7422 /* change Timeslot 6 before f_init() starts RSL */
7423 f_init_vty();
7424 f_ts_set_chcomb(0, 0, 6, "TCH/F_TCH/H_SDCCH8_PDCH");
7425 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
7426
7427 f_init(1, false);
7428 f_sleep(1.0);
7429
7430 var RslChannelNr pdch_chan_nr := valueof(t_RslChanNr_PDCH(6));
7431
7432 log("TCH/F_TCH/H_SDCCH8_PDCH pchan starts out in disabled mode:");
7433 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, NONE_MODE);
7434 /* The BSC will activate the dynamic PDCH by default, so confirm that */
7435 rsl_unused := f_exp_ipa_rx(0, tr_RSL_CHAN_ACT_PDCH(pdch_chan_nr, ?));
7436
7437 f_ipa_tx(0, ts_RSL_CHAN_ACT_ACK(pdch_chan_nr, 2342));
7438 f_sleep(1.0);
7439 log("TCH/F_TCH/H_SDCCH8_PDC requested to PDCH ACT on startup, which was ACKed, so now in PDCH:");
7440 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, PDCH_MODE);
7441
7442 /* Fill TS0 SDCCH channels (NOTE: only 3 SDCCH/4 channels are available
7443 * on CCCH+SDCCH4+CBCH) */
7444 var integer i;
Pau Espin Pedrolce4d5bb2021-10-25 13:31:25 +02007445 for (i := 0; i < NUM_SDCCH_PER_BTS; i := i + 1) {
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02007446 dt := f_est_dchan('23'O, i, '00010203040506'O);
7447 }
7448
7449 /* Now the dyn ts is selected. First PDCH is released, then sdcch chan is activated */
7450 f_ipa_tx(0, ts_RSL_CHAN_RQD(int2oct(oct2int('23'O) + i, 1), 2342));
7451 rsl_unused := f_exp_ipa_rx(0, tr_RSL_RF_CHAN_REL(pdch_chan_nr));
7452 f_ipa_tx(0, ts_RSL_RF_CHAN_REL_ACK(pdch_chan_nr));
7453
7454 rsl_msg := f_exp_ipa_rx(0, tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
7455 dt.rsl_chan_nr := rsl_msg.ies[0].body.chan_nr;
7456
7457 f_ts_dyn_mode_assert(0, 0, dt.rsl_chan_nr.tn, SDCCH8_MODE);
7458 f_ipa_tx(0, ts_RSL_CHAN_ACT_ACK(dt.rsl_chan_nr, 2342));
7459 rsl_msg := f_exp_ipa_rx(0, tr_RSL_IMM_ASSIGN(0));
7460 f_ts_dyn_mode_assert(0, 0, dt.rsl_chan_nr.tn, SDCCH8_MODE);
7461
7462 f_ipa_tx(0, ts_RSL_EST_IND(dt.rsl_chan_nr, valueof(ts_RslLinkID_DCCH(0)), '1234'O));
7463 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3('1234'O))) -> value rx_c_ind;
7464 dt.sccp_conn_id := rx_c_ind.connectionId;
7465 BSSAP.send(ts_BSSAP_CONNECT_res(dt.sccp_conn_id));
7466
7467 /* Instruct BSC to clear channel */
7468 var BssmapCause cause := 0;
7469 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
7470 f_exp_chan_rel_and_clear(dt, 0);
7471
7472 /* The BSC will switch the TS back to PDCH once the only lchan using it is released: */
7473 rsl_unused := f_exp_ipa_rx(0, tr_RSL_CHAN_ACT_PDCH(pdch_chan_nr, ?));
7474 f_ipa_tx(0, ts_RSL_CHAN_ACT_ACK(pdch_chan_nr, 2342));
7475 f_sleep(1.0);
7476 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, PDCH_MODE);
7477
7478 /* clean up config */
7479 f_ts_set_chcomb(0, 0, 6, "PDCH");
7480
7481 f_shutdown_helper();
7482}
7483
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02007484/* Validate all 8 subslots of a dynamics TS configured as SDCCH8 are used */
7485testcase TC_dyn_ts_sdcch8_all_subslots_used() runs on test_CT {
7486 var ASP_RSL_Unitdata rsl_ud;
7487 var integer i;
7488 var integer chreq_total, chreq_nochan;
7489
7490 f_init_vty();
7491 for (i := 1; i < 8; i := i + 1) {
7492 if (i == 2) {
7493 f_ts_set_chcomb(0, 0, i, "TCH/F_TCH/H_SDCCH8_PDCH");
7494 } else {
7495 f_ts_set_chcomb(0, 0, i, "PDCH");
7496 }
7497 }
7498 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
7499
7500 f_init(1);
7501
7502 /* The dyn TS want to activate PDCH mode, ACK that. */
7503 var RslChannelNr chan_nr;
7504 chan_nr := valueof(t_RslChanNr_PDCH(2));
7505 f_exp_ipa_rx(0, tr_RSL_CHAN_ACT_PDCH(chan_nr, ?));
7506 f_ipa_tx(0, ts_RSL_CHAN_ACT_ACK(chan_nr, 2342));
7507
7508 f_sleep(1.0);
7509
7510 /* Exhaust all dedicated SDCCH lchans.
7511 /* GSM 44.018 Table 9.1.8.2:
7512 * RA = '13'O -> Establishment cause = 0001xxxx (MS dual rate capable and asks for "SDCCH").
7513 */
7514 for (i := 0; i < NUM_SDCCH_PER_BTS; i := i+1) {
7515 f_est_dchan('13'O, NUM_SDCCH_PER_BTS + i, '00010203040506'O);
7516 }
7517
7518 /* Only the dyn TS is still available. Its first lchan gets converted to SDCCH8 */
7519 f_est_dchan_dyn('33'O, NUM_SDCCH_PER_BTS + i, '00010203040506'O);
7520 /* Also occupy the seven other SDCCH of the dyn TS */
7521 for (i := 0; i < 7; i := i+1) {
7522 f_est_dchan('33'O, NUM_SDCCH_PER_BTS + i, '00010203040506'O);
7523 }
7524
7525 /* clean up config */
7526 f_ts_reset_chcomb(0);
7527
7528 f_shutdown_helper();
7529}
7530
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02007531/* Test Osmocom dyn TS SDCCH8 activation / deactivation: If activating dyn TS as
7532 SDCCH8 would end up in having no free TCH, then BSC should decide to activate
7533 it as TCH directly instead. SYS#5309. */
7534testcase TC_dyn_ts_sdcch8_tch_call_act_deact() runs on test_CT {
7535 var RSL_Message rsl_unused, rsl_msg;
7536 var DchanTuple dt;
7537 var BSSAP_N_CONNECT_ind rx_c_ind;
7538 var integer i;
7539
7540 /* change Timeslot 6 before f_init() starts RSL */
7541 f_init_vty();
7542 for (i := 1; i < 8; i := i + 1) {
7543 if (i == 6) {
7544 f_ts_set_chcomb(0, 0, i, "TCH/F_TCH/H_SDCCH8_PDCH");
7545 } else {
7546 f_ts_set_chcomb(0, 0, i, "PDCH");
7547 }
7548 }
7549 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
7550
7551 f_init(1, false);
7552 f_sleep(1.0);
7553
7554 var RslChannelNr pdch_chan_nr := valueof(t_RslChanNr_PDCH(6));
7555
7556 log("TCH/F_TCH/H_SDCCH8_PDCH pchan starts out in disabled mode:");
7557 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, NONE_MODE);
7558 /* The BSC will activate the dynamic PDCH by default, so confirm that */
7559 rsl_unused := f_exp_ipa_rx(0, tr_RSL_CHAN_ACT_PDCH(pdch_chan_nr, ?));
7560
7561 f_ipa_tx(0, ts_RSL_CHAN_ACT_ACK(pdch_chan_nr, 2342));
7562 f_sleep(1.0);
7563 log("TCH/F_TCH/H_SDCCH8_PDC requested to PDCH ACT on startup, which was ACKed, so now in PDCH:");
7564 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, PDCH_MODE);
7565
7566 /* Fill TS0 SDCCH channels (NOTE: only 3 SDCCH/4 channels are available
7567 * on CCCH+SDCCH4+CBCH) */
Pau Espin Pedrol2ebbe7c2021-07-23 16:17:09 +02007568 var OCT1 ra := '43'O; /* RA containing reason=originating speech call*/
Pau Espin Pedrolce4d5bb2021-10-25 13:31:25 +02007569 for (i := 0; i < NUM_SDCCH_PER_BTS; i := i + 1) {
Pau Espin Pedrol2ebbe7c2021-07-23 16:17:09 +02007570 dt := f_est_dchan(ra, i, '00010203040506'O);
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02007571 }
7572
7573 /* Now the dyn ts is selected. First PDCH is released, then TCH chan is activated */
Pau Espin Pedrol2ebbe7c2021-07-23 16:17:09 +02007574 f_ipa_tx(0, ts_RSL_CHAN_RQD(int2oct(oct2int(ra) + i, 1), 2342));
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02007575 rsl_unused := f_exp_ipa_rx(0, tr_RSL_RF_CHAN_REL(pdch_chan_nr));
7576 f_ipa_tx(0, ts_RSL_RF_CHAN_REL_ACK(pdch_chan_nr));
7577
7578 rsl_msg := f_exp_ipa_rx(0, tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
7579 dt.rsl_chan_nr := rsl_msg.ies[0].body.chan_nr;
7580
7581 f_ts_dyn_mode_assert(0, 0, dt.rsl_chan_nr.tn, TCHH_MODE);
7582 f_ipa_tx(0, ts_RSL_CHAN_ACT_ACK(dt.rsl_chan_nr, 2342));
7583 rsl_msg := f_exp_ipa_rx(0, tr_RSL_IMM_ASSIGN(0));
7584 f_ts_dyn_mode_assert(0, 0, dt.rsl_chan_nr.tn, TCHH_MODE);
7585
7586 f_ipa_tx(0, ts_RSL_EST_IND(dt.rsl_chan_nr, valueof(ts_RslLinkID_DCCH(0)), '1234'O));
7587 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3('1234'O))) -> value rx_c_ind;
7588 dt.sccp_conn_id := rx_c_ind.connectionId;
7589 BSSAP.send(ts_BSSAP_CONNECT_res(dt.sccp_conn_id));
7590
7591 /* Instruct BSC to clear channel */
7592 var BssmapCause cause := 0;
7593 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
7594 f_exp_chan_rel_and_clear(dt, 0);
7595
7596 /* The BSC will switch the TS back to PDCH once the only lchan using it is released: */
7597 rsl_unused := f_exp_ipa_rx(0, tr_RSL_CHAN_ACT_PDCH(pdch_chan_nr, ?));
7598 f_ipa_tx(0, ts_RSL_CHAN_ACT_ACK(pdch_chan_nr, 2342));
7599 f_sleep(1.0);
7600 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, PDCH_MODE);
7601
7602 /* clean up config */
7603 f_ts_reset_chcomb(0);
7604 /* TODO: clean up other channels? */
7605
7606 f_shutdown_helper();
7607}
7608
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02007609/* Test Osmocom dyn TS SDCCH8 activation / deactivation when SDCCH fails at BTS */
7610testcase TC_dyn_ts_sdcch8_act_nack() runs on test_CT {
7611 var RSL_Message rsl_unused, rsl_msg;
7612 var DchanTuple dt;
7613 var BSSAP_N_CONNECT_ind rx_c_ind;
7614 var GsmRrMessage rr;
7615
7616 /* change Timeslot 6 before f_init() starts RSL */
7617 f_init_vty();
7618 f_ts_set_chcomb(0, 0, 6, "TCH/F_TCH/H_SDCCH8_PDCH");
7619 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
7620
7621 f_init(1, false);
7622 f_sleep(1.0);
7623
7624 var RslChannelNr pdch_chan_nr := valueof(t_RslChanNr_PDCH(6));
7625
7626 log("TCH/F_TCH/H_SDCCH8_PDCH pchan starts out in disabled mode:");
7627 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, NONE_MODE);
7628 /* The BSC will activate the dynamic PDCH by default, so confirm that */
7629 rsl_unused := f_exp_ipa_rx(0, tr_RSL_CHAN_ACT_PDCH(pdch_chan_nr, ?));
7630
7631 f_ipa_tx(0, ts_RSL_CHAN_ACT_ACK(pdch_chan_nr, 2342));
7632 f_sleep(1.0);
7633 log("TCH/F_TCH/H_SDCCH8_PDC requested to PDCH ACT on startup, which was ACKed, so now in PDCH:");
7634 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, PDCH_MODE);
7635
7636 /* Fill TS0 SDCCH channels (NOTE: only 3 SDCCH/4 channels are available
7637 * on CCCH+SDCCH4+CBCH) */
7638 var integer i;
Pau Espin Pedrolce4d5bb2021-10-25 13:31:25 +02007639 for (i := 0; i < NUM_SDCCH_PER_BTS; i := i + 1) {
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02007640 dt := f_est_dchan('23'O, i, '00010203040506'O);
7641 }
7642
7643 /* Now the dyn ts is selected. First PDCH is released, then sdcch chan is activated */
7644 f_ipa_tx(0, ts_RSL_CHAN_RQD(int2oct(oct2int('23'O) + i, 1), 2342));
7645 rsl_unused := f_exp_ipa_rx(0, tr_RSL_RF_CHAN_REL(pdch_chan_nr));
7646 f_ipa_tx(0, ts_RSL_RF_CHAN_REL_ACK(pdch_chan_nr));
7647
7648 rsl_msg := f_exp_ipa_rx(0, tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
7649 dt.rsl_chan_nr := rsl_msg.ies[0].body.chan_nr;
7650
7651 f_ts_dyn_mode_assert(0, 0, dt.rsl_chan_nr.tn, SDCCH8_MODE);
7652 f_ipa_tx(0, ts_RSL_CHAN_ACT_NACK(dt.rsl_chan_nr, RSL_ERR_EQUIPMENT_FAIL));
7653 rsl_msg := f_exp_ipa_rx(0, tr_RSL_IMM_ASSIGN(0));
7654 rr := dec_GsmRrMessage(rsl_msg.ies[1].body.full_imm_ass_info.payload);
7655 if (rr.header.message_type != IMMEDIATE_ASSIGNMENT_REJECT) {
7656 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Expected reject");
7657 }
7658
7659 /* FIXME? Currently the TS stays in state BORKEN: */
7660
7661 /* The BSC will switch the TS back to PDCH once the only lchan using it is released: */
7662 /* rsl_unused := f_exp_ipa_rx(0, tr_RSL_CHAN_ACT_PDCH(pdch_chan_nr, ?));
7663 * f_ipa_tx(0, ts_RSL_CHAN_ACT_ACK(pdch_chan_nr, 2342));
7664 * f_sleep(1.0);
7665 * f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, PDCH_MODE)
7666 */
7667
7668 /* clean up config */
7669 f_ts_set_chcomb(0, 0, 6, "PDCH");
7670
7671 f_shutdown_helper();
7672}
7673
Stefan Sperling0796a822018-10-05 13:01:39 +02007674testcase TC_chopped_ipa_ping() runs on test_CT {
Stefan Sperling554123f2018-10-09 14:12:30 +02007675 const Integers bsc_ipa_ports := {mp_bsc_rsl_port, mp_bsc_oml_port, mp_bsc_ctrl_port};
Stefan Sperling0796a822018-10-05 13:01:39 +02007676 for (var integer i := 0; i < lengthof(bsc_ipa_ports); i := i + 1) {
7677 IPA_Testing.f_run_TC_chopped_ipa_ping(mp_bsc_ip, bsc_ipa_ports[i], CONNECT_TO_SERVER);
7678 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02007679 f_shutdown_helper();
Stefan Sperling0796a822018-10-05 13:01:39 +02007680}
7681
Stefan Sperlingaa1e60f2018-10-15 16:34:07 +02007682testcase TC_chopped_ipa_payload() runs on test_CT {
7683 const Integers bsc_ipa_ports := {mp_bsc_rsl_port, mp_bsc_oml_port
7684 /* TODO: mp_bsc_ctrl_port does not work yet */};
7685 for (var integer i := 0; i < lengthof(bsc_ipa_ports); i := i + 1) {
7686 IPA_Testing.f_run_TC_chopped_ipa_payload(mp_bsc_ip, bsc_ipa_ports[i], CONNECT_TO_SERVER);
7687 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02007688 f_shutdown_helper();
Stefan Sperlingaa1e60f2018-10-15 16:34:07 +02007689}
7690
Pau Espin Pedrol8f773632019-11-05 11:46:53 +01007691/* Verify the BSC sends the MS Power Parameters IE during CHAN ACT to make sure
7692 the BTS does autonomous MS power control loop */
7693testcase TC_assignment_verify_ms_power_params_ie() runs on test_CT {
7694 var MSC_ConnHdlr vc_conn;
7695 var TestHdlrParams pars := f_gen_test_hdlr_pars();
7696 //pars.encr := valueof(t_EncrParams('01'O, f_rnd_octstring(8)));
7697 pars.exp_ms_power_params := true;
7698
7699 f_init(1, true);
7700 f_sleep(1.0);
7701 vc_conn := f_start_handler(refers(f_tc_assignment_fr_a5), pars);
7702 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02007703 f_shutdown_helper();
Pau Espin Pedrol8f773632019-11-05 11:46:53 +01007704}
Stefan Sperlingaa1e60f2018-10-15 16:34:07 +02007705
Vadim Yanitskiy4b233042021-06-30 00:58:43 +02007706/* Verify activation and deactivation of the BCCH carrier power reduction mode */
7707testcase TC_c0_power_red_mode() runs on test_CT {
7708 f_init(1);
7709
7710 for (var integer red := 6; red >= 0; red := red - 2) {
7711 /* Configure BCCH carrier power reduction mode via the VTY */
7712 f_vty_transceive(BSCVTY, "bts 0 c0-power-reduction " & int2str(red));
7713
7714 /* Expect Osmocom specific BS Power Control message on the RSL */
7715 var template RSL_Message tr_rsl_pdu := tr_RSL_BS_PWR_CTRL(
7716 chan_nr := t_RslChanNr_BCCH(0),
7717 bs_power := tr_RSL_IE_BS_Power(red / 2));
7718 tr_rsl_pdu.msg_disc := tr_RSL_MsgDisc(RSL_MDISC_CCHAN, false);
7719 var RSL_Message unused := f_exp_ipa_rx(0, tr_rsl_pdu);
7720
7721 /* Additionally verify the applied value over the CTRL interface */
7722 var CtrlValue cred := f_ctrl_get_bts(IPA_CTRL, 0, "c0-power-reduction");
7723 if (cred != int2str(red)) {
7724 setverdict(fail, "Unexpected BCCH carrier power reduction value ",
7725 cred, " (expected ", red, ")");
7726 }
7727 }
7728
7729 f_shutdown_helper();
7730}
7731
Neels Hofmeyr4f118412020-06-04 15:25:10 +02007732/***********************************************************************
7733 * MSC Pooling
7734 ***********************************************************************/
7735
Neels Hofmeyr4f118412020-06-04 15:25:10 +02007736template MobileIdentityLV ts_MI_TMSI_NRI_LV(integer nri_v, integer nri_bitlen := 10) :=
Harald Weltebf397612021-01-14 20:39:46 +01007737 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 +02007738
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02007739private 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 +02007740runs on MSC_ConnHdlr {
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02007741 interleave {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02007742 [] rsl_pt.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch exp_rr_rel_tmpl)) {
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02007743 f_logp(BSCVTY, "Got RSL RR Release");
7744 }
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02007745 [] rsl_pt.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02007746 f_logp(BSCVTY, "Got RSL Deact SACCH");
7747 }
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +02007748 [] rsl_pt.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02007749 f_logp(BSCVTY, "Got RSL RF Chan Rel, sending Rel Ack");
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02007750 rsl_pt.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
7751 f_rslem_unregister(0, g_chan_nr, PT := rsl_proc_pt);
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02007752 break;
7753 }
7754 }
7755}
7756
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02007757friend function f_perform_clear(RSL_DCHAN_PT rsl_pt := RSL, RSLEM_PROC_PT rsl_proc_pt := RSL_PROC,
7758 template PDU_ML3_NW_MS exp_rr_rel_tmpl := tr_RRM_RR_RELEASE)
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02007759runs on MSC_ConnHdlr {
Neels Hofmeyr767548a2020-08-09 20:26:07 +00007760 f_logp(BSCVTY, "MSC instructs BSC to clear channel");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02007761 BSSAP.send(ts_BSSMAP_ClearCommand(0));
7762 interleave {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02007763 [] rsl_pt.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch exp_rr_rel_tmpl)) {
Neels Hofmeyr767548a2020-08-09 20:26:07 +00007764 f_logp(BSCVTY, "Got RSL RR Release");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02007765 }
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02007766 [] rsl_pt.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {
Neels Hofmeyr767548a2020-08-09 20:26:07 +00007767 f_logp(BSCVTY, "Got RSL Deact SACCH");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02007768 }
7769 [] BSSAP.receive(tr_BSSMAP_ClearComplete) {
Neels Hofmeyr767548a2020-08-09 20:26:07 +00007770 f_logp(BSCVTY, "Got BSSMAP Clear Complete");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02007771 /* Also drop the SCCP connection */
7772 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
7773 }
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +02007774 [] rsl_pt.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
Neels Hofmeyr767548a2020-08-09 20:26:07 +00007775 f_logp(BSCVTY, "Got RSL RF Chan Rel, sending Rel Ack");
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02007776 rsl_pt.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
7777 f_rslem_unregister(0, g_chan_nr, PT := rsl_proc_pt);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02007778 }
7779 }
7780}
7781
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02007782private function f_perform_compl_l3(RSL_DCHAN_PT rsl_pt, RSLEM_PROC_PT rsl_proc_pt,
7783 template PDU_ML3_MS_NW l3_info, boolean do_clear := true, boolean expect_bssmap_l3 := true)
Neels Hofmeyr4f118412020-06-04 15:25:10 +02007784runs on MSC_ConnHdlr {
7785 timer T := 10.0;
7786 var octetstring l3_enc := enc_PDU_ML3_MS_NW(valueof(l3_info));
7787
Neels Hofmeyr767548a2020-08-09 20:26:07 +00007788 f_logp(BSCVTY, "establish channel, send Complete Layer 3 Info");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02007789 f_create_bssmap_exp(l3_enc);
7790
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02007791 /* RSL_Emulation.f_chan_est() on rsl_pt:
7792 * This is basically code dup with s/RSL/rsl_pt from:
Neels Hofmeyr4f118412020-06-04 15:25:10 +02007793 * RSL_Emulation.f_chan_est(g_pars.ra, l3_enc, g_pars.link_id, g_pars.fn);
7794 */
7795 var RSL_Message rx_rsl;
7796 var GsmRrMessage rr;
7797
7798 /* request a channel to be established */
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02007799 rsl_pt.send(ts_RSLDC_ChanRqd(g_pars.ra, g_pars.fn));
Neels Hofmeyr4f118412020-06-04 15:25:10 +02007800 /* expect immediate assignment.
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02007801 * Code dup with s/RSL/rsl_pt from:
Neels Hofmeyr4f118412020-06-04 15:25:10 +02007802 * rx_rsl := f_rx_or_fail(tr_RSL_IMM_ASSIGN);
7803 */
7804 timer Tt := 10.0;
7805
7806 /* request a channel to be established */
7807 Tt.start;
7808 alt {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02007809 [] rsl_pt.receive(tr_RSL_IMM_ASSIGN) -> value rx_rsl {
Neels Hofmeyr4f118412020-06-04 15:25:10 +02007810 Tt.stop;
7811 }
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02007812 [] rsl_pt.receive {
Neels Hofmeyr4f118412020-06-04 15:25:10 +02007813 setverdict(fail, "Unexpected RSL message on DCHAN");
7814 mtc.stop;
7815 }
7816 [] Tt.timeout {
7817 setverdict(fail, "Timeout waiting for RSL on DCHAN");
7818 mtc.stop;
7819 }
7820 }
7821 rr := dec_GsmRrMessage(rx_rsl.ies[1].body.full_imm_ass_info.payload);
7822 g_chan_nr := rr.payload.imm_ass.chan_desc.chan_nr;
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02007823 rsl_pt.send(ts_RSL_EST_IND(g_chan_nr, valueof(g_pars.link_id), l3_enc));
Neels Hofmeyr4f118412020-06-04 15:25:10 +02007824
7825
Neels Hofmeyr66e15092020-10-12 18:44:41 +00007826 if (expect_bssmap_l3) {
7827 f_logp(BSCVTY, "expect BSSAP Complete Layer 3 Info at MSC");
7828 var template PDU_BSSAP exp_l3_compl;
7829 exp_l3_compl := tr_BSSMAP_ComplL3()
7830 if (g_pars.aoip == false) {
7831 exp_l3_compl.pdu.bssmap.completeLayer3Information.codecList := omit;
7832 } else {
7833 exp_l3_compl.pdu.bssmap.completeLayer3Information.codecList := ?;
7834 }
Neels Hofmeyr4f118412020-06-04 15:25:10 +02007835
Neels Hofmeyr66e15092020-10-12 18:44:41 +00007836 var PDU_BSSAP bssap;
7837 T.start;
7838 alt {
7839 [] BSSAP.receive(exp_l3_compl) -> value bssap {
7840 f_logp(BSCVTY, "received expected Complete Layer 3 Info at MSC");
7841 log("rx exp_l3_compl = ", bssap);
7842 }
7843 [] BSSAP.receive(tr_BSSMAP_ComplL3) {
7844 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Received non-matching COMPLETE LAYER 3 INFORMATION");
7845 }
7846 [] T.timeout {
7847 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout waiting for COMPLETE LAYER 3 INFORMATION");
7848 }
Neels Hofmeyr4f118412020-06-04 15:25:10 +02007849 }
Neels Hofmeyr4f118412020-06-04 15:25:10 +02007850
Neels Hofmeyr66e15092020-10-12 18:44:41 +00007851 /* start ciphering, if requested */
7852 if (ispresent(g_pars.encr)) {
7853 f_logp(BSCVTY, "start ciphering");
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02007854 f_cipher_mode(g_pars.encr, rsl_pt := rsl_pt, rsl_proc_pt := rsl_proc_pt);
Neels Hofmeyr66e15092020-10-12 18:44:41 +00007855 }
Neels Hofmeyr4f118412020-06-04 15:25:10 +02007856 }
7857
7858 if (do_clear) {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02007859 f_perform_clear(rsl_pt, rsl_proc_pt);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02007860 }
7861 setverdict(pass);
7862 f_sleep(1.0);
7863}
7864
7865private function f_tc_mscpool_compl_l3(charstring id) runs on MSC_ConnHdlr {
7866 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
7867 if (g_pars.mscpool.rsl_idx == 0) {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02007868 f_perform_compl_l3(RSL, RSL_PROC, g_pars.mscpool.l3_info);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02007869 } else if (g_pars.mscpool.rsl_idx == 1) {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02007870 f_perform_compl_l3(RSL1, RSL1_PROC, g_pars.mscpool.l3_info);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02007871 } else if (g_pars.mscpool.rsl_idx == 2) {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02007872 f_perform_compl_l3(RSL2, RSL2_PROC, g_pars.mscpool.l3_info);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02007873 }
7874}
7875
7876/* Various Complete Layer 3 by IMSI all end up with the first MSC, because the other MSCs are not connected. */
7877private function f_tc_mscpool_L3Compl_on_1_msc(charstring id) runs on MSC_ConnHdlr {
7878 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02007879 f_perform_compl_l3(RSL, RSL_PROC, ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_IMSI_LV('001010000000001'H)), '00F110'O) );
7880 f_perform_compl_l3(RSL, RSL_PROC, ts_CM_SERV_REQ(CM_TYPE_MO_SMS, valueof(ts_MI_IMSI_LV('001010000000002'H))) );
7881 f_perform_compl_l3(RSL, RSL_PROC, ts_PAG_RESP(valueof(ts_MI_IMSI_LV('001010000000003'H))) );
7882 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 +02007883}
7884testcase TC_mscpool_L3Compl_on_1_msc() runs on test_CT {
7885
7886 f_init(1, true);
7887 f_sleep(1.0);
7888 var MSC_ConnHdlr vc_conn;
7889 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02007890
7891 f_ctrs_msc_init();
7892
Neels Hofmeyr4f118412020-06-04 15:25:10 +02007893 vc_conn := f_start_handler(refers(f_tc_mscpool_L3Compl_on_1_msc), pars);
7894 vc_conn.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02007895
7896 f_ctrs_msc_expect(0, "mscpool:subscr:new", 4);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02007897 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02007898}
7899
7900/* Three Layer 3 Complete by IMSI are round-robin'ed across two connected MSCs */
7901/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
7902 * just as well using only RSL. */
7903testcase TC_mscpool_L3Complete_by_imsi_round_robin() runs on test_CT {
7904
7905 f_init(nr_bts := 3, handler_mode := true, nr_msc := 2);
7906 f_sleep(1.0);
7907
7908 /* Control which MSC gets chosen next by the round-robin, otherwise
7909 * would be randomly affected by which other tests ran before this. */
7910 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
7911
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02007912 f_ctrs_msc_init();
7913
Neels Hofmeyr4f118412020-06-04 15:25:10 +02007914 var MSC_ConnHdlr vc_conn1;
7915 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
7916 pars1.mscpool.rsl_idx := 0;
7917 pars1.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_IMSI_LV('001010000000001'H)), '00F110'O));
7918 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
7919 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02007920 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02007921
7922 var MSC_ConnHdlr vc_conn2;
7923 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 1);
7924 pars2.mscpool.rsl_idx := 1;
7925 pars2.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, valueof(ts_MI_IMSI_LV('001010000000002'H))));
7926 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
7927 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02007928 f_ctrs_msc_expect(1, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02007929
7930 /* Test round-robin wrap to the first MSC */
7931 var MSC_ConnHdlr vc_conn3;
7932 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 0);
7933 pars3.mscpool.rsl_idx := 2;
7934 pars3.mscpool.l3_info := valueof(ts_PAG_RESP(valueof(ts_MI_IMSI_LV('001010000000003'H))));
7935 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
7936 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02007937 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02007938 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02007939}
7940
7941/* Three LU by TMSI are round-robin'ed across two connected MSCs, because they contain the NULL-NRI 0
7942 * (configured in osmo-bsc.cfg). */
7943/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
7944 * just as well using only RSL. */
7945testcase TC_mscpool_LU_by_tmsi_null_nri_0_round_robin() runs on test_CT {
7946
7947 f_init(nr_bts := 3, handler_mode := true, nr_msc := 2);
7948 f_sleep(1.0);
7949
7950 /* Control which MSC gets chosen next by the round-robin, otherwise
7951 * would be randomly affected by which other tests ran before this. */
7952 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
7953
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02007954 f_ctrs_msc_init();
7955
Neels Hofmeyr4f118412020-06-04 15:25:10 +02007956 var MSC_ConnHdlr vc_conn1;
7957 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
7958 pars1.mscpool.rsl_idx := 0;
7959 pars1.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(0)), '00F110'O));
7960 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
7961 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02007962 f_ctrs_msc_expect(0, "mscpool:subscr:reattach");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02007963
7964 var MSC_ConnHdlr vc_conn2;
7965 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 1);
7966 pars2.mscpool.rsl_idx := 1;
7967 pars2.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(0)), '00F110'O));
7968 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
7969 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02007970 f_ctrs_msc_expect(1, "mscpool:subscr:reattach");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02007971
7972 /* Test round-robin wrap to the first MSC */
7973 var MSC_ConnHdlr vc_conn3;
7974 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 0);
7975 pars3.mscpool.rsl_idx := 2;
7976 pars3.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(0)), '00F110'O));
7977 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
7978 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02007979 f_ctrs_msc_expect(0, "mscpool:subscr:reattach");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02007980 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02007981}
7982
7983/* Three LU by TMSI are round-robin'ed across two connected MSCs, because they contain the NULL-NRI 1
7984 * (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
7985 * NULL-NRI setting is stronger than that. */
7986/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
7987 * just as well using only RSL. */
7988testcase TC_mscpool_LU_by_tmsi_null_nri_1_round_robin() runs on test_CT {
7989
7990 f_init(nr_bts := 3, handler_mode := true, nr_msc := 2);
7991 f_sleep(1.0);
7992
7993 /* Control which MSC gets chosen next by the round-robin, otherwise
7994 * would be randomly affected by which other tests ran before this. */
7995 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
7996
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02007997 f_ctrs_msc_init();
7998
Neels Hofmeyr4f118412020-06-04 15:25:10 +02007999 var MSC_ConnHdlr vc_conn1;
8000 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
8001 pars1.mscpool.rsl_idx := 0;
8002 pars1.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(1)), '00F110'O));
8003 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8004 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008005 f_ctrs_msc_expect(0, "mscpool:subscr:reattach");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008006
8007 var MSC_ConnHdlr vc_conn2;
8008 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 1);
8009 pars2.mscpool.rsl_idx := 1;
8010 pars2.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(1)), '00F110'O));
8011 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8012 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008013 f_ctrs_msc_expect(1, "mscpool:subscr:reattach");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008014
8015 /* Test round-robin wrap to the first MSC */
8016 var MSC_ConnHdlr vc_conn3;
8017 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 0);
8018 pars3.mscpool.rsl_idx := 2;
8019 pars3.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(1)), '00F110'O));
8020 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8021 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008022 f_ctrs_msc_expect(0, "mscpool:subscr:reattach");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008023 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008024}
8025
8026/* Three Layer 3 Complete by TMSI are round-robin'ed across two connected MSCs, because they contain an NRI not
8027 * assigned to any MSC (configured in osmo-bsc.cfg). */
8028/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8029 * just as well using only RSL. */
8030testcase TC_mscpool_L3Complete_by_tmsi_unassigned_nri_round_robin() runs on test_CT {
8031
8032 f_init(nr_bts := 3, handler_mode := true, nr_msc := 2);
8033 f_sleep(1.0);
8034
8035 /* Control which MSC gets chosen next by the round-robin, otherwise
8036 * would be randomly affected by which other tests ran before this. */
8037 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
8038
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008039 f_ctrs_msc_init();
8040
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008041 var MSC_ConnHdlr vc_conn1;
8042 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
8043 pars1.mscpool.rsl_idx := 0;
8044 /* An NRI that is not assigned to any MSC */
8045 pars1.mscpool.l3_info := valueof(ts_ML3_MO_MM_IMSI_DET_Ind(valueof(ts_MI_TMSI_NRI_LV(1023))));
8046 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8047 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008048 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008049
8050 var MSC_ConnHdlr vc_conn2;
8051 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 1);
8052 pars2.mscpool.rsl_idx := 1;
8053 /* An NRI that is not assigned to any MSC */
8054 pars2.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(768)), '00F110'O));
8055 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8056 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008057 f_ctrs_msc_expect(1, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008058
8059 /* Test round-robin wrap to the first MSC */
8060 var MSC_ConnHdlr vc_conn3;
8061 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 0);
8062 pars3.mscpool.rsl_idx := 2;
8063 /* An NRI that is not assigned to any MSC */
8064 pars3.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_SS_ACT, valueof(ts_MI_TMSI_NRI_LV(819))));
8065 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8066 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008067 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008068 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008069}
8070
8071/* Three Layer 3 Complete by TMSI are round-robin'ed across two connected MSCs, because they contain an NRI
8072 * assigned to an MSC that is currently not connected (configured in osmo-bsc.cfg). */
8073/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8074 * just as well using only RSL. */
8075testcase TC_mscpool_L3Complete_by_tmsi_valid_nri_msc_not_connected_round_robin() runs on test_CT {
8076
8077 f_init(nr_bts := 3, handler_mode := true, nr_msc := 2);
8078 f_sleep(1.0);
8079
8080 /* Control which MSC gets chosen next by the round-robin, otherwise
8081 * would be randomly affected by which other tests ran before this. */
8082 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
8083
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008084 f_ctrs_msc_init();
8085
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008086 var MSC_ConnHdlr vc_conn1;
8087 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
8088 pars1.mscpool.rsl_idx := 0;
8089 /* An NRI that is assigned to an unconnected MSC */
8090 pars1.mscpool.l3_info := valueof(ts_PAG_RESP(valueof(ts_MI_TMSI_NRI_LV(512))));
8091 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8092 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008093 f_ctrs_msc_add(2, "mscpool:subscr:attach_lost");
8094 f_ctrs_msc_add(0, "mscpool:subscr:new");
8095 f_ctrs_msc_verify();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008096
8097 var MSC_ConnHdlr vc_conn2;
8098 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 1);
8099 pars2.mscpool.rsl_idx := 1;
8100 /* An NRI that is assigned to an unconnected MSC */
8101 pars2.mscpool.l3_info := valueof(ts_ML3_MO_MM_IMSI_DET_Ind(valueof(ts_MI_TMSI_NRI_LV(767))));
8102 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8103 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008104 f_ctrs_msc_add(2, "mscpool:subscr:attach_lost");
8105 f_ctrs_msc_add(1, "mscpool:subscr:new");
8106 f_ctrs_msc_verify();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008107
8108 /* Test round-robin wrap to the first MSC */
8109 var MSC_ConnHdlr vc_conn3;
8110 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 0);
8111 pars3.mscpool.rsl_idx := 2;
8112 /* An NRI that is assigned to an unconnected MSC */
8113 pars3.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(750)), '00F110'O));
8114 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8115 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008116 f_ctrs_msc_add(2, "mscpool:subscr:attach_lost");
8117 f_ctrs_msc_add(0, "mscpool:subscr:new");
8118 f_ctrs_msc_verify();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008119 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008120}
8121
8122/* Three Layer 3 Complete by TMSI with valid NRI for the second MSC are all directed to the second MSC (configured in
8123 * osmo-bsc.cfg). */
8124/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8125 * just as well using only RSL. */
8126testcase TC_mscpool_L3Complete_by_tmsi_valid_nri_1() runs on test_CT {
8127
8128 f_init(nr_bts := 3, handler_mode := true, nr_msc := 2);
8129 f_sleep(1.0);
8130
8131 /* All TMSIs in this test point at the second MSC, set the round robin to point at the first MSC to make sure
8132 * this is not using round-robin. */
8133 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
8134
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008135 f_ctrs_msc_init();
8136
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008137 var MSC_ConnHdlr vc_conn1;
8138 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 1);
8139 pars1.mscpool.rsl_idx := 0;
8140 /* An NRI of the second MSC's range (256-511) */
8141 pars1.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_SMS, valueof(ts_MI_TMSI_NRI_LV(256))));
8142 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8143 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008144 f_ctrs_msc_expect(1, "mscpool:subscr:known");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008145
8146 var MSC_ConnHdlr vc_conn2;
8147 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 1);
8148 pars2.mscpool.rsl_idx := 1;
8149 /* An NRI of the second MSC's range (256-511) */
8150 pars2.mscpool.l3_info := valueof(ts_PAG_RESP(valueof(ts_MI_TMSI_NRI_LV(260))));
8151 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8152 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008153 f_ctrs_msc_expect(1, "mscpool:subscr:known");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008154
8155 var MSC_ConnHdlr vc_conn3;
8156 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 1);
8157 pars3.mscpool.rsl_idx := 2;
8158 /* An NRI of the second MSC's range (256-511) */
8159 pars3.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(511)), '00F110'O));
8160 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8161 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008162 f_ctrs_msc_expect(1, "mscpool:subscr:known");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008163 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008164}
8165
8166/* Layer 3 Complete by TMSI with valid NRI for the third MSC are directed to the third MSC (configured in osmo-bsc.cfg),
8167 * while a round-robin remains unaffected by that. */
8168/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8169 * just as well using only RSL. */
8170testcase TC_mscpool_L3Complete_by_tmsi_valid_nri_2() runs on test_CT {
8171
8172 f_init(nr_bts := 3, handler_mode := true, nr_msc := 3);
8173 f_sleep(1.0);
8174
8175 /* All TMSIs in this test point at the third MSC, set the round robin to point at the second MSC to make sure
8176 * this is not using round-robin. */
8177 f_vty_transceive(BSCVTY, "mscpool roundrobin next 1");
8178
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008179 f_ctrs_msc_init();
8180
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008181 var MSC_ConnHdlr vc_conn1;
8182 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 2);
8183 pars1.mscpool.rsl_idx := 0;
8184 /* An NRI of the third MSC's range (512-767) */
8185 pars1.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_SMS, valueof(ts_MI_TMSI_NRI_LV(512))));
8186 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8187 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008188 f_ctrs_msc_expect(2, "mscpool:subscr:known");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008189
8190 var MSC_ConnHdlr vc_conn2;
8191 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 2);
8192 pars2.mscpool.rsl_idx := 1;
8193 /* An NRI of the third MSC's range (512-767) */
8194 pars2.mscpool.l3_info := valueof(ts_PAG_RESP(valueof(ts_MI_TMSI_NRI_LV(678))));
8195 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8196 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008197 f_ctrs_msc_expect(2, "mscpool:subscr:known");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008198
8199 /* The above forwardings to third MSC have not affected the round robin, which still points at the second MSC */
8200 var MSC_ConnHdlr vc_conn3;
8201 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 1);
8202 pars3.mscpool.rsl_idx := 2;
8203 pars3.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_IMSI_LV('001010000000013'H)), '00F110'O));
8204 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8205 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008206 f_ctrs_msc_expect(1, "mscpool:subscr:new");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008207 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008208}
8209
8210/* LU with a TMSI but indicating a different PLMN in its previous LAI: ignore the NRI. */
8211/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8212 * just as well using only RSL. */
8213testcase TC_mscpool_LU_by_tmsi_from_other_PLMN() runs on test_CT {
8214
8215 f_init(nr_bts := 3, handler_mode := true, nr_msc := 3);
8216 f_sleep(1.0);
8217
8218 /* The TMSIs in this test points at the second MSC, but since it is from a different PLMN, round-robin is used
8219 * instead, and hits msc 0. */
8220 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
8221
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008222 f_ctrs_msc_init();
8223
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008224 /* An NRI of the second MSC's range (256-511), but a PLMN that doesn't match with osmo-bsc.cfg */
8225 var MSC_ConnHdlr vc_conn1;
8226 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
8227 pars1.mscpool.rsl_idx := 0;
8228 pars1.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(260)), '99F999'O));
8229 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8230 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008231 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008232
8233 /* An NRI of the third MSC's range (512-767) and a matching PLMN gets directed by NRI. */
8234 var MSC_ConnHdlr vc_conn2;
8235 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 2);
8236 pars2.mscpool.rsl_idx := 1;
8237 pars2.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(555)), '00F110'O));
8238 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8239 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008240 f_ctrs_msc_expect(2, "mscpool:subscr:known");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008241 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008242}
8243
8244/* Make sure that whichever MSC paged a subscriber will also get the Paging Response. Page by IMSI, which would be
8245 * round-robined to another MSC, to make sure the Paging->Response relation is stronger than the NRI->MSC mapping. */
8246private function f_tc_mscpool_paging_imsi(charstring id) runs on MSC_ConnHdlr {
8247 var template BSSMAP_FIELD_CellIdentificationList cid_list := { cIl_CI := { ts_BSSMAP_CI_CI(0) } };
8248 //cid_list := { cIl_allInBSS := ''O };
8249 var RSL_ChanNeeded rsl_chneed := RSL_CHANNEED_SDCCH;
8250 var template BSSMAP_IE_ChannelNeeded bssmap_chneed := ts_BSSMAP_IE_ChanNeeded(int2bit(enum2int(valueof(rsl_chneed)),2));
8251 var BSSAP_N_UNITDATA_req paging;
8252 var hexstring imsi := '001010000000123'H;
8253
8254 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
8255
Neels Hofmeyr90f80962020-06-12 16:16:55 +02008256 paging := valueof(ts_BSSAP_UNITDATA_req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008257 valueof(ts_BSSMAP_Paging(imsi, cid_list, omit, bssmap_chneed))));
8258 BSSAP.send(paging);
8259
8260 /* Register any RSL conn so that the Paging Command gets received here. With the current RSL_Emulation's main()
8261 * handling of '[bts_role] IPA_PT.receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD()))' it doesn't matter at all which
8262 * channel number is picked here. */
8263 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(0, RSL_CHAN_NR_INVALID));
8264 f_rslem_register(0, new_chan_nr);
8265 RSL.receive(tr_RSL_PAGING_CMD(tr_MI_IMSI(imsi)));
8266 f_rslem_unregister(0, new_chan_nr);
8267
8268 /* Despite the round robin pointing at the second MSC ('roundrobin next 1'), the earlier Paging for the same IMSI
8269 * causes this Paging Response to go to the first MSC (bssap_idx := 0). */
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008270 f_perform_compl_l3(RSL, RSL_PROC, ts_PAG_RESP(valueof(ts_MI_IMSI_LV(imsi))) );
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008271 f_sleep(1.0);
8272}
8273testcase TC_mscpool_paging_and_response_imsi() runs on test_CT {
8274 f_init(nr_bts := 1, handler_mode := true, nr_msc := 3);
8275 f_sleep(1.0);
8276
8277 /* Testing a Paging on the first MSC to get a Paging Response back to the first MSC. Set round robin to the
8278 * second MSC to make sure we're getting the Paging logic, not a coincidental round robin match. */
8279 f_vty_transceive(BSCVTY, "mscpool roundrobin next 1");
8280
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008281 f_ctrs_msc_init();
8282
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008283 var MSC_ConnHdlr vc_conn1;
8284 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
8285 pars1.mscpool.rsl_idx := 0;
Neels Hofmeyr90f80962020-06-12 16:16:55 +02008286 pars1.sccp_addr_bsc := g_bssap[pars1.mscpool.bssap_idx].sccp_addr_peer;
8287 pars1.sccp_addr_msc := g_bssap[pars1.mscpool.bssap_idx].sccp_addr_own;
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008288 vc_conn1 := f_start_handler(refers(f_tc_mscpool_paging_imsi), pars1);
8289 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008290 f_ctrs_msc_expect(0, "mscpool:subscr:paged");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008291 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008292}
8293
8294/* Make sure that whichever MSC paged a subscriber will also get the Paging Response. Page by TMSI with an NRI value
8295 * that matches a different MSC, to make sure the Paging->Response relation is stronger than the NRI->MSC mapping. */
8296private function f_tc_mscpool_paging_tmsi(charstring id) runs on MSC_ConnHdlr {
8297 var template BSSMAP_FIELD_CellIdentificationList cid_list := { cIl_CI := { ts_BSSMAP_CI_CI(0) } };
8298 //cid_list := { cIl_allInBSS := ''O };
8299 var RSL_ChanNeeded rsl_chneed := RSL_CHANNEED_SDCCH;
8300 var template BSSMAP_IE_ChannelNeeded bssmap_chneed := ts_BSSMAP_IE_ChanNeeded(int2bit(enum2int(valueof(rsl_chneed)),2));
8301 var integer nri_v := 300; /* <-- second MSC's NRI */
Harald Weltebf397612021-01-14 20:39:46 +01008302 var octetstring tmsi := f_gen_tmsi(suffix := 0, nri_v := nri_v);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008303 var BSSAP_N_UNITDATA_req paging;
8304
8305 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
8306
Neels Hofmeyr90f80962020-06-12 16:16:55 +02008307 paging := valueof(ts_BSSAP_UNITDATA_req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008308 valueof(ts_BSSMAP_Paging('001010000000011'H, cid_list, tmsi, bssmap_chneed))));
8309 BSSAP.send(paging);
8310
8311 /* Register any RSL conn so that the Paging Command gets received here. With the current RSL_Emulation's main()
8312 * handling of '[bts_role] IPA_PT.receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD()))' it doesn't matter at all which
8313 * channel number is picked here. */
8314 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(0, RSL_CHAN_NR_INVALID));
8315 f_rslem_register(0, new_chan_nr);
8316 RSL.receive(tr_RSL_PAGING_CMD(t_MI_TMSI(tmsi)));
8317 f_rslem_unregister(0, new_chan_nr);
8318
8319 /* Despite the NRI matching the second MSC (NRI from 'msc 1' in osmo-bsc.cfg) and round robin pointing at the
8320 * third MSC ('roundrobin next 2'), the earlier Paging for the same TMSI causes this Paging Response to go to
8321 * the first MSC (bssap_idx := 0). */
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008322 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 +02008323 f_sleep(1.0);
8324}
8325testcase TC_mscpool_paging_and_response_tmsi() runs on test_CT {
8326 f_init(nr_bts := 1, handler_mode := true, nr_msc := 3);
8327 f_sleep(1.0);
8328
8329 /* Testing a Paging on the first MSC to get a Paging Response back to the first MSC. Set round robin to the
8330 * third MSC to make sure we're getting the Paging logic, not a coincidental round robin match. */
8331 f_vty_transceive(BSCVTY, "mscpool roundrobin next 2");
8332
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008333 f_ctrs_msc_init();
8334
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008335 var MSC_ConnHdlr vc_conn1;
8336 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
8337 pars1.mscpool.rsl_idx := 0;
Neels Hofmeyr90f80962020-06-12 16:16:55 +02008338 pars1.sccp_addr_bsc := g_bssap[pars1.mscpool.bssap_idx].sccp_addr_peer;
8339 pars1.sccp_addr_msc := g_bssap[pars1.mscpool.bssap_idx].sccp_addr_own;
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008340 vc_conn1 := f_start_handler(refers(f_tc_mscpool_paging_tmsi), pars1);
8341 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008342 f_ctrs_msc_expect(0, "mscpool:subscr:paged");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008343 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008344}
8345
8346/* For round-robin, skip an MSC that has 'no allow-attach' set. */
8347/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8348 * just as well using only RSL. */
8349testcase TC_mscpool_no_allow_attach_round_robin() runs on test_CT {
8350
8351 f_init(nr_bts := 3, handler_mode := true, nr_msc := 3);
8352 f_sleep(1.0);
Neels Hofmeyra460f1f2020-08-09 20:17:03 +00008353 /* Mark the second MSC as offloading, round-robin should skip this MSC now. */
8354 f_vty_msc_allow_attach(BSCVTY, {true, false, true});
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008355
8356 /* Control which MSC gets chosen next by the round-robin, otherwise
8357 * would be randomly affected by which other tests ran before this. */
8358 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
8359
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008360 f_ctrs_msc_init();
8361
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008362 var MSC_ConnHdlr vc_conn1;
8363 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
8364 pars1.mscpool.rsl_idx := 0;
8365 pars1.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_IMSI_LV('001010000000001'H)), '00F110'O));
8366 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8367 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008368 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008369
8370 var MSC_ConnHdlr vc_conn2;
8371 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 2);
8372 pars2.mscpool.rsl_idx := 1;
8373 pars2.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, valueof(ts_MI_IMSI_LV('001010000000002'H))));
8374 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8375 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008376 f_ctrs_msc_expect(2, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008377
8378 var MSC_ConnHdlr vc_conn3;
8379 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 0);
8380 pars3.mscpool.rsl_idx := 2;
8381 pars3.mscpool.l3_info := valueof(ts_PAG_RESP(valueof(ts_MI_IMSI_LV('001010000000003'H))));
8382 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8383 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008384 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008385 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008386}
8387
8388/* An MSC that has 'no allow-attach' set should still serve subscribers that are already attached according to their
8389 * TMSI NRI. */
8390testcase TC_mscpool_no_allow_attach_valid_nri() runs on test_CT {
8391
8392 f_init(nr_bts := 3, handler_mode := true, nr_msc := 3);
8393 f_sleep(1.0);
8394
Neels Hofmeyra460f1f2020-08-09 20:17:03 +00008395 /* Mark the second MSC as offloading, round-robin should skip this MSC now. */
8396 f_vty_msc_allow_attach(BSCVTY, {true, false, true});
8397
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008398 /* Control which MSC gets chosen next by the round-robin, otherwise
8399 * would be randomly affected by which other tests ran before this. */
8400 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
8401
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008402 f_ctrs_msc_init();
8403
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008404 /* Round robin points at msc 0, but the valid NRI directs to msc 1, even though msc 1 has 'no allow-attach'. */
8405 var MSC_ConnHdlr vc_conn1;
8406 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 1);
8407 pars1.mscpool.rsl_idx := 0;
8408 /* An NRI of the second MSC's range (256-511) */
8409 pars1.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, valueof(ts_MI_TMSI_NRI_LV(260))));
8410 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8411 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008412 f_ctrs_msc_expect(1, "mscpool:subscr:known");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008413
8414 var MSC_ConnHdlr vc_conn2;
8415 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 0);
8416 pars2.mscpool.rsl_idx := 1;
8417 pars2.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, valueof(ts_MI_IMSI_LV('001010000000002'H))));
8418 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8419 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008420 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008421
8422 var MSC_ConnHdlr vc_conn3;
8423 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 2);
8424 pars3.mscpool.rsl_idx := 2;
8425 pars3.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, valueof(ts_MI_IMSI_LV('001010000000003'H))));
8426 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8427 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008428 f_ctrs_msc_expect(2, "mscpool:subscr:new");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008429 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008430}
8431
Philipp Maier783681c2020-07-16 16:47:06 +02008432/* Allow/Deny emergency calls globally via VTY */
8433private function f_vty_allow_emerg_msc(boolean allow) runs on test_CT {
8434 f_vty_enter_cfg_msc(BSCVTY, 0);
8435 if (allow) {
8436 f_vty_transceive(BSCVTY, "allow-emergency allow");
8437 } else {
8438 f_vty_transceive(BSCVTY, "allow-emergency deny");
8439 }
8440 f_vty_transceive(BSCVTY, "exit");
8441 f_vty_transceive(BSCVTY, "exit");
8442}
8443
8444/* Allow/Deny emergency calls per BTS via VTY */
8445private function f_vty_allow_emerg_bts(boolean allow, integer bts_nr) runs on test_CT {
8446 f_vty_enter_cfg_bts(BSCVTY, bts_nr);
8447 if (allow) {
8448 f_vty_transceive(BSCVTY, "rach emergency call allowed 1");
8449 } else {
8450 f_vty_transceive(BSCVTY, "rach emergency call allowed 0");
8451 }
8452 f_vty_transceive(BSCVTY, "exit");
8453 f_vty_transceive(BSCVTY, "exit");
Neels Hofmeyrb6ed80c2020-10-12 22:52:39 +00008454 f_vty_transceive(BSCVTY, "exit");
Philipp Maier783681c2020-07-16 16:47:06 +02008455}
8456
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02008457/* Allow/Forbid Fast Return after SRVCC on a given BTS via VTY */
8458private function f_vty_allow_srvcc_fast_return(boolean allow, integer bts_nr) runs on test_CT {
8459 f_vty_enter_cfg_bts(BSCVTY, bts_nr);
8460 if (allow) {
8461 f_vty_transceive(BSCVTY, "srvcc fast-return allow");
8462 } else {
8463 f_vty_transceive(BSCVTY, "srvcc fast-return forbid");
8464 }
8465 f_vty_transceive(BSCVTY, "exit");
8466 f_vty_transceive(BSCVTY, "exit");
8467 f_vty_transceive(BSCVTY, "exit");
8468}
8469
Pau Espin Pedrol14475352021-07-22 15:48:16 +02008470/* Allow/Forbid TCH for signalling if SDCCH exhausted on a given BTS via VTY */
8471private function f_vty_allow_tch_for_signalling(boolean allow, integer bts_nr) runs on test_CT {
8472 f_vty_enter_cfg_bts(BSCVTY, bts_nr);
8473 if (allow) {
8474 f_vty_transceive(BSCVTY, "channel allocator allow-tch-for-signalling 1");
8475 } else {
8476 f_vty_transceive(BSCVTY, "channel allocator allow-tch-for-signalling 0");
8477 }
8478 f_vty_transceive(BSCVTY, "exit");
8479 f_vty_transceive(BSCVTY, "exit");
8480 f_vty_transceive(BSCVTY, "exit");
8481}
8482
Philipp Maier783681c2020-07-16 16:47:06 +02008483/* Begin assignmet procedure and send an EMERGENCY SETUP (RR) */
8484private function f_assignment_emerg_setup() runs on MSC_ConnHdlr {
8485 var PDU_ML3_MS_NW emerg_setup;
8486 var octetstring emerg_setup_enc;
8487 var RSL_Message emerg_setup_data_ind;
8488
8489 f_establish_fully(omit, omit);
8490
8491 emerg_setup := valueof(ts_ML3_MO_CC_EMERG_SETUP(1, valueof(ts_Bcap_voice)));
8492 emerg_setup_enc := enc_PDU_ML3_MS_NW(emerg_setup);
8493 emerg_setup_data_ind := valueof(ts_RSL_DATA_IND(g_chan_nr, valueof(ts_RslLinkID_DCCH(0)), emerg_setup_enc));
8494
8495 RSL.send(emerg_setup_data_ind);
8496}
8497
8498/* Test if the EMERGENCY SETUP gets passed on to the MSC via A when EMERGENCY
8499 * CALLS are permitted by the BSC config. */
8500private function f_TC_assignment_emerg_setup_allow(charstring id) runs on MSC_ConnHdlr {
8501 var PDU_BSSAP emerg_setup_data_ind_bssap;
8502 var PDU_ML3_MS_NW emerg_setup;
8503 timer T := 3.0;
8504
8505 f_assignment_emerg_setup()
8506
8507 T.start;
8508 alt {
8509 [] BSSAP.receive(tr_BSSAP_DTAP) -> value emerg_setup_data_ind_bssap {
8510 emerg_setup := dec_PDU_ML3_MS_NW(emerg_setup_data_ind_bssap.pdu.dtap);
8511 if (not isbound(emerg_setup.msgs.cc.emergencySetup)) {
8512 setverdict(fail, "no emergency setup");
8513 }
8514 }
8515 [] BSSAP.receive {
8516 setverdict(fail, "unexpected BSSAP message!");
8517 }
8518 [] T.timeout {
8519 setverdict(fail, "timout waiting for EMERGENCY SETUP!");
8520 }
8521 }
8522
8523 setverdict(pass);
8524}
8525
8526/* Test if the EMERGENCY SETUP gets blocked by the BSC if EMERGENCY CALLS are
8527 * forbidden by the BSC config. */
8528private function f_TC_assignment_emerg_setup_deny(charstring id) runs on MSC_ConnHdlr {
8529 var PDU_BSSAP emerg_setup_data_ind_bssap;
8530 timer T := 3.0;
8531
8532 f_assignment_emerg_setup()
8533
8534 T.start;
8535 alt {
8536 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_RELEASE)) {
8537 setverdict(pass);
8538 }
8539 [] RSL.receive {
8540 setverdict(fail, "unexpected RSL message!");
8541 }
8542 [] T.timeout {
8543 setverdict(fail, "timout waiting for RR CHANNEL RELEASE!");
8544 }
8545 }
8546}
8547
8548/* EMERGENCY CALL situation #1, allowed globally and by BTS */
8549testcase TC_assignment_emerg_setup_allow() runs on test_CT {
8550 var TestHdlrParams pars := f_gen_test_hdlr_pars();
8551 var MSC_ConnHdlr vc_conn;
8552
8553 f_init(1, true);
8554 f_sleep(1.0);
8555
8556 f_vty_allow_emerg_msc(true);
8557 f_vty_allow_emerg_bts(true, 0);
8558 vc_conn := f_start_handler(refers(f_TC_assignment_emerg_setup_allow), pars);
8559 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008560 f_shutdown_helper();
Philipp Maier783681c2020-07-16 16:47:06 +02008561}
8562
8563/* EMERGENCY CALL situation #2, forbidden globally but allowed by BTS */
8564testcase TC_assignment_emerg_setup_deny_msc() runs on test_CT {
8565 var TestHdlrParams pars := f_gen_test_hdlr_pars();
8566 var MSC_ConnHdlr vc_conn;
8567
8568 f_init(1, true);
8569 f_sleep(1.0);
8570
8571 f_vty_allow_emerg_msc(false);
8572 f_vty_allow_emerg_bts(true, 0);
8573 vc_conn := f_start_handler(refers(f_TC_assignment_emerg_setup_deny), pars);
8574 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008575 f_shutdown_helper();
Philipp Maier783681c2020-07-16 16:47:06 +02008576}
8577
8578/* EMERGENCY CALL situation #3, allowed globally but forbidden by BTS */
8579testcase TC_assignment_emerg_setup_deny_bts() runs on test_CT {
8580 var TestHdlrParams pars := f_gen_test_hdlr_pars();
8581 var MSC_ConnHdlr vc_conn;
8582
8583 /* Note: This simulates a spec violation by the MS, correct MS
8584 * implementations would not try to establish an emergency call because
8585 * the system information tells in advance that emergency calls are
8586 * not forbidden */
8587
8588 f_init(1, true);
8589 f_sleep(1.0);
8590
8591 f_vty_allow_emerg_msc(true);
8592 f_vty_allow_emerg_bts(false, 0);
8593 vc_conn := f_start_handler(refers(f_TC_assignment_emerg_setup_deny), pars);
8594 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008595 f_shutdown_helper();
Philipp Maier783681c2020-07-16 16:47:06 +02008596}
8597
Philipp Maier82812002020-08-13 18:48:27 +02008598/* Test what happens when an emergency call arrives while all TCH channels are
8599 * busy, the BSC is expected to terminate one call in favor of the incoming
8600 * emergency call */
8601testcase TC_emerg_premption() runs on test_CT {
8602 var ASP_RSL_Unitdata rsl_ud;
8603 var integer i;
8604 var integer chreq_total, chreq_nochan;
8605 var RSL_Message rx_rsl;
8606 var RslChannelNr chan_nr;
8607
8608 f_init(1);
8609 f_sleep(1.0);
8610
8611 f_vty_allow_emerg_msc(true);
8612 f_vty_allow_emerg_bts(true, 0);
8613
8614 /* Fill up all channels on the BTS */
8615 chreq_total := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:total");
8616 chreq_nochan := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:no_channel");
8617 for (i := 0; i < NUM_TCHF_PER_BTS + NUM_TCHH_PER_BTS + NUM_SDCCH_PER_BTS; i := i+1) {
8618 chan_nr := f_chreq_act_ack('33'O, i);
8619 }
8620 IPA_RSL[0].clear;
8621 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:total",
8622 chreq_total + NUM_TCHF_PER_BTS + NUM_TCHH_PER_BTS + NUM_SDCCH_PER_BTS);
8623
8624 /* Send Channel request for emegergency call */
8625 f_ipa_tx(0, ts_RSL_CHAN_RQD('A5'O, 23));
8626
8627 /* Expect the BSC to release one (the first) TCH/F on the BTS */
8628 chan_nr := valueof(t_RslChanNr_Bm(1));
8629 f_expect_chan_rel(0, chan_nr, expect_rr_chan_rel := false, expect_rll_rel_req := false);
8630
8631 /* Expect the BSC to send activate/assign the a channel for the emergency call */
8632 rx_rsl := f_exp_ipa_rx(0, tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
8633 chan_nr := rx_rsl.ies[0].body.chan_nr;
8634 f_ipa_tx(0, ts_RSL_CHAN_ACT_ACK(chan_nr, 33));
8635 rx_rsl := f_exp_ipa_rx(0, tr_RSL_IMM_ASSIGN(0));
Philipp Maier104f4c02020-09-11 18:12:18 +02008636
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008637 f_shutdown_helper();
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07008638}
8639
8640/* Hopping parameters per a timeslot */
Vadim Yanitskiybc6654a2020-09-13 01:27:40 +07008641private type record length(0..64) of GsmArfcn ArfcnList;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07008642private type record FHParamsTs {
8643 boolean enabled,
8644 uint6_t hsn,
8645 uint6_t maio,
8646 ArfcnList ma
8647};
8648
8649/* Hopping parameters per a transceiver */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07008650private type record FHParamsTrx {
Philipp Maier798d8952021-10-19 14:43:19 +02008651 GsmBandArfcn arfcn,
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07008652 FHParamsTs ts[8]
8653};
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07008654
8655/* Randomly generate the hopping parameters for the given timeslot numbers */
8656private function f_TC_fh_params_gen(template integer tr_tn := (1, 3, 5))
8657runs on test_CT return FHParamsTrx {
8658 var FHParamsTrx fhp;
8659
Philipp Maier798d8952021-10-19 14:43:19 +02008660 /* Generate a random ARFCN in the range of 0 - 3. This ARFCN will
8661 * fall in the GSM900 band. */
8662 fhp.arfcn.arfcn := f_rnd_int(3);
8663 fhp.arfcn.pcs := false;
Vadim Yanitskiye7c8c6e2020-09-13 14:33:03 +07008664
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07008665 for (var integer tn := 0; tn < 8; tn := tn + 1) {
8666 if (not match(tn, tr_tn)) {
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07008667 fhp.ts[tn].enabled := false;
8668 fhp.ts[tn].ma := { };
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07008669 continue;
8670 }
8671
8672 /* Random HSN / MAIO values: 0..63 */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07008673 fhp.ts[tn].hsn := f_rnd_int(64);
8674 fhp.ts[tn].maio := f_rnd_int(64);
8675 fhp.ts[tn].ma := { };
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07008676
8677 /* Random Mobile Allocation (hopping channels) */
8678 var integer ma_len := 2 + f_rnd_int(9); /* 2..10 channels */
8679 var integer step := 3 + f_rnd_int(4); /* 3..6 stepping */
8680 for (var integer i := 1; i <= ma_len; i := i + 1) {
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07008681 fhp.ts[tn].ma := fhp.ts[tn].ma & { i * step };
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07008682 }
8683
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07008684 fhp.ts[tn].enabled := true;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07008685 }
8686
8687 log("f_TC_fh_params_gen(): ", fhp);
8688 return fhp;
8689}
8690
8691/* Make sure that the given Channel Description IE matches the hopping configuration */
8692private function f_TC_fh_params_match_chan_desc(in FHParamsTrx fhp, in ChannelDescription cd)
8693{
8694 var template (present) ChannelDescription tr_cd;
8695 var template (present) MaioHsn tr_maio_hsn;
8696 var uint3_t tn := cd.chan_nr.tn;
8697
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07008698 if (fhp.ts[tn].enabled) {
8699 tr_maio_hsn := tr_HsnMaio(fhp.ts[tn].hsn, fhp.ts[tn].maio);
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07008700 tr_cd := tr_ChanDescH1(cd.chan_nr, tr_maio_hsn);
8701 } else {
Philipp Maier798d8952021-10-19 14:43:19 +02008702 tr_cd := tr_ChanDescH0(cd.chan_nr, fhp.arfcn.arfcn);
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07008703 }
8704
8705 if (not match(cd, tr_cd)) {
8706 setverdict(fail, "Channel Description IE does not match: ",
8707 cd, " vs expected ", tr_cd);
8708 }
8709}
8710
8711/* Make sure that the given Mobile Allocation IE matches the hopping configuration */
8712private function f_TC_fh_params_match_ma(in FHParamsTrx fhp, uint3_t tn,
8713 in MobileAllocationLV ma)
8714{
8715 var template MobileAllocationLV tr_ma := f_TC_fh_params_gen_tr_ma(fhp, tn, ma);
8716
8717 if (not match(ma, tr_ma)) {
8718 setverdict(fail, "Mobile Allocation IE does not match (tn := ",
8719 tn, "): ", ma, " vs expected: ", tr_ma);
8720 } else {
8721 setverdict(pass);
8722 }
8723}
8724
8725private function f_TC_fh_params_gen_tr_ma(in FHParamsTrx fhp, uint3_t tn,
8726 in MobileAllocationLV ma)
8727return template MobileAllocationLV {
8728 /* Mobile Allocation IE is expected to be empty if hopping is not enabled */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07008729 if (not fhp.ts[tn].enabled) {
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07008730 return { len := 0, ma := ''B };
8731 }
8732
8733 var bitstring full_mask := f_pad_bit(''B, 1024, '0'B);
8734 var bitstring slot_mask := f_pad_bit(''B, 1024, '0'B);
8735 var bitstring ma_mask := ''B;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07008736
8737 /* Compose the full bit-mask (all channels, up to 1024 entries) */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07008738 for (var integer i := 0; i < lengthof(fhp.ts); i := i + 1) {
8739 for (var integer j := 0; j < lengthof(fhp.ts[i].ma); j := j + 1) {
8740 if (full_mask[fhp.ts[i].ma[j]] == '1'B)
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07008741 { continue; }
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07008742 full_mask[fhp.ts[i].ma[j]] := '1'B;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07008743 }
8744 }
8745
Vadim Yanitskiye7c8c6e2020-09-13 14:33:03 +07008746 /* Take ARFCN of the TRX itself into account */
Philipp Maier798d8952021-10-19 14:43:19 +02008747 full_mask[fhp.arfcn.arfcn] := '1'B;
Vadim Yanitskiye7c8c6e2020-09-13 14:33:03 +07008748
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07008749 /* Compose a bit-mask for the given timeslot number */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07008750 for (var integer i := 0; i < lengthof(fhp.ts[tn].ma); i := i + 1) {
8751 slot_mask[fhp.ts[tn].ma[i]] := '1'B;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07008752 }
8753
8754 /* Finally, compose the Mobile Allocation bit-mask */
Vadim Yanitskiy3e997362020-09-05 21:08:34 +07008755 for (var integer i := 1; i < lengthof(full_mask); i := i + 1) {
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07008756 if (full_mask[i] != '1'B)
8757 { continue; }
8758
8759 /* FIXME: ma_mask := ma_mask & slot_mask[i]; // triggers a bug in TITAN */
8760 if (slot_mask[i] == '1'B) {
8761 ma_mask := ma_mask & '1'B;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07008762 } else {
8763 ma_mask := ma_mask & '0'B;
8764 }
8765 }
8766
Vadim Yanitskiy3e997362020-09-05 21:08:34 +07008767 /* ARFCN 0 (if present) goes to the last position of the bit-mask */
8768 if (full_mask[0] == '1'B) {
8769 /* FIXME: ma_mask := ma_mask & slot_mask[0]; // triggers a bug in TITAN */
8770 if (slot_mask[0] == '1'B) {
8771 ma_mask := ma_mask & '1'B;
8772 } else {
8773 ma_mask := ma_mask & '0'B;
8774 }
8775 }
8776
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07008777 /* Ensure that ma_mask is octet-aligned */
Vadim Yanitskiy2aa02522020-09-06 14:05:23 +07008778 var integer ma_mask_len := (lengthof(ma_mask) + 8 - 1) / 8;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07008779 ma_mask := f_pad_bit(ma_mask, ma_mask_len * 8, '0'B);
8780
8781 return { len := ma_mask_len, ma := ma_mask };
8782}
8783
Philipp Maier798d8952021-10-19 14:43:19 +02008784/* Configure the appropriate band for a given arfcn, exc */
8785private function f_TC_set_band_by_arfcn(integer bts_nr, GsmBandArfcn arfcn) runs on test_CT
8786{
8787 var charstring band;
8788 var GsmBandArfcn arfcn_ := valueof(ts_GsmBandArfcn(arfcn.arfcn, arfcn.pcs, false));
8789
8790 select (arfcn_) {
8791 case (tr_GsmBandArfcn((259..293), false, ?)) { band := "GSM450"; }
8792 case (tr_GsmBandArfcn((306..340), false, ?)) { band := "GSM480"; }
8793 case (tr_GsmBandArfcn((438..511), false, ?)) { band := "GSM750"; }
8794 case (tr_GsmBandArfcn((128..251), false, ?)) { band := "GSM850"; }
8795 case (tr_GsmBandArfcn((0..124), false, ?)) { band := "GSM900"; }
8796 case (tr_GsmBandArfcn((955..1023), false, ?)) { band := "GSM900"; }
8797 case (tr_GsmBandArfcn((512..885), false, ?)) { band := "DCS1800"; }
8798 case (tr_GsmBandArfcn((512..810), true, ?)) { band := "PCS1900"; }
8799 case else { return; }
8800 }
8801
8802 f_vty_enter_cfg_bts(BSCVTY, bts_nr);
8803 f_vty_transceive(BSCVTY, "band " & band);
8804 f_vty_transceive(BSCVTY, "end");
8805}
8806
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07008807/* Configure the hopping parameters in accordance with the given record */
8808private function f_TC_fh_params_set(in FHParamsTrx fhp,
8809 uint8_t bts_nr := 0,
8810 uint8_t trx_nr := 0)
8811runs on test_CT {
Philipp Maier798d8952021-10-19 14:43:19 +02008812
8813 f_TC_set_band_by_arfcn(bts_nr, fhp.arfcn);
8814
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07008815 /* Enter the configuration node for the given BTS/TRX numbers */
8816 f_vty_enter_cfg_trx(BSCVTY, bts_nr, trx_nr);
8817
Philipp Maier798d8952021-10-19 14:43:19 +02008818 f_vty_transceive(BSCVTY, "arfcn " & int2str(fhp.arfcn.arfcn));
Vadim Yanitskiye7c8c6e2020-09-13 14:33:03 +07008819
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07008820 for (var integer tn := 0; tn < lengthof(fhp.ts); tn := tn + 1) {
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07008821 f_vty_transceive(BSCVTY, "timeslot " & int2str(tn));
8822
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07008823 if (not fhp.ts[tn].enabled) {
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07008824 f_vty_transceive(BSCVTY, "hopping enabled 0");
8825 f_vty_transceive(BSCVTY, "exit"); /* go back */
8826 continue;
8827 }
8828
8829 /* Configure HSN / MAIO values */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07008830 f_vty_transceive(BSCVTY, "hopping sequence-number " & int2str(fhp.ts[tn].hsn));
8831 f_vty_transceive(BSCVTY, "hopping maio " & int2str(fhp.ts[tn].maio));
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07008832
8833 /* Configure the Mobile Allocation (hopping channels) */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07008834 for (var integer i := 0; i < lengthof(fhp.ts[tn].ma); i := i + 1) {
8835 f_vty_transceive(BSCVTY, "hopping arfcn add " & int2str(fhp.ts[tn].ma[i]));
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07008836 }
8837
8838 f_vty_transceive(BSCVTY, "hopping enabled 1");
8839 f_vty_transceive(BSCVTY, "exit"); /* go back */
8840 }
8841
8842 f_vty_transceive(BSCVTY, "end");
8843}
8844
8845/* Disable frequency hopping on all timeslots */
8846private function f_TC_fh_params_unset(in FHParamsTrx fhp,
8847 uint8_t bts_nr := 0,
Vadim Yanitskiye7c8c6e2020-09-13 14:33:03 +07008848 uint8_t trx_nr := 0,
Philipp Maier798d8952021-10-19 14:43:19 +02008849 GsmBandArfcn arfcn := {pcs := false, arfcn := 871})
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07008850runs on test_CT {
Philipp Maier798d8952021-10-19 14:43:19 +02008851
8852 f_TC_set_band_by_arfcn(bts_nr, arfcn);
8853
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07008854 /* Enter the configuration node for the given BTS/TRX numbers */
8855 f_vty_enter_cfg_trx(BSCVTY, bts_nr, trx_nr);
8856
Philipp Maier798d8952021-10-19 14:43:19 +02008857 f_vty_transceive(BSCVTY, "arfcn " & int2str(arfcn.arfcn));
Vadim Yanitskiye7c8c6e2020-09-13 14:33:03 +07008858
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07008859 for (var integer tn := 0; tn < lengthof(fhp.ts); tn := tn + 1) {
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07008860 f_vty_transceive(BSCVTY, "timeslot " & int2str(tn));
8861
8862 /* Delete all ARFCNs from the Mobile Allocation (if any) */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07008863 for (var integer i := 0; i < lengthof(fhp.ts[tn].ma); i := i + 1) {
8864 f_vty_transceive(BSCVTY, "hopping arfcn del " & int2str(fhp.ts[tn].ma[i]));
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07008865 }
8866
8867 f_vty_transceive(BSCVTY, "hopping enabled 0");
8868 f_vty_transceive(BSCVTY, "exit"); /* go back */
8869 }
8870
8871 f_vty_transceive(BSCVTY, "end");
8872 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
8873}
8874
8875/* Verify presence and correctness of the hopping parameters (HSN, MAIO)
8876 * in the Channel Identification IE of the RSL CHANnel ACTIVation message. */
8877testcase TC_fh_params_chan_activ() runs on test_CT {
8878 var FHParamsTrx fhp := f_TC_fh_params_gen();
8879 var RSL_Message rsl_msg;
8880 var RSL_IE_Body ie;
8881
8882 f_init_vty();
8883
8884 f_TC_fh_params_set(fhp); /* Enable frequency hopping */
8885 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
8886
8887 f_init(1);
8888
8889 /* CS domain: 3 (SDCCH/4+CBCH) + 4 (TCH/F) + 2 (TCH/H) channels available */
8890 for (var integer i := 0; i < 9; i := i + 1) {
8891 f_ipa_tx(0, ts_RSL_CHAN_RQD(f_rnd_ra_cs(), 23));
8892 rsl_msg := f_exp_ipa_rx(0, tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
8893
8894 /* Make sure that Channel Identification IE is present */
8895 if (not f_rsl_find_ie(rsl_msg, RSL_IE_CHAN_IDENT, ie)) {
8896 setverdict(fail, "RSL Channel Identification IE is absent");
8897 continue;
8898 }
8899
8900 /* Make sure that hopping parameters (HSN/MAIO) match */
8901 f_TC_fh_params_match_chan_desc(fhp, ie.chan_ident.ch_desc.v);
8902
8903 /* "Mobile Allocation shall be included but empty" - let's check this */
8904 if (ie.chan_ident.ma.v.len != 0) {
8905 setverdict(fail, "Mobile Allocation IE is not empty: ",
8906 ie.chan_ident.ma, ", despite it shall be");
8907 continue;
8908 }
8909 }
8910
8911 /* Disable frequency hopping */
8912 f_TC_fh_params_unset(fhp);
8913
Vadim Yanitskiy21726312020-09-04 01:45:36 +07008914 f_shutdown_helper();
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07008915}
8916
8917/* Verify the hopping parameters (HSN, MAIO, MA) in (RR) Immediate Assignment */
8918testcase TC_fh_params_imm_ass() runs on test_CT {
8919 var FHParamsTrx fhp := f_TC_fh_params_gen();
8920 var RSL_Message rsl_msg;
8921 var RSL_IE_Body ie;
8922
8923 f_init_vty();
8924
8925 f_TC_fh_params_set(fhp); /* Enable frequency hopping */
8926 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
8927
8928 f_init(1);
8929
8930 /* CS domain: 3 (SDCCH/4+CBCH) + 4 (TCH/F) + 2 (TCH/H) channels available */
8931 for (var integer i := 0; i < 9; i := i + 1) {
8932 f_ipa_tx(0, ts_RSL_CHAN_RQD(f_rnd_ra_cs(), 23));
8933 rsl_msg := f_exp_ipa_rx(0, tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
8934
8935 f_ipa_tx(0, ts_RSL_CHAN_ACT_ACK(rsl_msg.ies[0].body.chan_nr, 33));
8936 rsl_msg := f_exp_ipa_rx(0, tr_RSL_MsgTypeC(RSL_MT_IMMEDIATE_ASSIGN_CMD));
8937
8938 /* Make sure that Full Immediate Assign Info IE is present */
8939 if (not f_rsl_find_ie(rsl_msg, RSL_IE_FULL_IMM_ASS_INFO, ie)) {
8940 setverdict(fail, "RSL Full Immediate Assign Info IE is absent");
8941 continue;
8942 }
8943
8944 /* Decode the actual Immediate Assignment message */
8945 var GsmRrMessage rr_msg := dec_GsmRrMessage(ie.full_imm_ass_info.payload);
8946 if (not match(rr_msg.header, t_RrHeader(IMMEDIATE_ASSIGNMENT, ?))) {
8947 setverdict(fail, "Failed to match Immediate Assignment: ", rr_msg);
8948 continue;
8949 }
8950
8951 /* Make sure that hopping parameters (HSN/MAIO) match */
8952 f_TC_fh_params_match_chan_desc(fhp, rr_msg.payload.imm_ass.chan_desc);
8953
8954 /* Make sure that the Mobile Allocation IE matches */
8955 f_TC_fh_params_match_ma(fhp, rr_msg.payload.imm_ass.chan_desc.chan_nr.tn,
8956 rr_msg.payload.imm_ass.mobile_allocation);
8957 }
8958
8959 /* Disable frequency hopping */
8960 f_TC_fh_params_unset(fhp);
Philipp Maier82812002020-08-13 18:48:27 +02008961
Vadim Yanitskiy21726312020-09-04 01:45:36 +07008962 f_shutdown_helper();
Philipp Maier82812002020-08-13 18:48:27 +02008963}
8964
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +07008965/* Verify the hopping parameters (HSN, MAIO, MA) in (RR) Assignment Command */
8966testcase TC_fh_params_assignment_cmd() runs on test_CT {
8967 var FHParamsTrx fhp := f_TC_fh_params_gen();
8968 var RSL_Message rsl_msg;
8969 var RSL_IE_Body ie;
8970
8971 f_init_vty();
8972
8973 f_TC_fh_params_set(fhp); /* Enable frequency hopping */
8974 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
8975
8976 f_init(1);
8977
8978 /* HACK: work around "Couldn't find Expect for CRCX" */
8979 vc_MGCP.stop;
8980
8981 var template PDU_BSSAP ass_cmd := f_gen_ass_req();
8982 ass_cmd.pdu.bssmap.assignmentRequest.codecList := ts_BSSMAP_IE_CodecList({ts_CodecFR});
8983
8984 /* CS domain (TCH): 4 (TCH/F) + 2 (TCH/H) channels available
8985 * NOTE: only 3 SDCCH/4 channels are available on CCCH+SDCCH4+CBCH */
8986 for (var integer i := 0; i < 3; i := i + 1) {
8987 /* Establish a dedicated channel, so we can trigger (late) TCH assignment */
8988 var DchanTuple dt := f_est_dchan(f_rnd_ra_cs(), 23, f_rnd_octstring(16));
8989
8990 /* Send a BSSMAP Assignment Command, expect CHANnel ACTIVation */
8991 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ass_cmd));
8992 rsl_msg := f_exp_ipa_rx(0, tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
8993
8994 /* ACKnowledge CHANnel ACTIVation, expect RSL DATA REQuest */
8995 f_ipa_tx(0, ts_RSL_CHAN_ACT_ACK(rsl_msg.ies[0].body.chan_nr, 33));
8996 rsl_msg := f_exp_ipa_rx(0, tr_RSL_MsgTypeR(RSL_MT_DATA_REQ));
8997
8998 /* Make sure that L3 Information IE is present */
8999 if (not f_rsl_find_ie(rsl_msg, RSL_IE_L3_INFO, ie)) {
9000 setverdict(fail, "RSL L3 Information IE is absent");
9001 continue;
9002 }
9003
9004 /* Decode the L3 message and make sure it is (RR) Assignment Command */
9005 var GsmRrL3Message l3_msg := dec_GsmRrL3Message(ie.l3_info.payload);
9006 if (not match(l3_msg.header, t_RrL3Header(ASSIGNMENT_COMMAND))) {
9007 setverdict(fail, "Failed to match Assignment Command: ", l3_msg);
9008 continue;
9009 }
9010
9011 /* Make sure that hopping parameters (HSN/MAIO) match */
9012 var ChannelDescription chan_desc := l3_msg.payload.ass_cmd.chan_desc;
9013 f_TC_fh_params_match_chan_desc(fhp, chan_desc);
9014
9015 /* Make sure that Cell Channel Description IE is present if FH is enabled */
9016 if (chan_desc.h and not ispresent(l3_msg.payload.ass_cmd.cell_chan_desc)) {
Vadim Yanitskiy38d069d2020-09-02 17:18:57 +07009017 setverdict(fail, "FH enabled, but Cell Channel Description IE is absent");
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +07009018 continue;
9019 }
9020
9021 /* Make sure that the Mobile Allocation IE matches (if present) */
9022 var boolean ma_present := ispresent(l3_msg.payload.ass_cmd.mobile_allocation);
9023 if (chan_desc.h and ma_present) {
9024 f_TC_fh_params_match_ma(fhp, chan_desc.chan_nr.tn,
9025 l3_msg.payload.ass_cmd.mobile_allocation.v);
9026 } else if (chan_desc.h and not ma_present) {
9027 setverdict(fail, "FH enabled, but Mobile Allocation IE is absent");
9028 continue;
9029 } else if (not chan_desc.h and ma_present) {
9030 setverdict(fail, "FH disabled, but Mobile Allocation IE is present");
9031 continue;
9032 }
9033 }
9034
9035 /* Give the IUT some time to release all channels */
9036 f_sleep(3.0);
9037
9038 /* Disable frequency hopping */
9039 f_TC_fh_params_unset(fhp);
9040
Vadim Yanitskiy21726312020-09-04 01:45:36 +07009041 f_shutdown_helper();
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +07009042}
9043
Vadim Yanitskiy8f5430d2020-09-02 18:51:38 +07009044/* Verify the hopping parameters (HSN, MAIO, MA) in (RR) Handover Command */
9045private function f_TC_fh_params_handover_cmd(in FHParamsTrx fhp)
9046runs on test_CT {
9047 var RSL_Message rsl_msg;
9048 var RSL_IE_Body ie;
9049 var DchanTuple dt;
9050
9051 /* Establish a dedicated channel, so we can trigger handover */
9052 dt := f_est_dchan(f_rnd_ra_cs(), 23, f_rnd_octstring(16));
Vadim Yanitskiyc18ff472021-11-18 20:15:37 +03009053 f_sleep(0.5);
Vadim Yanitskiy8f5430d2020-09-02 18:51:38 +07009054
9055 /* Trigger handover from BTS0 to BTS1 */
9056 f_bts_0_cfg(BSCVTY, { "neighbor bts 1" });
9057 f_vty_handover(BSCVTY, 0, 0, dt.rsl_chan_nr, 1);
9058
9059 /* Expect RSL CHANnel ACTIVation on BTS1/TRX0/TS1 */
9060 rsl_msg := f_exp_ipa_rx(1, tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
9061
9062 /* ACKnowledge channel activation and expect (RR) Handover Command */
9063 f_ipa_tx(1, ts_RSL_CHAN_ACT_ACK(rsl_msg.ies[0].body.chan_nr, 33));
9064 rsl_msg := f_exp_ipa_rx(0, tr_RSL_MsgTypeR(RSL_MT_DATA_REQ));
9065
9066 /* Make sure that L3 Information IE is present */
9067 if (not f_rsl_find_ie(rsl_msg, RSL_IE_L3_INFO, ie)) {
9068 setverdict(fail, "RSL L3 Information IE is absent");
9069 return;
9070 }
9071
9072 /* Decode the L3 message and make sure it is (RR) Handover Command */
9073 var GsmRrL3Message l3_msg := dec_GsmRrL3Message(ie.l3_info.payload);
9074 if (not match(l3_msg.header, t_RrL3Header(HANDOVER_COMMAND))) {
9075 setverdict(fail, "Failed to match Handover Command: ", l3_msg);
9076 return;
9077 }
9078
9079 /* Make sure that we've got SDCCH/8 on TS1 (expected to be hopping) */
9080 var ChannelDescription chan_desc := l3_msg.payload.ho_cmd.chan_desc;
9081 if (not match(chan_desc.chan_nr, t_RslChanNr_SDCCH8(1, ?))) {
9082 setverdict(fail, "Unexpected channel number: ", chan_desc.chan_nr);
9083 return;
9084 }
9085
9086 /* Make sure that hopping parameters (HSN/MAIO) match */
9087 f_TC_fh_params_match_chan_desc(fhp, chan_desc);
9088
9089 /* Make sure that Cell Channel Description IE is present */
9090 if (not ispresent(l3_msg.payload.ho_cmd.cell_chan_desc)) {
9091 setverdict(fail, "FH enabled, but Cell Channel Description IE is absent");
9092 return;
9093 }
9094
9095 /* Make sure that the Mobile Allocation (after time) IE is present and matches */
9096 var boolean ma_present := ispresent(l3_msg.payload.ho_cmd.mobile_allocation);
9097 if (ma_present) {
9098 f_TC_fh_params_match_ma(fhp, chan_desc.chan_nr.tn,
9099 l3_msg.payload.ho_cmd.mobile_allocation.v);
9100 } else {
9101 setverdict(fail, "FH enabled, but Mobile Allocation IE is absent");
9102 return;
9103 }
9104}
9105testcase TC_fh_params_handover_cmd() runs on test_CT {
9106 var FHParamsTrx fhp := f_TC_fh_params_gen();
9107
9108 f_init_vty();
9109
9110 /* (Re)configure TS0 as BCCH and TS1 as SDCCH8 on BTS1/TRX0 */
9111 f_vty_enter_cfg_trx(BSCVTY, bts := 1, trx := 0);
9112
9113 f_vty_transceive(BSCVTY, "timeslot 0");
9114 f_vty_transceive(BSCVTY, "phys_chan_config ccch");
9115 f_vty_transceive(BSCVTY, "exit"); /* go back */
9116
9117 f_vty_transceive(BSCVTY, "timeslot 1");
9118 f_vty_transceive(BSCVTY, "phys_chan_config sdcch8");
9119 f_vty_transceive(BSCVTY, "end"); /* we're done */
9120
9121 f_TC_fh_params_set(fhp, 1); /* Enable frequency hopping on BTS1 */
9122 f_vty_transceive(BSCVTY, "drop bts connection 1 oml");
9123
9124 f_init(2);
9125
9126 f_TC_fh_params_handover_cmd(fhp);
9127
9128 /* Disable frequency hopping on BTS1 */
9129 f_TC_fh_params_unset(fhp, 1);
9130
9131 /* (Re)configure TS0 as CCCH+SDCCH4+CBCH and TS1 as TCH/F */
9132 f_vty_enter_cfg_trx(BSCVTY, bts := 1, trx := 0);
9133
9134 f_vty_transceive(BSCVTY, "timeslot 0");
9135 f_vty_transceive(BSCVTY, "phys_chan_config ccch+sdcch4+cbch");
9136 f_vty_transceive(BSCVTY, "exit"); /* go back */
9137
9138 f_vty_transceive(BSCVTY, "timeslot 1");
9139 f_vty_transceive(BSCVTY, "phys_chan_config tch/f");
9140 f_vty_transceive(BSCVTY, "end"); /* we're done */
9141
9142 f_shutdown_helper();
9143}
9144
Vadim Yanitskiyca974032020-09-01 07:20:39 +07009145/* Verify the hopping parameters in System Information Type 4 */
9146testcase TC_fh_params_si4_cbch() runs on test_CT {
9147 var FHParamsTrx fhp := f_TC_fh_params_gen(tr_tn := 1);
9148 var ASP_RSL_Unitdata rx_rsl_ud;
9149 timer T := 5.0;
9150
9151 f_init_vty();
9152
9153 /* (Re)configure TS0 as BCCH and TS1 as SDCCH8+CBCH */
9154 f_vty_enter_cfg_trx(BSCVTY, trx := 0);
9155
9156 f_vty_transceive(BSCVTY, "timeslot 0");
9157 f_vty_transceive(BSCVTY, "phys_chan_config ccch");
9158 f_vty_transceive(BSCVTY, "exit"); /* go back */
9159
9160 f_vty_transceive(BSCVTY, "timeslot 1");
9161 f_vty_transceive(BSCVTY, "phys_chan_config sdcch8+cbch");
9162 f_vty_transceive(BSCVTY, "end"); /* we're done */
9163
9164 f_TC_fh_params_set(fhp); /* Enable frequency hopping */
9165 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
9166
9167 f_init(1);
9168
9169 T.start;
9170 alt {
9171 [] IPA_RSL[0].receive(tr_ASP_RSL_UD(tr_RSL_BCCH_INFO(RSL_SYSTEM_INFO_4))) -> value rx_rsl_ud {
9172 var RSL_IE_Body ie := rx_rsl_ud.rsl.ies[2].body; /* FULL BCCH Information IE */
9173 var SystemInformation si := dec_SystemInformation(ie.other.payload);
9174
9175 /* Make sure that what we decoded is System Information Type 4 */
9176 if (si.header.message_type != SYSTEM_INFORMATION_TYPE_4) {
9177 setverdict(fail, "RSL FULL BCCH Information IE contains: ", si);
9178 repeat;
9179 }
9180
9181 /* Make sure that CBCH Channel Description IE is present */
9182 if (not ispresent(si.payload.si4.cbch_chan_desc)) {
9183 setverdict(fail, "CBCH Channel Description IE is absent");
9184 break;
9185 }
9186
9187 /* Finally, check the hopping parameters (HSN, MAIO) */
9188 var ChannelDescription chan_desc := si.payload.si4.cbch_chan_desc.v;
9189 f_TC_fh_params_match_chan_desc(fhp, chan_desc);
9190
9191 /* 3GPP TS 44.018, section 9.1.36.2 "CBCH Mobile Allocation":
9192 * The CBCH Mobile Allocation IE *shall* be present if FH is enabled. */
9193 if (chan_desc.h and not ispresent(si.payload.si4.cbch_mobile_alloc)) {
9194 setverdict(fail, "FH enabled, but Mobile Allocation IE is absent");
9195 break;
9196 } else if (chan_desc.h and ispresent(si.payload.si4.cbch_mobile_alloc)) {
9197 f_TC_fh_params_match_ma(fhp, chan_desc.chan_nr.tn,
9198 si.payload.si4.cbch_mobile_alloc.v);
9199 }
9200 }
9201 [] IPA_RSL[0].receive { repeat; }
9202 [] T.timeout {
9203 setverdict(fail, "Timeout waiting for RSL BCCH INFOrmation (SI4)");
9204 }
9205 }
9206
9207 /* Disable frequency hopping */
9208 f_TC_fh_params_unset(fhp);
9209
Vadim Yanitskiy8bc46012020-09-06 12:38:01 +07009210 /* (Re)configure TS0 as CCCH+SDCCH4+CBCH and TS1 as TCH/F */
Vadim Yanitskiyca974032020-09-01 07:20:39 +07009211 f_vty_enter_cfg_trx(BSCVTY, trx := 0);
9212
9213 f_vty_transceive(BSCVTY, "timeslot 0");
Vadim Yanitskiy8bc46012020-09-06 12:38:01 +07009214 f_vty_transceive(BSCVTY, "phys_chan_config ccch+sdcch4+cbch");
Vadim Yanitskiyca974032020-09-01 07:20:39 +07009215 f_vty_transceive(BSCVTY, "exit"); /* go back */
9216
9217 f_vty_transceive(BSCVTY, "timeslot 1");
9218 f_vty_transceive(BSCVTY, "phys_chan_config tch/f");
9219 f_vty_transceive(BSCVTY, "end"); /* we're done */
9220
Vadim Yanitskiy21726312020-09-04 01:45:36 +07009221 f_shutdown_helper();
Vadim Yanitskiyca974032020-09-01 07:20:39 +07009222}
9223
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02009224template (value) PDU_BSSAP_LE ts_BSSMAP_LE_BSSLAP(template (value) BSSLAP_PDU bsslap)
9225 := ts_BSSMAP_LE_ConnInfo(BSSMAP_LE_PROT_BSSLAP, data := enc_BSSLAP_PDU(valueof(bsslap)));
9226
9227private function f_match_bsslap(PDU_BSSAP_LE got_bsslap_msg,
9228 template (present) BSSLAP_PDU expect_bsslap)
9229{
9230 var BSSLAP_PDU bsslap := dec_BSSLAP_PDU(got_bsslap_msg.pdu.bssmap.co_info.bsslap_apdu.data);
9231 if (not match(bsslap, expect_bsslap)) {
9232 log("EXPECTING BSSLAP: ", expect_bsslap);
9233 log("GOT BSSLAP: ", bsslap);
9234 setverdict(fail, "BSSLAP is not as expected");
9235 mtc.stop;
9236 }
9237 setverdict(pass);
9238}
9239
9240/* GAD: this is an Ellipsoid point with uncertainty circle, encoded as in 3GPP TS 23.032 §7.3.2. */
9241const octetstring gad_ell_point_unc_circle := '10b0646d0d5f6627'O;
9242
9243private function f_expect_bsslap(template (present) BSSLAP_PDU expect_rx_bsslap) runs on MSC_ConnHdlr {
9244 var PDU_BSSAP_LE rx_bsslap;
9245 BSSAP_LE.receive(tr_BSSMAP_LE_ConnInfo(BSSMAP_LE_PROT_BSSLAP, ?)) -> value(rx_bsslap);
9246 f_match_bsslap(rx_bsslap, expect_rx_bsslap);
9247}
9248
9249/* With an active lchan, start BSSMAP Perform Location Request on A interface, starting BSSMAP-LE Perform Location
9250 * Request on Lb interface. Either with or without the SMLC doing a BSSLAP TA Request. */
9251private function f_lcs_loc_req_for_active_ms(boolean do_ta_request := false) runs on MSC_ConnHdlr {
9252 f_sleep(1.0);
9253
9254 f_establish_fully(omit, omit);
9255 f_bssap_le_register_imsi(g_pars.imsi, omit);
9256
9257 BSSAP.send(valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
9258 ts_CellId_CGI('262'H, '42'H, 23, 42))));
9259
9260 var PDU_BSSAP_LE plr;
9261 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?)) -> value(plr);
9262
9263 if (not do_ta_request) {
9264 /* verify TA Layer 3 in APDU. First the APDU type (BSSLAP), then the BSSLAP data contents. */
9265 var template BSSMAP_LE_IE_APDU expect_apdu := tr_BSSMAP_LE_APDU(BSSMAP_LE_PROT_BSSLAP, ?);
9266 if (not match(plr.pdu.bssmap.perf_loc_req.bsslap_apdu, expect_apdu)) {
9267 log("EXPECTING BSSMAP-LE APDU IE ", expect_apdu);
9268 log("GOT BSSMAP-LE APDU IE ", plr.pdu.bssmap.perf_loc_req.bsslap_apdu);
9269 setverdict(fail, "BSSMAP-LE APDU IE is not as expected");
9270 mtc.stop;
9271 }
9272 var template BSSLAP_PDU expect_ta_layer3 := tr_BSSLAP_TA_Layer3(tr_BSSLAP_IE_TA(0));
9273 var BSSLAP_PDU bsslap := dec_BSSLAP_PDU(plr.pdu.bssmap.perf_loc_req.bsslap_apdu.data);
9274 if (not match(bsslap, expect_ta_layer3)) {
9275 log("EXPECTING BSSLAP TA Layer 3: ", expect_ta_layer3);
9276 log("GOT BSSLAP: ", bsslap);
9277 setverdict(fail, "BSSLAP is not as expected");
9278 mtc.stop;
9279 }
9280 /* OsmoBSC directly sent the TA as BSSLAP APDU in the BSSMAP-LE Perform Location Request to the SMLC. The SMLC
9281 * has no need to request the TA from the BSC and directly responds. */
9282 } else {
9283 /* SMLC wants to ask the TA from the BSC explicitly in a BSSLAP TA Request message */
9284 BSSAP_LE.send(ts_BSSMAP_LE_BSSLAP(ts_BSSLAP_TA_Req));
9285 f_expect_bsslap(tr_BSSLAP_TA_Resp(?, ?));
9286 }
9287
9288 /* SMLC got the TA from the BSC, now responds with geo information data. */
9289 BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(gad_ell_point_unc_circle, omit));
9290 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
9291 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(tr_BSSMAP_IE_LocationEstimate(gad_ell_point_unc_circle)));
9292
9293 /* The LCS was using an active A-interface conn. It should still remain active after this. */
9294 f_mo_l3_transceive();
9295
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02009296 f_perform_clear();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02009297
9298 f_sleep(2.0);
9299 setverdict(pass);
9300}
9301
9302/* With an active lchan, start BSSMAP Perform Location Request on A interface, starting BSSMAP-LE Perform Location
9303 * Request on Lb interface. Without the SMLC doing a BSSLAP TA Request. */
9304private function f_tc_lcs_loc_req_for_active_ms(charstring id) runs on MSC_ConnHdlr {
9305 f_lcs_loc_req_for_active_ms(false);
9306}
9307testcase TC_lcs_loc_req_for_active_ms() runs on test_CT {
9308 var MSC_ConnHdlr vc_conn;
9309 var TestHdlrParams pars := f_gen_test_hdlr_pars();
9310
9311 f_init(1, true);
9312 f_sleep(1.0);
9313 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_for_active_ms), pars);
9314 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +01009315 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02009316}
9317
9318/* With an active lchan, start BSSMAP Perform Location Request on A interface, starting BSSMAP-LE Perform Location
9319 * Request on Lb interface. With the SMLC doing a BSSLAP TA Request. */
9320private function f_tc_lcs_loc_req_for_active_ms_ta_req(charstring id) runs on MSC_ConnHdlr {
9321 f_lcs_loc_req_for_active_ms(true);
9322}
9323testcase TC_lcs_loc_req_for_active_ms_ta_req() runs on test_CT {
9324 var MSC_ConnHdlr vc_conn;
9325 var TestHdlrParams pars := f_gen_test_hdlr_pars();
9326
9327 f_init(1, true);
9328 f_sleep(1.0);
9329 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_for_active_ms_ta_req), pars);
9330 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +01009331 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02009332}
9333
9334/* Clear the A-interface conn only, without doing anything on Abis. Useful for LCS, for cases where there is only an A
9335 * conn without an active lchan. */
9336private function f_clear_A_conn() runs on MSC_ConnHdlr
9337{
9338 var BssmapCause cause := 0;
9339 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
9340 BSSAP.receive(tr_BSSMAP_ClearComplete);
9341 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
9342
9343 timer no_more_bssap := 5.0;
9344 no_more_bssap.start;
9345 alt {
9346 [] no_more_bssap.timeout { break; }
9347 [] BSSAP.receive(tr_BSSAP_BSSMAP) {
9348 setverdict(fail, "Expected no more BSSAP after Clear Complete");
9349 mtc.stop;
9350 }
9351 }
9352 setverdict(pass);
9353}
9354
9355/* Verify that the A-interface connection is still working, and then clear it, without doing anything on Abis. Useful
9356 * for LCS, for cases where there is only an A conn without an active lchan. */
9357private function f_verify_active_A_conn_and_clear() runs on MSC_ConnHdlr
9358{
9359 f_logp(BSCVTY, "f_verify_active_A_conn_and_clear: test A link, then clear");
9360
9361 /* When an lchan is active, we can send some L3 data from the BTS side and verify that it shows up on the other
9362 * side towards the MSC. When there is no lchan, this is not possible. To probe whether the A-interface
9363 * connection is still up, we need something that echos back on the A-interface. Another LCS request! */
9364 BSSAP.send(valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
9365 ts_CellId_CGI('262'H, '42'H, 23, 42))));
9366 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?));
9367
9368 /* Right, the Perform Location Request showed up on Lb, now we can clear the A conn. */
9369 f_clear_A_conn();
9370 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocAbort(BSSMAP_LE_LCS_CAUSE_REQUEST_ABORTED));
9371 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
9372}
9373
9374/* With *no* active lchan, start BSSMAP Perform Location Request on A interface, starting BSSMAP-LE Perform Location
9375 * Request on Lb interface. BSC will Page for the subscriber as soon as we (virtual SMLC) request the TA via BSSLAP.
9376 */
9377private function f_tc_lcs_loc_req_for_idle_ms(charstring id) runs on MSC_ConnHdlr {
9378 f_sleep(1.0);
9379
9380 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
9381 f_bssap_le_register_imsi(g_pars.imsi, omit);
9382
9383 /* Register to receive the Paging Command */
9384 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
9385 g_chan_nr := new_chan_nr;
9386 f_rslem_register(0, g_chan_nr);
9387
9388 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
9389 valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
9390 ts_CellId_CGI('001'H, '01'H, 1, 0)))));
9391 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
9392
9393 var PDU_BSSAP_LE plr;
9394 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?)) -> value(plr);
9395
9396 /* SMLC wants to ask the TA from the BSC explicitly in a BSSLAP TA Request message */
9397 BSSAP_LE.send(ts_BSSMAP_LE_BSSLAP(ts_BSSLAP_TA_Req));
9398
9399 /* OsmoBSC needs to Page */
9400 RSL.receive(tr_RSL_PAGING_CMD(tr_MI_IMSI(g_pars.imsi)));
9401 f_logp(BSCVTY, "got Paging Command");
9402
9403 /* MS requests channel. Since the Paging was for LCS, the Paging Response does not trigger a Complete Layer 3 to
9404 * the MSC, and releases the lchan directly. */
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02009405 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);
9406 f_expect_lchan_rel(RSL, RSL_PROC);
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02009407
9408 /* From the Paging Response, the TA is now known to the BSC, and it responds to the SMLC. */
9409
9410 f_expect_bsslap(tr_BSSLAP_TA_Resp(?, ?));
9411
9412 /* SMLC got the TA from the BSC, now responds with geo information data. */
9413 BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(gad_ell_point_unc_circle, omit));
9414 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
9415
9416 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(tr_BSSMAP_IE_LocationEstimate(gad_ell_point_unc_circle)));
9417
9418 /* The lchan is gone, the A-interface conn was created for the LCS only.
9419 * Still it is clearly the MSC's job to decide whether to tear down the conn or not. */
9420 f_verify_active_A_conn_and_clear();
9421
9422 f_sleep(2.0);
9423 setverdict(pass);
9424}
9425testcase TC_lcs_loc_req_for_idle_ms() runs on test_CT {
9426 var MSC_ConnHdlr vc_conn;
9427 var TestHdlrParams pars := f_gen_test_hdlr_pars();
9428
9429 f_init(1, true);
9430 f_sleep(1.0);
9431
9432 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
9433 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
9434
9435 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_for_idle_ms), pars);
9436 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +01009437 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02009438}
9439
9440/* With no active lchan, start BSSMAP Perform Location Request on A interface, but omit IMSI; expect failure response.
9441 */
9442private function f_tc_lcs_loc_req_no_subscriber(charstring id) runs on MSC_ConnHdlr {
9443 f_sleep(1.0);
9444
9445 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
9446 f_bssap_le_register_imsi(g_pars.imsi, omit);
9447
9448 /* provoke an abort by omitting both IMSI and IMEI */
9449 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
9450 valueof(ts_BSSMAP_Perform_Location_Request(omit,
9451 ts_CellId_CGI('262'H, '42'H, 23, 42)))));
9452 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
9453
9454 /* BSC tells MSC about failure */
9455 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(
9456 locationEstimate := omit, positioningData := omit,
9457 lCS_Cause := tr_BSSMAP_LcsCause(BSSMAP_LCS_CAUSE_DATA_MISSING_IN_REQ)));
9458
9459 /* There is no lchan. Still the MSC's job to decide whether to tear down the conn or not. */
9460 f_verify_active_A_conn_and_clear();
9461
9462 f_sleep(2.0);
9463 setverdict(pass);
9464}
9465testcase TC_lcs_loc_req_no_subscriber() runs on test_CT {
9466 var MSC_ConnHdlr vc_conn;
9467 var TestHdlrParams pars := f_gen_test_hdlr_pars();
9468
9469 f_init(1, true);
9470 f_sleep(1.0);
9471
9472 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
9473 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
9474
9475 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_no_subscriber), pars);
9476 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +01009477 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02009478}
9479
9480/* With an active lchan, start a Perform Location Request on the A-interface, but virtual SMLC does not answer with
9481 * BSSMAP-LE Perform Location Response (before or after sending a BSSLAP TA Request) */
9482private function f_lcs_loc_req_for_active_ms_le_timeout(boolean do_ta) runs on MSC_ConnHdlr {
9483 f_sleep(1.0);
9484
9485 f_establish_fully(omit, omit);
9486 f_bssap_le_register_imsi(g_pars.imsi, omit);
9487
9488 BSSAP.send(valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
9489 ts_CellId_CGI('262'H, '42'H, 23, 42))));
9490
9491 var PDU_BSSAP_LE plr;
9492 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?)) -> value(plr);
9493
9494 if (do_ta) {
9495 /* SMLC wants to ask the TA from the BSC explicitly in a BSSLAP TA Request message */
9496 BSSAP_LE.send(ts_BSSMAP_LE_BSSLAP(ts_BSSLAP_TA_Req));
9497 f_expect_bsslap(tr_BSSLAP_TA_Resp(?, ?));
9498 }
9499
9500 /* SMLC fails to respond, BSC runs into timeout */
9501 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocAbort(BSSMAP_LE_LCS_CAUSE_SYSTEM_FAILURE));
9502 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
9503
9504 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(
9505 locationEstimate := omit, positioningData := omit,
9506 lCS_Cause := tr_BSSMAP_LcsCause(BSSMAP_LCS_CAUSE_SYSTEM_FAILURE)));
9507
9508 /* There is no lchan. Still the MSC's job to decide whether to tear down the conn or not. */
9509 f_verify_active_A_conn_and_clear();
9510
9511 f_sleep(2.0);
9512 setverdict(pass);
9513}
9514
9515/* With an active lchan, start a Perform Location Request on the A-interface, but virtual SMLC does not answer with
9516 * BSSMAP-LE Perform Location Response, without sending a BSSLAP TA Request. */
9517private function f_tc_lcs_loc_req_for_active_ms_le_timeout(charstring id) runs on MSC_ConnHdlr {
9518 f_lcs_loc_req_for_active_ms_le_timeout(false);
9519}
9520
9521testcase TC_lcs_loc_req_for_active_ms_le_timeout() runs on test_CT {
9522 var MSC_ConnHdlr vc_conn;
9523 var TestHdlrParams pars := f_gen_test_hdlr_pars();
9524
9525 f_init(1, true);
9526 f_sleep(1.0);
9527 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_for_active_ms_le_timeout), pars);
9528 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +01009529 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02009530}
9531
9532/* With an active lchan, start a Perform Location Request on the A-interface, but virtual SMLC does not answer with
9533 * BSSMAP-LE Perform Location Response, after sending a BSSLAP TA Request. */
9534private function f_tc_lcs_loc_req_for_active_ms_le_timeout2(charstring id) runs on MSC_ConnHdlr {
9535 f_lcs_loc_req_for_active_ms_le_timeout(true);
9536}
9537
9538testcase TC_lcs_loc_req_for_active_ms_le_timeout2() runs on test_CT {
9539 var MSC_ConnHdlr vc_conn;
9540 var TestHdlrParams pars := f_gen_test_hdlr_pars();
9541
9542 f_init(1, true);
9543 f_sleep(1.0);
9544 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_for_active_ms_le_timeout2), pars);
9545 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +01009546 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02009547}
9548
9549/* With *no* active lchan, start a Perform Location Request, expecting that the MS will be Paged. */
9550private function f_tc_lcs_loc_req_for_idle_ms_no_pag_resp(charstring id) runs on MSC_ConnHdlr {
9551 f_sleep(1.0);
9552
9553 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
9554 f_bssap_le_register_imsi(g_pars.imsi, omit);
9555
9556 /* Register to receive the Paging Command */
9557 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
9558 g_chan_nr := new_chan_nr;
9559 f_rslem_register(0, g_chan_nr);
9560
9561 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
9562 valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
9563 ts_CellId_CGI('001'H, '01'H, 1, 0)))));
9564 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
9565
9566 var PDU_BSSAP_LE plr;
9567 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?)) -> value(plr);
9568
9569 /* SMLC wants to ask the TA from the BSC explicitly in a BSSLAP TA Request message */
9570 BSSAP_LE.send(ts_BSSMAP_LE_BSSLAP(ts_BSSLAP_TA_Req));
9571
9572 /* OsmoBSC needs to Page */
9573 var PDU_BSSAP_LE rx_bsslap;
9574 alt {
9575 [] RSL.receive(tr_RSL_PAGING_CMD(tr_MI_IMSI(g_pars.imsi))) {
9576 f_logp(BSCVTY, "got Paging Command");
9577 repeat;
9578 }
9579 [] BSSAP_LE.receive(tr_BSSMAP_LE_ConnInfo(BSSMAP_LE_PROT_BSSLAP, ?)) -> value(rx_bsslap) {
9580 /* MS does not respond to Paging, TA Req runs into timeout. */
9581 f_match_bsslap(rx_bsslap, tr_BSSLAP_Abort(?));
9582 }
9583 }
9584
9585 /* SMLC responds with failure */
9586 BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(omit, BSSMAP_LE_LCS_CAUSE_REQUEST_ABORTED));
9587 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
9588
9589 /* BSC tells MSC about failure */
9590 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(
9591 locationEstimate := omit, positioningData := omit,
9592 lCS_Cause := tr_BSSMAP_LcsCause(BSSMAP_LCS_CAUSE_REQUEST_ABORTED)));
9593
9594 /* There is no lchan. Still the MSC's job to decide whether to tear down the conn or not. */
9595 f_verify_active_A_conn_and_clear();
9596
9597 f_sleep(2.0);
9598 setverdict(pass);
9599}
9600testcase TC_lcs_loc_req_for_idle_ms_no_pag_resp() runs on test_CT {
9601 var MSC_ConnHdlr vc_conn;
9602 var TestHdlrParams pars := f_gen_test_hdlr_pars();
9603
9604 f_init(1, true);
9605 f_sleep(1.0);
9606
9607 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
9608 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
9609
9610 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_for_idle_ms_no_pag_resp), pars);
9611 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +01009612 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02009613}
9614
9615/* During an ongoing Location Request, the MS sends a CM Service Request. Expect the same A-conn to be re-used / taken
9616 * over. */
9617private function f_tc_cm_service_during_lcs_loc_req(charstring id) runs on MSC_ConnHdlr {
9618 f_sleep(1.0);
9619
9620 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
9621 f_bssap_le_register_imsi(g_pars.imsi, omit);
9622
9623 /* Register to receive the Paging Command */
9624 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
9625 g_chan_nr := new_chan_nr;
9626 f_rslem_register(0, g_chan_nr);
9627
9628 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
9629 valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
9630 ts_CellId_CGI('001'H, '01'H, 1, 0)))));
9631 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
9632
9633 var PDU_BSSAP_LE plr;
9634 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?)) -> value(plr);
9635
9636 /* As the A-interface conn was established for LCS, the MS coincidentally decides to issue a CM Service Request
9637 * and establish Layer 3. It should use the existing A-interface conn. */
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02009638 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 +02009639 do_clear := false, expect_bssmap_l3 := true);
9640
9641 /* SMLC wants to ask the TA from the BSC explicitly in a BSSLAP TA Request message */
9642 BSSAP_LE.send(ts_BSSMAP_LE_BSSLAP(ts_BSSLAP_TA_Req));
9643
9644 /* OsmoBSC already has an lchan, no need to Page, just returns the TA */
9645 f_expect_bsslap(tr_BSSLAP_TA_Resp(?, ?));
9646
9647 /* SMLC got the TA from the BSC, now responds with geo information data. */
9648 BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(gad_ell_point_unc_circle, omit));
9649 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
9650 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(tr_BSSMAP_IE_LocationEstimate(gad_ell_point_unc_circle)));
9651
9652 /* The lchan should still exist, it was from a CM Service Request. */
9653 f_mo_l3_transceive();
9654
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02009655 f_perform_clear();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02009656
9657 f_sleep(2.0);
9658 setverdict(pass);
9659}
9660testcase TC_cm_service_during_lcs_loc_req() runs on test_CT {
9661 var MSC_ConnHdlr vc_conn;
9662 var TestHdlrParams pars := f_gen_test_hdlr_pars();
9663
9664 f_init(1, true);
9665 f_sleep(1.0);
9666
9667 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
9668 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
9669
9670 vc_conn := f_start_handler(refers(f_tc_cm_service_during_lcs_loc_req), pars);
9671 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +01009672 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02009673}
9674
9675/* During an ongoing Perform Location Request, do a Handover, an expect a BSSLAP Reset message from the BSC to indicate
9676 * the new lchan after handover. */
9677private function f_tc_ho_during_lcs_loc_req(charstring id) runs on MSC_ConnHdlr {
9678 f_sleep(1.0);
9679
9680 f_establish_fully(omit, omit);
9681 f_bssap_le_register_imsi(g_pars.imsi, omit);
9682
9683 BSSAP.send(valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
9684 ts_CellId_CGI('262'H, '42'H, 23, 42))));
9685
9686 var PDU_BSSAP_LE plr;
9687 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?)) -> value(plr);
9688
9689 /* SMLC ponders the Location Request, in the meantime the BSC decides to handover */
9690 f_bts_0_cfg(BSCVTY, {"neighbor bts 1"});
9691
9692 var HandoverState hs := {
9693 rr_ho_cmpl_seen := false,
9694 handover_done := false,
Neels Hofmeyrc741fcb2021-10-02 14:52:28 +02009695 old_chan_nr := -,
9696 expect_target_tsc := BTS_TSC[1]
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02009697 };
9698 /* issue hand-over command on VTY */
9699 f_vty_handover(BSCVTY, 0, 0, g_chan_nr, 1);
9700 /* temporarily suspend DChan processing on BTS1 to avoid race with RSLEM_register */
9701 f_rslem_suspend(RSL1_PROC);
9702
9703 /* From the MGW perspective, a handover is is characterized by
9704 * performing one MDCX operation with the MGW. So we expect to see
9705 * one more MDCX during handover. */
9706 g_media.mgcp_conn[0].mdcx_seen_exp := g_media.mgcp_conn[0].crcx_seen_exp + 1;
9707
9708 alt {
9709 [] as_handover(hs);
9710 }
9711
9712 var PDU_BSSAP_LE rx_bsslap;
9713
9714 interleave {
9715 /* Expect the BSC to inform the MSC about the handover */
9716 [] BSSAP.receive(tr_BSSMAP_HandoverPerformed);
9717
9718 /* Expect the BSC to inform the SMLC about the handover */
9719 [] BSSAP_LE.receive(tr_BSSMAP_LE_ConnInfo(BSSMAP_LE_PROT_BSSLAP, ?)) -> value(rx_bsslap) {
9720 f_match_bsslap(rx_bsslap, tr_BSSLAP_Reset(BSSLAP_CAUSE_INTRA_BSS_HO));
9721 }
9722 }
9723
9724 /* SMLC now responds with geo information data. */
9725 BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(gad_ell_point_unc_circle, omit));
9726 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
9727 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(tr_BSSMAP_IE_LocationEstimate(gad_ell_point_unc_circle)));
9728
9729 /* lchan still active */
9730 f_mo_l3_transceive(RSL1);
9731
9732 /* MSC decides it is done now. */
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02009733 f_perform_clear(RSL1, RSL1_PROC);
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02009734
9735 f_sleep(2.0);
9736 setverdict(pass);
9737}
9738testcase TC_ho_during_lcs_loc_req() runs on test_CT {
9739 var MSC_ConnHdlr vc_conn;
9740 var TestHdlrParams pars := f_gen_test_hdlr_pars();
9741
9742 f_init(2, true);
9743 f_sleep(1.0);
9744 vc_conn := f_start_handler(refers(f_tc_ho_during_lcs_loc_req), pars);
9745 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +01009746 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02009747}
9748
Neels Hofmeyrbf037052020-10-28 22:52:02 +00009749/* Attempt Complete Layer 3 without any MSC available (OS#4832) */
9750private function f_tc_no_msc(charstring id) runs on MSC_ConnHdlr {
9751 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
9752
9753 /* Also disable attach for the single connected MSC */
9754 f_vty_msc_allow_attach(BSCVTY, { false });
9755
9756 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) ));
9757 f_chan_est(g_pars.ra, l3_enc, g_pars.link_id, g_pars.fn);
9758
9759 /* No MSC is found, expecting a proper release on RSL */
9760 interleave {
9761 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_RELEASE)) {
9762 f_logp(BSCVTY, "Got RSL RR Release");
9763 }
9764 [] RSL.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {
9765 f_logp(BSCVTY, "Got RSL Deact SACCH");
9766 }
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +02009767 [] RSL.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
Neels Hofmeyrbf037052020-10-28 22:52:02 +00009768 f_logp(BSCVTY, "Got RSL RF Chan Rel, sending Rel Ack");
9769 RSL.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
Neels Hofmeyre680b012021-07-22 19:19:09 +02009770 f_rslem_unregister(0, g_chan_nr);
Neels Hofmeyrbf037052020-10-28 22:52:02 +00009771 }
9772 }
9773 setverdict(pass);
9774}
9775testcase TC_no_msc() runs on test_CT {
9776
9777 f_init(1, true);
9778 f_sleep(1.0);
9779 var MSC_ConnHdlr vc_conn;
9780 var TestHdlrParams pars := f_gen_test_hdlr_pars();
9781
9782 f_ctrs_bsc_init(counternames_bsc_mscpool);
9783
9784 vc_conn := f_start_handler(refers(f_tc_no_msc), pars);
9785 vc_conn.done;
9786
9787 f_ctrs_bsc_add("mscpool:subscr:no_msc");
9788 f_ctrs_bsc_verify();
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +01009789 f_shutdown_helper();
Neels Hofmeyrbf037052020-10-28 22:52:02 +00009790}
9791
Harald Welte0ea2d5e2018-04-07 21:40:29 +02009792/* Dyn PDCH todo:
9793 * activate OSMO as TCH/F
9794 * activate OSMO as TCH/H
9795 * does the BSC-located PCU socket get the updated INFO?
9796 * what if no PCU is connected at the time?
9797 * is the info correct on delayed PCU (re)connect?
9798 */
Harald Welte94e0c342018-04-07 11:33:23 +02009799
Neels Hofmeyr87857ec2021-04-25 16:17:47 +00009800private function f_TC_refuse_mode_modif_to_vamos(charstring id) runs on MSC_ConnHdlr {
9801 var PDU_BSSAP ass_cmd := f_gen_ass_req(g_pars.use_osmux);
9802 var template PDU_BSSAP exp_compl := f_gen_exp_compl(g_pars.use_osmux);
9803
9804 /* puzzle together the ASSIGNMENT REQ for given codec[s] */
9805 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
9806 ass_cmd.pdu.bssmap.assignmentRequest.codecList := g_pars.ass_codec_list;
9807 exp_compl.pdu.bssmap.assignmentComplete.speechCodec.codecElements[0] :=
9808 g_pars.ass_codec_list.codecElements[0];
9809 if (isvalue(g_pars.expect_mr_s0_s7)) {
9810 exp_compl.pdu.bssmap.assignmentComplete.speechCodec.codecElements[0].s0_7 :=
9811 g_pars.expect_mr_s0_s7;
9812 }
9813 }
9814 ass_cmd.pdu.bssmap.assignmentRequest.channelType :=
9815 f_BSSMAP_chtype_from_codec(g_pars.ass_codec_list.codecElements[0]);
9816 log("expecting ASS COMPL like this: ", exp_compl);
9817
9818 f_establish_fully(ass_cmd, exp_compl);
9819
Neels Hofmeyr8746b0d2021-06-01 17:25:39 +02009820 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 +00009821
9822 var RSL_Message rsl;
9823
9824 timer T := 5.0;
9825 T.start;
9826 alt {
9827 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr)) -> value rsl {
9828 var PDU_ML3_NW_MS l3 := dec_PDU_ML3_NW_MS(rsl.ies[2].body.l3_info.payload);
9829 log("Rx L3 from net: ", l3);
9830 if (ischosen(l3.msgs.rrm.channelModeModify)) {
9831 setverdict(fail, "Mode Modify to VAMOS succeeded even though BTS does not support VAMOS");
9832 mtc.stop;
9833 }
9834 }
9835 [] RSL.receive(tr_RSL_MODE_MODIFY_REQ(g_chan_nr, ?)) -> value rsl {
9836 setverdict(fail, "Mode Modify to VAMOS succeeded even though BTS does not support VAMOS");
9837 mtc.stop;
9838 }
9839 [] T.timeout {
9840 /* The BTS does not exhibit BTS_FEAT_VAMOS, so no VAMOS related Mode Modify should happen. */
9841 setverdict(pass);
9842 }
9843 }
9844 T.stop;
9845}
9846
9847/* The BSC does *not* indicate BTS_FEAT_VAMOS; make sure that a channel Mode Modify to VAMOS mode is refused by
9848 * osmo-bsc. */
9849testcase TC_refuse_mode_modif_to_vamos() runs on test_CT {
9850 var TestHdlrParams pars := f_gen_test_hdlr_pars();
9851 var MSC_ConnHdlr vc_conn;
9852
9853 f_init(1, true);
9854 f_sleep(1.0);
9855
9856 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
9857 vc_conn := f_start_handler(refers(f_TC_refuse_mode_modif_to_vamos), pars);
9858 vc_conn.done;
9859 f_shutdown_helper();
9860}
9861
9862/* The BSC does *not* indicate BTS_FEAT_VAMOS; make sure that a channel activation to VAMOS mode is refused by osmo-bsc.
9863 */
9864testcase TC_refuse_chan_act_to_vamos() runs on test_CT {
9865 f_init_vty();
9866
9867 f_init(1, false);
9868 f_sleep(1.0);
9869
9870 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 1 sub-slot 0 activate-vamos fr");
9871
9872 var ASP_RSL_Unitdata rx_rsl_ud;
9873 timer T := 5.0;
9874
9875 T.start;
9876 alt {
9877 [] IPA_RSL[0].receive(tr_ASP_RSL_UD(?, IPAC_PROTO_RSL_TRX0)) -> value rx_rsl_ud {
9878 if (rx_rsl_ud.rsl.msg_type == RSL_MT_CHAN_ACTIV) {
9879 T.stop;
9880 setverdict(fail, "CHANnel ACTivate in VAMOS mode succeeded even though BTS does not support VAMOS");
9881 mtc.stop;
9882 }
9883 repeat;
9884 }
9885 [] T.timeout {
9886 /* The BTS does not exhibit BTS_FEAT_VAMOS, so no VAMOS related CHANnel ACTivate should happen. */
9887 setverdict(pass);
9888 }
9889 }
9890}
9891
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +00009892private function f_TC_reassignment_codec(charstring id) runs on MSC_ConnHdlr {
9893 /* First fully set up a speech lchan */
9894 f_TC_assignment_codec(id);
9895
9896 /* Trigger re-assignment to another lchan */
9897 var AssignmentState assignment_st := valueof(ts_AssignmentStateInit);
9898
9899 /* Re-Assignment should tell the MGW endpoint the new lchan's RTP address and port, so expecting to see exactly
9900 * one MDCX on MGCP. */
9901 g_media.mgcp_conn[0].mdcx_seen_exp := g_media.mgcp_conn[0].mdcx_seen_exp + 1;
9902
9903 /* The new lchan will see all-new IPAC_CRCX and IPAC_MDCX messages telling the BTS the same RTP address and port
9904 * as the old lchan used. */
9905 g_media.bts.ipa_crcx_seen := false;
9906 g_media.bts.ipa_mdcx_seen := false;
9907
9908 /* Send different BTS side RTP port number for the new lchan */
9909 g_media.bts.bts.port_nr := 4223;
9910
9911 f_rslem_register(0, valueof(ts_RslChanNr_Bm(2))); /* <-- FIXME: can we somehow infer the timeslot that will be used? */
9912
9913 /* Trigger re-assignment. */
9914 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot " & int2str(g_chan_nr.tn) & " sub-slot 0 assignment");
9915
9916 timer T := 5.0;
9917 T.start;
9918 alt {
9919 [] as_assignment(assignment_st);
9920 [] as_Media();
9921 [] T.timeout {
9922 break;
9923 }
9924 }
9925
9926 if (not assignment_st.assignment_done) {
9927 setverdict(fail, "Assignment did not complete");
9928 mtc.stop;
9929 }
9930
9931 f_check_mgcp_expectations()
9932 setverdict(pass);
9933
9934 f_sleep(2.0);
9935 log("show lchan summary: ", f_vty_transceive_ret(BSCVTY, "show lchan summary"));
9936
9937 /* Instruct BSC to clear channel */
9938 var BssmapCause cause := 0;
9939 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
9940 interleave {
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +00009941 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_RELEASE)) {}
9942 [] RSL.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {}
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +02009943 [] RSL.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +00009944 RSL.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
Neels Hofmeyre680b012021-07-22 19:19:09 +02009945 f_rslem_unregister(0, g_chan_nr);
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +00009946 }
9947 [] BSSAP.receive(tr_BSSMAP_ClearComplete) {
9948 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
9949 }
9950 }
Neels Hofmeyr40a45d12021-09-23 22:57:12 +02009951 f_expect_dlcx_conns();
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +00009952
9953 f_sleep(0.5);
9954}
9955
9956testcase TC_reassignment_fr() runs on test_CT {
9957 var TestHdlrParams pars := f_gen_test_hdlr_pars();
9958 var MSC_ConnHdlr vc_conn;
9959
9960 f_init(1, true);
9961 f_sleep(1.0);
9962
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01009963 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +00009964
9965 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
9966 vc_conn := f_start_handler(refers(f_TC_reassignment_codec), pars);
9967 vc_conn.done;
9968
9969 /* from f_establish_fully() */
9970 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
9971 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
9972 /* from re-assignment */
9973 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
9974 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
9975 f_ctrs_bsc_and_bts_verify();
9976 f_shutdown_helper();
9977}
9978
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +02009979const charstring REEST_LOST_CONNECTION := "REEST_LOST_CONNECTION";
9980const charstring REEST_CLEAR := "REEST_CLEAR";
9981const charstring REEST_CLEAR_DONE := "REEST_CLEAR_DONE";
9982
9983/* CM Re-Establishment, 3GPP TS 24.008 4.5.1.6.
9984 * The MS <-> BTS loses radio connection, MS shows up on second BTS and asks for CM Re-Establishment.
9985 * BSC should establish a separate A conn for the same MS, the original A conn is then cleared by
9986 * the MSC as the CM Re-Establishment is handled.
9987 *
9988 * MS bts0 bts1 bsc msc test-component
9989 * |<----->|<----------------->|<-0-->| _1 Establish channel on bts 0
9990 * | | _1 wait a bit, to settle down
9991 * |<-x x--| | _1 "lose connection"
9992 * | | REEST_LOST_CONNECTION
9993 * |----------------->|------->|--1-->| _2 new A-conn: Chan Rqd, Imm Ass, Compl L3 with CM Re-Establishment Req
9994 * | | REEST_CLEAR
9995 * | |<-0---| _1 Clear Command on first A-conn
9996 * | |--0-->| _1 Clear Complete
9997 * | |<----------------->| | _1 Release first channel
9998 * | | REEST_CLEAR_DONE
9999 * |<-----------------|<-------|<-1---| _2 Chan Activ, Assignment Command
10000 * |<-----------------|<-------|<-1---| _2 Clear Command, Release
10001 *
10002 */
10003private function f_tc_cm_reestablishment_1(charstring id) runs on MSC_ConnHdlr {
10004 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
10005 var PDU_BSSAP ass_cmd := f_gen_ass_req();
10006
10007 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
10008 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
10009
10010 f_establish_fully(ass_cmd, exp_compl);
10011
10012 /* The original channel loses connection, MS attemts CM Re-Establishment on another cell, see
10013 * f_tc_cm_reestablishment_2(). This established channel stays active until MSC sends a Clear Command. The time
10014 * when exactly that happens is determined by f_tc_cm_reestablishment_2(). */
10015 f_sleep(2.0);
10016 COORD.send(REEST_LOST_CONNECTION);
10017
10018 alt {
10019 [] COORD.receive(REEST_CLEAR);
10020 [] RSL.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {
10021 setverdict(fail, "Unexpected channel release");
10022 mtc.stop;
10023 }
10024 [] RSL.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
10025 setverdict(fail, "Unexpected channel release");
10026 mtc.stop;
10027 }
10028 }
10029 f_perform_clear()
10030 f_expect_dlcx_conns();
Neels Hofmeyr969abd02021-09-23 22:24:08 +020010031 f_create_mgcp_delete_ep(g_media.mgcp_ep);
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020010032 COORD.send(REEST_CLEAR_DONE);
10033}
10034
10035private function f_tc_cm_reestablishment_2(charstring id) runs on MSC_ConnHdlr {
10036 f_MscConnHdlr_init(g_pars.media_nr, host_bts, host_mgw_mgcp, FR_AMR);
10037
10038 /* The MS lost the connection on the first channel, now establishes another one */
10039 COORD.receive(REEST_LOST_CONNECTION);
10040
10041 var MobileIdentityLV mi := valueof(ts_MI_IMSI_LV(g_pars.imsi));
10042 var PDU_ML3_MS_NW l3_info := valueof(ts_CM_REESTABL_REQ(mi));
10043 var octetstring l3_enc := enc_PDU_ML3_MS_NW(l3_info);
10044
10045 f_create_bssmap_exp(l3_enc);
Neels Hofmeyrc7b1f6d2021-07-20 23:21:36 +020010046 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 +020010047 BSSAP.receive(tr_BSSMAP_ComplL3(l3_enc));
10048
10049 /* MSC got the CM Re-Establishment request and first off clears the previous conn. */
10050 COORD.send(REEST_CLEAR);
10051 COORD.receive(REEST_CLEAR_DONE);
10052
10053 f_sleep(2.0);
10054
10055 /* Answer the CM Re-Establishment with an Assignment Command. */
10056 var template PDU_BSSAP expect_assignment_compl := f_gen_exp_compl();
10057 var PDU_BSSAP ass_cmd := f_gen_ass_req();
10058 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
10059 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
10060
10061 var AssignmentState st := valueof(ts_AssignmentStateInit);
10062 st.voice_call := true;
10063 st.is_assignment := true;
10064
10065 var ExpectCriteria mgcpcrit := {
10066 connid := omit,
10067 endpoint := omit,
10068 transid := omit
10069 };
10070 f_create_mgcp_expect(mgcpcrit);
10071
Neels Hofmeyrc7b1f6d2021-07-20 23:21:36 +020010072 f_rslem_dchan_queue_enable(RSL1_PROC);
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020010073
10074 BSSAP.send(ass_cmd);
10075
10076 var PDU_BSSAP bssap;
10077
10078 alt {
Neels Hofmeyrc7b1f6d2021-07-20 23:21:36 +020010079 [] as_assignment(st, rsl_pt := RSL1, rsl_proc_pt := RSL1_PROC);
10080 [] as_Media_ipacc(RSL1, RSL2);
10081 [] as_Media_mgw();
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020010082 [st.assignment_done] BSSAP.receive(expect_assignment_compl) {
10083 break;
10084 }
10085 }
10086
10087 f_sleep(3.0);
10088
10089 f_logp(BSCVTY, "f_tc_cm_reestablishment_2 clearing");
Neels Hofmeyrc7b1f6d2021-07-20 23:21:36 +020010090 f_perform_clear(RSL1, RSL1_PROC);
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020010091 f_expect_dlcx_conns();
10092}
10093
10094testcase TC_cm_reestablishment() runs on test_CT {
10095 var TestHdlrParams pars1 := f_gen_test_hdlr_pars();
10096 var MSC_ConnHdlr vc_conn1;
10097
10098 var TestHdlrParams pars2 := f_gen_test_hdlr_pars();
10099 var MSC_ConnHdlr vc_conn2;
10100 pars2.imsi := pars1.imsi;
10101 pars2.media_nr := 2;
Neels Hofmeyrbf720202021-10-02 12:58:24 +020010102 pars2.expect_tsc := BTS_TSC[1];
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020010103
10104 f_init(2, true, guard_timeout := 40.0);
10105 f_sleep(1.0);
10106
10107 vc_conn1 := f_start_handler_create(pars1);
10108 vc_conn2 := f_start_handler_create(pars2);
10109 connect(vc_conn1:COORD, vc_conn2:COORD);
10110 f_start_handler_run(vc_conn1, refers(f_tc_cm_reestablishment_1), pars1);
10111 f_start_handler_run(vc_conn2, refers(f_tc_cm_reestablishment_2), pars2);
10112 vc_conn1.done;
10113 vc_conn2.done;
10114
10115 f_shutdown_helper();
10116}
Neels Hofmeyr87857ec2021-04-25 16:17:47 +000010117
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020010118function f_exp_ipa_rx_nonfatal(integer bts_nr, template (present) RSL_Message t_rx, float t_secs := 2.0,
10119 IpaStreamId sid := IPAC_PROTO_RSL_TRX0, boolean ignore_other_rx := true)
10120runs on test_CT return template (omit) RSL_Message {
10121 var ASP_RSL_Unitdata rx_rsl_ud;
10122 timer T := t_secs;
10123
10124 T.start;
10125 alt {
10126 [] IPA_RSL[bts_nr].receive(tr_ASP_RSL_UD(t_rx, sid)) -> value rx_rsl_ud {
10127 T.stop;
10128 }
10129 [ignore_other_rx] IPA_RSL[bts_nr].receive { repeat; }
10130 [not ignore_other_rx] IPA_RSL[bts_nr].receive {
10131 log("f_exp_ipa_rx_nonfatal(): Got different message than ", t_rx);
10132 T.stop;
10133 return omit;
10134 }
10135 [] T.timeout {
10136 return omit;
10137 }
10138 }
10139 return rx_rsl_ud.rsl;
10140}
10141
10142private function f_vty_set_imm_ass(TELNETasp_PT pt, BtsNr bts_nr := 0, charstring imm_ass_setting := "post-chan-ack") {
10143 f_vty_enter_cfg_bts(pt, bts_nr);
10144 f_vty_transceive(pt, "immediate-assignment " & imm_ass_setting);
10145 f_vty_transceive(pt, "exit");
10146 f_vty_transceive(pt, "exit");
10147 f_vty_transceive(pt, "exit");
10148}
10149
10150private function f_verify_imm_ass(RSL_Message imm_ass, template uint8_t ra := ?, template GsmFrameNumber fn := ?,
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020010151 template RslChannelNr chan_nr := ?,
10152 template (present) uint12_t arfcn := ?,
10153 template (present) uint3_t tsc := ?)
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020010154{
10155 var RSL_IE_Body full_imm_ass_info;
10156 if (not f_rsl_find_ie(imm_ass, RSL_IE_FULL_IMM_ASS_INFO, full_imm_ass_info)) {
10157 setverdict(fail, "RSL Full Immediate Assign Info IE is absent");
10158 mtc.stop;
10159 }
10160
10161 var GsmRrMessage rr_imm_ass := dec_GsmRrMessage(full_imm_ass_info.full_imm_ass_info.payload);
10162 var template GsmRrMessage expect_imm_ass := tr_IMM_ASS(ra := ra,
10163 fn := fn,
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020010164 ch_desc := tr_ChanDescH0(chan_nr, arfcn, tsc),
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020010165 page_mode := ?);
10166 if (not match(rr_imm_ass, expect_imm_ass)) {
10167 log("Error: expected ", expect_imm_ass, " got ", rr_imm_ass);
10168 setverdict(fail, "Failed to match Immediate Assignment");
10169 mtc.stop;
10170 }
10171}
10172
10173testcase TC_imm_ass_post_chan_ack() runs on test_CT {
10174 var RSL_Message chan_act;
10175 var RSL_Message imm_ass;
10176
10177 f_init(1, false);
10178 f_sleep(1.0);
10179
10180 /* (should be the default anyway, just to make things clear) */
10181 f_vty_set_imm_ass(BSCVTY, 0, "post-chan-ack");
10182
10183 /* RA containing reason=LU */
10184 var GsmFrameNumber fn := 2342;
10185 var uint8_t ra := 2;
10186 f_ipa_tx(0, ts_RSL_CHAN_RQD(int2oct(ra, 1), fn));
10187
10188 chan_act := f_exp_ipa_rx(0, tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
10189
10190 /* First send the Chan Act ACK */
10191 var RslChannelNr chan_nr := chan_act.ies[0].body.chan_nr;
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020010192 var RSL_IE_Body chan_ident_ie;
10193 if (not f_rsl_find_ie(chan_act, RSL_IE_CHAN_IDENT, chan_ident_ie)) {
10194 setverdict(fail, "RSL Channel Identification IE is absent");
10195 mtc.stop;
10196 }
10197
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020010198 f_ipa_tx(0, ts_RSL_CHAN_ACT_ACK(chan_nr, fn + 10));
10199
10200 /* Then expect the Immediate Assignment, after we ACKed the chan act */
10201 imm_ass := f_exp_ipa_rx(0, tr_RSL_IMM_ASSIGN(0));
10202
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020010203 f_verify_imm_ass(imm_ass, ra, fn, chan_nr, chan_ident_ie.chan_ident.ch_desc.v.arfcn,
10204 chan_ident_ie.chan_ident.ch_desc.v.tsc);
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020010205
10206 /* Check that the lchan is working */
10207 var octetstring l3 := '00010203040506'O;
10208 f_ipa_tx(0, ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3));
10209
10210 var BSSAP_N_CONNECT_ind rx_c_ind;
10211 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3))) -> value rx_c_ind;
10212 BSSAP.send(ts_BSSAP_CONNECT_res(rx_c_ind.connectionId));
10213
10214 f_sleep(1.0);
10215 f_shutdown_helper();
10216}
10217
10218testcase TC_imm_ass_pre_chan_ack() runs on test_CT {
10219 var RSL_Message chan_act;
10220 var RSL_Message imm_ass;
10221
10222 f_init(1, false);
10223 f_sleep(1.0);
10224
10225 f_vty_set_imm_ass(BSCVTY, 0, "pre-chan-ack");
10226
10227 /* RA containing reason=LU */
10228 var GsmFrameNumber fn := 2342;
10229 var uint8_t ra := 2;
10230 f_ipa_tx(0, ts_RSL_CHAN_RQD(int2oct(ra, 1), fn));
10231
10232 /* (set bts 0 cfg back to default) */
10233 f_vty_set_imm_ass(BSCVTY);
10234
10235 chan_act := f_exp_ipa_rx(0, tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
10236 var RslChannelNr chan_nr := chan_act.ies[0].body.chan_nr;
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020010237 var RSL_IE_Body chan_ident_ie;
10238 if (not f_rsl_find_ie(chan_act, RSL_IE_CHAN_IDENT, chan_ident_ie)) {
10239 setverdict(fail, "RSL Channel Identification IE is absent");
10240 mtc.stop;
10241 }
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020010242
10243 /* *FIRST* expect the Immediate Assignment, before we ACK the chan act */
10244 imm_ass := f_exp_ipa_rx(0, tr_RSL_IMM_ASSIGN(0));
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020010245 f_verify_imm_ass(imm_ass, ra, fn, chan_nr, chan_ident_ie.chan_ident.ch_desc.v.arfcn,
10246 chan_ident_ie.chan_ident.ch_desc.v.tsc);
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020010247
10248 /* Only now send the Chan Act ACK */
10249 f_ipa_tx(0, ts_RSL_CHAN_ACT_ACK(chan_nr, fn+10));
10250
10251 /* Check that the lchan is working */
10252 var octetstring l3 := '00010203040506'O;
10253 f_ipa_tx(0, ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3));
10254
10255 var BSSAP_N_CONNECT_ind rx_c_ind;
10256 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3))) -> value rx_c_ind;
10257 BSSAP.send(ts_BSSAP_CONNECT_res(rx_c_ind.connectionId));
10258
10259 f_sleep(1.0);
10260 f_shutdown_helper();
10261}
10262
Neels Hofmeyr23158742021-09-07 19:08:07 +020010263testcase TC_imm_ass_pre_ts_ack() runs on test_CT {
10264 var RSL_Message chan_act;
10265 var RSL_Message imm_ass;
10266
10267 f_init(1, false);
10268 f_sleep(1.0);
10269
10270 f_vty_set_imm_ass(BSCVTY, 0, "pre-ts-ack");
10271
10272 /* RA containing reason=LU */
10273 var GsmFrameNumber fn := 2342;
10274 var uint8_t ra := 2;
10275 f_ipa_tx(0, ts_RSL_CHAN_RQD(int2oct(ra, 1), fn));
10276
10277 /* (set bts 0 cfg back to default) */
10278 f_vty_set_imm_ass(BSCVTY);
10279
10280 chan_act := f_exp_ipa_rx(0, tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
10281 var RslChannelNr chan_nr := chan_act.ies[0].body.chan_nr;
10282 var RSL_IE_Body chan_ident_ie;
10283 if (not f_rsl_find_ie(chan_act, RSL_IE_CHAN_IDENT, chan_ident_ie)) {
10284 setverdict(fail, "RSL Channel Identification IE is absent");
10285 mtc.stop;
10286 }
10287
10288 /* *FIRST* expect the Immediate Assignment, before we ACK the chan act */
10289 imm_ass := f_exp_ipa_rx(0, tr_RSL_IMM_ASSIGN(0));
10290 f_verify_imm_ass(imm_ass, ra, fn, chan_nr, chan_ident_ie.chan_ident.ch_desc.v.arfcn,
10291 chan_ident_ie.chan_ident.ch_desc.v.tsc);
10292
10293 /* Only now send the Chan Act ACK */
10294 f_ipa_tx(0, ts_RSL_CHAN_ACT_ACK(chan_nr, fn+10));
10295
10296 /* Check that the lchan is working */
10297 var octetstring l3 := '00010203040506'O;
10298 f_ipa_tx(0, ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3));
10299
10300 var BSSAP_N_CONNECT_ind rx_c_ind;
10301 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3))) -> value rx_c_ind;
10302 BSSAP.send(ts_BSSAP_CONNECT_res(rx_c_ind.connectionId));
10303
10304 f_sleep(1.0);
10305 f_shutdown_helper();
10306}
10307
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020010308testcase TC_imm_ass_pre_chan_ack_dyn_ts() runs on test_CT {
10309 /* change Timeslot 6 before f_init() starts RSL */
10310 f_init_vty();
10311 f_ts_set_chcomb(0, 0, 6, "TCH/F_TCH/H_PDCH");
10312 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
10313
10314 f_init(1, false);
10315 f_sleep(1.0);
10316
10317 var RslChannelNr chan_nr := valueof(t_RslChanNr_PDCH(6));
10318 /* The BSC will activate the dynamic PDCH by default, so confirm that */
10319 f_exp_ipa_rx(0, tr_RSL_CHAN_ACT_PDCH(chan_nr, ?));
10320 f_ipa_tx(0, ts_RSL_CHAN_ACT_ACK(chan_nr, 2323));
10321
10322 /* clean up timeslot 6 config, will only take effect when the OML drops the next time */
10323 f_ts_set_chcomb(0, 0, 6, "PDCH");
10324
10325 /* block all static timeslots so that the dyn TS will be used */
10326 f_disable_all_tch_f();
10327 f_disable_all_tch_h();
10328 f_disable_all_sdcch();
10329
10330 var RSL_Message chan_act;
10331 var RSL_Message imm_ass;
10332
10333 f_init(1, false);
10334 f_sleep(1.0);
10335
10336 f_vty_set_imm_ass(BSCVTY, 0, "pre-chan-ack");
10337
10338 /* RA containing reason=LU */
10339 var GsmFrameNumber fn := 2342;
10340 var uint8_t ra := 2;
10341 f_ipa_tx(0, ts_RSL_CHAN_RQD(int2oct(ra, 1), fn));
10342
10343 /* (set bts 0 cfg back to default) */
10344 f_vty_set_imm_ass(BSCVTY);
10345
10346 /* Expect the dyn TS to deactivate PDCH first */
10347 f_exp_ipa_rx(0, tr_RSL_RF_CHAN_REL(chan_nr));
10348 f_ipa_tx(0, ts_RSL_RF_CHAN_REL_ACK(chan_nr));
10349
10350 /* Now activation as SDCCH8 */
10351 chan_nr := valueof(t_RslChanNr_SDCCH8(tn := 6, sub_slot := 0));
10352
10353 chan_act := f_exp_ipa_rx(0, tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020010354 var RSL_IE_Body chan_ident_ie;
10355 if (not f_rsl_find_ie(chan_act, RSL_IE_CHAN_IDENT, chan_ident_ie)) {
10356 setverdict(fail, "RSL Channel Identification IE is absent");
10357 mtc.stop;
10358 }
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020010359
10360 /* *FIRST* expect the Immediate Assignment, before we ACK the chan act */
10361 imm_ass := f_exp_ipa_rx(0, tr_RSL_IMM_ASSIGN(0));
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020010362 f_verify_imm_ass(imm_ass, ra, fn, chan_nr, chan_ident_ie.chan_ident.ch_desc.v.arfcn,
10363 chan_ident_ie.chan_ident.ch_desc.v.tsc);
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020010364
10365 /* Only now send the Chan Act ACK */
10366 f_ipa_tx(0, ts_RSL_CHAN_ACT_ACK(chan_nr, fn+10));
10367
10368 /* Check that the lchan is working */
10369 var octetstring l3 := '00010203040506'O;
10370 f_ipa_tx(0, ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3));
10371
10372 var BSSAP_N_CONNECT_ind rx_c_ind;
10373 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3))) -> value rx_c_ind;
10374 BSSAP.send(ts_BSSAP_CONNECT_res(rx_c_ind.connectionId));
10375
10376 f_sleep(1.0);
10377 f_shutdown_helper();
10378}
10379
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020010380testcase TC_imm_ass_pre_ts_ack_dyn_ts() runs on test_CT {
10381 /* change Timeslot 6 before f_init() starts RSL */
10382 f_init_vty();
10383 f_ts_set_chcomb(0, 0, 6, "TCH/F_TCH/H_PDCH");
10384 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
10385
10386 f_init(1, false);
10387 f_sleep(1.0);
10388
10389 var RslChannelNr chan_nr := valueof(t_RslChanNr_PDCH(6));
10390 /* The BSC will activate the dynamic PDCH by default, so confirm that */
10391 f_exp_ipa_rx(0, tr_RSL_CHAN_ACT_PDCH(chan_nr, ?));
10392 f_ipa_tx(0, ts_RSL_CHAN_ACT_ACK(chan_nr, 2323));
10393
10394 /* clean up timeslot 6 config, will only take effect when the OML drops the next time */
10395 f_ts_set_chcomb(0, 0, 6, "PDCH");
10396
10397 /* block all static timeslots so that the dyn TS will be used */
10398 f_disable_all_tch_f();
10399 f_disable_all_tch_h();
10400 f_disable_all_sdcch();
10401
10402 var RSL_Message chan_act;
10403 var RSL_Message imm_ass;
10404
10405 f_init(1, false);
10406 f_sleep(1.0);
10407
10408 f_vty_set_imm_ass(BSCVTY, 0, "pre-ts-ack");
10409
10410 /* RA containing reason=LU */
10411 var GsmFrameNumber fn := 2342;
10412 var uint8_t ra := 2;
10413 f_ipa_tx(0, ts_RSL_CHAN_RQD(int2oct(ra, 1), fn));
10414
10415 /* (set bts 0 cfg back to default) */
10416 f_vty_set_imm_ass(BSCVTY);
10417
10418 /* Expect the dyn TS to deactivate PDCH first */
10419 f_exp_ipa_rx(0, tr_RSL_RF_CHAN_REL(chan_nr));
10420
10421 /* And already the Immediate Assignment even before the PDCH Deact ACK */
10422 imm_ass := f_exp_ipa_rx(0, tr_RSL_IMM_ASSIGN(0));
10423
10424 /* continue the Osmo style PDCH Deact (usual chan rel) */
10425 f_ipa_tx(0, ts_RSL_RF_CHAN_REL_ACK(chan_nr));
10426
10427 /* Now activation as SDCCH8 */
10428 chan_nr := valueof(t_RslChanNr_SDCCH8(tn := 6, sub_slot := 0));
10429
10430 chan_act := f_exp_ipa_rx(0, tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020010431 var RSL_IE_Body chan_ident_ie;
10432 if (not f_rsl_find_ie(chan_act, RSL_IE_CHAN_IDENT, chan_ident_ie)) {
10433 setverdict(fail, "RSL Channel Identification IE is absent");
10434 mtc.stop;
10435 }
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020010436 f_ipa_tx(0, ts_RSL_CHAN_ACT_ACK(chan_nr, fn+10));
10437
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020010438 f_verify_imm_ass(imm_ass, ra, fn, chan_nr, chan_ident_ie.chan_ident.ch_desc.v.arfcn,
10439 chan_ident_ie.chan_ident.ch_desc.v.tsc);
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020010440
10441 /* Check that the lchan is working */
10442 var octetstring l3 := '00010203040506'O;
10443 f_ipa_tx(0, ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3));
10444
10445 var BSSAP_N_CONNECT_ind rx_c_ind;
10446 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3))) -> value rx_c_ind;
10447 BSSAP.send(ts_BSSAP_CONNECT_res(rx_c_ind.connectionId));
10448
10449 f_sleep(1.0);
10450 f_shutdown_helper();
10451}
10452
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020010453/* GET and SET the bts.N.trx.M.rf_locked CTRL variable */
10454testcase TC_ctrl_trx_rf_locked() runs on test_CT {
10455 var MSC_ConnHdlr vc_conn;
10456
10457 f_init(nr_bts := 2, handler_mode := true, nr_msc := 1);
10458 f_sleep(1.0);
10459
10460 /* BTS 0, 1, 2 are OML unlocked, only BTS 0, 1 are actually connected to RSL. */
10461 f_ctrl_get_exp(IPA_CTRL, "rf_states",
10462 "0,0,operational,unlocked,on,rsl-up;" &
10463 "1,0,operational,unlocked,on,rsl-up;" &
10464 "2,0,operational,unlocked,on,rsl-down;" &
10465 "3,0,inoperational,locked,on,rsl-down;");
10466
10467 f_logp(BSCVTY, "TC_ctrl_trx_rf_locked: lock BTS 1 TRX 0");
10468 f_ctrl_set(IPA_CTRL, "bts.1.trx.0.rf_locked", "1");
10469 /* give it a moment to settle the FSM status */
10470 f_sleep(1.0);
10471
10472 /* Now BTS 1 TRX 0 should reflect "locked". Note the RF policy stays "on", because this is still handled
10473 * globally in osmo-bsc. Probably after sending "rf_locked 1" for a TRX, that TRX should reflect an RF policy
10474 * of "off"? But that's for a future patch if at all. */
10475 f_ctrl_get_exp(IPA_CTRL, "rf_states",
10476 "0,0,operational,unlocked,on,rsl-up;" &
10477 "1,0,operational,locked,on,rsl-up;" &
10478 "2,0,operational,unlocked,on,rsl-down;" &
10479 "3,0,inoperational,locked,on,rsl-down;");
10480
10481 f_logp(BSCVTY, "TC_ctrl_trx_rf_locked: lock the already locked TRX, nothing should change");
10482 f_ctrl_set(IPA_CTRL, "bts.1.trx.0.rf_locked", "1");
10483 f_sleep(1.0);
10484 f_ctrl_get_exp(IPA_CTRL, "rf_states",
10485 "0,0,operational,unlocked,on,rsl-up;" &
10486 "1,0,operational,locked,on,rsl-up;" &
10487 "2,0,operational,unlocked,on,rsl-down;" &
10488 "3,0,inoperational,locked,on,rsl-down;");
10489
10490 f_logp(BSCVTY, "TC_ctrl_trx_rf_locked: unlock BTS 1 TRX 0");
10491 f_ctrl_set(IPA_CTRL, "bts.1.trx.0.rf_locked", "0");
10492 f_sleep(1.0);
10493 f_ctrl_get_exp(IPA_CTRL, "rf_states",
10494 "0,0,operational,unlocked,on,rsl-up;" &
10495 "1,0,operational,unlocked,on,rsl-up;" &
10496 "2,0,operational,unlocked,on,rsl-down;" &
10497 "3,0,inoperational,locked,on,rsl-down;");
10498
10499 f_logp(BSCVTY, "TC_ctrl_trx_rf_locked: unlock an already unlocked TRX, nothing should change");
10500 f_ctrl_set(IPA_CTRL, "bts.0.trx.0.rf_locked", "0");
10501 f_sleep(1.0);
10502 f_ctrl_get_exp(IPA_CTRL, "rf_states",
10503 "0,0,operational,unlocked,on,rsl-up;" &
10504 "1,0,operational,unlocked,on,rsl-up;" &
10505 "2,0,operational,unlocked,on,rsl-down;" &
10506 "3,0,inoperational,locked,on,rsl-down;");
10507
10508 f_logp(BSCVTY, "TC_ctrl_trx_rf_locked: unlock an inoperational TRX");
10509 f_ctrl_set(IPA_CTRL, "bts.3.trx.0.rf_locked", "0");
10510 f_sleep(1.0);
10511 f_ctrl_get_exp(IPA_CTRL, "rf_states",
10512 "0,0,operational,unlocked,on,rsl-up;" &
10513 "1,0,operational,unlocked,on,rsl-up;" &
10514 "2,0,operational,unlocked,on,rsl-down;" &
10515 "3,0,inoperational,locked,on,rsl-down;");
10516
10517 f_shutdown_helper();
10518}
10519
Neels Hofmeyrb7581872021-11-07 14:02:49 +010010520const CounterNameVals counternames_cm_serv_rej := {
10521 { "cm_serv_rej", 0 },
10522 { "cm_serv_rej:imsi_unknown_in_hlr", 0 },
10523 { "cm_serv_rej:illegal_ms", 0 },
10524 { "cm_serv_rej:imsi_unknown_in_vlr", 0 },
10525 { "cm_serv_rej:imei_not_accepted", 0 },
10526 { "cm_serv_rej:illegal_me", 0 },
10527 { "cm_serv_rej:plmn_not_allowed", 0 },
10528 { "cm_serv_rej:loc_not_allowed", 0 },
10529 { "cm_serv_rej:roaming_not_allowed", 0 },
10530 { "cm_serv_rej:network_failure", 0 },
10531 { "cm_serv_rej:synch_failure", 0 },
10532 { "cm_serv_rej:congestion", 0 },
10533 { "cm_serv_rej:srv_opt_not_supported", 0 },
10534 { "cm_serv_rej:rqd_srv_opt_not_supported", 0 },
10535 { "cm_serv_rej:srv_opt_tmp_out_of_order", 0 },
10536 { "cm_serv_rej:call_can_not_be_identified", 0 },
10537 { "cm_serv_rej:incorrect_message", 0 },
10538 { "cm_serv_rej:invalid_mandantory_inf", 0 },
10539 { "cm_serv_rej:msg_type_not_implemented", 0 },
10540 { "cm_serv_rej:msg_type_not_compatible", 0 },
10541 { "cm_serv_rej:inf_eleme_not_implemented", 0 },
10542 { "cm_serv_rej:condtional_ie_error", 0 },
10543 { "cm_serv_rej:msg_not_compatible", 0 },
10544 { "cm_serv_rej:protocol_error", 0 },
10545 { "cm_serv_rej:retry_in_new_cell", 0 }
10546};
10547
10548private function f_TC_cm_serv_rej(charstring id) runs on MSC_ConnHdlr
10549{
10550 f_create_chan_and_exp();
Vadim Yanitskiya7fc5a62021-12-04 20:10:08 +030010551 /* we should now have a COMPL_L3 at the MSC */
Neels Hofmeyrb7581872021-11-07 14:02:49 +010010552 BSSAP.send(ts_PDU_DTAP_MT(ts_CM_SERV_REJ('02'O), '00'O));
Neels Hofmeyr87a65612021-11-16 15:56:45 +010010553 f_sleep(1.0);
Neels Hofmeyrb7581872021-11-07 14:02:49 +010010554}
10555testcase TC_cm_serv_rej() runs on test_CT {
10556 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10557 var MSC_ConnHdlr vc_conn;
10558
10559 f_init(1, true);
10560 f_sleep(1.0);
10561
10562 f_ctrs_bts_init(1, counternames_cm_serv_rej);
10563
10564 vc_conn := f_start_handler(refers(f_TC_cm_serv_rej), pars);
10565 vc_conn.done;
10566
10567 f_ctrs_bts_add(0, "cm_serv_rej", 1);
10568 f_ctrs_bts_add(0, "cm_serv_rej:imsi_unknown_in_hlr", 1);
10569 f_ctrs_bts_verify();
10570
Neels Hofmeyr87a65612021-11-16 15:56:45 +010010571 f_sleep(1.0);
Neels Hofmeyrb7581872021-11-07 14:02:49 +010010572 f_shutdown_helper();
10573}
10574
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020010575/* Reproduce a segfault happening when the SDCCH (primary) lchan is lost in-between a TCH Channel Activ and its Channel
10576 * Activ Ack (SYS#5627). */
10577private function f_TC_lost_sdcch_during_assignment(charstring id) runs on MSC_ConnHdlr {
10578 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Vadim Yanitskiyf0310e32021-10-26 00:30:59 +030010579
10580 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
10581 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020010582
10583 var BSSMAP_FIELD_CodecType codecType;
10584 codecType := valueof(ass_cmd.pdu.bssmap.assignmentRequest.codecList.codecElements[0].codecType);
10585
10586 f_MscConnHdlr_init(g_pars.media_nr, host_bts, host_mgw_mgcp, codecType);
10587
10588 /* First establish a signalling lchan */
10589 f_create_chan_and_exp();
10590 f_rslem_dchan_queue_enable();
10591
10592 /* we should now have a COMPL_L3 at the MSC */
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020010593
10594 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
10595 activate(as_Media_mgw());
10596
10597 var RslChannelNr chan_nr := { u := { ch0 := RSL_CHAN_NR_Bm_ACCH }, tn := 1 };
10598 f_rslem_register(0, chan_nr);
10599
10600 f_rslem_set_auto_chan_act_ack(RSL_PROC, false);
10601 BSSAP.send(ass_cmd);
10602
10603
10604 /* Wait for the Channel Activ for the TCH channel */
10605 var ASP_RSL_Unitdata rx_rsl_ud;
10606 RSL.receive(tr_ASP_RSL_UD(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV), sid := ?)) -> value rx_rsl_ud;
10607
10608 /* make the original SDCCH disappear */
10609 RSL.send(ts_RSL_REL_IND(g_chan_nr, valueof(ts_RslLinkID_DCCH(0))));
10610
10611 /* and ACK the TCH channel activation. This caused a segfault up to OsmoBSC 1.7.0 (SYS#5627) */
10612 RSL.send(ts_ASP_RSL_UD(ts_RSL_CHAN_ACT_ACK(chan_nr, 23), rx_rsl_ud.streamId));
10613
10614 interleave {
10615 [] BSSAP.receive(tr_BSSMAP_AssignmentFail);
10616 [] BSSAP.receive(tr_BSSMAP_ClearRequest);
10617 }
10618
10619 BSSAP.send(ts_BSSMAP_ClearCommand(0));
10620 BSSAP.receive(tr_BSSMAP_ClearComplete);
10621 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
10622
10623 var MgcpCommand mgcp;
10624 MGCP.receive(tr_DLCX()) -> value mgcp {
10625 MGCP.send(ts_DLCX_ACK2(mgcp.line.trans_id));
10626 };
10627
10628 f_sleep(0.5);
10629}
10630testcase TC_lost_sdcch_during_assignment() runs on test_CT {
10631 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10632 var MSC_ConnHdlr vc_conn;
10633
10634 f_init(1, true);
10635 f_sleep(1.0);
10636
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020010637 vc_conn := f_start_handler(refers(f_TC_lost_sdcch_during_assignment), pars);
10638 vc_conn.done;
10639
10640 f_shutdown_helper();
10641}
10642
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020010643const CounterNameVals counternames_bsc_bts_all_available_allocated := {
10644 { "all_allocated:sdcch", 0 },
10645 { "all_allocated:static_sdcch", 0 },
10646 { "all_allocated:tch", 0 },
10647 { "all_allocated:static_tch", 0 }
10648}
10649
10650private function f_all_allocated_expect_counter_change(charstring_list expect_changed) runs on test_CT
10651{
10652 /* Make sure counters settle first */
10653 f_sleep(1.0);
10654
10655 /* Take a baseline of counters */
10656 f_ctrs_bsc_and_bts_init(1, counternames_bsc_bts_all_available_allocated);
10657
10658 /* Elapse some time so that we see changes in counters, hopefully where expected */
10659 f_sleep(2.0);
10660
10661 /* Get new counters */
10662 var charstring_list all_changed := {};
10663 all_changed := all_changed & f_counter_name_vals_get_changed_n(IPA_CTRL, "bsc", g_ctr_bsc);
10664 all_changed := all_changed & f_counter_name_vals_get_changed_n(IPA_CTRL, "bts", g_ctr_bts);
10665
10666 /* Compare with expectations */
10667 var charstring_list all_expect_changed := {};
10668 for (var integer i := 0; i < lengthof(expect_changed); i := i + 1) {
10669 all_expect_changed := all_expect_changed & { "bsc.0." & expect_changed[i], "bts.0." & expect_changed[i] };
10670 }
10671 f_counter_name_vals_expect_changed_list(all_changed, all_expect_changed);
10672}
10673
10674testcase TC_ratectr_all_available_allocated() runs on test_CT {
10675 var ASP_RSL_Unitdata rsl_ud;
10676 var integer i;
10677 var integer chreq_total, chreq_nochan;
10678
10679 f_init(1);
10680 f_sleep(1.0);
10681
10682 /* Exhaust all dedicated SDCCH lchans.
10683 /* GSM 44.018 Table 9.1.8.2:
10684 * RA = '13'O -> Establishment cause = 0001xxxx (MS dual rate capable and asks for "SDCCH").
10685 */
10686 for (i := 0; i < NUM_SDCCH_PER_BTS; i := i+1) {
10687 f_est_dchan('13'O, NUM_SDCCH_PER_BTS + i, '00010203040506'O);
10688 }
10689
10690 /* Since only bts 0 is connected, expecting all_allocated to become true for both bts 0 and the "global" bsc
10691 * level.
10692 * All SDCCH are now occupied. */
10693 f_all_allocated_expect_counter_change({"all_allocated:sdcch", "all_allocated:static_sdcch"});
10694
10695 /* Also fill up all remaining (TCH) channels */
10696 for (i := 0; i < NUM_TCHF_PER_BTS + NUM_TCHH_PER_BTS; i := i+1) {
10697 f_est_dchan('33'O, NUM_SDCCH_PER_BTS + i, '00010203040506'O);
10698 }
10699
10700 /* All TCH are now also occupied */
10701 f_all_allocated_expect_counter_change({"all_allocated:sdcch", "all_allocated:static_sdcch",
10702 "all_allocated:tch", "all_allocated:static_tch"});
10703
10704 f_shutdown_helper();
10705}
10706
10707testcase TC_ratectr_all_available_allocated_dyn() runs on test_CT {
10708 var ASP_RSL_Unitdata rsl_ud;
10709 var integer i;
10710 var integer chreq_total, chreq_nochan;
10711
10712 f_init_vty();
10713 f_ts_set_chcomb(0, 0, 2, "TCH/F_TCH/H_PDCH");
10714 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
10715 /* Now we have 3 TCH/F, 1 OSMO_DYN, 1 TCH/H */
10716
10717 f_init(1, guard_timeout := 60.0);
10718 f_sleep(1.0);
10719
10720 /* The dyn TS wants to activate PDCH mode, ACK that. */
10721 var RslChannelNr chan_nr;
10722 chan_nr := valueof(t_RslChanNr_PDCH(2));
10723 f_exp_ipa_rx(0, tr_RSL_CHAN_ACT_PDCH(chan_nr, ?));
10724 f_ipa_tx(0, ts_RSL_CHAN_ACT_ACK(chan_nr, 2342));
10725
10726 /* Exhaust all dedicated SDCCH lchans.
10727 /* GSM 44.018 Table 9.1.8.2:
10728 * RA = '13'O -> Establishment cause = 0001xxxx (MS dual rate capable and asks for "SDCCH").
10729 */
10730 for (i := 0; i < NUM_SDCCH_PER_BTS; i := i+1) {
10731 f_est_dchan('13'O, NUM_SDCCH_PER_BTS + i, '00010203040506'O);
10732 }
10733
10734 /* The static SDCCH should now be occupied, while still 3x8 dynamic SDCCH potentially remain. So only
10735 * all_allocated:static_sdcch is counted, all_allocated:sdcch remains zero. */
10736 f_all_allocated_expect_counter_change({"all_allocated:static_sdcch"});
10737
10738 /* Request more SDCCH, hence convert the first dyn TS to SDCCH8.
10739 * Will release them later, so remember all the DchanTuples. */
10740 var DchanTuples dyn_sddch := {};
10741 dyn_sddch := dyn_sddch & { f_est_dchan_dyn('33'O, NUM_SDCCH_PER_BTS + i, '00010203040506'O) };
10742
10743 /* Also occupy the seven other SDCCH of the dyn TS */
10744 for (i := 0; i < 7; i := i+1) {
10745 dyn_sddch := dyn_sddch & { f_est_dchan('33'O, NUM_SDCCH_PER_BTS + i, '00010203040506'O) };
10746 }
10747
10748 /* Now all dynamic SDCCH are also occupied, so for the first time all_allocated:sdcch will trigger... */
10749 f_all_allocated_expect_counter_change({"all_allocated:sdcch", "all_allocated:static_sdcch"});
10750
10751 /* occupy the remaining TCH, three TCH/F and two TCH/H lchans */
10752 for (i := 0; i < 5; i := i+1) {
10753 f_est_dchan('33'O, NUM_SDCCH_PER_BTS + i, '00010203040506'O);
10754 }
10755
10756 /* All TCH lchans are now also occupied, both static and dynamic */
10757 f_all_allocated_expect_counter_change({"all_allocated:sdcch", "all_allocated:static_sdcch",
10758 "all_allocated:tch", "all_allocated:static_tch"});
10759
10760 /* Starting to release the dyn TS: as soon as the first SDCCH gets released, all_allocated:sdcch stops
10761 * incrementing. */
10762 var BssmapCause cause := 0;
10763 var DchanTuple dt := dyn_sddch[0];
10764 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
10765 f_exp_chan_rel_and_clear(dt, 0);
10766
10767 /* one dyn TS SDCCH is free again, so only the static_sdcch should increment. For tch, both static and dynamic
10768 * count as occupied, so those still both increment. */
10769 f_all_allocated_expect_counter_change({"all_allocated:static_sdcch",
10770 "all_allocated:tch", "all_allocated:static_tch"});
10771
10772 /* Release the remaining SDCCH of the dyn TS, so it becomes available as TCH again */
10773 for (i := 1; i < lengthof(dyn_sddch); i := i+1) {
10774 dt := dyn_sddch[i];
10775 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
10776 f_exp_chan_rel_and_clear(dt, 0);
10777 }
10778
10779 /* All SDCCH on the dyn TS are released, the dyn TS wants to activate PDCH again */
10780 chan_nr := valueof(t_RslChanNr_PDCH(2));
10781 f_exp_ipa_rx(0, tr_RSL_CHAN_ACT_PDCH(chan_nr, ?));
10782 f_ipa_tx(0, ts_RSL_CHAN_ACT_ACK(chan_nr, 2342));
10783
10784 /* Now all channels are occupied except the dyn TS, so expecting only the static counters to increment */
10785 f_all_allocated_expect_counter_change({"all_allocated:static_sdcch", "all_allocated:static_tch"});
10786
10787 /* clean up config */
10788 f_ts_reset_chcomb(0);
10789
10790 f_shutdown_helper();
10791}
10792
Harald Welte28d943e2017-11-25 15:00:50 +010010793control {
Harald Welte898113b2018-01-31 18:32:21 +010010794 /* CTRL interface testing */
Harald Welte4003d112017-12-09 22:35:39 +010010795 execute( TC_ctrl_msc_connection_status() );
Stefan Sperlingb041b3d2018-01-03 17:14:55 +010010796 execute( TC_ctrl_msc0_connection_status() );
Neels Hofmeyrf65ce872021-09-23 18:40:10 +020010797 /* In SCCPlite tests, only one MSC is configured. These tests assume that three MSCs are configured, so only run
10798 * these in the AoIP test suite. */
10799 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
10800 execute( TC_stat_num_msc_connected_1() );
10801 execute( TC_stat_num_msc_connected_2() );
10802 execute( TC_stat_num_msc_connected_3() );
10803 }
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +020010804 execute( TC_stat_num_bts_connected_1() );
10805 execute( TC_stat_num_bts_connected_2() );
10806 execute( TC_stat_num_bts_connected_3() );
Harald Welte96c94412017-12-09 03:12:45 +010010807 execute( TC_ctrl() );
Neels Hofmeyrf246a922020-05-13 02:27:10 +020010808 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_SCCPlite_SERVER) {
Pau Espin Pedrol5a2d7432019-06-07 19:43:45 +020010809 execute( TC_ctrl_location() );
10810 }
Harald Welte898113b2018-01-31 18:32:21 +010010811
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +020010812 execute( TC_si_default() );
Neels Hofmeyr66aeba42020-07-06 02:21:21 +020010813 execute( TC_si2quater_2_earfcns() );
10814 execute( TC_si2quater_3_earfcns() );
10815 execute( TC_si2quater_4_earfcns() );
10816 execute( TC_si2quater_5_earfcns() );
10817 execute( TC_si2quater_6_earfcns() );
Neels Hofmeyrad132f22020-07-08 02:20:16 +020010818 execute( TC_si2quater_12_earfcns() );
10819 execute( TC_si2quater_23_earfcns() );
10820 execute( TC_si2quater_32_earfcns() );
10821 execute( TC_si2quater_33_earfcns() );
10822 execute( TC_si2quater_42_earfcns() );
10823 execute( TC_si2quater_48_earfcns() );
10824 execute( TC_si2quater_49_earfcns() );
Pau Espin Pedrol85a84432020-07-20 18:45:03 +020010825 execute( TC_si_acc_rotate() );
Alexander Couzens4ad3a352020-09-10 22:29:12 +020010826 execute( TC_si_acc_ramp_rotate() );
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +020010827
Harald Welte898113b2018-01-31 18:32:21 +010010828 /* RSL DCHAN Channel ACtivation / Deactivation */
Harald Welteae026692017-12-09 01:03:01 +010010829 execute( TC_chan_act_noreply() );
Harald Welte4003d112017-12-09 22:35:39 +010010830 execute( TC_chan_act_counter() );
Harald Welteae026692017-12-09 01:03:01 +010010831 execute( TC_chan_act_ack_noest() );
Philipp Maier9c60a622020-07-09 15:08:46 +020010832 execute( TC_chan_act_ack_noest_emerg() );
Philipp Maier606f07d2020-08-12 17:21:58 +020010833 execute( TC_chan_rqd_emerg_deny() );
Harald Welteae026692017-12-09 01:03:01 +010010834 execute( TC_chan_act_ack_est_ind_noreply() );
10835 execute( TC_chan_act_ack_est_ind_refused() );
Harald Welte618ef642017-12-14 14:58:20 +010010836 execute( TC_chan_act_nack() );
Harald Welte799c97b2017-12-14 17:50:30 +010010837 execute( TC_chan_exhaustion() );
Vadim Yanitskiy1ff1fdf2018-11-27 01:32:57 +070010838 execute( TC_chan_deact_silence() );
Harald Welte4003d112017-12-09 22:35:39 +010010839 execute( TC_chan_rel_rll_rel_ind() );
10840 execute( TC_chan_rel_conn_fail() );
10841 execute( TC_chan_rel_hard_clear() );
Pau Espin Pedrol841b90d2021-04-15 16:42:52 +020010842 execute( TC_chan_rel_last_eutran_plmn_hard_clear_no_csfb() );
10843 execute( TC_chan_rel_last_eutran_plmn_hard_clear_csfb() );
Harald Welte99787102019-02-04 10:41:36 +010010844 execute( TC_chan_rel_hard_clear_csfb() );
Harald Welted8c36cd2017-12-09 23:05:31 +010010845 execute( TC_chan_rel_hard_rlsd() );
Harald Welte550daf92018-06-11 19:22:13 +020010846 execute( TC_chan_rel_hard_rlsd_ms_dead() );
Harald Welte85804d42017-12-10 14:11:58 +010010847 execute( TC_chan_rel_a_reset() );
Pau Espin Pedrolc675b612020-01-09 19:55:40 +010010848 execute( TC_chan_rel_sccp_tiar_timeout() );
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +020010849 execute( TC_chan_rel_rr_cause() );
Harald Welte6f521d82017-12-11 19:52:02 +010010850
Harald Weltecfe2c962017-12-15 12:09:32 +010010851 execute( TC_outbound_connect() );
Harald Welte898113b2018-01-31 18:32:21 +010010852
10853 /* Assignment related */
Harald Welte16a4adf2017-12-14 18:54:01 +010010854 execute( TC_assignment_cic_only() );
Harald Welte235ebf12017-12-15 14:18:16 +010010855 execute( TC_assignment_csd() );
10856 execute( TC_assignment_ctm() );
10857 execute( TC_assignment_sign() );
Pau Espin Pedrol07866632020-09-03 19:10:55 +020010858 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
10859 execute( TC_assignment_aoip_tla_v6() );
10860 }
Harald Welte235ebf12017-12-15 14:18:16 +010010861 execute( TC_assignment_fr_a5_0() );
10862 execute( TC_assignment_fr_a5_1() );
Neels Hofmeyrf246a922020-05-13 02:27:10 +020010863 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
Harald Welte8f67d1d2018-05-25 20:38:42 +020010864 execute( TC_assignment_fr_a5_1_codec_missing() );
10865 }
Harald Welte235ebf12017-12-15 14:18:16 +010010866 execute( TC_assignment_fr_a5_3() );
Neels Hofmeyr0d8ec532021-06-11 00:09:48 +020010867 execute( TC_assignment_fr_a5_4() );
Neels Hofmeyr0faeb7a2021-06-10 23:59:35 +020010868 execute( TC_assignment_fr_a5_4_fail() );
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +020010869 execute( TC_assignment_fr_a5_not_sup() );
Harald Welte3c86ea02018-05-10 22:28:05 +020010870 execute( TC_ciph_mode_a5_0() );
10871 execute( TC_ciph_mode_a5_1() );
Oliver Smith50b98122021-07-09 15:00:28 +020010872 execute( TC_ciph_mode_a5_2_0() );
Oliver Smith1dff88d2021-07-09 08:45:51 +020010873 execute( TC_ciph_mode_a5_2_1() );
Harald Welte3c86ea02018-05-10 22:28:05 +020010874 execute( TC_ciph_mode_a5_3() );
Neels Hofmeyr81ad27f2021-06-11 00:09:40 +020010875 execute( TC_ciph_mode_a5_4() );
Harald Welte16a4adf2017-12-14 18:54:01 +010010876
Harald Welte60aa5762018-03-21 19:33:13 +010010877 execute( TC_assignment_codec_fr() );
Neels Hofmeyr559d5d02021-04-16 16:50:49 +020010878 execute( TC_assignment_codec_fr_by_mode_modify() );
Harald Welte60aa5762018-03-21 19:33:13 +010010879 execute( TC_assignment_codec_hr() );
10880 execute( TC_assignment_codec_efr() );
10881 execute( TC_assignment_codec_amr_f() );
10882 execute( TC_assignment_codec_amr_h() );
Philipp Maier8a581d22019-03-26 18:32:48 +010010883
Neels Hofmeyrf246a922020-05-13 02:27:10 +020010884 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
Philipp Maier8a581d22019-03-26 18:32:48 +010010885 execute( TC_assignment_codec_amr_f_S1() );
10886 execute( TC_assignment_codec_amr_h_S1() );
10887 execute( TC_assignment_codec_amr_f_S124() );
10888 execute( TC_assignment_codec_amr_h_S124() );
10889 execute( TC_assignment_codec_amr_f_S0() );
10890 execute( TC_assignment_codec_amr_f_S02() );
10891 execute( TC_assignment_codec_amr_f_S024() );
10892 execute( TC_assignment_codec_amr_f_S0247() );
10893 execute( TC_assignment_codec_amr_h_S0() );
10894 execute( TC_assignment_codec_amr_h_S02() );
10895 execute( TC_assignment_codec_amr_h_S024() );
10896 execute( TC_assignment_codec_amr_h_S0247() );
10897 execute( TC_assignment_codec_amr_f_S01234567() );
10898 execute( TC_assignment_codec_amr_f_S0234567() );
10899 execute( TC_assignment_codec_amr_f_zero() );
10900 execute( TC_assignment_codec_amr_f_unsupp() );
10901 execute( TC_assignment_codec_amr_h_S7() );
Neels Hofmeyr21863562020-11-26 00:34:33 +000010902 execute( TC_assignment_codec_amr_f_start_mode_auto() );
10903 execute( TC_assignment_codec_amr_h_start_mode_auto() );
Neels Hofmeyr3eb94562020-11-26 02:40:26 +000010904 execute( TC_assignment_codec_amr_f_start_mode_4() );
10905 execute( TC_assignment_codec_amr_h_start_mode_4() );
Neels Hofmeyr454d7922020-11-26 02:24:57 +000010906 execute( TC_assignment_codec_amr_startmode_cruft() );
Philipp Maier8a581d22019-03-26 18:32:48 +010010907 }
Harald Welte60aa5762018-03-21 19:33:13 +010010908
Philipp Maierac09bfc2019-01-08 13:41:39 +010010909 execute( TC_assignment_codec_fr_exhausted_req_hr() );
10910 execute( TC_assignment_codec_fr_exhausted_req_fr() );
10911 execute( TC_assignment_codec_fr_exhausted_req_fr_hr() );
10912 execute( TC_assignment_codec_fr_exhausted_req_hr_fr() );
10913 execute( TC_assignment_codec_hr_exhausted_req_fr() );
10914 execute( TC_assignment_codec_hr_exhausted_req_hr() );
10915 execute( TC_assignment_codec_hr_exhausted_req_hr_fr() );
10916 execute( TC_assignment_codec_hr_exhausted_req_fr_hr() );
10917 execute( TC_assignment_codec_req_hr_fr() );
10918 execute( TC_assignment_codec_req_fr_hr() );
Pau Espin Pedrol14475352021-07-22 15:48:16 +020010919 execute( TC_assignment_sdcch_exhausted_req_signalling() );
10920 execute( TC_assignment_sdcch_exhausted_req_signalling_tch_forbidden() );
10921 execute( TC_assignment_sdcch_exhausted_req_voice_tch_forbidden() );
Philipp Maierac09bfc2019-01-08 13:41:39 +010010922
Pau Espin Pedrol23510fb2021-07-20 17:00:38 +020010923 execute( TC_assignment_osmux() );
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +020010924
Harald Welte898113b2018-01-31 18:32:21 +010010925 /* RLL Establish Indication on inactive DCHAN / SAPI */
Harald Welte5cd20ed2017-12-13 21:03:20 +010010926 execute( TC_rll_est_ind_inact_lchan() );
10927 execute( TC_rll_est_ind_inval_sapi1() );
10928 execute( TC_rll_est_ind_inval_sapi3() );
10929 execute( TC_rll_est_ind_inval_sacch() );
10930
Vadim Yanitskiy61f784a2020-10-01 21:12:19 +070010931 /* DLCI / RSL Link ID conversion for MO/MT messages on SAPI0/SAPI3 */
10932 execute( TC_tch_dlci_link_id_sapi() );
10933
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +070010934 /* SAPI N Reject triggered by RLL establishment failures */
10935 execute( TC_rll_rel_ind_sapi_n_reject() );
10936 execute( TC_rll_err_ind_sapi_n_reject() );
10937 execute( TC_rll_timeout_sapi_n_reject() );
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +070010938 execute( TC_rll_sapi_n_reject_dlci_cc() );
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +070010939
Harald Welte898113b2018-01-31 18:32:21 +010010940 /* Paging related tests */
Harald Welte6f521d82017-12-11 19:52:02 +010010941 execute( TC_paging_imsi_nochan() );
10942 execute( TC_paging_tmsi_nochan() );
10943 execute( TC_paging_tmsi_any() );
10944 execute( TC_paging_tmsi_sdcch() );
10945 execute( TC_paging_tmsi_tch_f() );
10946 execute( TC_paging_tmsi_tch_hf() );
10947 execute( TC_paging_imsi_nochan_cgi() );
10948 execute( TC_paging_imsi_nochan_lac_ci() );
10949 execute( TC_paging_imsi_nochan_ci() );
10950 execute( TC_paging_imsi_nochan_lai() );
10951 execute( TC_paging_imsi_nochan_lac() );
10952 execute( TC_paging_imsi_nochan_all() );
Harald Welte751d3eb2018-01-31 15:51:06 +010010953 execute( TC_paging_imsi_nochan_plmn_lac_rnc() );
10954 execute( TC_paging_imsi_nochan_rnc() );
10955 execute( TC_paging_imsi_nochan_lac_rnc() );
10956 execute( TC_paging_imsi_nochan_lacs() );
10957 execute( TC_paging_imsi_nochan_lacs_empty() );
Stefan Sperling049a86e2018-03-20 15:51:00 +010010958 execute( TC_paging_imsi_nochan_cgi_unknown_cid() );
Harald Welte10985002017-12-12 09:29:15 +010010959 execute( TC_paging_imsi_a_reset() );
Harald Weltee65d40e2017-12-13 00:09:06 +010010960 execute( TC_paging_imsi_load() );
Philipp Maier779a7922018-02-16 11:00:37 +010010961 execute( TC_paging_counter() );
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +010010962 execute( TC_paging_resp_unsol() );
Harald Welte4e9b9cc2017-12-14 18:31:02 +010010963
10964 execute( TC_rsl_drop_counter() );
Stefan Sperling830dc9d2018-02-12 21:08:28 +010010965 execute( TC_rsl_unknown_unit_id() );
10966
10967 execute( TC_oml_unknown_unit_id() );
Harald Welte898113b2018-01-31 18:32:21 +010010968
10969 execute( TC_classmark() );
Harald Welteeddf0e92020-06-21 19:42:15 +020010970 execute( TC_common_id() );
Harald Welte898113b2018-01-31 18:32:21 +010010971 execute( TC_unsol_ass_fail() );
Harald Welteea99a002018-01-31 20:46:43 +010010972 execute( TC_unsol_ass_compl() );
Harald Weltefbf9b5e2018-01-31 20:41:23 +010010973 execute( TC_unsol_ho_fail() );
Harald Weltee3bd6582018-01-31 22:51:25 +010010974 execute( TC_err_82_short_msg() );
Harald Weltee9e02e42018-01-31 23:36:25 +010010975 execute( TC_err_84_unknown_msg() );
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +010010976
Harald Welte261af4b2018-02-12 21:20:39 +010010977 execute( TC_ho_int() );
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +020010978 execute( TC_ho_int_a5_0() );
10979 execute( TC_ho_int_a5_1() );
10980 execute( TC_ho_int_a5_3() );
10981 execute( TC_ho_int_a5_4() );
Neels Hofmeyr5f144212020-11-03 15:41:58 +000010982 execute( TC_ho_int_radio_link_failure() );
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +010010983
Neels Hofmeyrafe2ea52021-11-24 15:16:12 +010010984 /* TC_ho_out_of_this_bsc is run last, see comment below */
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +020010985 execute( TC_ho_out_fail_no_msc_response() );
10986 execute( TC_ho_out_fail_rr_ho_failure() );
Neels Hofmeyrd8a602c2019-07-09 19:46:01 +020010987 execute( TC_ho_out_fail_no_result_after_ho_cmd() );
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +010010988
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +010010989 execute( TC_ho_into_this_bsc() );
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +020010990 execute( TC_ho_into_this_bsc_a5_0() );
10991 execute( TC_ho_into_this_bsc_a5_1() );
10992 execute( TC_ho_into_this_bsc_a5_3() );
10993 execute( TC_ho_into_this_bsc_a5_4() );
Pau Espin Pedrol07866632020-09-03 19:10:55 +020010994 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
10995 execute( TC_ho_into_this_bsc_tla_v6() );
10996 }
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +020010997 execute( TC_srvcc_eutran_to_geran() );
Pau Espin Pedrol35801c32021-04-19 13:03:20 +020010998 execute( TC_srvcc_eutran_to_geran_ho_out() );
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +020010999 execute( TC_srvcc_eutran_to_geran_forbid_fast_return() );
11000 execute( TC_srvcc_eutran_to_geran_ho_out_forbid_fast_return() );
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +010011001 execute( TC_ho_in_fail_msc_clears() );
11002 execute( TC_ho_in_fail_msc_clears_after_ho_detect() );
11003 execute( TC_ho_in_fail_no_detect() );
11004 execute( TC_ho_in_fail_no_detect2() );
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +010011005
Neels Hofmeyr91401012019-07-11 00:42:35 +020011006 execute( TC_ho_neighbor_config_1() );
11007 execute( TC_ho_neighbor_config_2() );
11008 execute( TC_ho_neighbor_config_3() );
11009 execute( TC_ho_neighbor_config_4() );
11010 execute( TC_ho_neighbor_config_5() );
11011 execute( TC_ho_neighbor_config_6() );
11012 execute( TC_ho_neighbor_config_7() );
11013
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +010011014 execute( TC_bssap_rlsd_does_not_cause_bssmap_reset() );
Neels Hofmeyr4ff93282018-03-12 04:25:35 +010011015 execute( TC_bssmap_clear_does_not_cause_bssmap_reset() );
Neels Hofmeyrfd445c32018-03-09 15:39:31 +010011016 execute( TC_ms_rel_ind_does_not_cause_bssmap_reset() );
Harald Welte94e0c342018-04-07 11:33:23 +020011017
11018 execute( TC_dyn_pdch_ipa_act_deact() );
11019 execute( TC_dyn_pdch_ipa_act_nack() );
11020 execute( TC_dyn_pdch_osmo_act_deact() );
11021 execute( TC_dyn_pdch_osmo_act_nack() );
Pau Espin Pedrol37a4c152021-11-16 19:02:23 +010011022 execute( TC_dyn_ts_sdcch8_act_deact() );
11023 execute( TC_dyn_ts_sdcch8_all_subslots_used() );
11024 execute( TC_dyn_ts_sdcch8_tch_call_act_deact() );
11025 execute( TC_dyn_ts_sdcch8_act_nack() );
Harald Welte99f3ca02018-06-14 13:40:29 +020011026
Stefan Sperling0796a822018-10-05 13:01:39 +020011027 execute( TC_chopped_ipa_ping() );
Stefan Sperlingaa1e60f2018-10-15 16:34:07 +020011028 execute( TC_chopped_ipa_payload() );
Stefan Sperling0796a822018-10-05 13:01:39 +020011029
Pau Espin Pedrol8f773632019-11-05 11:46:53 +010011030 /* Power control related */
11031 execute( TC_assignment_verify_ms_power_params_ie() );
Vadim Yanitskiy4b233042021-06-30 00:58:43 +020011032 execute( TC_c0_power_red_mode() );
Neels Hofmeyr4f118412020-06-04 15:25:10 +020011033
11034 /* MSC pooling */
11035 /* FIXME: in SCCPlite, indicating how many MSCs should be connected does currently not work. Since
11036 * RESET->RESET-ACK is unconditionally negotiated for all configured MSCs, they always all appear as connected
11037 * to osmo-bsc. The MSC pooling tests however require disconnecting selected MSCs, and hence don't work out as
11038 * intended on SCCPlite. So for now, run these only for SCCP/M3UA. */
11039 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
11040 execute( TC_mscpool_L3Compl_on_1_msc() );
11041 execute( TC_mscpool_L3Complete_by_imsi_round_robin() );
11042 execute( TC_mscpool_LU_by_tmsi_null_nri_0_round_robin() );
11043 execute( TC_mscpool_LU_by_tmsi_null_nri_1_round_robin() );
11044 execute( TC_mscpool_L3Complete_by_tmsi_unassigned_nri_round_robin() );
11045 execute( TC_mscpool_L3Complete_by_tmsi_valid_nri_msc_not_connected_round_robin() );
11046 execute( TC_mscpool_L3Complete_by_tmsi_valid_nri_1() );
11047 execute( TC_mscpool_L3Complete_by_tmsi_valid_nri_2() );
11048 execute( TC_mscpool_LU_by_tmsi_from_other_PLMN() );
11049 execute( TC_mscpool_paging_and_response_imsi() );
11050 execute( TC_mscpool_paging_and_response_tmsi() );
11051 execute( TC_mscpool_no_allow_attach_round_robin() );
11052 execute( TC_mscpool_no_allow_attach_valid_nri() );
11053 }
11054
Harald Welte99f3ca02018-06-14 13:40:29 +020011055 execute( TC_early_conn_fail() );
11056 execute( TC_late_conn_fail() );
Oliver Smithaf03bef2021-08-24 15:34:51 +020011057 execute( TC_stats_conn_fail() );
Harald Welte99f3ca02018-06-14 13:40:29 +020011058
Philipp Maier783681c2020-07-16 16:47:06 +020011059 /* Emergency call handling (deny / allow) */
11060 execute( TC_assignment_emerg_setup_allow() );
11061 execute( TC_assignment_emerg_setup_deny_msc() );
11062 execute( TC_assignment_emerg_setup_deny_bts() );
Philipp Maier82812002020-08-13 18:48:27 +020011063 execute( TC_emerg_premption() );
11064
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +070011065 /* Frequency hopping parameters handling */
11066 execute( TC_fh_params_chan_activ() );
11067 execute( TC_fh_params_imm_ass() );
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +070011068 execute( TC_fh_params_assignment_cmd() );
Vadim Yanitskiy8f5430d2020-09-02 18:51:38 +070011069 execute( TC_fh_params_handover_cmd() );
Vadim Yanitskiyca974032020-09-01 07:20:39 +070011070 execute( TC_fh_params_si4_cbch() );
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020011071
11072 if (mp_enable_lcs_tests) {
11073 execute( TC_lcs_loc_req_for_active_ms() );
11074 execute( TC_lcs_loc_req_for_active_ms_ta_req() );
11075 execute( TC_lcs_loc_req_for_idle_ms() );
11076 execute( TC_lcs_loc_req_no_subscriber() );
11077 execute( TC_lcs_loc_req_for_active_ms_le_timeout() );
11078 execute( TC_lcs_loc_req_for_active_ms_le_timeout2() );
11079 execute( TC_lcs_loc_req_for_idle_ms_no_pag_resp() );
11080 execute( TC_cm_service_during_lcs_loc_req() );
11081 execute( TC_ho_during_lcs_loc_req() );
11082 }
Neels Hofmeyrbf037052020-10-28 22:52:02 +000011083
11084 execute( TC_no_msc() );
Neels Hofmeyr87857ec2021-04-25 16:17:47 +000011085
11086 execute( TC_refuse_chan_act_to_vamos() );
11087 execute( TC_refuse_mode_modif_to_vamos() );
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000011088
11089 execute( TC_reassignment_fr() );
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020011090
11091 execute( TC_cm_reestablishment() );
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011092
11093 execute( TC_imm_ass_post_chan_ack() );
11094 execute( TC_imm_ass_pre_chan_ack() );
Neels Hofmeyr23158742021-09-07 19:08:07 +020011095 execute( TC_imm_ass_pre_ts_ack() );
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011096 execute( TC_imm_ass_pre_chan_ack_dyn_ts() );
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011097 execute( TC_imm_ass_pre_ts_ack_dyn_ts() );
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020011098
11099 execute( TC_ctrl_trx_rf_locked() );
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020011100
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011101 execute( TC_ratectr_all_available_allocated() );
11102 execute( TC_ratectr_all_available_allocated_dyn() );
11103
Neels Hofmeyrb7581872021-11-07 14:02:49 +010011104 execute( TC_cm_serv_rej() );
11105
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020011106 execute( TC_lost_sdcch_during_assignment() );
Neels Hofmeyrafe2ea52021-11-24 15:16:12 +010011107
11108 /* Run TC_ho_out_of_this_bsc last, because it may trigger a segfault before osmo-bsc's patch
11109 * with change-id I5a3345ab0005a73597f5c27207480912a2f5aae6 */
11110 execute( TC_ho_out_of_this_bsc() );
Harald Welte28d943e2017-11-25 15:00:50 +010011111}
11112
11113}