blob: c485ec50682f3e1da064ddbff4a1f59e40d9b20f [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];
Vadim Yanitskiy96bb9cb2021-12-10 21:14:15 +0300723 pars.imsi := f_rnd_imsi('00101'H);
724
725 log(testcasename(), ": using IMSI ", pars.imsi);
Neels Hofmeyrb5b7a6e2021-06-04 19:03:45 +0200726
Philipp Maier48604732018-10-09 15:00:37 +0200727 return pars;
728}
729
Neels Hofmeyr22c3f792020-06-17 02:49:28 +0200730/* Convenience functions for rate counters using g_ctr_msc. */
731
732private function f_ctrs_msc_init(integer mscs_count := NUM_MSC, CounterNameVals counternames := counternames_msc_mscpool) runs on test_CT {
733 g_ctr_msc := f_counter_name_vals_get_n(IPA_CTRL, "msc", mscs_count, counternames);
734 log("initial msc rate counters: ", g_ctr_msc);
735}
736
737private function f_ctrs_msc_add(integer msc_nr, charstring countername, integer val := 1) runs on test_CT {
Neels Hofmeyr9656e922020-06-30 01:27:01 +0200738 f_counter_name_vals_list_add(g_ctr_msc, msc_nr, countername, val);
Neels Hofmeyr22c3f792020-06-17 02:49:28 +0200739}
740
741/* f_ctrs_msc_init();
742 * f_do_thing(on_msc := 0);
743 * f_do_thing(on_msc := 0);
744 * f_do_other(on_msc := 1);
745 * f_ctrs_msc_add(0, "thing", 2);
746 * f_ctrs_msc_add(1, "other");
747 * f_ctrs_msc_verify();
748 */
749private function f_ctrs_msc_verify() runs on test_CT {
750 log("verifying msc rate counters: ", g_ctr_msc);
751 f_counter_name_vals_expect_n(IPA_CTRL, "msc", g_ctr_msc);
752}
753
754/* convenience: f_ctrs_msc_add() and f_ctrs_msc_verify() in one call.
755 * f_ctrs_msc_init();
756 * f_do_thing(on_msc := 0);
757 * f_do_thing(on_msc := 0);
758 * f_do_thing(on_msc := 0);
759 * f_ctrs_msc_expect(0, "thing", 3);
760 */
761private function f_ctrs_msc_expect(integer msc_nr, charstring countername, integer val := 1) runs on test_CT {
762 f_ctrs_msc_add(msc_nr, countername, val);
763 f_ctrs_msc_verify();
764}
765
Neels Hofmeyr12941bd2020-08-29 03:21:26 +0000766/* Convenience functions for rate counters using g_ctr_bts, always also including g_ctr_bsc. */
767
Neels Hofmeyrb7581872021-11-07 14:02:49 +0100768private 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 +0000769 g_ctr_bts := f_counter_name_vals_get_n(IPA_CTRL, "bts", bts_count, counternames);
Neels Hofmeyr4dec8cc2021-11-29 15:59:44 +0100770 log("initial bts rate counters: ", g_ctr_bts);
Neels Hofmeyrb7581872021-11-07 14:02:49 +0100771}
772
773function f_ctrs_bsc_and_bts_init(integer bts_count := NUM_BTS, CounterNameVals counternames := counternames_bsc_bts_handover) runs on test_CT {
774 f_ctrs_bts_init(bts_count, counternames);
Neels Hofmeyr12941bd2020-08-29 03:21:26 +0000775 f_ctrs_bsc_init(counternames);
776}
777
Neels Hofmeyrac432fa2021-11-02 16:45:56 +0100778private function f_ctrs_bsc_and_bts_handover_init(integer bts_count := NUM_BTS) runs on test_CT {
779 var CounterNameVals bts_names := counternames_bsc_bts_handover & counternames_bts_handover;
Neels Hofmeyr4dec8cc2021-11-29 15:59:44 +0100780 f_ctrs_bts_init(bts_count, bts_names);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +0100781 f_ctrs_bsc_init(counternames_bsc_bts_handover);
782}
783
784private function f_ctrs_bts_add(integer bts_nr, charstring countername, integer val := 1) runs on test_CT {
Neels Hofmeyr12941bd2020-08-29 03:21:26 +0000785 f_counter_name_vals_list_add(g_ctr_bts, bts_nr, countername, val);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +0100786}
787
788private function f_ctrs_bsc_and_bts_add(integer bts_nr, charstring countername, integer val := 1) runs on test_CT {
789 f_ctrs_bts_add(bts_nr, countername, val);
Neels Hofmeyr12941bd2020-08-29 03:21:26 +0000790 f_ctrs_bsc_add(countername, val);
791}
792
Neels Hofmeyrb7581872021-11-07 14:02:49 +0100793function f_ctrs_bts_verify() runs on test_CT {
794 f_counter_name_vals_expect_n(IPA_CTRL, "bts", g_ctr_bts);
795}
796
Neels Hofmeyr12941bd2020-08-29 03:21:26 +0000797/* f_ctrs_bsc_and_bts_init();
798 * f_do_thing(on_bts := 0);
799 * f_do_thing(on_bts := 0);
800 * f_do_other(on_bts := 1);
801 * f_ctrs_bsc_and_bts_add(0, "thing", 2);
802 * f_ctrs_bsc_and_bts_add(1, "other");
803 * f_ctrs_bsc_and_bts_verify();
804 */
805private function f_ctrs_bsc_and_bts_verify() runs on test_CT {
Neels Hofmeyrb7581872021-11-07 14:02:49 +0100806 f_ctrs_bts_verify();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +0000807 f_ctrs_bsc_verify();
808}
809
810/* convenience: f_ctrs_bsc_and_bts_add() and f_ctrs_bsc_and_bts_verify() in one call.
811 * f_ctrs_bsc_and_bts_init();
812 * f_do_thing(on_bts := 0);
813 * f_do_thing(on_bts := 0);
814 * f_do_thing(on_bts := 0);
815 * f_ctrs_bsc_and_bts_expect(0, "thing", 3);
816 */
817private function f_ctrs_bsc_and_bts_expect(integer bts_nr, charstring countername, integer val := 1) runs on test_CT {
818 f_ctrs_bsc_and_bts_add(bts_nr, countername, val);
819 f_ctrs_bsc_and_bts_verify();
820}
821
822
823/* Convenience functions for rate counters using g_ctr_bsc. */
824
825private function f_ctrs_bsc_init(CounterNameVals counternames := counternames_bsc_bts_handover) runs on test_CT {
826 g_ctr_bsc := f_counter_name_vals_get_n(IPA_CTRL, "bsc", 1, counternames);
827 log("initial bsc rate counters: ", g_ctr_bsc);
828}
829
830private function f_ctrs_bsc_add(charstring countername, integer val := 1) runs on test_CT {
831 f_counter_name_vals_list_add(g_ctr_bsc, 0, countername, val);
832}
833
834/* f_ctrs_bsc_init();
835 * f_do_thing();
836 * f_do_thing();
837 * f_do_other();
838 * f_ctrs_bsc_add("thing", 2);
839 * f_ctrs_bsc_add("other");
840 * f_ctrs_bsc_verify();
841 */
842private function f_ctrs_bsc_verify() runs on test_CT {
843 f_counter_name_vals_expect_n(IPA_CTRL, "bsc", g_ctr_bsc);
844}
845
846/* convenience: f_ctrs_bsc_add() and f_ctrs_bsc_verify() in one call.
847 * f_ctrs_bsc_init();
848 * f_do_thing();
849 * f_ctrs_bsc_expect("thing", 1);
850 */
851private function f_ctrs_bsc_expect(charstring countername, integer val := 1) runs on test_CT {
852 f_ctrs_bsc_add(countername, val);
853 f_ctrs_bsc_verify();
854}
855
Neels Hofmeyr22c3f792020-06-17 02:49:28 +0200856
Neels Hofmeyr9f3e6ac2021-04-08 23:09:24 +0200857friend function f_shutdown_helper() runs on test_CT {
Daniel Willmann637ef6c2018-07-25 10:49:09 +0200858 all component.stop;
Philipp Maier282ca4b2018-02-27 17:17:00 +0100859 setverdict(pass);
Daniel Willmannafce8662018-07-06 23:11:32 +0200860 mtc.stop;
Philipp Maier282ca4b2018-02-27 17:17:00 +0100861}
862
Neels Hofmeyrf246a922020-05-13 02:27:10 +0200863private function f_legacy_bssap_reset(integer bssap_idx := 0) runs on test_CT {
Harald Weltea4ca4462018-02-09 00:17:14 +0100864 var BSSAP_N_UNITDATA_ind ud_ind;
Pau Espin Pedrol24c05992020-09-01 12:54:12 +0200865 var boolean reset_received := false;
Harald Weltea4ca4462018-02-09 00:17:14 +0100866 timer T := 5.0;
Neels Hofmeyrf246a922020-05-13 02:27:10 +0200867 BSSAP.send(ts_BSSAP_UNITDATA_req(g_bssap[bssap_idx].sccp_addr_peer, g_bssap[bssap_idx].sccp_addr_own,
868 ts_BSSMAP_Reset(0, g_osmux_enabled)));
Harald Weltea4ca4462018-02-09 00:17:14 +0100869 T.start;
870 alt {
Neels Hofmeyrf246a922020-05-13 02:27:10 +0200871 [] BSSAP.receive(tr_BSSAP_UNITDATA_ind(g_bssap[bssap_idx].sccp_addr_own, g_bssap[bssap_idx].sccp_addr_peer,
872 tr_BSSMAP_ResetAck(g_osmux_enabled))) {
Neels Hofmeyr4f5d7be2020-10-16 16:28:16 +0200873 log("BSSMAP: Received RESET-ACK in response to RESET, we're ready to go!");
Harald Weltea4ca4462018-02-09 00:17:14 +0100874 }
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +0200875 [] BSSAP.receive(tr_BSSAP_UNITDATA_ind(?, ?, tr_BSSMAP_Reset(g_osmux_enabled))) -> value ud_ind {
Neels Hofmeyr4f5d7be2020-10-16 16:28:16 +0200876 log("BSSMAP: Respoding to inbound RESET with RESET-ACK");
Harald Weltea4ca4462018-02-09 00:17:14 +0100877 BSSAP.send(ts_BSSAP_UNITDATA_req(ud_ind.callingAddress, ud_ind.calledAddress,
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +0200878 ts_BSSMAP_ResetAck(g_osmux_enabled)));
Pau Espin Pedrol24c05992020-09-01 12:54:12 +0200879 reset_received := true;
Harald Weltea4ca4462018-02-09 00:17:14 +0100880 repeat;
881 }
882 [] BSSAP.receive { repeat; }
Pau Espin Pedrol24c05992020-09-01 12:54:12 +0200883 [] T.timeout {
Neels Hofmeyr4f5d7be2020-10-16 16:28:16 +0200884 log("BSSMAP: Timeout waiting for RESET-ACK after sending RESET");
Pau Espin Pedrol24c05992020-09-01 12:54:12 +0200885 /* If we received a RESET after ours was sent, it
886 may be a race condition where the other peer beacame
887 available after we sent it, but we are in a desired
888 state anyway, so go forward. */
889 if (not reset_received) {
890 setverdict(fail);
891 }
892 }
Harald Weltea4ca4462018-02-09 00:17:14 +0100893 }
Harald Welte28d943e2017-11-25 15:00:50 +0100894}
895
Harald Welteae026692017-12-09 01:03:01 +0100896type record IPA_Client {
Harald Welte21b46bd2017-12-17 19:46:32 +0100897 /* IPA Emulation component reference */
Harald Welteae026692017-12-09 01:03:01 +0100898 IPA_Emulation_CT vc_IPA,
Harald Welte21b46bd2017-12-17 19:46:32 +0100899 /* Unit-ID and other CCM parameters to use for IPA client emulation */
Harald Welteae026692017-12-09 01:03:01 +0100900 IPA_CCM_Parameters ccm_pars,
Harald Welte21b46bd2017-12-17 19:46:32 +0100901 /* String identifier for this IPA Client */
Harald Welte624f9632017-12-16 19:26:04 +0100902 charstring id,
Harald Welte21b46bd2017-12-17 19:46:32 +0100903 /* Associated RSL Emulation Component (if any). Only used in "Handler mode" */
Harald Welte624f9632017-12-16 19:26:04 +0100904 RSL_Emulation_CT vc_RSL optional
Harald Welte28d943e2017-11-25 15:00:50 +0100905}
906
Harald Welte21b46bd2017-12-17 19:46:32 +0100907/*! Start the IPA/RSL related bits for one IPA_Client.
908 * \param clnt IPA_Client for which to establish
909 * \param bsc_host IP address / hostname of the BSC
910 * \param bsc_port TCP port number of the BSC
911 * \param i number identifying this BTS
912 * \param handler_mode Start an RSL_Emulation_CT component (true) or not (false) */
Harald Welte624f9632017-12-16 19:26:04 +0100913function f_ipa_rsl_start(inout IPA_Client clnt, charstring bsc_host, PortNumber bsc_port, integer i,
914 boolean handler_mode := false)
Harald Welte28d943e2017-11-25 15:00:50 +0100915runs on test_CT {
Harald Welteae026692017-12-09 01:03:01 +0100916 timer T := 10.0;
917
Harald Welte96c94412017-12-09 03:12:45 +0100918 clnt.id := "IPA" & int2str(i) & "-RSL";
Harald Welte71389132021-12-09 21:58:18 +0100919 clnt.vc_IPA := IPA_Emulation_CT.create(clnt.id & "-IPA") alive;
Harald Welteae026692017-12-09 01:03:01 +0100920 clnt.ccm_pars := c_IPA_default_ccm_pars;
921 clnt.ccm_pars.name := "Osmocom TTCN-3 BTS Simulator";
922 clnt.ccm_pars.unit_id := int2str(1234+i) & "/0/0";
Harald Welte624f9632017-12-16 19:26:04 +0100923 if (handler_mode) {
Harald Welte71389132021-12-09 21:58:18 +0100924 clnt.vc_RSL := RSL_Emulation_CT.create(clnt.id & "-RSL") alive;
Harald Welte89ab1912018-02-23 18:56:29 +0100925 connect(clnt.vc_RSL:CCHAN_PT, self:RSL_CCHAN[i]);
Harald Welte624f9632017-12-16 19:26:04 +0100926 }
Harald Welteae026692017-12-09 01:03:01 +0100927
928 map(clnt.vc_IPA:IPA_PORT, system:IPA_CODEC_PT);
Harald Welte624f9632017-12-16 19:26:04 +0100929 if (handler_mode) {
930 connect(clnt.vc_IPA:IPA_RSL_PORT, clnt.vc_RSL:IPA_PT);
931 } else {
932 connect(clnt.vc_IPA:IPA_RSL_PORT, self:IPA_RSL[i]);
933 }
Harald Welteae026692017-12-09 01:03:01 +0100934
Harald Welte5d1a2202017-12-13 19:51:29 +0100935 clnt.vc_IPA.start(IPA_Emulation.main_client(bsc_host, bsc_port, "", 10000+i, clnt.ccm_pars));
Harald Welte624f9632017-12-16 19:26:04 +0100936 if (handler_mode) {
937 clnt.vc_RSL.start(RSL_Emulation.main());
938 return;
939 }
Harald Welteae026692017-12-09 01:03:01 +0100940
941 /* wait for IPA RSL link to connect and send ID ACK */
942 T.start;
943 alt {
Vadim Yanitskiya2afacc2020-05-18 21:16:19 +0700944 [] IPA_RSL[i].receive(tr_ASP_IPA_EV(ASP_IPA_EVENT_ID_ACK)) {
Harald Welteae026692017-12-09 01:03:01 +0100945 T.stop;
Vadim Yanitskiy9b4e3562020-05-25 21:40:52 +0700946 IPA_RSL[i].send(ts_ASP_RSL_UD(ts_RSL_PAGING_LOAD_IND(23)));
Harald Welteae026692017-12-09 01:03:01 +0100947 }
Harald Welte60e823a2017-12-10 14:10:59 +0100948 [] IPA_RSL[i].receive(ASP_IPA_Event:?) { repeat }
Harald Welteae026692017-12-09 01:03:01 +0100949 [] IPA_RSL[i].receive { repeat }
950 [] T.timeout {
Harald Welte96c94412017-12-09 03:12:45 +0100951 setverdict(fail, "Timeout RSL waiting for ASP_IPA_EVENT_ID_ACK");
Daniel Willmannafce8662018-07-06 23:11:32 +0200952 mtc.stop;
Harald Welteae026692017-12-09 01:03:01 +0100953 }
954 }
955}
956
Harald Welte12055472018-03-17 20:10:08 +0100957function f_ipa_rsl_stop(inout IPA_Client clnt) runs on test_CT {
958 if (not isbound(clnt) or not isbound(clnt.vc_IPA)) {
959 return;
960 }
961 clnt.vc_IPA.stop;
962 if (isbound(clnt.vc_RSL)) {
963 clnt.vc_RSL.stop;
964 }
965}
966
Harald Welte21b46bd2017-12-17 19:46:32 +0100967/* Wait for the OML connection to be brought up by the external osmo-bts-omldummy */
Harald Weltea5d2ab22017-12-09 14:21:42 +0100968function f_wait_oml(integer bts_nr, charstring status, float secs_max) runs on test_CT {
969 timer T := secs_max;
970 T.start;
971 while (true) {
972 if (f_ctrl_get_bts(IPA_CTRL, bts_nr, "oml-connection-state") == status) {
973 T.stop;
Harald Weltebd868bd2017-12-10 18:28:40 +0100974 /* the 'degraded' state exists from OML connection time, and we have to wait
975 * until all MO's are initialized */
976 T.start(1.0);
977 T.timeout;
Harald Weltea5d2ab22017-12-09 14:21:42 +0100978 return;
979 }
Harald Weltef0d6ac62017-12-17 17:02:21 +0100980 f_sleep(0.1);
Harald Weltea5d2ab22017-12-09 14:21:42 +0100981 if (not T.running) {
Max99253902018-11-16 17:57:39 +0100982 setverdict(fail, "Timeout waiting for BTS" & int2str(bts_nr) & " oml-connection-state ", status);
Daniel Willmannafce8662018-07-06 23:11:32 +0200983 mtc.stop;
Harald Weltea5d2ab22017-12-09 14:21:42 +0100984 }
985 }
986}
987
Harald Welte21b46bd2017-12-17 19:46:32 +0100988/* global altstep for global guard timer; also takes care of responding RESET witH RESET-ACK */
Harald Welteae026692017-12-09 01:03:01 +0100989altstep as_Tguard() runs on test_CT {
Harald Welte60e823a2017-12-10 14:10:59 +0100990 var BSSAP_N_UNITDATA_ind ud_ind;
Neels Hofmeyrcc3f76a2018-03-12 01:43:25 +0100991 [] T_guard.timeout {
992 setverdict(fail, "Timeout of T_guard");
Daniel Willmannafce8662018-07-06 23:11:32 +0200993 mtc.stop;
Neels Hofmeyrcc3f76a2018-03-12 01:43:25 +0100994 }
Harald Welte60e823a2017-12-10 14:10:59 +0100995 /* always respond with RESET ACK to RESET */
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +0200996 [] BSSAP.receive(tr_BSSAP_UNITDATA_ind(?, ?, tr_BSSMAP_Reset(g_osmux_enabled))) -> value ud_ind {
Harald Welte60e823a2017-12-10 14:10:59 +0100997 BSSAP.send(ts_BSSAP_UNITDATA_req(ud_ind.callingAddress, ud_ind.calledAddress,
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +0200998 ts_BSSMAP_ResetAck(g_osmux_enabled)));
Harald Welte69c1c262017-12-13 21:02:08 +0100999 repeat;
Harald Welte60e823a2017-12-10 14:10:59 +01001000 }
Harald Welte28d943e2017-11-25 15:00:50 +01001001}
1002
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +01001003altstep no_bssmap_reset() runs on test_CT {
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02001004 [] BSSAP.receive(tr_BSSAP_UNITDATA_ind(?, ?, tr_BSSMAP_Reset(g_osmux_enabled))) {
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +01001005 setverdict(fail, "unexpected BSSMAP Reset");
Daniel Willmannafce8662018-07-06 23:11:32 +02001006 mtc.stop;
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +01001007 }
1008}
1009
Daniel Willmann191e0d92018-01-17 12:44:35 +01001010function f_init_mgcp(charstring id) runs on test_CT {
1011 id := id & "-MGCP";
1012
1013 var MGCPOps ops := {
1014 create_cb := refers(MGCP_Emulation.ExpectedCreateCallback),
1015 unitdata_cb := refers(MGCP_Emulation.DummyUnitdataCallback)
1016 };
1017 var MGCP_conn_parameters mgcp_pars := {
1018 callagent_ip := mp_bsc_ip,
Harald Welte9e4273e2018-01-29 22:01:22 +01001019 callagent_udp_port := -1,
Daniel Willmann191e0d92018-01-17 12:44:35 +01001020 mgw_ip := mp_test_ip,
Pau Espin Pedrol1a026a52019-06-18 17:21:52 +02001021 mgw_udp_port := 2427,
Pau Espin Pedrolfd02ad42019-06-18 17:45:20 +02001022 /* Enable it for SCCPlite, since we have 2 MGCP sockets towards MGW (UDP one +
1023 the on with MGCP over IPA forwarded from MSC one) */
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001024 multi_conn_mode := (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_SCCPlite_SERVER)
Daniel Willmann191e0d92018-01-17 12:44:35 +01001025 };
1026
Harald Welte71389132021-12-09 21:58:18 +01001027 vc_MGCP := MGCP_Emulation_CT.create(id) alive;
Daniel Willmann191e0d92018-01-17 12:44:35 +01001028 vc_MGCP.start(MGCP_Emulation.main(ops, mgcp_pars, id));
1029}
1030
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02001031/* Enable or disable (current default) Osmux. When enabling, BSSMAP Reset
1032 * contains extra IE (OsmuxSupport) and osmo-bsc will handle AssignReq with
1033 * OsmuxCID IE.
1034 */
1035private function f_vty_allow_osmux(boolean allow) runs on test_CT {
1036 f_vty_enter_cfg_msc(BSCVTY, 0);
1037 if (allow) {
1038 f_vty_transceive(BSCVTY, "osmux on");
1039 } else {
1040 f_vty_transceive(BSCVTY, "osmux off");
1041 }
1042 f_vty_transceive(BSCVTY, "exit");
1043 f_vty_transceive(BSCVTY, "exit");
1044 g_osmux_enabled := allow;
1045}
1046
Max2253c0b2018-11-06 19:28:05 +01001047function f_init_vty(charstring id := "foo") runs on test_CT {
Harald Welte94e0c342018-04-07 11:33:23 +02001048 if (BSCVTY.checkstate("Mapped")) {
1049 /* skip initialization if already executed once */
1050 return;
1051 }
Harald Weltebc03c762018-02-12 18:09:38 +01001052 map(self:BSCVTY, system:BSCVTY);
1053 f_vty_set_prompts(BSCVTY);
1054 f_vty_transceive(BSCVTY, "enable");
Pau Espin Pedrolc675b612020-01-09 19:55:40 +01001055 f_cs7_inst_0_cfg(BSCVTY, {"sccp-timer ias " & int2str(g_bsc_sccp_timer_ias),
1056 "sccp-timer iar " & int2str(g_bsc_sccp_timer_iar)});
Harald Weltebc03c762018-02-12 18:09:38 +01001057}
1058
Neels Hofmeyr9f3e6ac2021-04-08 23:09:24 +02001059friend function f_logp(TELNETasp_PT pt, charstring log_msg)
Neels Hofmeyr4f118412020-06-04 15:25:10 +02001060{
1061 // log on TTCN3 log output
1062 log(log_msg);
1063 // log in stderr log
Neels Hofmeyr767548a2020-08-09 20:26:07 +00001064 f_vty_transceive(pt, "logp lglobal notice TTCN3 f_logp(): " & log_msg);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02001065}
1066
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +02001067private function f_sysinfo_seen(integer rsl_idx, RSL_Message rsl) runs on test_CT
1068{
1069 if (rsl_idx >= lengthof(g_system_information)) {
1070 g_system_information[rsl_idx] := SystemInformationConfig_omit
1071 }
1072 f_sysinfo_dec_raw(g_system_information[rsl_idx], rsl);
1073}
1074
1075altstep as_catch_RSL_sysinfo(integer rsl_idx) runs on test_CT {
1076 var ASP_RSL_Unitdata rx_rsl_ud;
1077
1078 /* For handler_mode := false, receiving the RSL bootstrap messages directly on IPA_RSL */
1079 [] IPA_RSL[rsl_idx].receive(tr_ASP_RSL_UD(tr_RSL_NO_BCCH_INFO)) -> value rx_rsl_ud {
1080 f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
1081 repeat;
1082 }
1083 [] IPA_RSL[rsl_idx].receive(tr_ASP_RSL_UD(tr_RSL_BCCH_INFO)) -> value rx_rsl_ud {
1084 f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
1085 repeat;
1086 }
1087 [] IPA_RSL[rsl_idx].receive(tr_ASP_RSL_UD(tr_RSL_NO_SACCH_FILL)) -> value rx_rsl_ud {
1088 f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
1089 repeat;
1090 }
1091 [] IPA_RSL[rsl_idx].receive(tr_ASP_RSL_UD(tr_RSL_SACCH_FILL)) -> value rx_rsl_ud {
1092 f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
1093 repeat;
1094 }
1095
1096 /* For handler_mode := true, receiving the RSL bootstrap messages via RSL_Emulation */
1097 [] RSL_CCHAN[rsl_idx].receive(tr_ASP_RSL_UD(tr_RSL_NO_BCCH_INFO)) -> value rx_rsl_ud {
1098 f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
1099 repeat;
1100 }
1101 [] RSL_CCHAN[rsl_idx].receive(tr_ASP_RSL_UD(tr_RSL_BCCH_INFO)) -> value rx_rsl_ud {
1102 f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
1103 repeat;
1104 }
1105 [] RSL_CCHAN[rsl_idx].receive(tr_ASP_RSL_UD(tr_RSL_NO_SACCH_FILL)) -> value rx_rsl_ud {
1106 f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
1107 repeat;
1108 }
1109 [] RSL_CCHAN[rsl_idx].receive(tr_ASP_RSL_UD(tr_RSL_SACCH_FILL)) -> value rx_rsl_ud {
1110 f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
1111 repeat;
1112 }
1113}
1114
Neels Hofmeyra460f1f2020-08-09 20:17:03 +00001115/* TODO: use BooleanList from COMMON/src/General_Types.ttcn */
1116private type record of boolean my_BooleanList;
1117
1118private function f_vty_msc_allow_attach(TELNETasp_PT pt, my_BooleanList allow_attach_list)
1119{
Neels Hofmeyr8f576712020-08-12 22:49:53 +00001120 var charstring config := f_vty_transceive_ret(pt, "show running-config");
1121
Neels Hofmeyra460f1f2020-08-09 20:17:03 +00001122 for (var integer msc_nr := 0; msc_nr < sizeof(allow_attach_list); msc_nr := msc_nr+1) {
Neels Hofmeyr8f576712020-08-12 22:49:53 +00001123 if (f_strstr(config, "\nmsc " & int2str(msc_nr) & "\n") < 0) {
1124 /* There is no 'msc N' for this msc_nr in the running config, so don't create an empty msc by
1125 * stepping into that config node. */
1126 log("msc ", msc_nr, " is not configured, skipping");
1127 continue;
1128 }
Neels Hofmeyra460f1f2020-08-09 20:17:03 +00001129 f_vty_enter_cfg_msc(pt, msc_nr);
1130 if (allow_attach_list[msc_nr]) {
1131 /* strict := false: ignore if osmo-bsc does not support this config option (latest build) */
1132 f_vty_transceive(pt, "allow-attach", strict := false);
1133 } else {
1134 f_vty_transceive(pt, "no allow-attach", strict := false);
1135 }
1136 f_vty_transceive(pt, "exit");
1137 f_vty_transceive(pt, "exit");
1138 }
1139}
1140
Harald Welte21b46bd2017-12-17 19:46:32 +01001141/* global initialization function
1142 * \param nr_bts Number of BTSs we should start/bring up
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001143 * \param handler_mode Start an RSL_Emulation_CT component (true) or not (false).
1144 * \param nr_msc Number of virtual MSCs to bring up to connect to osmo-bsc.
1145 */
1146function f_init(integer nr_bts := NUM_BTS, boolean handler_mode := false, boolean allow_osmux := false,
Neels Hofmeyr4fbad7f2020-06-16 00:30:47 +02001147 integer nr_msc := 1, float guard_timeout := 30.0) runs on test_CT {
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001148 var integer bssap_idx;
Harald Welte28d943e2017-11-25 15:00:50 +01001149
Harald Welteae026692017-12-09 01:03:01 +01001150 if (g_initialized) {
1151 return;
Harald Welte28d943e2017-11-25 15:00:50 +01001152 }
Harald Welteae026692017-12-09 01:03:01 +01001153 g_initialized := true;
1154
Neels Hofmeyr4fbad7f2020-06-16 00:30:47 +02001155 T_guard.start(guard_timeout);
Daniel Willmanne68f9272018-11-27 15:15:28 +01001156 activate(as_Tguard());
1157
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02001158 f_init_vty("VirtMSC");
Pau Espin Pedrol23510fb2021-07-20 17:00:38 +02001159 f_vty_allow_osmux(allow_osmux);
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02001160
Neels Hofmeyra460f1f2020-08-09 20:17:03 +00001161 var my_BooleanList allow_attach := { false, false, false };
Daniel Willmannebdecc02020-08-12 15:30:17 +02001162 f_init_statsd("VirtMSC", vc_STATSD, mp_test_ip, mp_bsc_statsd_port);
1163
Neels Hofmeyr9db8e0e2021-08-23 20:45:58 +02001164 /* Make sure each MSC's internal state is "DISCONNECTED" at first */
1165 for (bssap_idx := 0; bssap_idx < NUM_MSC; bssap_idx := bssap_idx+1) {
1166 f_vty_transceive(BSCVTY, "msc " & int2str(bssap_idx) & " bssmap reset", strict := false);
1167 }
1168
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001169 for (bssap_idx := 0; bssap_idx < nr_msc; bssap_idx := bssap_idx+1) {
Neels Hofmeyra460f1f2020-08-09 20:17:03 +00001170 allow_attach[bssap_idx] := true;
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001171 /* Call a function of our 'parent component' RAN_Adapter_CT to start the
1172 * MSC-side BSSAP emulation */
1173 if (handler_mode) {
1174 var RanOps ranops := MSC_RanOps;
1175 ranops.use_osmux := g_osmux_enabled;
1176 f_ran_adapter_init(g_bssap[bssap_idx], mp_bssap_cfg[bssap_idx], "VirtMSC", ranops);
1177 connect(self:SCCPLITE_IPA_CTRL, g_bssap[bssap_idx].vc_RAN:CTRL_CLIENT);
1178 f_ran_adapter_start(g_bssap[bssap_idx]);
1179 } else {
1180 f_ran_adapter_init(g_bssap[bssap_idx], mp_bssap_cfg[bssap_idx], "VirtMSC", omit);
1181 connect(self:BSSAP, g_bssap[bssap_idx].vc_SCCP:SCCP_SP_PORT);
1182 f_ran_adapter_start(g_bssap[bssap_idx]);
1183 f_legacy_bssap_reset();
1184 }
Harald Welte67089ee2018-01-17 22:19:03 +01001185 }
Harald Welted5833a82018-05-27 16:52:56 +02001186
Neels Hofmeyrcfe44062020-10-15 02:28:08 +02001187 if (mp_enable_lcs_tests) {
1188 if (handler_mode) {
1189 f_bssap_le_adapter_init(g_bssap_le, mp_bssap_le_cfg, "VirtSMLC", SMLC_BssapLeOps);
1190 } else {
1191 f_bssap_le_adapter_init(g_bssap_le, mp_bssap_le_cfg, "VirtSMLC", omit);
1192 connect(self:BSSAP_LE, g_bssap_le.vc_SCCP:SCCP_SP_PORT);
1193 }
1194 f_bssap_le_adapter_start(g_bssap_le);
Harald Welte47cd0e32020-08-21 12:39:11 +02001195 }
Harald Welte47cd0e32020-08-21 12:39:11 +02001196
Neels Hofmeyra460f1f2020-08-09 20:17:03 +00001197 /* start the test with exactly all enabled MSCs allowed to attach */
1198 f_vty_msc_allow_attach(BSCVTY, allow_attach);
1199
Pau Espin Pedrol9a5b8ff2021-01-04 19:01:31 +01001200 f_ipa_ctrl_start_client(mp_bsc_ip, mp_bsc_ctrl_port);
Harald Welte28d943e2017-11-25 15:00:50 +01001201
Daniel Willmann191e0d92018-01-17 12:44:35 +01001202 f_init_mgcp("VirtMSC");
1203
Neels Hofmeyr0b7365b2020-07-04 00:52:34 +02001204 for (var integer i := 0; i < nr_bts; i := i+1) {
1205 f_init_bts(i, handler_mode);
Harald Welte696ddb62017-12-08 14:01:43 +01001206 }
Neels Hofmeyr0b7365b2020-07-04 00:52:34 +02001207}
Harald Welte696ddb62017-12-08 14:01:43 +01001208
Neels Hofmeyr0b7365b2020-07-04 00:52:34 +02001209function f_init_bts(integer bts_idx := 0, boolean handler_mode := false)
1210runs on test_CT {
1211 /* wait until osmo-bts-omldummy has respawned */
1212 f_wait_oml(bts_idx, "degraded", 5.0);
1213
1214 /* start RSL connection */
1215 f_ipa_rsl_start(bts[bts_idx].rsl, mp_bsc_ip, mp_bsc_rsl_port, bts_idx, handler_mode);
1216 /* wait until BSC tells us "connected" */
1217 f_wait_oml(bts_idx, "connected", 5.0);
Harald Welte28d943e2017-11-25 15:00:50 +01001218}
1219
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +02001220function f_init_bts_and_check_sysinfo(integer bts_idx := 0, boolean handler_mode := false,
1221 template SystemInformationConfig expect_si)
1222runs on test_CT {
1223 var default sysinfo := activate(as_catch_RSL_sysinfo(bts_idx));
1224
1225 f_init_bts(bts_idx, handler_mode);
1226
1227 /* Give some time to (hopefully/most likely) collect all system informations from RSL startup.
1228 * We could stop as soon as all expected SI are received, but then we might miss SI that we don't expect and
1229 * that might be sent afterwards. So rather give a generous timeout and be quite sure to catch all SI.
1230 */
1231 f_sleep(5.0);
1232 log("RSL ", bts_idx, " SYSTEM INFORMATION: ", g_system_information[bts_idx]);
1233
1234 deactivate(sysinfo);
1235
1236 if (match(g_system_information[bts_idx], expect_si)) {
1237 setverdict(pass);
1238 } else {
1239 log("RSL ", bts_idx, ": EXPECTED SI: ", expect_si);
1240 log("RSL ", bts_idx, ": GOT SI: ", g_system_information[bts_idx]);
1241 setverdict(fail, "received SI does not match expectations");
1242 return;
1243 }
1244}
1245
Maxd4e56962018-10-31 19:08:25 +01001246/* expect to receive a RSL message matching a specified template on a given BTS / stream */
Harald Welte65e419a2020-08-21 12:38:33 +02001247function 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 +01001248runs on test_CT return RSL_Message {
1249 var ASP_RSL_Unitdata rx_rsl_ud;
1250 timer T := t_secs;
1251
1252 T.start;
1253 alt {
Vadim Yanitskiy9b4e3562020-05-25 21:40:52 +07001254 [] IPA_RSL[bts_nr].receive(tr_ASP_RSL_UD(t_rx, sid)) -> value rx_rsl_ud {
Harald Welteae026692017-12-09 01:03:01 +01001255 T.stop;
1256 }
1257 [] IPA_RSL[bts_nr].receive { repeat; }
Harald Welteb2917702017-12-10 15:48:52 +01001258 [] T.timeout {
1259 setverdict(fail, "Timeout expecting ", t_rx);
Daniel Willmannafce8662018-07-06 23:11:32 +02001260 mtc.stop;
Harald Welteb2917702017-12-10 15:48:52 +01001261 }
Harald Welteae026692017-12-09 01:03:01 +01001262 }
1263 return rx_rsl_ud.rsl;
1264}
1265
Harald Welte21b46bd2017-12-17 19:46:32 +01001266/* helper function to transmit RSL on a given BTS/stream */
Harald Welte65e419a2020-08-21 12:38:33 +02001267function 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 +01001268runs on test_CT {
Vadim Yanitskiy9b4e3562020-05-25 21:40:52 +07001269 IPA_RSL[bts_nr].send(ts_ASP_RSL_UD(t_tx, sid));
Harald Welteae026692017-12-09 01:03:01 +01001270}
1271
1272
Harald Welte4003d112017-12-09 22:35:39 +01001273/* verify we get a CHAN_ACT after CHAN RQD */
Harald Welteae026692017-12-09 01:03:01 +01001274testcase TC_chan_act_noreply() runs on test_CT {
1275 var BSSAP_N_UNITDATA_ind ud_ind;
Harald Welte930d0a72018-03-22 22:08:40 +01001276 var RSL_Message rsl_unused;
Harald Welte28d943e2017-11-25 15:00:50 +01001277
Harald Welte89d42e82017-12-17 16:42:41 +01001278 f_init(1);
Harald Welte28d943e2017-11-25 15:00:50 +01001279
Vadim Yanitskiy9b4e3562020-05-25 21:40:52 +07001280 IPA_RSL[0].send(ts_ASP_RSL_UD(ts_RSL_CHAN_RQD('23'O, 23)));
Harald Welte930d0a72018-03-22 22:08:40 +01001281 rsl_unused := f_exp_ipa_rx(0, tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001282 f_shutdown_helper();
Harald Welte28d943e2017-11-25 15:00:50 +01001283}
1284
Neels Hofmeyr734b1a32021-11-29 16:00:17 +01001285const CounterNameVals counternames_bts_chreq := {
1286 { "chreq:total", 0 },
1287 { "chreq:attempted_emerg", 0 },
1288 { "chreq:attempted_call", 0 },
1289 { "chreq:attempted_location_upd", 0 },
1290 { "chreq:attempted_pag", 0 },
1291 { "chreq:attempted_pdch", 0 },
1292 { "chreq:attempted_other", 0 },
1293 { "chreq:attempted_unknown", 0 },
1294 { "chreq:successful", 0 },
1295 { "chreq:successful_emerg", 0 },
1296 { "chreq:successful_call", 0 },
1297 { "chreq:successful_location_upd", 0 },
1298 { "chreq:successful_pag", 0 },
1299 { "chreq:successful_pdch", 0 },
1300 { "chreq:successful_other", 0 },
1301 { "chreq:successful_unknown", 0 },
1302 { "chreq:no_channel", 0 },
1303 { "chreq:max_delay_exceeded", 0 }
1304};
1305
1306/* verify the "chreq:*" counters */
1307private function f_chan_act_counter(OCT1 ra, charstring chreq_ctr_suffix) runs on test_CT
1308{
1309 var GsmFrameNumber fn := 23;
1310
1311 f_logp(BSCVTY, "f_chan_act_counter(" & chreq_ctr_suffix & ")");
1312
1313 var RSL_Message rx_rsl;
1314 f_ipa_tx(0, ts_RSL_CHAN_RQD(ra, fn));
1315 rx_rsl := f_exp_ipa_rx(0, tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
1316 var RslChannelNr chan_nr := rx_rsl.ies[0].body.chan_nr;
1317
1318 f_ctrs_bts_add(0, "chreq:total");
1319 f_ctrs_bts_add(0, "chreq:attempted_" & chreq_ctr_suffix);
1320 f_ctrs_bts_verify();
1321
1322 f_ipa_tx(0, ts_RSL_CHAN_ACT_ACK(chan_nr, fn+10));
1323 rx_rsl := f_exp_ipa_rx(0, tr_RSL_IMM_ASSIGN(0));
1324
1325 f_ctrs_bts_add(0, "chreq:successful");
1326 f_ctrs_bts_add(0, "chreq:successful_" & chreq_ctr_suffix);
1327 f_ctrs_bts_verify();
1328
1329 /* test is done, release RSL Conn Fail Ind to clean up */
1330 f_ipa_tx(0, ts_RSL_CONN_FAIL_IND(chan_nr, RSL_ERR_RADIO_LINK_FAIL));
1331 rx_rsl := f_exp_ipa_rx(0, tr_RSL_MsgTypeD(RSL_MT_RF_CHAN_REL), 10.0);
1332 f_ipa_tx(0, ts_RSL_RF_CHAN_REL_ACK(chan_nr));
1333 f_sleep(1.0);
1334}
1335
Harald Welte4003d112017-12-09 22:35:39 +01001336testcase TC_chan_act_counter() runs on test_CT {
1337 var BSSAP_N_UNITDATA_ind ud_ind;
1338 var integer chreq_total;
Harald Welte930d0a72018-03-22 22:08:40 +01001339 var RSL_Message rsl_unused;
Harald Welte4003d112017-12-09 22:35:39 +01001340
Harald Welte89d42e82017-12-17 16:42:41 +01001341 f_init(1);
Harald Welte4003d112017-12-09 22:35:39 +01001342
Neels Hofmeyr734b1a32021-11-29 16:00:17 +01001343 f_vty_allow_emerg_bts(true, 0);
1344
1345 f_ctrs_bts_init(1, counternames_bts_chreq);
1346
1347 /* emergency call: RA & 0xe0 == 0xa0 --> CHREQ_T_EMERG_CALL */
1348 f_chan_act_counter('a3'O, "emerg");
1349
1350 /* voice TCH/H: RA & 0xf0 == 0x40 --> CHREQ_T_VOICE_CALL_TCH_H */
1351 f_chan_act_counter('43'O, "call");
1352
1353 /* LU: RA & 0xf0 == 0x00 --> CHREQ_T_LOCATION_UPD */
1354 f_chan_act_counter('03'O, "location_upd");
1355
1356 /* Paging: RA & 0xf0 == 0x20 --> CHREQ_T_PAG_R_TCH_F */
1357 f_chan_act_counter('23'O, "pag");
1358 /* Paging: RA & 0xf0 == 0x30 --> CHREQ_T_PAG_R_TCH_FH */
1359 f_chan_act_counter('33'O, "pag");
1360
1361 /* LU: RA & 0xfc == 0x78 --> CHREQ_T_PDCH_TWO_PHASE */
1362 /* no PCU, so PDCH not allowed. Skip this test for now. */
1363 /* f_chan_act_counter('7b'O, "pdch"); */
1364
1365 /* LU: RA & 0xf0 == 0x10 --> CHREQ_T_SDCCH */
1366 f_chan_act_counter('13'O, "other");
Harald Welte4003d112017-12-09 22:35:39 +01001367
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001368 f_shutdown_helper();
Harald Welte4003d112017-12-09 22:35:39 +01001369}
1370
Harald Welteae026692017-12-09 01:03:01 +01001371/* CHAN RQD -> CHAN ACT -> CHAN ACT ACK -> RF CHAN REL */
Philipp Maier9c60a622020-07-09 15:08:46 +02001372private function f_TC_chan_act_ack_noest(OCT1 ra := '23'O) runs on test_CT {
Harald Welteae026692017-12-09 01:03:01 +01001373 var RSL_Message rx_rsl;
1374
Harald Welteae026692017-12-09 01:03:01 +01001375 /* Send CHAN RQD and wait for allocation; acknowledge it */
Philipp Maier9c60a622020-07-09 15:08:46 +02001376 var RslChannelNr chan_nr := f_chreq_act_ack(ra);
Harald Welteae026692017-12-09 01:03:01 +01001377
1378 /* expect BSC to disable the channel again if there's no RLL EST IND */
1379 rx_rsl := f_exp_ipa_rx(0, tr_RSL_MsgTypeD(RSL_MT_RF_CHAN_REL), T3101_MAX);
1380
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001381 f_shutdown_helper();
Harald Welteae026692017-12-09 01:03:01 +01001382}
1383
Philipp Maier9c60a622020-07-09 15:08:46 +02001384/* Normal variant */
1385testcase TC_chan_act_ack_noest() runs on test_CT {
Philipp Maieraf58db22020-08-12 17:24:40 +02001386 f_init(1);
Philipp Maier9c60a622020-07-09 15:08:46 +02001387 f_TC_chan_act_ack_noest();
1388}
1389
1390/* Emergency call variant */
1391testcase TC_chan_act_ack_noest_emerg() runs on test_CT {
1392 /* See also: 3GPP TS 04.08, Table 9.9, ra=101xxxxx */
Philipp Maieraf58db22020-08-12 17:24:40 +02001393 f_init(1);
1394 f_vty_allow_emerg_bts(true, 0);
Philipp Maier9c60a622020-07-09 15:08:46 +02001395 f_TC_chan_act_ack_noest(ra := 'A5'O);
1396}
1397
Philipp Maier606f07d2020-08-12 17:21:58 +02001398/* Emergency call variant, but emergency calls are not allowed */
1399testcase TC_chan_rqd_emerg_deny() runs on test_CT {
1400 /* See also: 3GPP TS 04.08, Table 9.9, ra=101xxxxx */
1401
1402 var RSL_Message rx_rsl;
1403 var GsmRrMessage rr;
1404
1405 f_init(1);
1406 f_vty_allow_emerg_bts(false, 0);
1407
1408 IPA_RSL[0].clear;
1409 f_ipa_tx(0, ts_RSL_CHAN_RQD('A5'O, 23));
1410
1411 rx_rsl := f_exp_ipa_rx(0, tr_RSL_MsgTypeC(RSL_MT_IMMEDIATE_ASSIGN_CMD));
1412 rr := dec_GsmRrMessage(rx_rsl.ies[1].body.full_imm_ass_info.payload);
1413 if (rr.header.message_type == IMMEDIATE_ASSIGNMENT_REJECT) {
1414 setverdict(pass);
1415 } else {
1416 setverdict(fail, "immediate assignment not rejected");
1417 }
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +01001418
1419 f_shutdown_helper();
Philipp Maier606f07d2020-08-12 17:21:58 +02001420}
1421
Harald Welteae026692017-12-09 01:03:01 +01001422/* Test behavior if MSC never answers to CR */
1423testcase TC_chan_act_ack_est_ind_noreply() runs on test_CT {
Harald Weltef77aef62018-01-28 15:35:42 +01001424 var RslLinkId main_dcch := valueof(ts_RslLinkID_DCCH(0));
1425 var IpaStreamId sid := IPAC_PROTO_RSL_TRX0;
Harald Welteae026692017-12-09 01:03:01 +01001426 var RSL_Message rx_rsl;
Harald Weltef77aef62018-01-28 15:35:42 +01001427 var ASP_RSL_Unitdata rx_rsl_ud;
Harald Welteae026692017-12-09 01:03:01 +01001428
Harald Welte89d42e82017-12-17 16:42:41 +01001429 f_init(1);
Harald Welteae026692017-12-09 01:03:01 +01001430
1431 /* Send CHAN RQD and wait for allocation; acknowledge it */
Harald Welted6939652017-12-13 21:02:46 +01001432 var RslChannelNr chan_nr := f_chreq_act_ack();
Harald Welteae026692017-12-09 01:03:01 +01001433
1434 var octetstring l3 := '00010203040506'O
1435 f_ipa_tx(0, ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3));
1436
1437 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3)));
1438
1439 /* expect BSC to disable the channel again if there's no response from MSC */
Harald Weltef77aef62018-01-28 15:35:42 +01001440 /* MS waits 20s (T3210) at LU; 10s (T3230) at CM SERV REQ and 5s (T3220) AT detach */
Neels Hofmeyra5302c82018-11-04 23:09:58 +01001441 f_expect_chan_rel(0, chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001442 f_shutdown_helper();
Harald Welteae026692017-12-09 01:03:01 +01001443}
1444
1445/* Test behavior if MSC answers with CREF to CR */
1446testcase TC_chan_act_ack_est_ind_refused() runs on test_CT {
1447 var BSSAP_N_CONNECT_ind rx_c_ind;
1448 var RSL_Message rx_rsl;
1449
Harald Welte89d42e82017-12-17 16:42:41 +01001450 f_init(1);
Harald Welteae026692017-12-09 01:03:01 +01001451
1452 /* Send CHAN RQD and wait for allocation; acknowledge it */
Harald Welted6939652017-12-13 21:02:46 +01001453 var RslChannelNr chan_nr := f_chreq_act_ack();
Harald Welteae026692017-12-09 01:03:01 +01001454
1455 var octetstring l3 := '00010203040506'O
1456 f_ipa_tx(0, ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3));
1457
1458 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3))) -> value rx_c_ind;
1459 BSSAP.send(ts_BSSAP_DISC_req(rx_c_ind.connectionId, 0));
1460
1461 /* expect BSC to disable the channel */
Neels Hofmeyra5302c82018-11-04 23:09:58 +01001462 f_expect_chan_rel(0, chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001463 f_shutdown_helper();
Harald Welteae026692017-12-09 01:03:01 +01001464}
1465
Harald Welte618ef642017-12-14 14:58:20 +01001466/* CHAN RQD -> CHAN ACT -> CHAN ACT NACK -> RF CHAN REL */
1467testcase TC_chan_act_nack() runs on test_CT {
1468 var RSL_Message rx_rsl;
1469 var integer chact_nack;
1470
Harald Welte89d42e82017-12-17 16:42:41 +01001471 f_init(1);
Harald Welte618ef642017-12-14 14:58:20 +01001472
1473 chact_nack := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", 0, "chan_act:nack");
1474
1475 f_ipa_tx(0, ts_RSL_CHAN_RQD('33'O, 33));
1476 rx_rsl := f_exp_ipa_rx(0, tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
1477 var RslChannelNr chan_nr := rx_rsl.ies[0].body.chan_nr;
1478
1479 f_ipa_tx(0, ts_RSL_CHAN_ACT_NACK(chan_nr, RSL_ERR_EQUIPMENT_FAIL));
1480
1481 /* wait for some time to hope the NACK arrives before the CTRL GET below */
1482 f_sleep(0.5);
1483
1484 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", 0, "chan_act:nack", chact_nack+1);
1485
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001486 f_shutdown_helper();
Harald Welte618ef642017-12-14 14:58:20 +01001487}
1488
Harald Welte799c97b2017-12-14 17:50:30 +01001489/* Test for channel exhaustion due to RACH overload */
1490testcase TC_chan_exhaustion() runs on test_CT {
1491 var ASP_RSL_Unitdata rsl_ud;
1492 var integer i;
1493 var integer chreq_total, chreq_nochan;
1494
Harald Welte89d42e82017-12-17 16:42:41 +01001495 f_init(1);
Harald Welte799c97b2017-12-14 17:50:30 +01001496
1497 chreq_total := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:total");
1498 chreq_nochan := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:no_channel");
1499
Neels Hofmeyr85fa37f2021-10-06 13:50:38 +02001500 /* GSM 44.018 Table 9.1.8.2:
Pau Espin Pedrolfe200d72018-12-10 12:41:04 +01001501 * RA = '33'O -> Establishment cause = 0011xxxx (MS dual rate capable and asks for "TCH/H or TCH/F").
1502 * With current setup, expect 4xSDCCH + 4xTCH/F + 1xTCH/H to succeed */
Philipp Maiercb6cc482018-03-26 13:08:00 +02001503 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 +01001504 var RslChannelNr chan_nr := f_chreq_act_ack('33'O, i);
Harald Welte799c97b2017-12-14 17:50:30 +01001505 }
1506
1507 IPA_RSL[0].clear;
1508
Harald Weltedd8cbf32018-01-28 12:07:52 +01001509 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:total",
Philipp Maiercb6cc482018-03-26 13:08:00 +02001510 chreq_total + NUM_TCHF_PER_BTS + NUM_TCHH_PER_BTS + NUM_SDCCH_PER_BTS);
Harald Welte799c97b2017-12-14 17:50:30 +01001511
1512 /* now expect additional channel activations to fail */
1513 f_ipa_tx(0, ts_RSL_CHAN_RQD('42'O, 42));
1514
1515 alt {
Vadim Yanitskiy9b4e3562020-05-25 21:40:52 +07001516 [] IPA_RSL[0].receive(tr_ASP_RSL_UD(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV))) {
Harald Welte799c97b2017-12-14 17:50:30 +01001517 setverdict(fail, "Received CHAN ACT ACK without resources?!?");
1518 }
Vadim Yanitskiy9b4e3562020-05-25 21:40:52 +07001519 [] IPA_RSL[0].receive(tr_ASP_RSL_UD(tr_RSL_IMM_ASSIGN(?))) -> value rsl_ud {
Harald Welte799c97b2017-12-14 17:50:30 +01001520 var GsmRrMessage rr;
1521 /* match on IMM ASS REJ */
1522 rr := dec_GsmRrMessage(rsl_ud.rsl.ies[1].body.full_imm_ass_info.payload);
1523 if (rr.header.message_type == IMMEDIATE_ASSIGNMENT_REJECT) {
1524 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:total",
Philipp Maiercb6cc482018-03-26 13:08:00 +02001525 chreq_total + NUM_TCHF_PER_BTS + NUM_TCHH_PER_BTS + NUM_SDCCH_PER_BTS+1);
Harald Welte799c97b2017-12-14 17:50:30 +01001526 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:no_channel",
1527 chreq_nochan+1);
1528 setverdict(pass);
1529 } else {
1530 repeat;
1531 }
1532 }
1533 [] IPA_RSL[0].receive { repeat; }
1534 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001535 f_shutdown_helper();
Harald Welte799c97b2017-12-14 17:50:30 +01001536}
1537
Vadim Yanitskiy1ff1fdf2018-11-27 01:32:57 +07001538/* Test channel deactivation due to silence from MS */
1539testcase TC_chan_deact_silence() runs on test_CT {
1540 var RslChannelNr chan_nr;
1541
1542 f_init(1);
1543
1544 /* Request for a dedicated channel */
1545 chan_nr := f_chreq_act_ack('23'O);
1546
1547 /* Wait some time until the channel is released */
1548 f_sleep(2.0);
1549
1550 /* Expect CHANnel RELease */
1551 alt {
Vadim Yanitskiy9b4e3562020-05-25 21:40:52 +07001552 [] IPA_RSL[0].receive(tr_ASP_RSL_UD(tr_RSL_MsgTypeD(RSL_MT_RF_CHAN_REL))) {
Vadim Yanitskiy1ff1fdf2018-11-27 01:32:57 +07001553 log("Received CHANnel RELease");
1554 setverdict(pass);
1555 }
Vadim Yanitskiy9b4e3562020-05-25 21:40:52 +07001556 [] IPA_RSL[0].receive(tr_ASP_RSL_UD(tr_RSL_IMM_ASSIGN(?))) {
Vadim Yanitskiy1ff1fdf2018-11-27 01:32:57 +07001557 /* See OS#3709, OsmoBSC should not send Immediate
1558 * Assignment Reject since a dedicated channel was
1559 * already allocated, and Immediate Assignment was
1560 * already sent. */
1561 setverdict(fail, "Unexpected Immediate Assignment!");
1562 }
1563 [] IPA_RSL[0].receive {
1564 setverdict(fail, "Unexpected RSL message!");
1565 }
1566 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001567 f_shutdown_helper();
Vadim Yanitskiy1ff1fdf2018-11-27 01:32:57 +07001568}
1569
Harald Weltecfe2c962017-12-15 12:09:32 +01001570/***********************************************************************
1571 * Assignment Testing
1572 ***********************************************************************/
1573
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02001574/* Verify that the BSC refuses any BSSAP connection from the MSC (They are all BSC->MSC direction,
1575 * except for the inter-BSC handover, MT side) */
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001576testcase TC_outbound_connect(integer bssap_idx := 0) runs on test_CT {
Harald Welte89d42e82017-12-17 16:42:41 +01001577 f_init(1);
Harald Weltecfe2c962017-12-15 12:09:32 +01001578
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001579 BSSAP.send(ts_BSSAP_CONNECT_req(g_bssap[bssap_idx].sccp_addr_peer, g_bssap[bssap_idx].sccp_addr_own,
1580 2342, ts_BSSMAP_AssignmentReq));
Harald Weltecfe2c962017-12-15 12:09:32 +01001581 BSSAP.receive(tr_BSSAP_DISC_ind(2342, ?, ?));
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001582 f_shutdown_helper();
Harald Weltecfe2c962017-12-15 12:09:32 +01001583}
1584
Harald Welte16a4adf2017-12-14 18:54:01 +01001585/* Test behavior if MSC answers with CREF to CR */
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001586testcase TC_assignment_cic_only(integer bssap_idx := 0) runs on test_CT {
Harald Welte16a4adf2017-12-14 18:54:01 +01001587 var BSSAP_N_CONNECT_ind rx_c_ind;
1588 var RSL_Message rx_rsl;
1589 var DchanTuple dt;
1590
Harald Welte89d42e82017-12-17 16:42:41 +01001591 f_init(1);
Harald Welte16a4adf2017-12-14 18:54:01 +01001592
1593 dt := f_est_dchan('23'O, 23, '00000000'O);
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001594 if (mp_bssap_cfg[bssap_idx].transport == BSSAP_TRANSPORT_AoIP) {
Harald Welte17b27da2018-05-25 20:33:53 +02001595 /* send assignment without AoIP IEs */
1596 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_AssignmentReq(ts_BSSMAP_IE_CIC(0, 1))));
1597 } else {
1598 /* Send assignmetn without CIC in IPA case */
1599 var BSSMAP_IE_AoIP_TransportLayerAddress tla :=
1600 valueof(ts_BSSMAP_IE_AoIP_TLA4('01020304'O, 2342));
1601 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_AssignmentReq(omit, tla)));
1602 }
Harald Welte16a4adf2017-12-14 18:54:01 +01001603 alt {
1604 [] BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_AssignmentComplete)) {
1605 setverdict(fail, "AoIP BSC cannot accept ASSIGNMENT without AoIP Transport IE");
1606 }
Harald Welte235ebf12017-12-15 14:18:16 +01001607 /* TODO: Actually expect GSM0808_CAUSE_REQ_A_IF_TYPE_NOT_SUPP */
Harald Welte16a4adf2017-12-14 18:54:01 +01001608 [] BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_AssignmentFail)) {
1609 setverdict(pass);
1610 }
1611 [] BSSAP.receive { repeat; }
1612 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001613 f_shutdown_helper();
Harald Welte16a4adf2017-12-14 18:54:01 +01001614}
1615
Harald Welteed848512018-05-24 22:27:58 +02001616/* generate an assignment request for either AoIP or SCCPlite */
Pau Espin Pedrol07866632020-09-03 19:10:55 +02001617function 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 +02001618 var PDU_BSSAP ass_cmd;
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02001619 var BSSMAP_IE_Osmo_OsmuxCID osmux_cid := valueof(ts_OsmuxCID(0));
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001620 if (mp_bssap_cfg[bssap_idx].transport == BSSAP_TRANSPORT_AoIP) {
Harald Welteed848512018-05-24 22:27:58 +02001621 var BSSMAP_IE_AoIP_TransportLayerAddress tla :=
Pau Espin Pedrol07866632020-09-03 19:10:55 +02001622 valueof(f_ts_BSSMAP_IE_AoIP_TLA(aoip_tla, 2342));
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02001623 if (osmux_enabled) {
1624 ass_cmd := valueof(ts_BSSMAP_AssignmentReq(omit, tla, osmux_cid));
1625 } else {
1626 ass_cmd := valueof(ts_BSSMAP_AssignmentReq(omit, tla));
1627 }
Harald Welteed848512018-05-24 22:27:58 +02001628 } else {
1629 var BSSMAP_IE_CircuitIdentityCode cic := valueof(ts_BSSMAP_IE_CIC(0,1));
Pau Espin Pedrol096d73d2019-06-06 12:49:17 +02001630 ass_cmd := valueof(ts_BSSMAP_AssignmentReq(cic, omit));
Harald Welteed848512018-05-24 22:27:58 +02001631 }
1632 return ass_cmd;
1633}
1634
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02001635function f_gen_handover_req(integer bssap_idx := 0, charstring aoip_tla := "1.2.3.4",
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02001636 template (omit) BSSMAP_oldToNewBSSIEs oldToNewBSSIEs := omit,
1637 template (omit) TestHdlrEncrParams enc := omit) return PDU_BSSAP {
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01001638 var PDU_BSSAP ho_req;
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02001639
1640 var BSSMAP_IE_EncryptionInformation encryptionInformation :=
1641 valueof(ts_BSSMAP_IE_EncrInfo('0000000000000000'O,'01'O));
1642 var template BSSMAP_IE_ChosenEncryptionAlgorithm chosenEncryptionAlgorithm := omit;
1643 var template BSSMAP_IE_KC128 kc128 := omit;
1644 if (ispresent(enc)) {
1645 var TestHdlrEncrParams v_enc := valueof(enc);
1646 encryptionInformation := valueof(ts_BSSMAP_IE_EncrInfo(v_enc.enc_key, v_enc.enc_alg));
1647 chosenEncryptionAlgorithm := valueof(
1648 ts_BSSMAP_IE_ChosenEncryptionAlgorithm(int2oct(enum2int(
Oliver Smith598e1ed2021-07-09 10:28:40 +02001649 f_cipher_mode_bssmap_to_rsl(v_enc.enc_alg)), 1)));
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02001650 if (ispresent(v_enc.enc_kc128)) {
1651 kc128 := ts_BSSMAP_IE_Kc128(v_enc.enc_kc128);
1652 }
1653 }
1654
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001655 if (mp_bssap_cfg[bssap_idx].transport == BSSAP_TRANSPORT_AoIP) {
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01001656 var BSSMAP_IE_AoIP_TransportLayerAddress tla :=
Pau Espin Pedrol07866632020-09-03 19:10:55 +02001657 valueof(f_ts_BSSMAP_IE_AoIP_TLA(aoip_tla, 2342));
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02001658 ho_req := valueof(ts_BSSMAP_HandoverRequest(omit, tla, oldToNewBSSIEs := oldToNewBSSIEs,
1659 encryptionInformation := encryptionInformation,
1660 chosenEncryptionAlgorithm := chosenEncryptionAlgorithm,
1661 kC128 := kc128));
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01001662 } else {
1663 var BSSMAP_IE_CircuitIdentityCode cic := valueof(ts_BSSMAP_IE_CIC(0,1));
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02001664 ho_req := valueof(ts_BSSMAP_HandoverRequest(cic, omit, oldToNewBSSIEs := oldToNewBSSIEs,
1665 encryptionInformation := encryptionInformation,
1666 chosenEncryptionAlgorithm := chosenEncryptionAlgorithm,
1667 kC128 := kc128));
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01001668 }
1669 return ho_req;
1670}
1671
Harald Welteed848512018-05-24 22:27:58 +02001672/* generate an assignment complete template for either AoIP or SCCPlite */
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001673function f_gen_exp_compl(boolean expect_osmux := false, integer bssap_idx := 0) return template PDU_BSSAP {
Harald Welteed848512018-05-24 22:27:58 +02001674 var template PDU_BSSAP exp_compl;
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02001675 var BSSMAP_IE_Osmo_OsmuxCID osmux_cid := valueof(ts_OsmuxCID(0));
Neels Hofmeyrf246a922020-05-13 02:27:10 +02001676 if (mp_bssap_cfg[bssap_idx].transport == BSSAP_TRANSPORT_AoIP) {
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02001677 if (expect_osmux) {
1678 exp_compl := tr_BSSMAP_AssignmentComplete(omit, ?, osmux_cid);
1679 } else {
1680 exp_compl := tr_BSSMAP_AssignmentComplete(omit, ?, omit);
1681 }
Harald Welteed848512018-05-24 22:27:58 +02001682 } else {
1683 /* CIC is optional "*" as the MSC allocated it */
Pau Espin Pedrol096d73d2019-06-06 12:49:17 +02001684 exp_compl := tr_BSSMAP_AssignmentComplete(*, omit);
Harald Welteed848512018-05-24 22:27:58 +02001685 }
1686 return exp_compl;
1687}
1688
Harald Welte235ebf12017-12-15 14:18:16 +01001689/* Run everything required up to sending a caller-specified assignment command and expect response */
1690function f_assignment_exp(PDU_BSSAP ass_cmd, template PDU_BSSAP exp, charstring fail_text)
1691runs on test_CT {
1692 var BSSAP_N_CONNECT_ind rx_c_ind;
1693 var RSL_Message rx_rsl;
1694 var DchanTuple dt;
1695
Harald Welte89d42e82017-12-17 16:42:41 +01001696 f_init(1);
Harald Welte235ebf12017-12-15 14:18:16 +01001697
1698 dt := f_est_dchan('23'O, 23, '00000000'O);
1699 /* send assignment without AoIP IEs */
1700 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ass_cmd));
1701 alt {
1702 [] BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_AssignmentComplete)) {
1703 if (ischosen(exp.pdu.bssmap.assignmentComplete)) {
1704 setverdict(pass);
1705 } else {
1706 setverdict(fail, fail_text);
1707 }
1708 }
1709 [] BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_AssignmentFail)) {
1710 if (ischosen(exp.pdu.bssmap.assignmentFailure)) {
1711 setverdict(pass);
1712 } else {
1713 setverdict(fail, fail_text);
1714 }
1715 }
1716 [] BSSAP.receive { repeat; }
1717 }
1718}
1719testcase TC_assignment_csd() runs on test_CT {
1720 var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
Harald Welteed848512018-05-24 22:27:58 +02001721 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Harald Welte235ebf12017-12-15 14:18:16 +01001722 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelTypeCSD);
1723 //exp_fail.pdu.bssmap.assignmentFailure.cause.causeValue := int2bit(enum2int(GSM0808_CAUSE_REQ_CODEC_TYPE_OR_CONFIG_UNAVAIL), 7);
1724 f_assignment_exp(ass_cmd, exp_fail, "BSC accepted Assignment for CSD");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001725 f_shutdown_helper();
Harald Welte235ebf12017-12-15 14:18:16 +01001726}
1727
1728testcase TC_assignment_ctm() runs on test_CT {
1729 var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
Harald Welteed848512018-05-24 22:27:58 +02001730 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Harald Welte235ebf12017-12-15 14:18:16 +01001731 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelTypeCTM);
1732 //exp_fail.pdu.bssmap.assignmentFailure.cause.causeValue := int2bit(enum2int(GSM0808_CAUSE_REQ_CODEC_TYPE_OR_CONFIG_UNAVAIL), 7);
1733 f_assignment_exp(ass_cmd, exp_fail, "BSC accepted Assignment for Speech+CTM");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001734 f_shutdown_helper();
Harald Welte235ebf12017-12-15 14:18:16 +01001735}
1736
Harald Welte4003d112017-12-09 22:35:39 +01001737type record DchanTuple {
1738 integer sccp_conn_id,
1739 RslChannelNr rsl_chan_nr
Harald Weltea5d2ab22017-12-09 14:21:42 +01001740}
1741
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +02001742type record of DchanTuple DchanTuples;
1743
Harald Welted6939652017-12-13 21:02:46 +01001744/* Send CHAN RQD and wait for allocation; acknowledge it */
1745private function f_chreq_act_ack(OCT1 ra := '23'O, GsmFrameNumber fn := 23)
1746runs on test_CT return RslChannelNr {
1747 var RSL_Message rx_rsl;
1748 f_ipa_tx(0, ts_RSL_CHAN_RQD(ra, fn));
1749 rx_rsl := f_exp_ipa_rx(0, tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
1750 var RslChannelNr chan_nr := rx_rsl.ies[0].body.chan_nr;
1751 f_ipa_tx(0, ts_RSL_CHAN_ACT_ACK(chan_nr, fn+10));
Daniel Willmannf4ac4ce2018-08-02 14:06:30 +02001752 rx_rsl := f_exp_ipa_rx(0, tr_RSL_IMM_ASSIGN(0));
Harald Welted6939652017-12-13 21:02:46 +01001753 return chan_nr;
1754}
1755
Harald Welte4003d112017-12-09 22:35:39 +01001756/* helper function to establish a dedicated channel via BTS and MSC */
1757function f_est_dchan(OCT1 ra, GsmFrameNumber fn, octetstring l3)
1758runs on test_CT return DchanTuple {
1759 var BSSAP_N_CONNECT_ind rx_c_ind;
Harald Welte4003d112017-12-09 22:35:39 +01001760 var DchanTuple dt;
Harald Weltea5d2ab22017-12-09 14:21:42 +01001761
Harald Welte4003d112017-12-09 22:35:39 +01001762 /* Send CHAN RQD and wait for allocation; acknowledge it */
Harald Welted6939652017-12-13 21:02:46 +01001763 dt.rsl_chan_nr := f_chreq_act_ack(ra, fn);
Harald Welte4003d112017-12-09 22:35:39 +01001764
1765 f_ipa_tx(0, ts_RSL_EST_IND(dt.rsl_chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3));
1766
1767 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3))) -> value rx_c_ind;
1768 dt.sccp_conn_id := rx_c_ind.connectionId;
1769 BSSAP.send(ts_BSSAP_CONNECT_res(dt.sccp_conn_id));
1770
1771 return dt;
Harald Weltea5d2ab22017-12-09 14:21:42 +01001772}
1773
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02001774/* Like f_est_dchan(), but for the first lchan of a dynamic timeslot: first ACK the deactivation of PDCH. */
1775function f_est_dchan_dyn(OCT1 ra, GsmFrameNumber fn, octetstring l3)
1776runs on test_CT return DchanTuple {
1777 var BSSAP_N_CONNECT_ind rx_c_ind;
1778 var DchanTuple dt;
1779
1780 /* Send CHAN RQD */
1781 var RSL_Message rx_rsl;
1782 f_ipa_tx(0, ts_RSL_CHAN_RQD(ra, fn));
1783
1784 /* The dyn TS first deactivates PDCH */
1785 rx_rsl := f_exp_ipa_rx(0, tr_RSL_MsgTypeD(RSL_MT_RF_CHAN_REL), T3101_MAX);
1786 dt.rsl_chan_nr := rx_rsl.ies[0].body.chan_nr;
1787 f_ipa_tx(0, ts_RSL_RF_CHAN_REL_ACK(dt.rsl_chan_nr));
1788
1789 rx_rsl := f_exp_ipa_rx(0, tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
1790 dt.rsl_chan_nr := rx_rsl.ies[0].body.chan_nr;
1791
1792 /* Now activates the signalling channel */
1793 f_ipa_tx(0, ts_RSL_CHAN_ACT_ACK(dt.rsl_chan_nr, fn+10));
1794 rx_rsl := f_exp_ipa_rx(0, tr_RSL_IMM_ASSIGN(0));
1795
1796 f_ipa_tx(0, ts_RSL_EST_IND(dt.rsl_chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3));
1797
1798 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3))) -> value rx_c_ind;
1799 dt.sccp_conn_id := rx_c_ind.connectionId;
1800 BSSAP.send(ts_BSSAP_CONNECT_res(dt.sccp_conn_id));
1801
1802 return dt;
1803}
1804
Harald Welte641fcbe2018-06-14 10:58:35 +02001805/* expect RF CAN REL from BTS, acknowledge it and clear the MSC side */
1806private function f_exp_chan_rel_and_clear(DchanTuple dt, integer bts_nr := 0) runs on test_CT {
1807 var RSL_Message rx_rsl;
1808 /* expect BSC to disable the channel */
1809 rx_rsl := f_exp_ipa_rx(0, tr_RSL_MsgTypeD(RSL_MT_RF_CHAN_REL), T3101_MAX);
1810 /* respond with CHAN REL ACK */
1811 f_ipa_tx(0, ts_RSL_RF_CHAN_REL_ACK(dt.rsl_chan_nr));
1812
1813 /* expect Clear Complete from BSC */
1814 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete));
1815
1816 /* MSC disconnects as instructed. */
1817 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
1818}
1819
Harald Welte4003d112017-12-09 22:35:39 +01001820/* Test behavior of channel release after unilateral RLL REL IND (DISC from MS) */
1821testcase TC_chan_rel_rll_rel_ind() runs on test_CT {
Neels Hofmeyr27f64362018-03-12 01:44:00 +01001822 var BSSAP_N_DATA_ind rx_di;
Harald Welte4003d112017-12-09 22:35:39 +01001823 var DchanTuple dt;
Harald Welte96c94412017-12-09 03:12:45 +01001824
Harald Welte89d42e82017-12-17 16:42:41 +01001825 f_init(1);
Harald Welte96c94412017-12-09 03:12:45 +01001826
Harald Welte4003d112017-12-09 22:35:39 +01001827 dt := f_est_dchan('23'O, 23, '00010203040506'O);
1828
1829 /* simulate RLL REL IND */
1830 f_ipa_tx(0, ts_RSL_REL_IND(dt.rsl_chan_nr, valueof(ts_RslLinkID_DCCH(0))));
1831
Neels Hofmeyr27f64362018-03-12 01:44:00 +01001832 /* expect Clear Request on MSC side */
1833 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearRequest)) -> value rx_di;
1834
1835 /* Instruct BSC to clear channel */
1836 var BssmapCause cause := bit2int(rx_di.userData.pdu.bssmap.clearRequest.cause.causeValue);
1837 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
1838
Harald Welte4003d112017-12-09 22:35:39 +01001839 /* expect BSC to disable the channel */
Harald Welte641fcbe2018-06-14 10:58:35 +02001840 f_exp_chan_rel_and_clear(dt, 0);
Neels Hofmeyr27f64362018-03-12 01:44:00 +01001841
1842 /* wait for SCCP emulation to do its job */
1843 f_sleep(1.0);
Harald Welte4003d112017-12-09 22:35:39 +01001844
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001845 f_shutdown_helper();
Harald Welte4003d112017-12-09 22:35:39 +01001846}
1847
1848/* Test behavior of channel release after CONN FAIL IND from BTS */
1849testcase TC_chan_rel_conn_fail() runs on test_CT {
1850 var BSSAP_N_DATA_ind rx_di;
Harald Welte4003d112017-12-09 22:35:39 +01001851 var DchanTuple dt;
1852
Harald Welte89d42e82017-12-17 16:42:41 +01001853 f_init(1);
Harald Welte4003d112017-12-09 22:35:39 +01001854
1855 dt := f_est_dchan('23'O, 23, '00010203040506'O);
1856
1857 /* simulate CONN FAIL IND */
Harald Weltea8ed9062017-12-14 09:46:01 +01001858 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 +01001859 /* TODO: different cause values? */
1860
Harald Welte4003d112017-12-09 22:35:39 +01001861 /* expect Clear Request from BSC */
1862 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearRequest)) -> value rx_di;
1863
1864 /* Instruct BSC to clear channel */
1865 var BssmapCause cause := bit2int(rx_di.userData.pdu.bssmap.clearRequest.cause.causeValue);
1866 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
1867
Harald Welte6ff76ea2018-01-28 13:08:01 +01001868 /* expect BSC to disable the channel */
Harald Welte641fcbe2018-06-14 10:58:35 +02001869 f_exp_chan_rel_and_clear(dt, 0);
Harald Welte4003d112017-12-09 22:35:39 +01001870
1871 /* wait for SCCP emulation to do its job */
1872 f_sleep(1.0);
1873
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001874 f_shutdown_helper();
Harald Welte4003d112017-12-09 22:35:39 +01001875}
1876
Harald Welte99f3ca02018-06-14 13:40:29 +02001877/* Test behavior of early CONN FAIL IND from BTS (before EST IND!) */
1878/* See also https://www.osmocom.org/issues/3182 */
1879testcase TC_early_conn_fail() runs on test_CT {
1880 var RSL_Message rx_rsl;
1881 var DchanTuple dt;
1882
1883 f_init(1);
1884
1885 /* BTS->BSC: Send CHAN RQD and wait for allocation; acknowledge it */
Harald Weltec46ea3c2020-10-10 18:46:12 +02001886 dt.rsl_chan_nr := f_chreq_act_ack(f_rnd_ra_cs(), 23);
Harald Welte99f3ca02018-06-14 13:40:29 +02001887
1888 /* BTS->BSC: simulate CONN FAIL IND */
1889 f_ipa_tx(0, ts_RSL_CONN_FAIL_IND(dt.rsl_chan_nr, RSL_ERR_RADIO_LINK_FAIL));
1890
1891 /* BTS->BSC: Expect RF channel release from BSC on Abis */
1892 rx_rsl := f_exp_ipa_rx(0, tr_RSL_MsgTypeD(RSL_MT_RF_CHAN_REL), 10.0);
1893
1894 /* BTS<-BSC: respond with CHAN REL ACK */
1895 f_ipa_tx(0, ts_RSL_RF_CHAN_REL_ACK(dt.rsl_chan_nr));
1896
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001897 f_shutdown_helper();
Harald Welte99f3ca02018-06-14 13:40:29 +02001898}
1899
1900/* Test behavior of late CONN FAIL IND from BTS (ater REL IND!) */
1901/* See also https://www.osmocom.org/issues/3182 */
1902testcase TC_late_conn_fail() runs on test_CT {
1903 var RSL_Message rx_rsl;
1904 var DchanTuple dt;
1905
1906 f_init(1);
1907
1908 dt := f_est_dchan('23'O, 23, '00010203040506'O);
1909
1910 /* BSC<-MSC: Instruct BSC to clear connection */
1911 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(0)));
1912
1913 /* BTS->BSC: expect BSC to deactivate SACCH */
1914 rx_rsl := f_exp_ipa_rx(0, tr_RSL_DEACT_SACCH(dt.rsl_chan_nr));
1915
1916 /* BTS->BSC: simulate a late CONN FAIL IND from BTS */
1917 f_ipa_tx(0, ts_RSL_CONN_FAIL_IND(dt.rsl_chan_nr, RSL_ERR_RADIO_LINK_FAIL));
1918
1919 /* BTS<-BSC: Expect RF channel release from BSC on Abis */
1920 rx_rsl := f_exp_ipa_rx(0, tr_RSL_MsgTypeD(RSL_MT_RF_CHAN_REL), 10.0);
1921 /* BTS->BSC: respond with CHAN REL ACK */
1922 f_ipa_tx(0, ts_RSL_RF_CHAN_REL_ACK(dt.rsl_chan_nr));
1923
1924 /* BSC->MSC: expect Clear Complete from BSC */
1925 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete));
1926
1927 /* BSC<-MSC: MSC disconnects as requested. */
1928 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
1929
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02001930 f_shutdown_helper();
Harald Welte99f3ca02018-06-14 13:40:29 +02001931}
1932
Oliver Smithaf03bef2021-08-24 15:34:51 +02001933private function f_TC_stats_conn_fail(charstring id) runs on MSC_ConnHdlr {
1934 var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
1935 var PDU_BSSAP ass_cmd := f_gen_ass_req();
1936
1937 f_statsd_reset();
1938
1939 /* Establish SDCCH */
1940 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelTypeCSD);
1941 f_establish_fully(ass_cmd, exp_fail);
1942
1943 /* Expect stats to be 0 */
1944 var StatsDExpects expect := {
1945 {name := "TTCN3.bts.0.chan.rf_fail", mtype := "c", min := 0, max := 0},
1946 {name := "TTCN3.bts.0.chan.rf_fail_sdcch", mtype := "c", min := 0, max := 0}
1947 };
1948 f_statsd_expect(expect);
1949
1950 /* Simulate CONN FAIL IND on SDCCH */
1951 RSL.send(ts_ASP_RSL_UD(
1952 ts_RSL_CONN_FAIL_IND(g_chan_nr, RSL_ERR_RADIO_LINK_FAIL),
1953 IPAC_PROTO_RSL_TRX0));
1954
Neels Hofmeyr58be48a2021-09-07 18:39:21 +02001955 f_sleep(1.0);
1956
Oliver Smithaf03bef2021-08-24 15:34:51 +02001957 /* Expect stats to be 1 */
1958 expect := {
1959 {name := "TTCN3.bts.0.chan.rf_fail", mtype := "c", min := 1, max := 1},
1960 {name := "TTCN3.bts.0.chan.rf_fail_sdcch", mtype := "c", min := 1, max := 1}
1961 };
1962 f_statsd_expect(expect);
1963}
1964testcase TC_stats_conn_fail() runs on test_CT {
1965 var TestHdlrParams pars := f_gen_test_hdlr_pars();
1966 var MSC_ConnHdlr vc_conn;
1967
1968 f_init(1, true);
1969 f_sleep(1.0);
1970
1971 vc_conn := f_start_handler(refers(f_TC_stats_conn_fail), pars);
1972 vc_conn.done;
1973
1974 f_shutdown_helper();
1975}
1976
Neels Hofmeyrf44ccd12018-11-05 19:15:23 +01001977function f_expect_chan_rel(integer bts_nr, RslChannelNr rsl_chan_nr,
Neels Hofmeyra5302c82018-11-04 23:09:58 +01001978 boolean expect_deact_sacch := true,
1979 boolean expect_rr_chan_rel := true,
1980 boolean expect_rll_rel_req := true,
Harald Welte99787102019-02-04 10:41:36 +01001981 boolean handle_rll_rel := true,
Pau Espin Pedrol36bd4fa2021-04-15 13:00:24 +02001982 template CellSelIndValue expect_cells := omit,
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02001983 template RR_Cause expect_rr_cause := ?
Neels Hofmeyra5302c82018-11-04 23:09:58 +01001984 ) runs on test_CT {
Harald Welte91d54a52018-01-28 15:35:07 +01001985
1986 var RslLinkId main_dcch := valueof(ts_RslLinkID_DCCH(0));
Neels Hofmeyra5302c82018-11-04 23:09:58 +01001987 var boolean got_deact_sacch := false;
1988 var boolean got_rr_chan_rel := false;
1989 var boolean got_rll_rel_req := false;
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02001990 var ASP_RSL_Unitdata ud;
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02001991 var RSL_IE_Body l3_ie;
1992 var PDU_ML3_NW_MS l3;
1993 var RR_Cause got_cause;
Neels Hofmeyra5302c82018-11-04 23:09:58 +01001994 log("f_expect_chan_rel() expecting: expect_deact_sacch=", expect_deact_sacch, " expect_rr_chan_rel=", expect_rr_chan_rel,
1995 " expect_rll_rel_req=", expect_rll_rel_req);
Harald Welte91d54a52018-01-28 15:35:07 +01001996 alt {
Vadim Yanitskiy9b4e3562020-05-25 21:40:52 +07001997 [] IPA_RSL[bts_nr].receive(tr_ASP_RSL_UD(tr_RSL_DEACT_SACCH(rsl_chan_nr))) {
Neels Hofmeyra5302c82018-11-04 23:09:58 +01001998 got_deact_sacch := true;
Harald Welte91d54a52018-01-28 15:35:07 +01001999 repeat;
2000 }
Pau Espin Pedrol841b90d2021-04-15 16:42:52 +02002001 [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 +01002002 got_rr_chan_rel := true;
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002003
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002004 if (f_rsl_find_ie(ud.rsl, RSL_IE_L3_INFO, l3_ie) == false) {
2005 setverdict(fail, "cannot find L3");
2006 mtc.stop;
2007 }
2008 l3 := dec_PDU_ML3_NW_MS(l3_ie.l3_info.payload);
2009
Pau Espin Pedrol36bd4fa2021-04-15 13:00:24 +02002010 if (not istemplatekind(expect_cells, "omit")) {
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002011 var CellSelIndValue cells := dec_CellSelIndValue(
2012 l3.msgs.rrm.channelRelease.cellSelectionIndicator.cellSelectionIndicatorValue);
2013
Pau Espin Pedrol36bd4fa2021-04-15 13:00:24 +02002014 log("GOT RR CHANNEL RELEASE WITH CELLS: ", cells);
2015 if (match(cells, expect_cells)) {
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002016 setverdict(pass);
2017 } else {
Pau Espin Pedrol36bd4fa2021-04-15 13:00:24 +02002018 log("EXPECTED CELLS: ", expect_cells);
2019 setverdict(fail, "Received cells list on RR Channel Release does not match expectations");
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002020 }
2021 }
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002022
2023 if (not istemplatekind(expect_rr_cause, "omit")) {
2024 int2enum(oct2int(l3.msgs.rrm.channelRelease.rRCause.valuePart), got_cause);
2025 log("GOT CAUSE CODE: ", l3.msgs.rrm.channelRelease.rRCause.valuePart, " = ", got_cause);
2026 if (match(got_cause, expect_rr_cause)) {
2027 setverdict(pass);
2028 } else {
2029 log("EXPECTED CAUSE CODE: ", expect_rr_cause);
2030 setverdict(fail, "Received RR Channel Release Cause code does not match expectations");
2031 }
2032 }
Harald Welte99787102019-02-04 10:41:36 +01002033 repeat;
2034 }
Pau Espin Pedrol841b90d2021-04-15 16:42:52 +02002035 [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 +01002036 got_rr_chan_rel := true;
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002037
2038 if (not istemplatekind(expect_rr_cause, "omit")) {
2039 if (f_rsl_find_ie(ud.rsl, RSL_IE_L3_INFO, l3_ie) == false) {
2040 setverdict(fail, "cannot find L3");
2041 mtc.stop;
2042 }
2043 l3 := dec_PDU_ML3_NW_MS(l3_ie.l3_info.payload);
2044
2045 int2enum(oct2int(l3.msgs.rrm.channelRelease.rRCause.valuePart), got_cause);
2046 log("GOT CAUSE CODE: ", l3.msgs.rrm.channelRelease.rRCause.valuePart, " = ", got_cause);
2047 if (match(got_cause, expect_rr_cause)) {
2048 setverdict(pass);
2049 } else {
2050 log("EXPECTED CAUSE CODE: ", expect_rr_cause);
2051 setverdict(fail, "Received RR Channel Release Cause code does not match expectations");
2052 }
2053 }
Neels Hofmeyr211169d2018-11-07 00:37:29 +01002054 repeat;
2055 }
Vadim Yanitskiy9b4e3562020-05-25 21:40:52 +07002056 [] IPA_RSL[bts_nr].receive(tr_ASP_RSL_UD(tr_RSL_REL_REQ(rsl_chan_nr, ?))) {
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002057 got_rll_rel_req := true;
Harald Welte91d54a52018-01-28 15:35:07 +01002058 /* FIXME: Why are we getting this for LinkID SACCH? */
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002059 if (handle_rll_rel) {
2060 f_ipa_tx(0, ts_RSL_REL_CONF(rsl_chan_nr, main_dcch));
2061 }
Harald Welte91d54a52018-01-28 15:35:07 +01002062 repeat;
2063 }
Vadim Yanitskiy9b4e3562020-05-25 21:40:52 +07002064 [] IPA_RSL[bts_nr].receive(tr_ASP_RSL_UD(tr_RSL_MsgTypeD(RSL_MT_RF_CHAN_REL))) {
Harald Welte91d54a52018-01-28 15:35:07 +01002065 /* respond with CHAN REL ACK */
2066 f_ipa_tx(0, ts_RSL_RF_CHAN_REL_ACK(rsl_chan_nr));
2067 }
2068 /* ignore any user data */
Vadim Yanitskiy9b4e3562020-05-25 21:40:52 +07002069 [] IPA_RSL[bts_nr].receive(tr_ASP_RSL_UD(tr_RSL_MsgTypeR(?))) {
Harald Welte91d54a52018-01-28 15:35:07 +01002070 repeat;
2071 }
2072 }
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002073
2074 log("f_expect_chan_rel() summary: got_deact_sacch=", got_deact_sacch, " got_rr_chan_rel=", got_rr_chan_rel,
2075 " got_rll_rel_req=", got_rll_rel_req);
2076
2077 if (expect_deact_sacch != got_deact_sacch) {
2078 setverdict(fail, "f_expect_chan_rel(): expect_deact_sacch=", expect_deact_sacch, " got_deact_sacch=", got_deact_sacch);
2079 }
2080 if (expect_rr_chan_rel != got_rr_chan_rel) {
2081 setverdict(fail, "f_expect_chan_rel(): expect_rr_chan_rel=", expect_rr_chan_rel, " got_rr_chan_rel=", got_rr_chan_rel);
2082 }
2083 if (expect_rll_rel_req != got_rll_rel_req) {
2084 setverdict(fail, "f_expect_chan_rel(): expect_rll_rel_req=", expect_rll_rel_req, " got_rll_rel_req=", got_rll_rel_req);
2085 }
Harald Welte91d54a52018-01-28 15:35:07 +01002086}
2087
Harald Welte4003d112017-12-09 22:35:39 +01002088/* Test behavior of channel release after hard Clear Command from MSC */
2089testcase TC_chan_rel_hard_clear() runs on test_CT {
2090 var BSSAP_N_DATA_ind rx_di;
Harald Welte4003d112017-12-09 22:35:39 +01002091 var DchanTuple dt;
Harald Welte4003d112017-12-09 22:35:39 +01002092
Harald Welte89d42e82017-12-17 16:42:41 +01002093 f_init(1);
Harald Welte4003d112017-12-09 22:35:39 +01002094
2095 dt := f_est_dchan('23'O, 23, '00010203040506'O);
2096
2097 /* Instruct BSC to clear channel */
2098 var BssmapCause cause := 0;
2099 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
2100
2101 /* expect Clear Complete from BSC on A */
2102 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete)) {
2103 /* release the SCCP connection */
2104 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2105 }
2106
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002107 f_expect_chan_rel(0, dt.rsl_chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002108 f_shutdown_helper();
Harald Welte4003d112017-12-09 22:35:39 +01002109}
2110
Pau Espin Pedrol841b90d2021-04-15 16:42:52 +02002111function f_TC_chan_rel_last_eutran_plmn_hard_clear(boolean tx_csfb_ind) runs on test_CT {
2112 var BSSAP_N_DATA_ind rx_di;
2113 var DchanTuple dt;
2114
2115 f_init(1);
2116
2117 dt := f_est_dchan('23'O, 23, '00010203040506'O);
2118 /* Send CommonID with some random PLMN (BSC doesn't take it into account
2119 /* yet when generating the EUTRAN neigh list in RR CHannel Release) */
2120 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_CommonId('001019876543210'H, '323454'O)));
2121
2122 /* Instruct BSC to clear channel */
2123 var BssmapCause cause := 0;
2124 if (tx_csfb_ind) {
2125 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommandCSFB(cause)));
2126 } else {
2127 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
2128 }
2129
2130 /* expect Clear Complete from BSC on A */
2131 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete)) {
2132 /* release the SCCP connection */
2133 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2134 }
2135
2136 /* 1 neighbor is added by default in osmo-bts.cfg and
2137 SystemInformationConfig_default, use that: */
2138 var template CellSelIndValue exp_cells := f_tr_rr_chan_rel_earfcns(1);
2139
2140 f_expect_chan_rel(0, dt.rsl_chan_nr, expect_rll_rel_req := false, expect_cells := exp_cells);
2141 f_shutdown_helper();
2142}
2143
2144/* Test behavior of RR Channel rRelease after Clear Command without CSFB indicator
2145 from MSC, previously receiving any CommonID containing the "Last Used E-UTRAN
2146 PLMN Id". According to spec (3GPP TS 48.008 sec 3.1.30) that's the bit requesting
2147 EUTRAN neighbor list sent later on by BSC in RR Channel, so receiving CSFB
2148 Indicator or not shouldn't matter at all. */
2149testcase TC_chan_rel_last_eutran_plmn_hard_clear_no_csfb() runs on test_CT {
2150 f_TC_chan_rel_last_eutran_plmn_hard_clear(false);
2151}
2152
2153/* Test behavior of RR Channel rRelease after Clear Command with CSFB indicator from
2154 MSC, previously receiving any CommonID containing the "Last Used E-UTRAN PLMN
2155 Id". According to spec (3GPP TS 48.008 sec 3.1.30) that's the bit requesting
2156 EUTRAN neighbor list sent later on by BSC in RR Channel. */
2157testcase TC_chan_rel_last_eutran_plmn_hard_clear_csfb() runs on test_CT {
2158 f_TC_chan_rel_last_eutran_plmn_hard_clear(true);
2159}
2160
2161/* Test behavior of RR Channel Release after Clear Command with CSFB indicator from
2162 MSC, without receiving any CommonID containing the "Last Used E-UTRAN PLMN
2163 Id". According to spec (TS 48.008 version 16.0.0 Release 16 "3.2.1.21") the
2164 CSFB Indicator should not be used anymore, and hence, there should be no
2165 EUTRAN neighbor list sent by BSC in RR Channel release since no CommonId with
2166 Last Used E-UTRAN PLMN Id" IE was sent for this conn. */
Harald Welte99787102019-02-04 10:41:36 +01002167testcase TC_chan_rel_hard_clear_csfb() runs on test_CT {
2168 var BSSAP_N_DATA_ind rx_di;
2169 var DchanTuple dt;
2170
2171 f_init(1);
2172
2173 dt := f_est_dchan('23'O, 23, '00010203040506'O);
2174
2175 /* Instruct BSC to clear channel */
2176 var BssmapCause cause := 0;
2177 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommandCSFB(cause)));
2178
2179 /* expect Clear Complete from BSC on A */
2180 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete)) {
2181 /* release the SCCP connection */
2182 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2183 }
2184
Pau Espin Pedrol841b90d2021-04-15 16:42:52 +02002185 f_expect_chan_rel(0, dt.rsl_chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002186 f_shutdown_helper();
Harald Welte99787102019-02-04 10:41:36 +01002187}
2188
Harald Welted8c36cd2017-12-09 23:05:31 +01002189/* Test behavior of channel release after hard RLSD from MSC */
2190testcase TC_chan_rel_hard_rlsd() runs on test_CT {
Harald Welted8c36cd2017-12-09 23:05:31 +01002191 var DchanTuple dt;
Harald Welted8c36cd2017-12-09 23:05:31 +01002192
Harald Welte89d42e82017-12-17 16:42:41 +01002193 f_init(1);
Harald Welted8c36cd2017-12-09 23:05:31 +01002194
2195 dt := f_est_dchan('23'O, 23, '00010203040506'O);
2196
2197 /* release the SCCP connection */
2198 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2199
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002200 f_expect_chan_rel(0, dt.rsl_chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002201 f_shutdown_helper();
Harald Welted8c36cd2017-12-09 23:05:31 +01002202}
2203
Harald Welte550daf92018-06-11 19:22:13 +02002204/* Test behavior of channel release after hard RLSD from MSC and MS is not responding to RLL REL REQ */
2205testcase TC_chan_rel_hard_rlsd_ms_dead() runs on test_CT {
2206 var DchanTuple dt;
2207
2208 f_init(1);
2209
2210 dt := f_est_dchan('23'O, 23, '00010203040506'O);
2211
2212 /* release the SCCP connection */
2213 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2214
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002215 f_expect_chan_rel(0, dt.rsl_chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002216 f_shutdown_helper();
Harald Welte550daf92018-06-11 19:22:13 +02002217}
2218
Harald Welte85804d42017-12-10 14:11:58 +01002219/* Test behavior of channel release after BSSMAP RESET from MSC */
2220testcase TC_chan_rel_a_reset() runs on test_CT {
Harald Welte85804d42017-12-10 14:11:58 +01002221 var DchanTuple dt;
Harald Welte85804d42017-12-10 14:11:58 +01002222
Harald Welte89d42e82017-12-17 16:42:41 +01002223 f_init(1);
Harald Welte85804d42017-12-10 14:11:58 +01002224
2225 dt := f_est_dchan('23'O, 23, '00010203040506'O);
2226
2227 /* Clear the queue, it might still contain stuff like IMMEDIATE ASSIGN */
2228 IPA_RSL[0].clear;
2229
2230 /* perform BSSAP RESET, expect RESET ACK and DISC.ind on connection */
Neels Hofmeyrf246a922020-05-13 02:27:10 +02002231 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 +01002232 interleave {
Neels Hofmeyrf246a922020-05-13 02:27:10 +02002233 [] 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 +01002234 [] BSSAP.receive(tr_BSSAP_DISC_ind(dt.sccp_conn_id, ?, ?)) { }
2235 }
2236
Neels Hofmeyra5302c82018-11-04 23:09:58 +01002237 f_expect_chan_rel(0, dt.rsl_chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002238 f_shutdown_helper();
Harald Welte85804d42017-12-10 14:11:58 +01002239}
2240
Pau Espin Pedrolc675b612020-01-09 19:55:40 +01002241/* Verify T(iar) triggers and releases the channel */
2242testcase TC_chan_rel_sccp_tiar_timeout() runs on test_CT {
2243 var DchanTuple dt;
2244
2245 /* Set T(iar) in BSC low enough that it will trigger before other side
2246 has time to keep alive with a T(ias). Keep recommended ratio of
2247 T(iar) >= T(ias)*2 */
2248 g_bsc_sccp_timer_ias := 2;
2249 g_bsc_sccp_timer_iar := 5;
2250
2251 f_init(1);
2252
2253 dt := f_est_dchan('23'O, 23, '00010203040506'O);
2254 f_expect_chan_rel(0, dt.rsl_chan_nr, expect_rll_rel_req := false);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002255 f_shutdown_helper();
Pau Espin Pedrolc675b612020-01-09 19:55:40 +01002256}
2257
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002258private function f_tc_chan_rel_rr_cause(myBSSMAP_Cause clear_cmd_cause, template RR_Cause expect_rr_cause)
2259runs on test_CT
2260{
2261 var DchanTuple dt;
2262
2263 dt := f_est_dchan('23'O, 23, '00010203040506'O);
2264 var BssmapCause cause := 0;
2265 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(enum2int(clear_cmd_cause))));
2266 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete)) {
2267 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2268 }
2269
2270 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 +02002271}
2272
2273/* Test that Clear Command cause codes affect the RR Channel Release cause code */
2274testcase TC_chan_rel_rr_cause() runs on test_CT {
2275 f_init(1);
2276
2277 f_tc_chan_rel_rr_cause(GSM0808_CAUSE_CALL_CONTROL, GSM48_RR_CAUSE_NORMAL);
2278 f_tc_chan_rel_rr_cause(GSM0808_CAUSE_HANDOVER_SUCCESSFUL, GSM48_RR_CAUSE_NORMAL);
2279 f_tc_chan_rel_rr_cause(GSM0808_CAUSE_PREEMPTION, GSM48_RR_CAUSE_PREMPTIVE_REL);
2280 f_tc_chan_rel_rr_cause(GSM0808_CAUSE_RADIO_INTERFACE_MESSAGE_FAILURE, GSM48_RR_CAUSE_PROT_ERROR_UNSPC);
2281 f_tc_chan_rel_rr_cause(GSM0808_CAUSE_RADIO_INTERFACE_FAILURE, GSM48_RR_CAUSE_ABNORMAL_UNSPEC);
2282 f_tc_chan_rel_rr_cause(GSM0808_CAUSE_EQUIPMENT_FAILURE, GSM48_RR_CAUSE_ABNORMAL_UNSPEC);
Vadim Yanitskiye18aebb2021-01-03 13:10:43 +01002283
2284 f_shutdown_helper();
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +02002285}
2286
Harald Welte5cd20ed2017-12-13 21:03:20 +01002287/* Test behavior if RSL EST IND for non-active channel */
2288testcase TC_rll_est_ind_inact_lchan() runs on test_CT {
2289 timer T := 2.0;
2290
Harald Welte89d42e82017-12-17 16:42:41 +01002291 f_init(1);
Harald Welte5cd20ed2017-12-13 21:03:20 +01002292
2293 var octetstring l3 := '00010203040506'O;
2294 var RslChannelNr chan_nr := valueof(t_RslChanNr_Bm(6));
2295 f_ipa_tx(0, ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3));
2296
2297 T.start;
2298 alt {
2299 [] BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3))) {
2300 setverdict(fail, "MSC received COMPL L3 for non-active lchan");
2301 }
2302 [] BSSAP.receive {}
2303 [] IPA_RSL[0].receive {}
2304 [] T.timeout {}
2305 }
2306
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002307 f_shutdown_helper();
Harald Welte5cd20ed2017-12-13 21:03:20 +01002308}
2309
2310/* Test behavior if RSL EST IND for invalid SAPI */
2311testcase TC_rll_est_ind_inval_sapi1() runs on test_CT {
2312 var RslChannelNr chan_nr;
2313
Harald Welte89d42e82017-12-17 16:42:41 +01002314 f_init(1);
Harald Welte5cd20ed2017-12-13 21:03:20 +01002315
2316 chan_nr := f_chreq_act_ack()
2317
2318 var octetstring l3 := '00010203040506'O;
2319 f_ipa_tx(0, ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(1)), l3));
2320
2321 timer T := 2.0;
2322 T.start;
2323 alt {
2324 [] BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3))) {
2325 setverdict(fail, "MSC received COMPL L3 for invalid SAPI 1");
2326 }
2327 [] BSSAP.receive { repeat; }
2328 [] IPA_RSL[0].receive { repeat; }
2329 [] T.timeout {}
2330 }
2331
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002332 f_shutdown_helper();
Harald Welte5cd20ed2017-12-13 21:03:20 +01002333}
2334
2335/* Test behavior if RSL EST IND for invalid SAPI */
2336testcase TC_rll_est_ind_inval_sapi3() runs on test_CT {
2337 timer T := 2.0;
2338
Harald Welte89d42e82017-12-17 16:42:41 +01002339 f_init(1);
Harald Welte5cd20ed2017-12-13 21:03:20 +01002340
2341 var RslChannelNr chan_nr := f_chreq_act_ack();
2342
2343 var octetstring l3 := '00010203040506'O;
2344 f_ipa_tx(0, ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(3)), l3));
2345
2346 T.start;
2347 alt {
2348 [] BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3))) {
2349 setverdict(fail, "MSC received COMPL L3 for invalid SAPI 3");
2350 }
2351 [] BSSAP.receive { repeat; }
2352 [] IPA_RSL[0].receive { repeat; }
2353 [] T.timeout {}
2354 }
2355
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002356 f_shutdown_helper();
Harald Welte5cd20ed2017-12-13 21:03:20 +01002357}
2358
2359/* Test behavior if RSL EST IND for invalid SACCH */
2360testcase TC_rll_est_ind_inval_sacch() runs on test_CT {
2361 timer T := 2.0;
2362
Harald Welte89d42e82017-12-17 16:42:41 +01002363 f_init(1);
Harald Welte5cd20ed2017-12-13 21:03:20 +01002364
2365 var RslChannelNr chan_nr := f_chreq_act_ack();
2366
2367 var octetstring l3 := '00010203040506'O;
2368 f_ipa_tx(0, ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_SACCH(0)), l3));
2369
2370 T.start;
2371 alt {
2372 [] BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3))) {
2373 setverdict(fail, "MSC received COMPL L3 for invalid Link SACCH");
2374 }
2375 [] BSSAP.receive { repeat; }
2376 [] IPA_RSL[0].receive { repeat; }
2377 [] T.timeout {}
2378 }
2379
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002380 f_shutdown_helper();
Harald Welte5cd20ed2017-12-13 21:03:20 +01002381}
2382
Vadim Yanitskiy61f784a2020-10-01 21:12:19 +07002383/* Verify DLCI / RSL Link ID conversion for MO/MT messages on SAPI0/SAPI3 */
2384private function f_TC_tch_dlci_link_id_sapi(charstring id) runs on MSC_ConnHdlr {
2385 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
2386 var PDU_BSSAP ass_cmd := f_gen_ass_req();
2387
2388 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
2389 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
2390
2391 f_establish_fully(ass_cmd, exp_compl);
2392
2393 /* SAPI0 has already been established by f_establish_fully(), establish SAPI3 */
2394 RSL.send(ts_RSL_EST_IND(g_chan_nr, ts_RslLinkID_SACCH(3), '0904'O));
2395 /* Expect BSSAP/DTAP on SAPI3 (DLCI IE) */
2396 BSSAP.receive(PDU_BSSAP:{
2397 discriminator := '1'B,
2398 spare := '0000000'B,
2399 dlci := 'C3'O,
2400 lengthIndicator := ?,
2401 pdu := { dtap := '0904'O }
2402 });
2403
2404 /* Send messages on DCCH/SAPI0 and ACCH/SAPI3 */
2405 for (var integer i := 0; i < 32; i := i + 1) {
2406 var octetstring l3 := '09'O & f_rnd_octstring(14);
2407 var template (value) RslLinkId link_id;
2408 var template (value) OCT1 dlci;
2409
2410 if (i mod 2 == 0) {
2411 /* SAPI0 on FACCH or SDCCH */
2412 link_id := ts_RslLinkID_DCCH(0);
2413 dlci := '80'O;
2414 } else {
2415 /* SAPI3 on SACCH */
2416 link_id := ts_RslLinkID_SACCH(3);
2417 dlci := 'C3'O;
2418 }
2419
2420 /* Send MO message: RSL -> BSSAP */
Neels Hofmeyr0aa719b2020-10-12 18:43:09 +00002421 f_mo_l3_transceive(RSL, link_id, dlci, l3);
Vadim Yanitskiy61f784a2020-10-01 21:12:19 +07002422 /* Send MT message: BSSAP -> RSL */
Neels Hofmeyr0aa719b2020-10-12 18:43:09 +00002423 f_mt_l3_transceive(RSL, link_id, dlci, l3);
Vadim Yanitskiy61f784a2020-10-01 21:12:19 +07002424 }
2425}
2426testcase TC_tch_dlci_link_id_sapi() runs on test_CT {
2427 var TestHdlrParams pars := f_gen_test_hdlr_pars();
2428 var MSC_ConnHdlr vc_conn;
2429
2430 f_init(1, true);
2431 f_sleep(1.0);
2432
2433 vc_conn := f_start_handler(refers(f_TC_tch_dlci_link_id_sapi), pars);
2434 vc_conn.done;
2435
2436 f_shutdown_helper();
2437}
2438
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002439private function f_exp_sapi_n_reject(template (present) GsmSapi sapi := ?,
2440 template myBSSMAP_Cause cause := ?,
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +07002441 template (present) BIT2 cc := ?,
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002442 float T_val := 2.0)
2443runs on test_CT {
2444 var BSSAP_N_DATA_ind rx_di;
2445 timer T;
2446
2447 var template BSSMAP_IE_Cause tr_cause := tr_BSSMAP_IE_Cause(cause);
2448 var template PDU_BSSAP tr_pdu := tr_BSSMAP_SAPInReject(sapi);
2449
2450 T.start(T_val);
2451 alt {
2452 [] BSSAP.receive(tr_BSSAP_DATA_ind(?, tr_pdu)) -> value rx_di {
2453 var BSSMAP_IE_Cause rx_cause := rx_di.userData.pdu.bssmap.sAPInReject.cause;
2454 if (not match(rx_cause, tr_cause)) {
2455 setverdict(fail, "Rx unexpected Cause IE: ",
2456 rx_cause, " vs expected ", tr_cause);
2457 }
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +07002458
2459 /* Who ever on the earth decided to define this field as two separate bits?!? */
2460 var BIT2 rx_cc := rx_di.userData.pdu.bssmap.sAPInReject.dLCI.c2
2461 & rx_di.userData.pdu.bssmap.sAPInReject.dLCI.c1;
2462 if (not match(rx_cc, cc)) {
2463 setverdict(fail, "Rx unexpected Control Channel type: ",
2464 rx_cc, " vs expected ", cc);
2465 }
2466
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002467 setverdict(pass);
2468 }
2469 [] BSSAP.receive(BSSAP_N_DATA_ind:?) -> value rx_di {
2470 setverdict(fail, "Rx unexpected BSSAP PDU: ", rx_di);
2471 }
2472 [] T.timeout {
2473 setverdict(fail, "Timeout waiting for BSSMAP SAPI N Reject");
2474 }
2475 }
2476}
2477
2478/* Check if we get SAPI N Reject on receipt of unexpected RLL RELease INDication */
2479testcase TC_rll_rel_ind_sapi_n_reject() runs on test_CT {
2480 var octetstring rnd_data := f_rnd_octstring(16);
2481 var RSL_Message rx_rsl;
2482 var DchanTuple dt;
2483
2484 f_init(1);
2485
2486 /* MS establishes a SAPI=0 link on DCCH */
2487 dt := f_est_dchan(f_rnd_ra_cs(), 23, rnd_data);
2488
2489 /* MSC sends some data on (not yet established) SAPI=3 link */
2490 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSAP_DTAP(rnd_data, '03'O)));
2491 /* BSC attempts to establish a SAPI=3 link on DCCH */
2492 rx_rsl := f_exp_ipa_rx(0, tr_RSL_EST_REQ(dt.rsl_chan_nr, tr_RslLinkID_DCCH(3)));
2493
2494 /* MS sends unexpected RELease INDication on SAPI=3 */
2495 f_ipa_tx(0, ts_RSL_REL_IND(dt.rsl_chan_nr, ts_RslLinkID_DCCH(3)));
2496 /* We expect to receive BSSMAP SAPI N Reject message from the BSC */
2497 f_exp_sapi_n_reject(3, GSM0808_CAUSE_MS_NOT_EQUIPPED);
2498
2499 /* Clean up the connection */
2500 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2501 f_expect_chan_rel(0, dt.rsl_chan_nr, expect_rll_rel_req := false);
2502
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002503 f_shutdown_helper();
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002504}
2505
2506/* Check if we get SAPI N Reject on receipt of unexpected RLL ERROR INDication */
2507testcase TC_rll_err_ind_sapi_n_reject() runs on test_CT {
2508 var octetstring rnd_data := f_rnd_octstring(16);
2509 var RSL_Message rx_rsl;
2510 var DchanTuple dt;
2511
2512 f_init(1);
2513
2514 /* MS establishes a SAPI=0 link on DCCH */
2515 dt := f_est_dchan(f_rnd_ra_cs(), 23, rnd_data);
2516
2517 /* MSC sends some data on (not yet established) SAPI=3 link */
2518 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSAP_DTAP(rnd_data, '03'O)));
2519 /* BSC attempts to establish a SAPI=3 link on DCCH */
2520 rx_rsl := f_exp_ipa_rx(0, tr_RSL_EST_REQ(dt.rsl_chan_nr, tr_RslLinkID_DCCH(3)));
2521
2522 /* BTS sends unexpected ERROR INDication on SAPI=3 */
2523 f_ipa_tx(0, ts_RSL_ERROR_IND(dt.rsl_chan_nr, ts_RslLinkID_DCCH(3), ''O));
2524 /* We expect to receive BSSMAP SAPI N Reject message from the BSC */
2525 f_exp_sapi_n_reject(3, GSM0808_CAUSE_BSS_NOT_EQUIPPED);
2526
2527 /* Clean up the connection */
2528 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2529 f_expect_chan_rel(0, dt.rsl_chan_nr, expect_rll_rel_req := false);
2530
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002531 f_shutdown_helper();
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002532}
2533
2534/* Check if we get SAPI N Reject due to a SAPI=3 link establishment timeout */
2535testcase TC_rll_timeout_sapi_n_reject() runs on test_CT {
2536 var octetstring rnd_data := f_rnd_octstring(16);
2537 var RSL_Message rx_rsl;
2538 var DchanTuple dt;
2539
2540 f_init(1);
2541
2542 /* MS establishes a SAPI=0 link on DCCH */
2543 dt := f_est_dchan(f_rnd_ra_cs(), 23, rnd_data);
2544
2545 /* MSC sends some data on (not yet established) SAPI=3 link */
2546 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSAP_DTAP(rnd_data, '03'O)));
2547 /* BSC attempts to establish a SAPI=3 link on DCCH */
2548 rx_rsl := f_exp_ipa_rx(0, tr_RSL_EST_REQ(dt.rsl_chan_nr, tr_RslLinkID_DCCH(3)));
2549
2550 /* MS does not respond, so the link establishment timeout triggers SAPI N Reject */
2551 f_exp_sapi_n_reject(3, GSM0808_CAUSE_BSS_NOT_EQUIPPED, T_val := 8.0);
2552
2553 /* Clean up the connection */
2554 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2555 f_expect_chan_rel(0, dt.rsl_chan_nr, expect_rll_rel_req := false);
2556
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002557 f_shutdown_helper();
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +07002558}
2559
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +07002560/* Check DLCI CC (Control Channel type) bits in SAPI N Reject */
2561testcase TC_rll_sapi_n_reject_dlci_cc() runs on test_CT {
2562 var octetstring rnd_data := f_rnd_octstring(16);
2563 var RSL_Message rx_rsl;
2564 var DchanTuple dt;
2565
2566 f_init(1);
2567
2568 /* MS establishes a SAPI=0 link on DCCH */
2569 dt := f_est_dchan(f_rnd_ra_cs(), 23, rnd_data);
2570
2571 /* MSC sends some data on (not yet established) SAPI=3 link */
2572 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSAP_DTAP(rnd_data, '03'O)));
2573 /* BSC attempts to establish a SAPI=3 link on DCCH */
2574 rx_rsl := f_exp_ipa_rx(0, tr_RSL_EST_REQ(dt.rsl_chan_nr, tr_RslLinkID_DCCH(3)));
2575
2576 /* MS sends unexpected ERROR INDication on DCCH/ACCH SAPI=3 */
2577 f_ipa_tx(0, ts_RSL_ERROR_IND(dt.rsl_chan_nr, ts_RslLinkID_DCCH(3), ''O));
2578 f_exp_sapi_n_reject(3, GSM0808_CAUSE_MS_NOT_EQUIPPED, '10'B);
2579
2580 /* Clean up the connection */
2581 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2582 f_expect_chan_rel(0, dt.rsl_chan_nr, expect_rll_rel_req := false);
2583
2584 f_shutdown_helper();
2585}
2586
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +02002587testcase TC_si_default() runs on test_CT {
2588 f_init(0);
2589 f_init_bts_and_check_sysinfo(0, expect_si := SystemInformationConfig_default);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002590 f_shutdown_helper();
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +02002591}
Harald Welte4003d112017-12-09 22:35:39 +01002592
Neels Hofmeyr56f24782020-07-09 00:50:49 +02002593/* We're testing SI2quater with lists of EARFCNs. Instead of just incrementing EARFCNs, also pick some from the edges of
2594 * the entire value range. This function provides the same EARFCN numbers for the same earfcn_index */
2595private function f_test_si2quater_earfcn_by_idx(integer earfcn_index) return uint16_t
2596{
2597 select (earfcn_index) {
2598 case (0) {
2599 /* E-ARFCN 111 is already added in the osmo-bsc.cfg */
2600 return 111;
2601 }
2602 case (1) {
2603 return 1;
2604 }
2605 case (2) {
2606 return 0;
2607 }
2608 case (3) {
2609 return 65535;
2610 }
2611 case else {
2612 return 23 * (earfcn_index - 3);
2613 }
2614 }
2615}
2616
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002617function f_test_si2quater(integer total_earfcns, template SystemInformationConfig expect_si,
2618 template CellSelIndValue expect_cells := omit) runs on test_CT {
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002619
2620 f_init(0);
2621
2622 /* E-ARFCN 111 is already added in the osmo-bsc.cfg, so only add more arfcns if total_earfcns > 1 */
2623 for (var integer i := 1; i < total_earfcns; i := i + 1) {
Neels Hofmeyr56f24782020-07-09 00:50:49 +02002624 f_bts_0_cfg(BSCVTY, {"si2quater neighbor-list add earfcn " & int2str(f_test_si2quater_earfcn_by_idx(i))
2625 & " thresh-hi 20 thresh-lo 10 prio 3 qrxlv 22 meas 3"});
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002626 }
2627
2628 f_init_bts_and_check_sysinfo(0, expect_si := expect_si);
2629
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002630 if (not istemplatekind(expect_cells, "omit")) {
2631 /* Also check that RR Channel Release contains these EARFCNs.
2632 * (copied code from TC_chan_rel_hard_clear_csfb) */
2633 var BSSAP_N_DATA_ind rx_di;
2634 var DchanTuple dt;
2635
2636 dt := f_est_dchan('23'O, 23, '00010203040506'O);
Pau Espin Pedrold0046312021-04-19 16:35:58 +02002637 /* Send CommonID with some random PLMN (BSC doesn't take it into account
2638 * yet when generating the EUTRAN neigh list in RR CHannel Release) */
2639 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_CommonId('001019876543210'H, '323454'O)));
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002640
2641 /* Instruct BSC to clear channel */
2642 var BssmapCause cause := 0;
2643 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommandCSFB(cause)));
2644
2645 /* expect Clear Complete from BSC on A */
2646 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete)) {
2647 /* release the SCCP connection */
2648 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
2649 }
2650
Pau Espin Pedrol841b90d2021-04-15 16:42:52 +02002651 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 +02002652 }
2653
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002654 for (var integer i := 1; i < total_earfcns; i := i + 1) {
Neels Hofmeyr56f24782020-07-09 00:50:49 +02002655 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 +02002656 }
2657}
2658
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002659private function f_tr_si2quater_earfcns(integer count) return template SI2quaterRestOctetsList
2660{
2661 var template SI2quaterRestOctetsList si2quater := {};
2662 var integer si2quater_count := (count + 2) / 3;
2663
2664 for (var integer i := 0; i < count; i := i + 1) {
Neels Hofmeyr56f24782020-07-09 00:50:49 +02002665 var integer earfcn := f_test_si2quater_earfcn_by_idx(i);
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002666 var integer index := i / 3;
2667 var integer earfcn_index := i mod 3;
2668 if (index >= lengthof(si2quater)) {
2669 si2quater[index] := tr_SI2quaterRestOctets_EUTRAN(index := index, count := si2quater_count - 1);
2670 }
2671 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);
2672 }
2673
2674 return si2quater;
2675}
2676
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002677private function f_tr_rr_chan_rel_earfcns(integer count) return template CellSelIndValue
2678{
2679 var template CellSelIndValue_EUTRAN_Descrs cells := {};
2680
Alexander Couzensf74b5cb2020-09-10 22:28:40 +02002681 /* the lte neighbors must match the config & vty to pass this test */
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002682 for (var integer i := 0; i < count; i := i + 1) {
2683 var integer earfcn := f_test_si2quater_earfcn_by_idx(i);
Alexander Couzensf74b5cb2020-09-10 22:28:40 +02002684 cells[i] := tr_CellSelIndValue_EUTRAN_Descr(earfcn, '1'B, 3);
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002685 }
2686
2687 return tr_CellSelIndValue_EUTRAN(cells);
2688}
2689
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002690private function f_tc_si2quater_n_earfcns(integer n) runs on test_CT
2691{
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002692 var template SystemInformationConfig sic := SystemInformationConfig_default;
Pau Espin Pedrol8ab62e42020-12-18 16:19:11 +01002693 sic.si2quater := f_tr_si2quater_earfcns(n);
Neels Hofmeyr0edf4ac2020-07-10 17:33:24 +02002694 var template CellSelIndValue cells := f_tr_rr_chan_rel_earfcns(n);
2695 f_test_si2quater(n, sic, cells);
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002696}
2697
2698testcase TC_si2quater_2_earfcns() runs on test_CT {
2699 f_tc_si2quater_n_earfcns(2);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002700 f_shutdown_helper();
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002701}
2702
2703testcase TC_si2quater_3_earfcns() runs on test_CT {
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002704 f_tc_si2quater_n_earfcns(3);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002705 f_shutdown_helper();
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002706}
2707
2708testcase TC_si2quater_4_earfcns() runs on test_CT {
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002709 f_tc_si2quater_n_earfcns(4);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002710 f_shutdown_helper();
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002711}
2712
2713testcase TC_si2quater_5_earfcns() runs on test_CT {
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002714 f_tc_si2quater_n_earfcns(5);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002715 f_shutdown_helper();
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002716}
2717
2718testcase TC_si2quater_6_earfcns() runs on test_CT {
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002719 f_tc_si2quater_n_earfcns(6);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002720 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002721}
2722
2723testcase TC_si2quater_12_earfcns() runs on test_CT {
2724 f_tc_si2quater_n_earfcns(12);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002725 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002726}
2727
2728testcase TC_si2quater_23_earfcns() runs on test_CT {
2729 f_tc_si2quater_n_earfcns(23);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002730 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002731}
2732
2733testcase TC_si2quater_32_earfcns() runs on test_CT {
2734 f_tc_si2quater_n_earfcns(32);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002735 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002736}
2737
2738testcase TC_si2quater_33_earfcns() runs on test_CT {
2739 f_tc_si2quater_n_earfcns(33);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002740 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002741}
2742
2743testcase TC_si2quater_42_earfcns() runs on test_CT {
2744 f_tc_si2quater_n_earfcns(42);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002745 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002746}
2747
2748testcase TC_si2quater_48_earfcns() runs on test_CT {
2749 f_tc_si2quater_n_earfcns(48);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002750 f_shutdown_helper();
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002751}
2752
2753/* verify the VTY error response when adding too many EARFCNs, and showing that osmo-bsc still sends 16 SI2quater with
2754 * 48 EARFCNs. */
2755testcase TC_si2quater_49_earfcns() runs on test_CT {
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002756 var template SystemInformationConfig sic := SystemInformationConfig_default;
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002757 sic.si2quater := f_tr_si2quater_earfcns(48); /* 48, not 49! */
2758 f_init(0);
2759
2760 for (var integer i := 1; i < 48; i := i + 1) {
Neels Hofmeyr56f24782020-07-09 00:50:49 +02002761 f_bts_0_cfg(BSCVTY, {"si2quater neighbor-list add earfcn " & int2str(f_test_si2quater_earfcn_by_idx(i))
2762 & " thresh-hi 20 thresh-lo 10 prio 3 qrxlv 22 meas 3"});
Neels Hofmeyrad132f22020-07-08 02:20:16 +02002763 }
2764
2765 /* The 49th EARFCN no longer fits, expect VTY error */
2766 f_vty_enter_cfg_bts(BSCVTY, 0);
2767 var charstring vty_error;
2768 vty_error := f_vty_transceive_ret(BSCVTY,
2769 "si2quater neighbor-list add earfcn 70 thresh-hi 20 thresh-lo 10 prio 3 qrxlv 22 meas 3")
2770 f_vty_transceive(BSCVTY, "end");
2771
2772 if (f_strstr(vty_error, "Unable to add ARFCN 70") >= 0) {
2773 log("Got expected VTY error: ", vty_error);
2774 setverdict(pass);
2775 } else {
2776 setverdict(fail, "Expected the 49th EUTRAN ARFCN to be rejected by vty config, got: ", vty_error);
2777 }
2778
2779 f_init_bts_and_check_sysinfo(0, expect_si := sic);
2780
2781 for (var integer i := 1; i < 48; i := i + 1) {
Neels Hofmeyr56f24782020-07-09 00:50:49 +02002782 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 +02002783 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002784 f_shutdown_helper();
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002785}
2786
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02002787private function f_acc09_count_allowed(AccessControlClass acc) return uint8_t
2788{
2789 var uint8_t count := 0;
2790 for (var integer i := 5; i < 16; i := i + 1) {
2791 if (acc[i] == '0'B) { /* the list marks barred, we count allowed */
2792 count := count + 1;
2793 }
2794 }
2795 return count;
2796}
2797
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02002798private function f_recv_next_si1(integer rsl_idx := 0) runs on test_CT return SystemInformationType1
2799{
2800 var ASP_RSL_Unitdata rx_rsl_ud;
2801 var SystemInformationType1 last_si1;
2802
2803 timer T := 30.0;
2804 T.start;
2805 alt {
2806 [] IPA_RSL[rsl_idx].receive(tr_ASP_RSL_UD((tr_RSL_NO_BCCH_INFO,
2807 tr_RSL_BCCH_INFO,
2808 tr_RSL_NO_SACCH_FILL,
2809 tr_RSL_SACCH_FILL))
2810 ) -> value rx_rsl_ud {
2811 f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
2812 if (g_system_information[rsl_idx].si1 == omit) {
2813 repeat;
2814 }
2815 last_si1 := g_system_information[rsl_idx].si1;
2816 g_system_information[rsl_idx].si1 := omit;
2817 T.stop;
2818 }
Vadim Yanitskiy79ebd5e2021-01-04 00:12:55 +01002819 [] IPA_RSL[rsl_idx].receive { repeat; }
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02002820 [] T.timeout { setverdict(fail, "Timeout receiving next SI1"); }
2821 }
2822 return last_si1;
2823}
2824
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02002825/* verify ACC rotate feature */
2826testcase TC_si_acc_rotate() runs on test_CT {
2827 var template SystemInformationConfig sic := SystemInformationConfig_default;
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02002828 var SystemInformationType1 last_si1;
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02002829 var AccessControlClass acc;
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02002830 var uint8_t count;
2831 var integer times_allowed[10] := { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
2832
2833 f_init(0, guard_timeout := 60.0);
2834
2835 f_bts_0_cfg(BSCVTY, {"rach access-control-class 5 barred",
2836 "access-control-class-rotate 3",
2837 "access-control-class-rotate-quantum 1"});
2838
2839 /* Init and get first sysinfo */
2840 f_init_bts_and_check_sysinfo(0, expect_si := ?);
2841
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02002842 for (var integer i:= 0; i < 20; i := i + 1) {
2843 last_si1 := f_recv_next_si1(0);
2844 acc := last_si1.rach_control.acc;
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02002845 count := f_acc09_count_allowed(acc);
2846 log("RSL: GOT SI1 ACC len=", count, ": ", acc);
2847
2848 if (count != 3) {
2849 log("RSL: EXPECTED SI ACC len=3");
2850 setverdict(fail, "received SI does not match expectations");
2851 break;
2852 }
2853
2854 for (var integer j := 0; j < 10; j := j + 1) {
2855 if (acc[16 - 1 - j] == '0'B) { /* the list marks barred, we count allowed */
2856 times_allowed[j] := times_allowed[j] + 1;
2857 }
2858 }
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02002859 }
2860
2861 for (var integer j := 0; j < 10; j := j + 1) {
2862 log("ACC", j, " allowed ", times_allowed[j], " times" );
2863 if (j != 5 and times_allowed[j] < 3) {
2864 setverdict(fail, "ACC", j, " ERROR: allowed ", times_allowed[j], " < 1 times");
2865 } else if (j == 5 and times_allowed[j] > 0) {
2866 setverdict(fail, "ACC", j, " ERROR: allowed ", times_allowed[j], " > 0 times");
2867 }
2868 }
2869
2870 f_bts_0_cfg(BSCVTY, {"access-control-class-rotate 10",
2871 "rach access-control-class 5 allowed"});
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002872 f_shutdown_helper();
Pau Espin Pedrol85a84432020-07-20 18:45:03 +02002873}
Neels Hofmeyr66aeba42020-07-06 02:21:21 +02002874
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02002875/* verify ACC startup ramp+rotate feature */
2876testcase TC_si_acc_ramp_rotate() runs on test_CT {
2877 var template SystemInformationConfig sic := SystemInformationConfig_default;
2878 var SystemInformationType1 last_si1;
2879 var AccessControlClass acc;
2880 var ASP_RSL_Unitdata rx_rsl_ud;
2881 var uint8_t count;
2882 var uint8_t prev_count;
2883 var integer times_allowed[10] := { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
2884
2885 f_init(0, guard_timeout := 80.0);
2886
2887 f_bts_0_cfg(BSCVTY, {"rach access-control-class 4 barred",
2888 "access-control-class-rotate 0",
2889 "access-control-class-rotate-quantum 1",
2890 "access-control-class-ramping",
2891 "access-control-class-ramping-step-interval 5",
2892 "access-control-class-ramping-step-size 5"});
2893
2894 /* Init and get first sysinfo */
2895 f_init_bts_and_check_sysinfo(0, expect_si := ?);
2896 last_si1 := g_system_information[0].si1;
2897 acc := last_si1.rach_control.acc;
2898 count := f_acc09_count_allowed(acc);
2899 /* Adm subset size was set to 0 above, so wait until all ACC are barred */
2900 while (count > 0) {
2901 last_si1 := f_recv_next_si1(0);
2902 acc := last_si1.rach_control.acc;
2903 count := f_acc09_count_allowed(acc);
2904 log("RSL: wait len()=0: GOT SI1 ACC len=", count, ": ", acc);
2905 }
2906
2907 /* Increase adm subset size, we should see ramping start up */
2908 f_bts_0_cfg(BSCVTY, {"access-control-class-rotate 10"});
2909 prev_count := 0;
2910 while (true) {
2911 last_si1 := f_recv_next_si1(0);
2912 acc := last_si1.rach_control.acc;
2913 count := f_acc09_count_allowed(acc);
2914 log("RSL: GOT SI1 ACC len=", count, ": ", acc);
2915
2916 if (prev_count > count) {
2917 setverdict(fail, "ACC allowed count dropped while expecting grow: ", prev_count, " -> ", count);
2918 break;
2919 }
2920
2921 if (count == 9) {
2922 break; /* Maximum reached (10 - 1 perm barred), done here */
2923 }
2924
2925 prev_count := count;
2926 }
2927
2928 setverdict(pass);
2929
2930 f_bts_0_cfg(BSCVTY, {"access-control-class-rotate 10",
2931 "rach access-control-class 4 allowed",
2932 "no access-control-class-ramping"});
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002933 f_shutdown_helper();
Pau Espin Pedrolc6136cd2020-07-24 13:20:02 +02002934}
2935
Harald Welte4003d112017-12-09 22:35:39 +01002936testcase TC_ctrl_msc_connection_status() runs on test_CT {
2937 var charstring ctrl_resp;
2938
Harald Welte89d42e82017-12-17 16:42:41 +01002939 f_init(1);
Harald Welte4003d112017-12-09 22:35:39 +01002940
2941 /* See https://osmocom.org/issues/2729 */
2942 f_ctrl_get_exp(IPA_CTRL, "msc_connection_status", "connected");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002943 f_shutdown_helper();
Harald Welte4003d112017-12-09 22:35:39 +01002944}
2945
Stefan Sperlingb041b3d2018-01-03 17:14:55 +01002946testcase TC_ctrl_msc0_connection_status() runs on test_CT {
2947 var charstring ctrl_resp;
2948
2949 f_init(1);
Stefan Sperlingb041b3d2018-01-03 17:14:55 +01002950
2951 f_ctrl_get_exp(IPA_CTRL, "msc.0.connection_status", "connected");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02002952 f_shutdown_helper();
Stefan Sperlingb041b3d2018-01-03 17:14:55 +01002953}
2954
Neels Hofmeyr0bc470d2021-08-21 13:37:13 +02002955/* Verify correct stats on the number of configured and connected MSCs */
2956private function f_tc_stat_num_msc_connected_msc_connhdlr(integer expect_num_msc_connected) runs on MSC_ConnHdlr {
2957 g_pars := f_gen_test_hdlr_pars();
2958 var StatsDExpects expect := {
2959 { name := "TTCN3.bsc.0.num_msc.connected", mtype := "g", min := expect_num_msc_connected, max := expect_num_msc_connected },
2960 { name := "TTCN3.bsc.0.num_msc.total", mtype := "g", min := NUM_MSC, max := NUM_MSC }
2961 };
2962 f_statsd_expect(expect);
2963}
2964
2965private function f_tc_stat_num_msc_connected_test_ct(void_fn tc_fn, integer nr_msc) runs on test_CT
2966{
2967 var MSC_ConnHdlr vc_conn;
2968
2969 f_init(nr_bts := 1, handler_mode := true, nr_msc := nr_msc);
2970 f_sleep(1.0);
2971 vc_conn := f_start_handler(tc_fn);
2972 vc_conn.done;
2973
2974 /* Also verify stat exposed on CTRL interface */
2975 f_ctrl_get_exp(IPA_CTRL, "stat_item.last.bsc.0.num_msc:connected", int2str(nr_msc));
2976 f_ctrl_get_exp(IPA_CTRL, "stat_item.last.bsc.0.num_msc:total", int2str(NUM_MSC));
2977
2978 f_shutdown_helper();
2979}
2980
2981/* Verify that when 1 MSC is active, that num_msc:connected reports 1. */
2982private function f_tc_stat_num_msc_connected_1(charstring id) runs on MSC_ConnHdlr {
2983 f_tc_stat_num_msc_connected_msc_connhdlr(1);
2984}
2985testcase TC_stat_num_msc_connected_1() runs on test_CT {
2986 f_tc_stat_num_msc_connected_test_ct(refers(f_tc_stat_num_msc_connected_1), 1);
2987}
2988
2989/* Verify that when 2 MSCs are active, that num_msc:connected reports 2. */
2990private function f_tc_stat_num_msc_connected_2(charstring id) runs on MSC_ConnHdlr {
2991 f_tc_stat_num_msc_connected_msc_connhdlr(2);
2992}
2993testcase TC_stat_num_msc_connected_2() runs on test_CT {
2994 f_tc_stat_num_msc_connected_test_ct(refers(f_tc_stat_num_msc_connected_2), 2);
2995}
2996
2997/* Verify that when 3 MSCs are active, that num_msc:connected reports 3. */
2998private function f_tc_stat_num_msc_connected_3(charstring id) runs on MSC_ConnHdlr {
2999 f_tc_stat_num_msc_connected_msc_connhdlr(3);
3000}
3001testcase TC_stat_num_msc_connected_3() runs on test_CT {
3002 f_tc_stat_num_msc_connected_test_ct(refers(f_tc_stat_num_msc_connected_3), 3);
3003}
3004
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +02003005/* Verify correct stats on the number of configured and connected MSCs */
3006private function f_tc_stat_num_bts_connected_msc_connhdlr(integer expect_num_bts_connected) runs on MSC_ConnHdlr {
3007 g_pars := f_gen_test_hdlr_pars();
3008 var StatsDExpects expect := {
3009 { name := "TTCN3.bsc.0.num_bts.oml_connected", mtype := "g", min := expect_num_bts_connected, max := NUM_BTS_CFG },
3010 { name := "TTCN3.bsc.0.num_bts.all_trx_rsl_connected", mtype := "g", min := expect_num_bts_connected, max := expect_num_bts_connected },
3011 { name := "TTCN3.bsc.0.num_bts.total", mtype := "g", min := NUM_BTS_CFG, max := NUM_BTS_CFG },
3012 { name := "TTCN3.bsc.0.num_trx.rsl_connected", mtype := "g", min := expect_num_bts_connected, max := expect_num_bts_connected },
3013 { name := "TTCN3.bsc.0.num_trx.total", mtype := "g", min := NUM_BTS_CFG, max := NUM_BTS_CFG }
3014 };
3015 f_statsd_expect(expect);
3016}
3017
3018private function f_tc_stat_num_bts_connected_test_ct(void_fn tc_fn, integer nr_bts) runs on test_CT {
3019 var MSC_ConnHdlr vc_conn;
3020
3021 f_init(nr_bts := nr_bts, handler_mode := true, nr_msc := 1);
3022 f_sleep(1.0);
3023 vc_conn := f_start_handler(tc_fn);
3024 vc_conn.done;
3025
3026 /* Also verify stat exposed on CTRL interface */
3027 f_ctrl_get_exp(IPA_CTRL, "stat_item.last.bsc.0.num_bts:all_trx_rsl_connected", int2str(nr_bts));
3028 f_ctrl_get_exp(IPA_CTRL, "stat_item.last.bsc.0.num_bts:total", int2str(NUM_BTS_CFG));
3029 f_ctrl_get_exp(IPA_CTRL, "stat_item.last.bsc.0.num_trx:rsl_connected", int2str(nr_bts));
3030 f_ctrl_get_exp(IPA_CTRL, "stat_item.last.bsc.0.num_trx:total", int2str(NUM_BTS_CFG));
3031
Neels Hofmeyra41ae302021-09-06 22:06:02 +02003032 /* Verify rf_states exposed on CTRL interface */
3033 var charstring expect_net_rf_states := "";
3034 for (var integer i := 0; i < NUM_BTS_CFG; i := i + 1) {
3035 var charstring expect_bts_rf_states := int2str(i) & ",0,";
3036 if (i < NUM_BTS) {
3037 /* In these tests, OML for the first NUM_BTS are always connected via osmo-bts-omldummy */
3038 expect_bts_rf_states := expect_bts_rf_states & "operational,unlocked,";
3039 } else {
3040 /* For remaining i < NUM_BTS_CFG, OML is not connected, i.e. inoperational */
3041 expect_bts_rf_states := expect_bts_rf_states & "inoperational,locked,";
3042 }
3043 /* The RF policy is still global in osmo-bsc, i.e. always "on" */
3044 expect_bts_rf_states := expect_bts_rf_states & "on,";
3045 if (i < nr_bts) {
3046 /* For BTS where RSL is connected, the RSL state will be "up" */
3047 expect_bts_rf_states := expect_bts_rf_states & "rsl-up;";
3048 } else {
3049 expect_bts_rf_states := expect_bts_rf_states & "rsl-down;";
3050 }
3051
3052 f_ctrl_get_exp(IPA_CTRL, "bts." & int2str(i) & ".rf_states", expect_bts_rf_states);
3053 expect_net_rf_states := expect_net_rf_states & expect_bts_rf_states;
3054 }
3055 f_ctrl_get_exp(IPA_CTRL, "rf_states", expect_net_rf_states);
3056
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +02003057 f_shutdown_helper();
3058}
3059
3060/* Verify that when 1 BTS is connected, that num_{bts,trx}:*_connected reports 1. */
3061private function f_tc_stat_num_bts_connected_1(charstring id) runs on MSC_ConnHdlr {
3062 f_tc_stat_num_bts_connected_msc_connhdlr(1);
3063}
3064testcase TC_stat_num_bts_connected_1() runs on test_CT {
3065 f_tc_stat_num_bts_connected_test_ct(refers(f_tc_stat_num_bts_connected_1), 1);
3066}
3067
3068/* Verify that when 2 BTS is connected, that num_{bts,trx}:*_connected reports 2. */
3069private function f_tc_stat_num_bts_connected_2(charstring id) runs on MSC_ConnHdlr {
3070 f_tc_stat_num_bts_connected_msc_connhdlr(2);
3071}
3072testcase TC_stat_num_bts_connected_2() runs on test_CT {
3073 f_tc_stat_num_bts_connected_test_ct(refers(f_tc_stat_num_bts_connected_2), 2);
3074}
3075
3076/* Verify that when 3 BTS is connected, that num_{bts,trx}:*_connected reports 3. */
3077private function f_tc_stat_num_bts_connected_3(charstring id) runs on MSC_ConnHdlr {
3078 f_tc_stat_num_bts_connected_msc_connhdlr(3);
3079}
3080testcase TC_stat_num_bts_connected_3() runs on test_CT {
3081 f_tc_stat_num_bts_connected_test_ct(refers(f_tc_stat_num_bts_connected_3), 3);
3082}
3083
Harald Welte4003d112017-12-09 22:35:39 +01003084testcase TC_ctrl() runs on test_CT {
3085 var charstring ctrl_resp;
3086
Harald Welte89d42e82017-12-17 16:42:41 +01003087 f_init(1);
Harald Welte4003d112017-12-09 22:35:39 +01003088
3089 /* all below values must match the osmo-bsc.cfg config file used */
3090
Harald Welte6a129692018-03-17 17:30:14 +01003091 f_ctrl_get_exp(IPA_CTRL, "mcc", "001");
3092 f_ctrl_get_exp(IPA_CTRL, "mnc", "01");
Oliver Smith75aa0202019-08-19 14:17:50 +02003093 f_ctrl_get_exp(IPA_CTRL, "number-of-bts", "4");
Harald Welte4003d112017-12-09 22:35:39 +01003094
3095 var integer bts_nr := 0;
3096 f_ctrl_get_exp_bts(IPA_CTRL, bts_nr, "location-area-code", "1");
3097 f_ctrl_get_exp_bts(IPA_CTRL, bts_nr, "cell-identity", "0");
3098 f_ctrl_get_exp_bts(IPA_CTRL, bts_nr, "oml-connection-state", "connected");
3099 f_ctrl_get_exp_bts(IPA_CTRL, bts_nr, "gprs-mode", "gprs");
3100 f_ctrl_get_exp_bts(IPA_CTRL, bts_nr, "rf_state", "operational,unlocked,on");
3101 f_ctrl_get_exp_trx(IPA_CTRL, bts_nr, 0, "arfcn", "871");
3102 f_ctrl_get_exp_trx(IPA_CTRL, bts_nr, 0, "max-power-reduction", "20");
3103
3104 var integer uptime := str2int(f_ctrl_get_bts(IPA_CTRL, bts_nr, "oml-uptime"));
3105 f_sleep(2.0);
3106 if (str2int(f_ctrl_get_bts(IPA_CTRL, bts_nr, "oml-uptime")) < uptime+1) {
3107 setverdict(fail, "oml-uptime not incrementing as expected");
3108 }
3109 /* TODO: Disconnect RSL, imply that OML is disconnected and check for uptime zero? */
3110
3111 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bsc", 0, "paging:attempted", 0);
3112
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003113 f_shutdown_helper();
Harald Welte96c94412017-12-09 03:12:45 +01003114}
3115
Pau Espin Pedrol5a2d7432019-06-07 19:43:45 +02003116/* Verify that Upon receival of SET "location", BSC forwards a TRAP
3117 "location-state" over the SCCPlite IPA conn */
3118testcase TC_ctrl_location() runs on test_CT {
3119 var MSC_ConnHdlr vc_conn;
3120 var integer bts_nr := 0;
3121
3122 f_init(1, true);
3123 f_sleep(1.0);
3124
3125 f_ctrl_set_bts(IPA_CTRL, bts_nr, "location", "1234567,fix3d,0.340000,0.560000,0.780000");
3126 f_ctrl_exp_trap(SCCPLITE_IPA_CTRL, "bts." & int2str(bts_nr) & ".location-state",
3127 "1234567,fix3d,0.340000,0.560000,0.780000,operational,unlocked,on,001,01");
3128
3129 f_ctrl_set(SCCPLITE_IPA_CTRL, "rf_locked", "1");
3130 f_sleep(2.0);
3131
3132 f_ctrl_set_bts(IPA_CTRL, bts_nr, "location", "1234888,fix3d,0.350000,0.570000,0.790000");
3133 f_ctrl_exp_trap(SCCPLITE_IPA_CTRL, "bts." & int2str(bts_nr) & ".location-state",
3134 "1234888,fix3d,0.350000,0.570000,0.790000,operational,locked,off,001,01");
3135
3136 /* should match the one from config */
3137 f_ctrl_set(SCCPLITE_IPA_CTRL, "rf_locked", "0");
3138
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003139 f_shutdown_helper();
Pau Espin Pedrol5a2d7432019-06-07 19:43:45 +02003140}
3141
Harald Welte6f521d82017-12-11 19:52:02 +01003142
3143/***********************************************************************
3144 * Paging Testing
3145 ***********************************************************************/
3146
3147type record Cell_Identity {
3148 GsmMcc mcc,
3149 GsmMnc mnc,
3150 GsmLac lac,
3151 GsmCellId ci
3152};
Harald Welte24135bd2018-03-17 19:27:53 +01003153private const Cell_Identity cid := { '001'H, '01'H, 1, 0 };
Stefan Sperling049a86e2018-03-20 15:51:00 +01003154private const Cell_Identity unknown_cid := { '678'H, 'f90'H, 1, 0 };
Harald Welte6f521d82017-12-11 19:52:02 +01003155
Harald Welte5d1a2202017-12-13 19:51:29 +01003156type set of integer BtsIdList;
3157
3158private function f_bts_in_list(integer bts_id, BtsIdList bts_ids) return boolean {
3159 for (var integer j := 0; j < sizeof(bts_ids); j := j + 1) {
3160 if (bts_id == bts_ids[j]) {
3161 return true;
3162 }
3163 }
3164 return false;
3165}
Harald Welte6f521d82017-12-11 19:52:02 +01003166
3167/* core paging test helper function; used by most paging test cases */
3168private function f_pageing_helper(hexstring imsi,
3169 template BSSMAP_FIELD_CellIdentificationList cid_list,
Harald Welte5d1a2202017-12-13 19:51:29 +01003170 BtsIdList bts_ids := { 0 },
Harald Welte6f521d82017-12-11 19:52:02 +01003171 template RSL_ChanNeeded rsl_chneed := omit,
Vadim Yanitskiycc4623d2020-03-28 06:14:06 +07003172 template (omit) OCT4 tmsi := omit) runs on test_CT
Harald Welte6f521d82017-12-11 19:52:02 +01003173{
3174 var template BSSMAP_IE_ChannelNeeded bssmap_chneed;
Vadim Yanitskiycc4623d2020-03-28 06:14:06 +07003175 var template MobileIdentityV mi;
Harald Welte6f521d82017-12-11 19:52:02 +01003176 var RSL_Message rx_rsl;
3177 var integer paging_group := hex2int(imsi[lengthof(imsi)-1]);
Harald Welte5d1a2202017-12-13 19:51:29 +01003178 var integer i;
Harald Welte6f521d82017-12-11 19:52:02 +01003179
3180 f_init();
Harald Welte6f521d82017-12-11 19:52:02 +01003181
3182 /* Clear the queue, it might still contain stuff like BCCH FILLING */
Harald Weltec3068592018-03-17 19:55:31 +01003183 for (i := 0; i < NUM_BTS; i := i + 1) {
3184 IPA_RSL[i].clear;
Harald Welte5d1a2202017-12-13 19:51:29 +01003185 }
Harald Welte6f521d82017-12-11 19:52:02 +01003186
3187 if (isvalue(rsl_chneed)) {
3188 /* The values of 08.08 3.2.2.36 and 08.58 9.3.40 are luckily identical */
3189 bssmap_chneed := ts_BSSMAP_IE_ChanNeeded(int2bit(enum2int(valueof(rsl_chneed)),2));
3190 } else {
3191 bssmap_chneed := omit;
3192 }
3193
Neels Hofmeyrf246a922020-05-13 02:27:10 +02003194 BSSAP.send(ts_BSSAP_UNITDATA_req(g_bssap[0].sccp_addr_peer, g_bssap[0].sccp_addr_own,
3195 ts_BSSMAP_Paging(imsi, cid_list, tmsi, bssmap_chneed)));
Harald Welte6f521d82017-12-11 19:52:02 +01003196
Vadim Yanitskiycc4623d2020-03-28 06:14:06 +07003197 if (not istemplatekind(tmsi, "omit")) {
3198 mi := t_MI_TMSI(tmsi);
Harald Welte6f521d82017-12-11 19:52:02 +01003199 } else {
Vadim Yanitskiycc4623d2020-03-28 06:14:06 +07003200 mi := tr_MI_IMSI(imsi);
Harald Welte6f521d82017-12-11 19:52:02 +01003201 }
Vadim Yanitskiycc4623d2020-03-28 06:14:06 +07003202
Harald Welte5d1a2202017-12-13 19:51:29 +01003203 for (i := 0; i < sizeof(bts_ids); i := i + 1) {
Vadim Yanitskiycc4623d2020-03-28 06:14:06 +07003204 rx_rsl := f_exp_ipa_rx(bts_ids[i], tr_RSL_PAGING_CMD(mi));
Harald Welte5d1a2202017-12-13 19:51:29 +01003205 /* check channel type, paging group */
3206 if (rx_rsl.ies[1].body.paging_group != paging_group) {
3207 setverdict(fail, "Paging for wrong paging group");
3208 }
3209 if (ispresent(rsl_chneed) and
3210 rx_rsl.ies[3].body.chan_needed.chan_needed != valueof(rsl_chneed)) {
3211 setverdict(fail, "RSL Channel Needed != BSSMAP Channel Needed");
3212 }
Harald Welte6f521d82017-12-11 19:52:02 +01003213 }
Harald Welte2fccd982018-01-31 15:48:19 +01003214 f_sleep(2.0);
Harald Welte5d1a2202017-12-13 19:51:29 +01003215 /* do a quick check on all not-included BTSs if they received paging */
3216 for (i := 0; i < NUM_BTS; i := i + 1) {
3217 timer T := 0.1;
3218 if (f_bts_in_list(i, bts_ids)) {
3219 continue;
3220 }
3221 T.start;
3222 alt {
Vadim Yanitskiy9b4e3562020-05-25 21:40:52 +07003223 [] IPA_RSL[i].receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD(mi))) {
Harald Welte5d1a2202017-12-13 19:51:29 +01003224 setverdict(fail, "Paging on BTS ", i, " which is not part of ", bts_ids);
3225 }
3226 [] IPA_RSL[i].receive { repeat; }
3227 [] T.timeout { }
3228 }
Harald Welte6f521d82017-12-11 19:52:02 +01003229 }
3230
3231 setverdict(pass);
3232}
3233
Harald Welte5d1a2202017-12-13 19:51:29 +01003234const BtsIdList c_BtsId_all := { 0, 1, 2 };
Harald Welte751d3eb2018-01-31 15:51:06 +01003235const BtsIdList c_BtsId_none := { };
Harald Welte5d1a2202017-12-13 19:51:29 +01003236const BtsIdList c_BtsId_LAC1 := { 0, 1 };
3237const BtsIdList c_BtsId_LAC2 := { 2 };
3238
Harald Welte6f521d82017-12-11 19:52:02 +01003239/* PAGING by IMSI + TMSI */
3240testcase TC_paging_imsi_nochan() runs on test_CT {
3241 var BSSMAP_FIELD_CellIdentificationList cid_list;
3242 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Philipp Maier8c04b0a2018-02-23 13:48:48 +01003243 f_pageing_helper('001010100000001'H, cid_list, c_BtsId_all, omit, omit);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003244 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003245}
3246
3247/* PAGING by IMSI + TMSI */
3248testcase TC_paging_tmsi_nochan() runs on test_CT {
3249 var BSSMAP_FIELD_CellIdentificationList cid_list;
3250 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003251 f_pageing_helper('001010100000001'H, cid_list, c_BtsId_all, omit, 'A1B2C301'O);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003252 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003253}
3254
3255/* Paging with different "channel needed' values */
3256testcase TC_paging_tmsi_any() runs on test_CT {
3257 var BSSMAP_FIELD_CellIdentificationList cid_list;
3258 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003259 f_pageing_helper('001010100000002'H, cid_list, c_BtsId_all, RSL_CHANNEED_ANY, 'A1B2C302'O);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003260 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003261}
3262testcase TC_paging_tmsi_sdcch() runs on test_CT {
3263 var BSSMAP_FIELD_CellIdentificationList cid_list;
3264 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003265 f_pageing_helper('001010100000003'H, cid_list, c_BtsId_all, RSL_CHANNEED_SDCCH, 'A1B2C303'O);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003266 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003267}
3268testcase TC_paging_tmsi_tch_f() runs on test_CT {
3269 var BSSMAP_FIELD_CellIdentificationList cid_list;
3270 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003271 f_pageing_helper('001010000000004'H, cid_list, c_BtsId_all, RSL_CHANNEED_TCH_F, 'A1B2C304'O);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003272 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003273}
3274testcase TC_paging_tmsi_tch_hf() runs on test_CT {
3275 var BSSMAP_FIELD_CellIdentificationList cid_list;
3276 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003277 f_pageing_helper('001010000000005'H, cid_list, c_BtsId_all, RSL_CHANNEED_TCH_ForH, 'A1B2C305'O);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003278 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003279}
3280
3281/* Paging by CGI */
3282testcase TC_paging_imsi_nochan_cgi() runs on test_CT {
3283 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3284 cid_list := { cIl_CGI := { ts_BSSMAP_CI_CGI(cid.mcc, cid.mnc, cid.lac, cid.ci) } };
Harald Welte5d1a2202017-12-13 19:51:29 +01003285 f_pageing_helper('001010000000006'H, cid_list, { 0 });
Philipp Maier282ca4b2018-02-27 17:17:00 +01003286 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003287}
3288
3289/* Paging by LAC+CI */
3290testcase TC_paging_imsi_nochan_lac_ci() runs on test_CT {
3291 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3292 cid_list := { cIl_LAC_CI := { ts_BSSMAP_CI_LAC_CI(cid.lac, cid.ci) } };
Harald Welte5d1a2202017-12-13 19:51:29 +01003293 f_pageing_helper('001010000000007'H, cid_list, { 0 });
Philipp Maier282ca4b2018-02-27 17:17:00 +01003294 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003295}
3296
3297/* Paging by CI */
3298testcase TC_paging_imsi_nochan_ci() runs on test_CT {
3299 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3300 cid_list := { cIl_CI := { ts_BSSMAP_CI_CI(cid.ci) } };
Harald Welte5d1a2202017-12-13 19:51:29 +01003301 f_pageing_helper('001010000000008'H, cid_list, { 0 });
Philipp Maier282ca4b2018-02-27 17:17:00 +01003302 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003303}
3304
3305/* Paging by LAI */
3306testcase TC_paging_imsi_nochan_lai() runs on test_CT {
3307 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3308 cid_list := { cIl_LAI := { ts_BSSMAP_CI_LAI(cid.mcc, cid.mnc, cid.lac) } };
Harald Welte5d1a2202017-12-13 19:51:29 +01003309 f_pageing_helper('001010000000009'H, cid_list, c_BtsId_LAC1);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003310 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003311}
3312
3313/* Paging by LAC */
3314testcase TC_paging_imsi_nochan_lac() runs on test_CT {
3315 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3316 cid_list := { cIl_LAC := { ts_BSSMAP_CI_LAC(cid.lac) } };
Harald Welte5d1a2202017-12-13 19:51:29 +01003317 f_pageing_helper('001010000000010'H, cid_list, c_BtsId_LAC1);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003318 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003319}
3320
3321/* Paging by "all in BSS" */
3322testcase TC_paging_imsi_nochan_all() runs on test_CT {
3323 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3324 cid_list := { cIl_allInBSS := ''O };
Harald Welte5d1a2202017-12-13 19:51:29 +01003325 f_pageing_helper('001010000000011'H, cid_list, c_BtsId_all);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003326 f_shutdown_helper();
Harald Welte6f521d82017-12-11 19:52:02 +01003327}
3328
Stefan Sperling7b5e1782018-03-20 19:32:43 +01003329/* Paging by PLMN+LAC+RNC; We do not implement this; Verify nothing is paged */
Harald Welte751d3eb2018-01-31 15:51:06 +01003330testcase TC_paging_imsi_nochan_plmn_lac_rnc() runs on test_CT {
3331 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3332 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 +01003333 f_pageing_helper('001010000000012'H, cid_list, c_BtsId_none);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003334 f_shutdown_helper();
Harald Welte751d3eb2018-01-31 15:51:06 +01003335}
Harald Welte6f521d82017-12-11 19:52:02 +01003336
Stefan Sperling7b5e1782018-03-20 19:32:43 +01003337/* Paging by RNC; We do not implement this; Verify nothing is paged */
Harald Welte751d3eb2018-01-31 15:51:06 +01003338testcase TC_paging_imsi_nochan_rnc() runs on test_CT {
3339 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3340 cid_list := { cIl_RNC := { int2oct(13, 2) } };
Stefan Sperling7b5e1782018-03-20 19:32:43 +01003341 f_pageing_helper('001010000000013'H, cid_list, c_BtsId_none);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003342 f_shutdown_helper();
Harald Welte751d3eb2018-01-31 15:51:06 +01003343}
3344
Stefan Sperling7b5e1782018-03-20 19:32:43 +01003345/* Paging by LAC+RNC; We do not implement; Verify nothing is paged */
Harald Welte751d3eb2018-01-31 15:51:06 +01003346testcase TC_paging_imsi_nochan_lac_rnc() runs on test_CT {
3347 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3348 cid_list := { cIl_LAC_RNC := { ts_BSSMAP_CI_LAC_RNC(cid.lac, 14) } };
Stefan Sperling7b5e1782018-03-20 19:32:43 +01003349 f_pageing_helper('001010000000014'H, cid_list, c_BtsId_none);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003350 f_shutdown_helper();
Harald Welte751d3eb2018-01-31 15:51:06 +01003351}
3352
Harald Welte6f521d82017-12-11 19:52:02 +01003353/* Paging on multiple cells (multiple entries in list): Verify all of them page */
Harald Welte751d3eb2018-01-31 15:51:06 +01003354testcase TC_paging_imsi_nochan_lacs() runs on test_CT {
3355 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3356 cid_list := { cIl_LAC := { ts_BSSMAP_CI_LAC(1), ts_BSSMAP_CI_LAC(2) } };
3357 f_pageing_helper('001010000000015'H, cid_list, c_BtsId_all);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003358 f_shutdown_helper();
Harald Welte751d3eb2018-01-31 15:51:06 +01003359}
3360
3361/* Paging on empty list: Verify none of them page */
3362testcase TC_paging_imsi_nochan_lacs_empty() runs on test_CT {
3363 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3364 cid_list := { cIl_LAC := { } };
3365 f_pageing_helper('001010000000016'H, cid_list, c_BtsId_none);
Philipp Maier282ca4b2018-02-27 17:17:00 +01003366 f_shutdown_helper();
Harald Welte751d3eb2018-01-31 15:51:06 +01003367}
3368
Stefan Sperling049a86e2018-03-20 15:51:00 +01003369/* Paging by CGI with unknown MCC/MNC: Verify nothing is paged. */
3370testcase TC_paging_imsi_nochan_cgi_unknown_cid() runs on test_CT {
3371 var template BSSMAP_FIELD_CellIdentificationList cid_list;
3372 cid_list := { cIl_CGI := { ts_BSSMAP_CI_CGI(unknown_cid.mcc, unknown_cid.mnc, unknown_cid.lac, unknown_cid.ci) } };
3373 f_pageing_helper('001010000000006'H, cid_list, c_BtsId_none);
3374 f_shutdown_helper();
3375}
3376
Harald Welte6f521d82017-12-11 19:52:02 +01003377/* Verify paging retransmission interval + count */
3378/* Verify paging stops after channel establishment */
Harald Welte6f521d82017-12-11 19:52:02 +01003379/* Test behavior under paging overload */
Harald Welteae026692017-12-09 01:03:01 +01003380
Harald Weltee65d40e2017-12-13 00:09:06 +01003381/* Verify PCH load */
3382testcase TC_paging_imsi_load() runs on test_CT {
3383 var BSSMAP_FIELD_CellIdentificationList cid_list;
3384 timer T := 4.0;
Harald Welte2caa1062018-03-17 18:19:05 +01003385 timer T_retrans := 1.0;
Harald Weltee65d40e2017-12-13 00:09:06 +01003386 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003387 f_pageing_helper('001010123456789'H, cid_list, c_BtsId_all);
Harald Weltee65d40e2017-12-13 00:09:06 +01003388
3389 /* tell BSC there is no paging space anymore */
3390 f_ipa_tx(0, ts_RSL_PAGING_LOAD_IND(0));
Harald Welte3b57ab52018-03-17 18:01:10 +01003391 f_sleep(0.2);
3392 IPA_RSL[0].clear;
Harald Weltee65d40e2017-12-13 00:09:06 +01003393
3394 /* Wait for 4 seconds if any more PAGING CMD are received on RSL. Normally,
3395 * there would be 8 retransmissions during 4 seconds */
3396 T.start;
Harald Welte2caa1062018-03-17 18:19:05 +01003397 T_retrans.start;
Harald Weltee65d40e2017-12-13 00:09:06 +01003398 alt {
Vadim Yanitskiy9b4e3562020-05-25 21:40:52 +07003399 [] IPA_RSL[0].receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD(?))) {
Harald Weltee65d40e2017-12-13 00:09:06 +01003400 setverdict(fail, "Received PAGING after LOAD_IND(0)");
Daniel Willmannafce8662018-07-06 23:11:32 +02003401 mtc.stop;
Harald Weltee65d40e2017-12-13 00:09:06 +01003402 }
Harald Welte2caa1062018-03-17 18:19:05 +01003403 [] T_retrans.timeout {
3404 /* re-trnsmit the zero-space LOAD IND to avoid BSC 'auto credit' */
3405 f_ipa_tx(0, ts_RSL_PAGING_LOAD_IND(0));
3406 T_retrans.start;
3407 repeat;
3408 }
Harald Weltee65d40e2017-12-13 00:09:06 +01003409 [] T.timeout {
3410 setverdict(pass);
3411 }
3412 }
Philipp Maier282ca4b2018-02-27 17:17:00 +01003413
3414 f_shutdown_helper();
Harald Weltee65d40e2017-12-13 00:09:06 +01003415}
3416
Harald Welte235ebf12017-12-15 14:18:16 +01003417/* Verify Paging Counter */
Harald Welte1ff69992017-12-14 12:31:17 +01003418testcase TC_paging_counter() runs on test_CT {
3419 var BSSMAP_FIELD_CellIdentificationList cid_list;
3420 timer T := 4.0;
3421 var integer i;
3422 var integer paging_attempted_bsc;
3423 var integer paging_attempted_bts[NUM_BTS];
Oliver Smith8b343d32021-11-26 13:01:42 +01003424 var integer paging_expired_bsc;
Harald Welte1ff69992017-12-14 12:31:17 +01003425 var integer paging_expired_bts[NUM_BTS];
3426 cid_list := valueof(ts_BSSMAP_CIL_noCell);
3427
3428 f_init();
3429
3430 /* read counters before paging */
3431 paging_attempted_bsc := f_ctrl_get_ratectr_abs(IPA_CTRL, "bsc", 0, "paging:attempted");
Oliver Smith8b343d32021-11-26 13:01:42 +01003432 if (Misc_Helpers.f_osmo_repo_is("nightly")) { /* osmo-bsc > 1.8.0 */
3433 paging_expired_bsc := f_ctrl_get_ratectr_abs(IPA_CTRL, "bsc", 0, "paging:expired");
3434 }
Harald Welte1ff69992017-12-14 12:31:17 +01003435 for (i := 0; i < NUM_BTS; i := i+1) {
3436 paging_attempted_bts[i] := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", i, "paging:attempted");
3437 paging_expired_bts[i] := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", i, "paging:expired");
3438 }
3439
3440 f_pageing_helper('001230000000001'H, cid_list, c_BtsId_all);
3441
3442 /* expect the attempted pages on BSC and each BTSs to have incremented by one */
3443 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bsc", 0, "paging:attempted", paging_attempted_bsc+1);
3444 for (i := 0; i < NUM_BTS; i := i+1) {
3445 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", i, "paging:attempted",
3446 paging_attempted_bts[i]+1);
3447 }
3448
3449 /* assume that 12s later the paging on all BTSs have expired and hence incremented by 1 */
3450 f_sleep(12.0);
Oliver Smith8b343d32021-11-26 13:01:42 +01003451 if (Misc_Helpers.f_osmo_repo_is("nightly")) { /* osmo-bsc > 1.8.0 */
3452 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bsc", 0, "paging:expired", paging_expired_bsc+1);
3453 }
Harald Welte1ff69992017-12-14 12:31:17 +01003454 for (i := 0; i < NUM_BTS; i := i+1) {
3455 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", i, "paging:expired",
3456 paging_expired_bts[i]+1);
3457 }
Harald Welte1ff69992017-12-14 12:31:17 +01003458
Philipp Maier282ca4b2018-02-27 17:17:00 +01003459 f_shutdown_helper();
Harald Welte1ff69992017-12-14 12:31:17 +01003460}
3461
3462
Harald Welte10985002017-12-12 09:29:15 +01003463/* Verify paging stops after A-RESET */
3464testcase TC_paging_imsi_a_reset() runs on test_CT {
3465 var BSSMAP_FIELD_CellIdentificationList cid_list;
3466 timer T := 3.0;
3467 cid_list := valueof(ts_BSSMAP_CIL_noCell);
Harald Welte5d1a2202017-12-13 19:51:29 +01003468 f_pageing_helper('001010123456789'H, cid_list, c_BtsId_all);
Harald Welte10985002017-12-12 09:29:15 +01003469
3470 /* Perform a BSSMAP Reset and wait for ACK */
Neels Hofmeyrf246a922020-05-13 02:27:10 +02003471 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 +01003472 alt {
Neels Hofmeyrf246a922020-05-13 02:27:10 +02003473 [] 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 +01003474 [] BSSAP.receive { repeat; }
3475 }
3476
Daniel Willmanncbef3982018-07-30 09:22:40 +02003477 /* Wait to avoid a possible race condition if a paging message is
3478 * received right before the reset ACK. */
3479 f_sleep(0.2);
3480
Harald Welte10985002017-12-12 09:29:15 +01003481 /* Clear the queue, it might still contain stuff like BCCH FILLING */
Philipp Maier1e6b4422018-02-23 14:02:13 +01003482 for (var integer i := 0; i < sizeof(IPA_RSL); i := i+1) {
3483 IPA_RSL[i].clear;
3484 }
Harald Welte10985002017-12-12 09:29:15 +01003485
3486 /* Wait for 3 seconds if any more PAGING CMD are received on RSL */
3487 T.start;
3488 alt {
Vadim Yanitskiy9b4e3562020-05-25 21:40:52 +07003489 [] IPA_RSL[0].receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD(?))) {
Harald Welte10985002017-12-12 09:29:15 +01003490 setverdict(fail, "Received PAGING after A-RESET");
Daniel Willmannafce8662018-07-06 23:11:32 +02003491 mtc.stop;
Harald Welte10985002017-12-12 09:29:15 +01003492 }
Vadim Yanitskiy9b4e3562020-05-25 21:40:52 +07003493 [] IPA_RSL[1].receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD(?))) {
Harald Welte5d1a2202017-12-13 19:51:29 +01003494 setverdict(fail, "Received PAGING after A-RESET");
Daniel Willmannafce8662018-07-06 23:11:32 +02003495 mtc.stop;
Harald Welte5d1a2202017-12-13 19:51:29 +01003496 }
Vadim Yanitskiy9b4e3562020-05-25 21:40:52 +07003497 [] IPA_RSL[2].receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD(?))) {
Harald Welte5d1a2202017-12-13 19:51:29 +01003498 setverdict(fail, "Received PAGING after A-RESET");
Daniel Willmannafce8662018-07-06 23:11:32 +02003499 mtc.stop;
Harald Welte5d1a2202017-12-13 19:51:29 +01003500 }
Harald Welte10985002017-12-12 09:29:15 +01003501 [] T.timeout {
3502 setverdict(pass);
3503 }
3504 }
Philipp Maier282ca4b2018-02-27 17:17:00 +01003505
3506 f_shutdown_helper();
Harald Welte10985002017-12-12 09:29:15 +01003507}
Harald Welteae026692017-12-09 01:03:01 +01003508
Philipp Maierf45824a2019-08-14 14:44:10 +02003509/* Verify how we handle unsolicited Paging Response. In case of an unsolicit
3510 * paging response we can not know which MSC is in charge, so we will blindly
3511 * pick the first configured MSC. This behavior is required in order to make
3512 * MT-CSFB calls working because in those cases the BSC can not know that the
3513 * MSC has already paged the subscriver via SGs. So any MT-CSFB call will look
3514 * like an unsolicited Paging Response to the MSC.
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +01003515 */
3516testcase TC_paging_resp_unsol() runs on test_CT {
3517
3518 f_init(1);
Philipp Maierf45824a2019-08-14 14:44:10 +02003519 timer T := 5.0;
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +01003520
3521 var BSSAP_N_CONNECT_ind rx_c_ind;
3522 var DchanTuple dt;
3523 var PDU_ML3_MS_NW l3 := valueof(ts_PAG_RESP(valueof(ts_MI_IMSI_LV('001010008880018'H))));
Philipp Maierf45824a2019-08-14 14:44:10 +02003524 var octetstring rr_pag_resp := enc_PDU_ML3_MS_NW(l3);
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +01003525
3526 /* Send CHAN RQD and wait for allocation; acknowledge it */
3527 dt.rsl_chan_nr := f_chreq_act_ack();
3528
3529 /* Send unsolicited Paging response (no matching Paging CMD stored in BSC) */
3530 f_ipa_tx(0, ts_RSL_EST_IND(dt.rsl_chan_nr, valueof(ts_RslLinkID_DCCH(0)), enc_PDU_ML3_MS_NW(l3)));
3531
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +01003532
Philipp Maierf45824a2019-08-14 14:44:10 +02003533 /* Expevct a CR with a matching Paging response on the A-Interface */
3534 T.start;
3535 alt {
3536 [] BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(rr_pag_resp))) {
3537 setverdict(pass);
3538 }
3539 [] BSSAP.receive {
3540 setverdict(fail, "Received unexpected message on A-Interface!");
3541 }
3542 [] T.timeout {
3543 setverdict(fail, "Received nothing on A-Interface!");
3544 }
3545 }
3546
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003547 f_shutdown_helper();
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +01003548}
3549
Harald Welte4e9b9cc2017-12-14 18:31:02 +01003550/* Test RSL link drop causes counter increment */
3551testcase TC_rsl_drop_counter() runs on test_CT {
3552 var integer rsl_fail;
3553
Harald Welte89d42e82017-12-17 16:42:41 +01003554 f_init(1);
Harald Welte4e9b9cc2017-12-14 18:31:02 +01003555
3556 rsl_fail := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", 0, "rsl_fail");
3557
3558 bts[0].rsl.vc_IPA.stop;
3559
3560 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", 0, "rsl_fail", rsl_fail+1);
3561
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003562 f_shutdown_helper();
Harald Welte4e9b9cc2017-12-14 18:31:02 +01003563}
3564
3565/* TODO: Test OML link drop causes counter increment */
3566
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003567/* The body of TC_rsl_unknown_unit_id() and TC_oml_unknown_unit_id() tests. */
3568function f_ipa_unknown_unit_id(integer mp_bsc_ipa_port) runs on test_CT return boolean {
3569 timer T := 10.0;
3570
3571 bts[0].rsl.id := "IPA-0-RSL";
Harald Welte71389132021-12-09 21:58:18 +01003572 bts[0].rsl.vc_IPA := IPA_Emulation_CT.create(bts[0].rsl.id & "-IPA") alive;
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003573 bts[0].rsl.ccm_pars := c_IPA_default_ccm_pars;
3574 bts[0].rsl.ccm_pars.name := "Osmocom TTCN-3 BTS Simulator";
Oliver Smith92c2bdb2019-08-20 15:11:24 +02003575 bts[0].rsl.ccm_pars.unit_id := "99/0/0"; /* value which is unknown at BTS */
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003576
Pau Espin Pedrol9a5b8ff2021-01-04 19:01:31 +01003577 f_ipa_ctrl_start_client(mp_bsc_ip, mp_bsc_ctrl_port);
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003578
3579 f_init_mgcp("VirtMSC");
3580
3581 /* start RSL/OML connection (XXX re-uses RSL port/protocol definitions for OML) */
3582 map(bts[0].rsl.vc_IPA:IPA_PORT, system:IPA);
3583 connect(bts[0].rsl.vc_IPA:IPA_RSL_PORT, self:IPA_RSL[0]);
3584 bts[0].rsl.vc_IPA.start(IPA_Emulation.main_client(mp_bsc_ip, mp_bsc_ipa_port, "", 10000, bts[0].rsl.ccm_pars));
3585
3586 /* wait for IPA OML link to connect and then disconnect */
3587 T.start;
3588 alt {
Vadim Yanitskiya2afacc2020-05-18 21:16:19 +07003589 [] IPA_RSL[0].receive(tr_ASP_IPA_EV(ASP_IPA_EVENT_DOWN)) {
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003590 T.stop;
3591 return true;
3592 }
3593 [] IPA_RSL[0].receive { repeat }
3594 [] T.timeout {
Daniel Willmannafce8662018-07-06 23:11:32 +02003595 return false;
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003596 }
3597 }
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003598 return false;
3599}
3600
3601/* BSC should close an RSL connection from a BTS with unknown unit ID (OS#2714). */
3602testcase TC_rsl_unknown_unit_id() runs on test_CT {
3603 if (f_ipa_unknown_unit_id(mp_bsc_rsl_port)) {
3604 setverdict(pass);
3605 } else {
3606 setverdict(fail, "Timeout RSL waiting for connection to close");
3607 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003608 f_shutdown_helper();
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003609}
3610
3611
3612/* BSC should close an RSL connection from a BTS with unknown unit ID (OS#2714). */
3613testcase TC_oml_unknown_unit_id() runs on test_CT {
3614 if (f_ipa_unknown_unit_id(mp_bsc_oml_port)) {
3615 setverdict(pass);
3616 } else {
3617 setverdict(fail, "Timeout OML waiting for connection to close");
3618 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003619 f_shutdown_helper();
Stefan Sperling830dc9d2018-02-12 21:08:28 +01003620}
3621
3622
Harald Weltec1a2fff2017-12-17 11:06:19 +01003623/***********************************************************************
Harald Welte6811d102019-04-14 22:23:14 +02003624 * "New world" test cases using RSL_Emulation + RAN_Emulation
Harald Weltec1a2fff2017-12-17 11:06:19 +01003625 ***********************************************************************/
3626
Harald Welte6811d102019-04-14 22:23:14 +02003627import from RAN_Emulation all;
Harald Welte47cd0e32020-08-21 12:39:11 +02003628import from BSSAP_LE_Emulation all;
Harald Weltec1a2fff2017-12-17 11:06:19 +01003629import from RSL_Emulation all;
3630import from MSC_ConnectionHandler all;
3631
3632type function void_fn(charstring id) runs on MSC_ConnHdlr;
3633
Harald Welte336820c2018-05-31 20:34:52 +02003634/* helper function to create and connect a MSC_ConnHdlr component */
Neels Hofmeyrf246a922020-05-13 02:27:10 +02003635private function f_connect_handler(inout MSC_ConnHdlr vc_conn, integer bssap_idx := 0) runs on test_CT {
3636 connect(vc_conn:RAN, g_bssap[bssap_idx].vc_RAN:PROC);
Daniel Willmann191e0d92018-01-17 12:44:35 +01003637 connect(vc_conn:MGCP_PROC, vc_MGCP:MGCP_PROC);
Harald Weltec1a2fff2017-12-17 11:06:19 +01003638 connect(vc_conn:RSL, bts[0].rsl.vc_RSL:CLIENT_PT);
Harald Weltef70df652018-01-29 22:00:23 +01003639 connect(vc_conn:RSL_PROC, bts[0].rsl.vc_RSL:RSL_PROC);
Philipp Maier88f4ae82018-03-01 14:00:58 +01003640 if (isvalue(bts[1])) {
Philipp Maier956a92f2018-02-16 10:58:07 +01003641 connect(vc_conn:RSL1, bts[1].rsl.vc_RSL:CLIENT_PT);
3642 connect(vc_conn:RSL1_PROC, bts[1].rsl.vc_RSL:RSL_PROC);
3643 }
Neels Hofmeyr91401012019-07-11 00:42:35 +02003644 if (isvalue(bts[2])) {
3645 connect(vc_conn:RSL2, bts[2].rsl.vc_RSL:CLIENT_PT);
3646 connect(vc_conn:RSL2_PROC, bts[2].rsl.vc_RSL:RSL_PROC);
3647 }
Neels Hofmeyrf246a922020-05-13 02:27:10 +02003648 connect(vc_conn:BSSAP, g_bssap[bssap_idx].vc_RAN:CLIENT);
Neels Hofmeyrcfe44062020-10-15 02:28:08 +02003649 if (mp_enable_lcs_tests) {
3650 connect(vc_conn:BSSAP_LE, g_bssap_le.vc_BSSAP_LE:CLIENT);
3651 connect(vc_conn:BSSAP_LE_PROC, g_bssap_le.vc_BSSAP_LE:PROC);
3652 }
Daniel Willmann191e0d92018-01-17 12:44:35 +01003653 connect(vc_conn:MGCP, vc_MGCP:MGCP_CLIENT);
Pau Espin Pedrolfd02ad42019-06-18 17:45:20 +02003654 connect(vc_conn:MGCP_MULTI, vc_MGCP:MGCP_CLIENT_MULTI);
Daniel Willmannebdecc02020-08-12 15:30:17 +02003655 connect(vc_conn:STATSD_PROC, vc_STATSD:STATSD_PROC);
Harald Welte336820c2018-05-31 20:34:52 +02003656}
3657
Neels Hofmeyrda436782021-07-20 22:09:06 +02003658function f_start_handler_create(template (omit) TestHdlrParams pars := omit)
Harald Welte336820c2018-05-31 20:34:52 +02003659runs on test_CT return MSC_ConnHdlr {
3660 var charstring id := testcasename();
3661 var MSC_ConnHdlr vc_conn;
Neels Hofmeyrf246a922020-05-13 02:27:10 +02003662 var integer bssap_idx := 0;
3663 if (isvalue(pars)) {
3664 bssap_idx := valueof(pars).mscpool.bssap_idx;
3665 }
Harald Welte336820c2018-05-31 20:34:52 +02003666 vc_conn := MSC_ConnHdlr.create(id);
Neels Hofmeyrf246a922020-05-13 02:27:10 +02003667 f_connect_handler(vc_conn, bssap_idx);
Neels Hofmeyrda436782021-07-20 22:09:06 +02003668 return vc_conn;
3669}
3670
3671function f_start_handler_run(MSC_ConnHdlr vc_conn, void_fn fn, template (omit) TestHdlrParams pars := omit)
3672runs on test_CT return MSC_ConnHdlr {
3673 var charstring id := testcasename();
Neels Hofmeyr1708d1b2020-10-10 16:56:48 +02003674 /* Emit a marker to appear in the SUT's own logging output */
Neels Hofmeyrda436782021-07-20 22:09:06 +02003675 f_logp(BSCVTY, id & "() start");
Harald Weltea0630032018-03-20 21:09:55 +01003676 vc_conn.start(f_handler_init(fn, id, pars));
Harald Weltec1a2fff2017-12-17 11:06:19 +01003677 return vc_conn;
3678}
3679
Neels Hofmeyrda436782021-07-20 22:09:06 +02003680function f_start_handler(void_fn fn, template (omit) TestHdlrParams pars := omit)
3681runs on test_CT return MSC_ConnHdlr {
3682 return f_start_handler_run(f_start_handler_create(pars), fn, pars);
3683}
3684
Harald Weltea0630032018-03-20 21:09:55 +01003685/* first function inside ConnHdlr component; sets g_pars + starts function */
3686private function f_handler_init(void_fn fn, charstring id, template (omit) TestHdlrParams pars := omit)
3687runs on MSC_ConnHdlr {
3688 if (isvalue(pars)) {
3689 g_pars := valueof(pars);
3690 }
3691 fn.apply(id);
3692}
3693
Oliver Smith26a3db72021-07-09 13:51:29 +02003694private function f_vty_encryption_a5(charstring options) runs on test_CT {
3695 f_vty_transceive(BSCVTY, "configure terminal");
3696 f_vty_transceive(BSCVTY, "network");
3697 f_vty_transceive(BSCVTY, "encryption a5 " & options);
3698 f_vty_transceive(BSCVTY, "exit");
3699 f_vty_transceive(BSCVTY, "exit");
3700}
3701
3702private function f_vty_encryption_a5_reset() runs on test_CT {
3703 /* keep in sync with docker-playground.git ttcn3-bsc-test/osmo-bsc.cfg */
3704 f_vty_encryption_a5("0 1 3");
3705}
3706
Harald Welte3c86ea02018-05-10 22:28:05 +02003707/* Establish signalling channel (non-assignment case) followed by cipher mode */
3708private function f_tc_ciph_mode_a5(charstring id) runs on MSC_ConnHdlr {
Harald Welteed848512018-05-24 22:27:58 +02003709 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
3710 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Harald Welte3c86ea02018-05-10 22:28:05 +02003711 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelTypeSIGNAL);
Philipp Maier23000732018-05-18 11:25:37 +02003712 ass_cmd.pdu.bssmap.assignmentRequest.circuitIdentityCode := omit;
3713 ass_cmd.pdu.bssmap.assignmentRequest.aoIPTransportLayer := omit;
3714 exp_compl.pdu.bssmap.assignmentComplete.circuitIdentityCode := omit;
3715 exp_compl.pdu.bssmap.assignmentComplete.aoIPTransportLayer := omit;
Harald Welte3c86ea02018-05-10 22:28:05 +02003716
Philipp Maier23000732018-05-18 11:25:37 +02003717 f_establish_fully(ass_cmd, exp_compl);
Harald Welte3c86ea02018-05-10 22:28:05 +02003718}
3719testcase TC_ciph_mode_a5_0() runs on test_CT {
3720 var MSC_ConnHdlr vc_conn;
Philipp Maier48604732018-10-09 15:00:37 +02003721 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte3c86ea02018-05-10 22:28:05 +02003722 pars.encr := valueof(t_EncrParams('01'O, f_rnd_octstring(8)));
3723
3724 f_init(1, true);
3725 f_sleep(1.0);
3726 vc_conn := f_start_handler(refers(f_tc_ciph_mode_a5), pars);
3727 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003728 f_shutdown_helper();
Harald Welte3c86ea02018-05-10 22:28:05 +02003729}
3730testcase TC_ciph_mode_a5_1() runs on test_CT {
3731 var MSC_ConnHdlr vc_conn;
Philipp Maier48604732018-10-09 15:00:37 +02003732 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte3c86ea02018-05-10 22:28:05 +02003733 pars.encr := valueof(t_EncrParams('02'O, f_rnd_octstring(8)));
3734
3735 f_init(1, true);
3736 f_sleep(1.0);
3737 vc_conn := f_start_handler(refers(f_tc_ciph_mode_a5), pars);
3738 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003739 f_shutdown_helper();
Harald Welte3c86ea02018-05-10 22:28:05 +02003740}
Oliver Smith50b98122021-07-09 15:00:28 +02003741/* OS#4975: verify that A5/2 is preferred over A5/0 */
3742testcase TC_ciph_mode_a5_2_0() runs on test_CT {
3743 var MSC_ConnHdlr vc_conn;
3744 var TestHdlrParams pars := f_gen_test_hdlr_pars();
3745
3746 pars.encr := valueof(t_EncrParams('05'O, f_rnd_octstring(8))); /* A5/0 and A5/2 (0x01|0x04)*/
3747 pars.encr_exp_enc_alg := '04'O; /* A5/2 */
3748
3749 f_init(1, true);
3750 f_vty_encryption_a5("0 1 2 3");
3751 f_sleep(1.0);
3752 vc_conn := f_start_handler(refers(f_tc_ciph_mode_a5), pars);
3753 vc_conn.done;
3754 f_vty_encryption_a5_reset();
3755 f_shutdown_helper();
3756}
Oliver Smith1dff88d2021-07-09 08:45:51 +02003757/* OS#4975: verify that A5/1 is preferred over A5/2 */
3758testcase TC_ciph_mode_a5_2_1() runs on test_CT {
3759 var MSC_ConnHdlr vc_conn;
3760 var TestHdlrParams pars := f_gen_test_hdlr_pars();
3761
3762 pars.encr := valueof(t_EncrParams('06'O, f_rnd_octstring(8))); /* A5/1 and A5/2 (0x02|0x04)*/
3763 pars.encr_exp_enc_alg := '02'O; /* A5/1 */
3764
3765 f_init(1, true);
3766 f_vty_encryption_a5("1 2");
3767 f_sleep(1.0);
3768 vc_conn := f_start_handler(refers(f_tc_ciph_mode_a5), pars);
3769 vc_conn.done;
3770 f_vty_encryption_a5_reset();
3771 f_shutdown_helper();
3772}
Harald Welte3c86ea02018-05-10 22:28:05 +02003773testcase TC_ciph_mode_a5_3() runs on test_CT {
3774 var MSC_ConnHdlr vc_conn;
Philipp Maier48604732018-10-09 15:00:37 +02003775 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte3c86ea02018-05-10 22:28:05 +02003776 pars.encr := valueof(t_EncrParams('08'O, f_rnd_octstring(8)));
3777
3778 f_init(1, true);
3779 f_sleep(1.0);
3780 vc_conn := f_start_handler(refers(f_tc_ciph_mode_a5), pars);
3781 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003782 f_shutdown_helper();
Harald Welte3c86ea02018-05-10 22:28:05 +02003783}
Neels Hofmeyr81ad27f2021-06-11 00:09:40 +02003784/* Establish a Signalling channel with A5/4 encryption. */
3785testcase TC_ciph_mode_a5_4() runs on test_CT {
3786 var MSC_ConnHdlr vc_conn;
3787 var TestHdlrParams pars := f_gen_test_hdlr_pars();
3788 pars.encr := valueof(t_EncrParams('10'O, f_rnd_octstring(8), f_rnd_octstring(16)));
Harald Welte3c86ea02018-05-10 22:28:05 +02003789
Neels Hofmeyr81ad27f2021-06-11 00:09:40 +02003790 f_init(1, true);
Oliver Smith26a3db72021-07-09 13:51:29 +02003791 f_vty_encryption_a5("0 1 3 4");
Neels Hofmeyr81ad27f2021-06-11 00:09:40 +02003792 f_sleep(1.0);
3793 vc_conn := f_start_handler(refers(f_tc_ciph_mode_a5), pars);
3794 vc_conn.done;
Oliver Smith26a3db72021-07-09 13:51:29 +02003795 f_vty_encryption_a5_reset();
Neels Hofmeyr81ad27f2021-06-11 00:09:40 +02003796 f_shutdown_helper();
3797}
Pau Espin Pedrol07866632020-09-03 19:10:55 +02003798/* establish initial channel, enable ciphering followed by assignment to ciphered channel */
3799private function f_tc_assignment_aoip_tla_v6(charstring id) runs on MSC_ConnHdlr {
3800 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
3801 var PDU_BSSAP ass_cmd := f_gen_ass_req(aoip_tla := "::3");
3802 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
3803 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
3804
3805 f_establish_fully(ass_cmd, exp_compl);
3806}
3807testcase TC_assignment_aoip_tla_v6() runs on test_CT {
3808 var MSC_ConnHdlr vc_conn;
3809 var TestHdlrParams pars := f_gen_test_hdlr_pars();
3810
3811 f_init(1, true);
3812 f_sleep(1.0);
3813 vc_conn := f_start_handler(refers(f_tc_assignment_aoip_tla_v6), pars);
3814 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003815 f_shutdown_helper();
Pau Espin Pedrol07866632020-09-03 19:10:55 +02003816}
3817
Harald Welte3c86ea02018-05-10 22:28:05 +02003818
3819/* establish initial channel, enable ciphering followed by assignment to ciphered channel */
Harald Welte651fcdc2018-05-10 20:23:16 +02003820private function f_tc_assignment_fr_a5(charstring id) runs on MSC_ConnHdlr {
Harald Welteed848512018-05-24 22:27:58 +02003821 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
3822 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Harald Weltec1a2fff2017-12-17 11:06:19 +01003823
Harald Welte552620d2017-12-16 23:21:36 +01003824 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
3825 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
Harald Welte73cd2712017-12-17 00:44:52 +01003826
Harald Weltea0630032018-03-20 21:09:55 +01003827 f_establish_fully(ass_cmd, exp_compl);
Harald Welte552620d2017-12-16 23:21:36 +01003828}
Harald Welte552620d2017-12-16 23:21:36 +01003829testcase TC_assignment_fr_a5_0() runs on test_CT {
3830 var MSC_ConnHdlr vc_conn;
Philipp Maier48604732018-10-09 15:00:37 +02003831 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte651fcdc2018-05-10 20:23:16 +02003832 pars.encr := valueof(t_EncrParams('01'O, f_rnd_octstring(8)));
Harald Welte552620d2017-12-16 23:21:36 +01003833
Harald Welte89d42e82017-12-17 16:42:41 +01003834 f_init(1, true);
Harald Welte552620d2017-12-16 23:21:36 +01003835 f_sleep(1.0);
Harald Welte651fcdc2018-05-10 20:23:16 +02003836 vc_conn := f_start_handler(refers(f_tc_assignment_fr_a5), pars);
Harald Welte552620d2017-12-16 23:21:36 +01003837 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003838 f_shutdown_helper();
Harald Welte552620d2017-12-16 23:21:36 +01003839}
Harald Welte552620d2017-12-16 23:21:36 +01003840testcase TC_assignment_fr_a5_1() runs on test_CT {
Harald Weltec1a2fff2017-12-17 11:06:19 +01003841 var MSC_ConnHdlr vc_conn;
Philipp Maier48604732018-10-09 15:00:37 +02003842 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte651fcdc2018-05-10 20:23:16 +02003843 pars.encr := valueof(t_EncrParams('02'O, f_rnd_octstring(8)));
Harald Weltec1a2fff2017-12-17 11:06:19 +01003844
Harald Welte89d42e82017-12-17 16:42:41 +01003845 f_init(1, true);
Harald Weltec1a2fff2017-12-17 11:06:19 +01003846 f_sleep(1.0);
Harald Welte651fcdc2018-05-10 20:23:16 +02003847 vc_conn := f_start_handler(refers(f_tc_assignment_fr_a5), pars);
3848 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003849 f_shutdown_helper();
Harald Welte651fcdc2018-05-10 20:23:16 +02003850}
3851testcase TC_assignment_fr_a5_3() runs on test_CT {
3852 var MSC_ConnHdlr vc_conn;
Philipp Maier48604732018-10-09 15:00:37 +02003853 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte651fcdc2018-05-10 20:23:16 +02003854 pars.encr := valueof(t_EncrParams('08'O, f_rnd_octstring(8)));
Harald Weltec1a2fff2017-12-17 11:06:19 +01003855
Harald Welte651fcdc2018-05-10 20:23:16 +02003856 f_init(1, true);
3857 f_sleep(1.0);
3858 vc_conn := f_start_handler(refers(f_tc_assignment_fr_a5), pars);
Harald Weltec1a2fff2017-12-17 11:06:19 +01003859 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003860 f_shutdown_helper();
Harald Weltec1a2fff2017-12-17 11:06:19 +01003861}
Neels Hofmeyr0d8ec532021-06-11 00:09:48 +02003862/* Establish a Signalling channel and re-assign to TCH/F with A5/4 encryption. */
3863testcase TC_assignment_fr_a5_4() runs on test_CT {
3864 var MSC_ConnHdlr vc_conn;
3865 var TestHdlrParams pars := f_gen_test_hdlr_pars();
3866 pars.encr := valueof(t_EncrParams('10'O, f_rnd_octstring(8), f_rnd_octstring(16)));
3867
3868 f_init(1, true);
Oliver Smith7eabd312021-07-12 14:18:56 +02003869 f_vty_encryption_a5("0 1 3 4");
Neels Hofmeyr0d8ec532021-06-11 00:09:48 +02003870 f_sleep(1.0);
3871 vc_conn := f_start_handler(refers(f_tc_assignment_fr_a5), pars);
3872 vc_conn.done;
Oliver Smith7eabd312021-07-12 14:18:56 +02003873 f_vty_encryption_a5_reset();
Neels Hofmeyr0d8ec532021-06-11 00:09:48 +02003874 f_shutdown_helper();
3875}
Harald Weltec1a2fff2017-12-17 11:06:19 +01003876
Neels Hofmeyr0faeb7a2021-06-10 23:59:35 +02003877/* Allow only A5/4, but omit the Kc128 IE from MSC's msg. Expect Cipher Mode Reject. */
3878testcase TC_assignment_fr_a5_4_fail() runs on test_CT {
3879 var TestHdlrParams pars := f_gen_test_hdlr_pars();
3880 var MSC_ConnHdlr vc_conn;
3881
3882 f_init(1, true);
3883 f_sleep(1.0);
3884
3885 pars.encr := valueof(t_EncrParams('10'O, f_rnd_octstring(8))); // A5/4 support, but Kc128 missing!
3886 vc_conn := f_start_handler(refers(f_TC_assignment_a5_not_sup), pars);
3887 vc_conn.done;
3888 f_shutdown_helper();
3889}
3890
Harald Welte552620d2017-12-16 23:21:36 +01003891/* Expect ASSIGNMENT FAIL if mandatory IE is missing */
3892private function f_tc_assignment_fr_a5_1_codec_missing(charstring id) runs on MSC_ConnHdlr {
Philipp Maier48604732018-10-09 15:00:37 +02003893 g_pars := f_gen_test_hdlr_pars();
Harald Welte552620d2017-12-16 23:21:36 +01003894 var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
Harald Welteed848512018-05-24 22:27:58 +02003895 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Harald Welte552620d2017-12-16 23:21:36 +01003896
3897 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02003898 /* Omit: ass_cmd.pdu.bssmap.assignmentRequest.codecList */
3899
Harald Weltea0630032018-03-20 21:09:55 +01003900 f_establish_fully(ass_cmd, exp_fail);
Harald Welte552620d2017-12-16 23:21:36 +01003901}
Harald Welte552620d2017-12-16 23:21:36 +01003902testcase TC_assignment_fr_a5_1_codec_missing() runs on test_CT {
3903 var MSC_ConnHdlr vc_conn;
3904
Harald Welte89d42e82017-12-17 16:42:41 +01003905 f_init(1, true);
Harald Welte552620d2017-12-16 23:21:36 +01003906 f_sleep(1.0);
3907
Harald Welte8863fa12018-05-10 20:15:27 +02003908 vc_conn := f_start_handler(refers(f_tc_assignment_fr_a5_1_codec_missing));
Harald Welte552620d2017-12-16 23:21:36 +01003909 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003910 f_shutdown_helper();
Harald Welte552620d2017-12-16 23:21:36 +01003911}
3912
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +02003913private function f_TC_assignment_a5_not_sup(charstring id) runs on MSC_ConnHdlr {
3914 var template PDU_BSSAP exp_ass_cpl := f_gen_exp_compl();
3915 var PDU_BSSAP exp_ass_req := f_gen_ass_req();
Harald Welte552620d2017-12-16 23:21:36 +01003916
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +02003917 exp_ass_req.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
3918 exp_ass_req.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
3919
3920 /* this is like the beginning of f_establish_fully(), but only up to ciphering reject */
3921
3922 var BSSMAP_FIELD_CodecType codecType;
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +02003923
3924 codecType := exp_ass_req.pdu.bssmap.assignmentRequest.codecList.codecElements[0].codecType;
3925 f_MscConnHdlr_init(g_pars.media_nr, host_bts, host_mgw_mgcp, codecType);
3926
3927 f_create_chan_and_exp();
3928 /* we should now have a COMPL_L3 at the MSC */
3929
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +02003930 /* Start ciphering, expect Cipher Mode Reject */
Neels Hofmeyr6c388f22021-06-11 02:36:56 +02003931 f_cipher_mode(g_pars.encr, exp_fail := true);
Harald Welte552620d2017-12-16 23:21:36 +01003932}
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +02003933testcase TC_assignment_fr_a5_not_sup() runs on test_CT {
3934 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte552620d2017-12-16 23:21:36 +01003935 var MSC_ConnHdlr vc_conn;
3936
Harald Welte89d42e82017-12-17 16:42:41 +01003937 f_init(1, true);
Harald Welte552620d2017-12-16 23:21:36 +01003938 f_sleep(1.0);
3939
Neels Hofmeyr0588cad2021-06-11 01:38:18 +02003940 pars.encr := valueof(t_EncrParams('20'O, f_rnd_octstring(8), f_rnd_octstring(16)));
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +02003941 vc_conn := f_start_handler(refers(f_TC_assignment_a5_not_sup), pars);
Harald Welte552620d2017-12-16 23:21:36 +01003942 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003943 f_shutdown_helper();
Harald Welte552620d2017-12-16 23:21:36 +01003944}
3945
3946
Harald Welte4532e0a2017-12-23 02:05:44 +01003947private function f_tc_assignment_sign(charstring id) runs on MSC_ConnHdlr {
Philipp Maier48604732018-10-09 15:00:37 +02003948 g_pars := f_gen_test_hdlr_pars();
Harald Welte4532e0a2017-12-23 02:05:44 +01003949 var template PDU_BSSAP exp_compl := tr_BSSMAP_AssignmentComplete(omit, omit);
Philipp Maier48604732018-10-09 15:00:37 +02003950 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Harald Welte4532e0a2017-12-23 02:05:44 +01003951 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelTypeSIGNAL);
Daniel Willmannebdecc02020-08-12 15:30:17 +02003952
3953 f_statsd_reset();
Harald Weltea0630032018-03-20 21:09:55 +01003954 f_establish_fully(ass_cmd, exp_compl);
Daniel Willmannebdecc02020-08-12 15:30:17 +02003955
3956 var StatsDExpects expect := {
Daniel Willmannc5398f72020-09-21 10:41:35 +02003957 { name := "TTCN3.bts.0.chreq.total", mtype := "c", min := 1, max := 1},
3958 { name := "TTCN3.bts.0.chreq.successful", mtype := "c", min := 1, max := 1},
Daniel Willmannebdecc02020-08-12 15:30:17 +02003959 { name := "TTCN3.bsc.0.assignment.attempted", mtype := "c", min := 1, max := 1},
3960 { name := "TTCN3.bsc.0.assignment.completed", mtype := "c", min := 1, max := 1}
3961 };
3962 f_statsd_expect(expect);
Harald Welte4532e0a2017-12-23 02:05:44 +01003963}
3964
3965testcase TC_assignment_sign() runs on test_CT {
3966 var MSC_ConnHdlr vc_conn;
3967
3968 f_init(1, true);
3969 f_sleep(1.0);
3970
Harald Welte8863fa12018-05-10 20:15:27 +02003971 vc_conn := f_start_handler(refers(f_tc_assignment_sign));
Harald Welte4532e0a2017-12-23 02:05:44 +01003972 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02003973 f_shutdown_helper();
Harald Welte4532e0a2017-12-23 02:05:44 +01003974}
3975
Harald Welte60aa5762018-03-21 19:33:13 +01003976/***********************************************************************
3977 * Codec (list) testing
3978 ***********************************************************************/
3979
3980/* check if the given rsl_mode is compatible with the a_elem */
3981private function f_match_codec(BSSMAP_FIELD_CodecElement a_elem, RSL_IE_ChannelMode rsl_mode)
3982return boolean {
3983 select (a_elem.codecType) {
3984 case (GSM_FR) {
3985 if (match(rsl_mode, tr_RSL_ChanMode(RSL_CHRT_TCH_F, RSL_CMOD_SP_GSM1))) {
3986 return true;
3987 }
3988 }
3989 case (GSM_HR) {
3990 if (match(rsl_mode, tr_RSL_ChanMode(RSL_CHRT_TCH_H, RSL_CMOD_SP_GSM1))) {
3991 return true;
3992 }
3993 }
3994 case (GSM_EFR) {
3995 if (match(rsl_mode, tr_RSL_ChanMode(RSL_CHRT_TCH_F, RSL_CMOD_SP_GSM2))) {
3996 return true;
3997 }
3998 }
3999 case (FR_AMR) {
4000 if (match(rsl_mode, tr_RSL_ChanMode(RSL_CHRT_TCH_F, RSL_CMOD_SP_GSM3))) {
4001 return true;
4002 }
4003 }
4004 case (HR_AMR) {
4005 if (match(rsl_mode, tr_RSL_ChanMode(RSL_CHRT_TCH_H, RSL_CMOD_SP_GSM3))) {
4006 return true;
4007 }
4008 }
4009 case else { }
4010 }
4011 return false;
4012}
4013
4014/* check if the given rsl_mode is compatible with the a_list */
4015private function f_match_codecs(BSSMAP_IE_SpeechCodecList a_list, RSL_IE_ChannelMode rsl_mode)
4016return boolean {
4017 for (var integer i := 0; i < sizeof(a_list); i := i+1) {
4018 if (f_match_codec(a_list.codecElements[i], rsl_mode)) {
4019 return true;
4020 }
4021 }
4022 return false;
4023}
4024
4025/* determine BSSMAP_IE_ChannelType from *first* element of BSSMAP_FIELD_CodecElement */
Philipp Maier61f6b572018-07-06 14:03:38 +02004026function f_BSSMAP_chtype_from_codec(BSSMAP_FIELD_CodecElement a_elem)
Harald Welte60aa5762018-03-21 19:33:13 +01004027return BSSMAP_IE_ChannelType {
4028 /* FIXME: actually look at all elements of BSSMAP_IE_SpeechCodecList */
4029 var BSSMAP_IE_ChannelType ret := valueof(ts_BSSMAP_IE_ChannelType);
4030 select (a_elem.codecType) {
4031 case (GSM_FR) {
4032 ret.channelRateAndType := ChRate_TCHF;
4033 ret.speechId_DataIndicator := Spdi_TCHF_FR;
4034 }
4035 case (GSM_HR) {
4036 ret.channelRateAndType := ChRate_TCHH;
4037 ret.speechId_DataIndicator := Spdi_TCHH_HR;
4038 }
4039 case (GSM_EFR) {
4040 ret.channelRateAndType := ChRate_TCHF;
4041 ret.speechId_DataIndicator := Spdi_TCHF_EFR;
4042 }
4043 case (FR_AMR) {
4044 ret.channelRateAndType := ChRate_TCHF;
4045 ret.speechId_DataIndicator := Spdi_TCHF_AMR;
4046 }
4047 case (HR_AMR) {
4048 ret.channelRateAndType := ChRate_TCHH;
4049 ret.speechId_DataIndicator := Spdi_TCHH_AMR;
4050 }
4051 case else {
4052 setverdict(fail, "Unsupported codec ", a_elem);
Daniel Willmannafce8662018-07-06 23:11:32 +02004053 mtc.stop;
Harald Welte60aa5762018-03-21 19:33:13 +01004054 }
4055 }
4056 return ret;
4057}
4058
Harald Weltea63b9102018-03-22 20:36:16 +01004059private function f_rsl_chmod_tmpl_from_codec(BSSMAP_FIELD_CodecElement a_elem)
4060return template RSL_IE_Body {
4061 var template RSL_IE_Body mode_ie := {
4062 chan_mode := {
4063 len := ?,
4064 reserved := ?,
4065 dtx_d := ?,
4066 dtx_u := ?,
4067 spd_ind := RSL_SPDI_SPEECH,
4068 ch_rate_type := -,
4069 coding_alg_rate := -
4070 }
4071 }
4072
4073 select (a_elem.codecType) {
4074 case (GSM_FR) {
4075 mode_ie.chan_mode.ch_rate_type := RSL_CHRT_TCH_F;
4076 mode_ie.chan_mode.coding_alg_rate := RSL_CMOD_SP_GSM1;
4077 }
4078 case (GSM_HR) {
4079 mode_ie.chan_mode.ch_rate_type := RSL_CHRT_TCH_H;
4080 mode_ie.chan_mode.coding_alg_rate := RSL_CMOD_SP_GSM1;
4081 }
4082 case (GSM_EFR) {
4083 mode_ie.chan_mode.ch_rate_type := RSL_CHRT_TCH_F;
4084 mode_ie.chan_mode.coding_alg_rate := RSL_CMOD_SP_GSM2;
4085 }
4086 case (FR_AMR) {
4087 mode_ie.chan_mode.ch_rate_type := RSL_CHRT_TCH_F;
4088 mode_ie.chan_mode.coding_alg_rate := RSL_CMOD_SP_GSM3;
4089 }
4090 case (HR_AMR) {
4091 mode_ie.chan_mode.ch_rate_type := RSL_CHRT_TCH_H;
4092 mode_ie.chan_mode.coding_alg_rate := RSL_CMOD_SP_GSM3;
4093 }
4094 }
4095 return mode_ie;
4096}
4097
Harald Welte60aa5762018-03-21 19:33:13 +01004098type record CodecListTest {
4099 BSSMAP_IE_SpeechCodecList codec_list,
4100 charstring id
4101}
4102type record of CodecListTest CodecListTests
4103
4104private function f_TC_assignment_codec(charstring id) runs on MSC_ConnHdlr {
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02004105 var PDU_BSSAP ass_cmd := f_gen_ass_req(g_pars.use_osmux);
4106 var template PDU_BSSAP exp_compl := f_gen_exp_compl(g_pars.use_osmux);
Harald Welte60aa5762018-03-21 19:33:13 +01004107
4108 /* puzzle together the ASSIGNMENT REQ for given codec[s] */
Neels Hofmeyrf246a922020-05-13 02:27:10 +02004109 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
Harald Welte79f3f542018-05-25 20:02:37 +02004110 ass_cmd.pdu.bssmap.assignmentRequest.codecList := g_pars.ass_codec_list;
4111 exp_compl.pdu.bssmap.assignmentComplete.speechCodec.codecElements[0] :=
4112 g_pars.ass_codec_list.codecElements[0];
Philipp Maierd0e64b02019-03-13 14:15:23 +01004113 if (isvalue(g_pars.expect_mr_s0_s7)) {
4114 exp_compl.pdu.bssmap.assignmentComplete.speechCodec.codecElements[0].s0_7 :=
4115 g_pars.expect_mr_s0_s7;
4116 }
Harald Welte79f3f542018-05-25 20:02:37 +02004117 }
Harald Welte60aa5762018-03-21 19:33:13 +01004118 ass_cmd.pdu.bssmap.assignmentRequest.channelType :=
4119 f_BSSMAP_chtype_from_codec(g_pars.ass_codec_list.codecElements[0]);
Harald Welte60aa5762018-03-21 19:33:13 +01004120 log("expecting ASS COMPL like this: ", exp_compl);
4121
4122 f_establish_fully(ass_cmd, exp_compl);
Harald Weltea63b9102018-03-22 20:36:16 +01004123
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004124 if (not g_pars.expect_channel_mode_modify) {
4125 /* Verify that the RSL-side activation actually matches our expectations */
4126 var RSL_Message rsl := f_rslem_get_last_act(RSL_PROC, 0, g_chan_nr);
Harald Weltea63b9102018-03-22 20:36:16 +01004127
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004128 var RSL_IE_Body mode_ie;
4129 if (f_rsl_find_ie(rsl, RSL_IE_CHAN_MODE, mode_ie) == false) {
4130 setverdict(fail, "Couldn't find CHAN_MODE IE");
Daniel Willmannafce8662018-07-06 23:11:32 +02004131 mtc.stop;
Neels Hofmeyrbcf62bc2018-07-04 00:24:33 +02004132 }
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004133 var template RSL_IE_Body t_mode_ie := f_rsl_chmod_tmpl_from_codec(g_pars.ass_codec_list.codecElements[0]);
4134 if (not match(mode_ie, t_mode_ie)) {
4135 log("mode_ie ", mode_ie, " != t_mode_ie ", t_mode_ie);
4136 setverdict(fail, "RSL Channel Mode IE doesn't match expectation");
Neels Hofmeyrbcf62bc2018-07-04 00:24:33 +02004137 }
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004138
4139 var RSL_IE_Body mr_conf;
4140 if (g_pars.expect_mr_conf_ie != omit) {
4141 if (f_rsl_find_ie(rsl, RSL_IE_MR_CONFIG, mr_conf) == false) {
4142 setverdict(fail, "Missing MR CONFIG IE in RSL Chan Activ");
4143 mtc.stop;
4144 }
Neels Hofmeyrbcf62bc2018-07-04 00:24:33 +02004145 log("found RSL MR CONFIG IE: ", mr_conf);
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004146
4147 if (not match(mr_conf, g_pars.expect_mr_conf_ie)) {
4148 setverdict(fail, "RSL MR CONFIG IE does not match expectation. Expected: ",
4149 g_pars.expect_mr_conf_ie);
4150 }
4151 } else {
4152 if (f_rsl_find_ie(rsl, RSL_IE_MR_CONFIG, mr_conf) == true) {
4153 log("found RSL MR CONFIG IE: ", mr_conf);
4154 setverdict(fail, "Found MR CONFIG IE in RSL Chan Activ, expecting omit");
4155 mtc.stop;
4156 }
Neels Hofmeyrbcf62bc2018-07-04 00:24:33 +02004157 }
4158 }
Harald Welte60aa5762018-03-21 19:33:13 +01004159}
4160
Philipp Maierd0e64b02019-03-13 14:15:23 +01004161private function f_TC_assignment_codec_fail(charstring id) runs on MSC_ConnHdlr {
4162
4163 var PDU_BSSAP ass_cmd := f_gen_ass_req();
4164 var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
4165
4166 /* puzzle together the ASSIGNMENT REQ for given codec[s] */
Neels Hofmeyrf246a922020-05-13 02:27:10 +02004167 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
Philipp Maierd0e64b02019-03-13 14:15:23 +01004168 ass_cmd.pdu.bssmap.assignmentRequest.codecList := g_pars.ass_codec_list;
4169 }
4170 ass_cmd.pdu.bssmap.assignmentRequest.channelType :=
4171 f_BSSMAP_chtype_from_codec(g_pars.ass_codec_list.codecElements[0]);
4172 log("expecting ASS FAIL like this: ", exp_fail);
4173
4174 f_establish_fully(ass_cmd, exp_fail);
4175}
4176
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004177const CounterNameVals counternames_bsc_bts_assignment := {
4178 { "assignment:attempted", 0 },
4179 { "assignment:completed", 0 },
4180 { "assignment:stopped", 0 },
4181 { "assignment:no_channel", 0 },
4182 { "assignment:timeout", 0 },
4183 { "assignment:failed", 0 },
4184 { "assignment:error", 0 }
4185};
4186
4187const CounterNameVals counternames_bts_assignment := {
4188 { "assignment:attempted_sign", 0 },
4189 { "assignment:attempted_speech", 0 },
4190 { "assignment:completed_sign", 0 },
4191 { "assignment:completed_speech", 0 },
4192 { "assignment:stopped_sign", 0 },
4193 { "assignment:stopped_speech", 0 },
4194 { "assignment:no_channel_sign", 0 },
4195 { "assignment:no_channel_speech", 0 },
4196 { "assignment:timeout_sign", 0 },
4197 { "assignment:timeout_speech", 0 },
4198 { "assignment:failed_sign", 0 },
4199 { "assignment:failed_speech", 0 },
4200 { "assignment:error_sign", 0 },
4201 { "assignment:error_speech", 0 }
4202};
4203
4204function f_ctrs_bsc_and_bts_assignment_init(integer bts_count := NUM_BTS) runs on test_CT {
4205 var CounterNameVals bts_names := counternames_bsc_bts_assignment & counternames_bts_assignment;
4206 f_ctrs_bts_init(bts_count, bts_names);
4207 f_ctrs_bsc_init(counternames_bsc_bts_assignment);
4208}
4209
Harald Welte60aa5762018-03-21 19:33:13 +01004210testcase TC_assignment_codec_fr() runs on test_CT {
Philipp Maier48604732018-10-09 15:00:37 +02004211 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte60aa5762018-03-21 19:33:13 +01004212 var MSC_ConnHdlr vc_conn;
4213
4214 f_init(1, true);
4215 f_sleep(1.0);
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004216 f_ctrs_bsc_and_bts_assignment_init(1);
Harald Welte60aa5762018-03-21 19:33:13 +01004217
4218 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
Harald Welte8863fa12018-05-10 20:15:27 +02004219 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
Harald Welte60aa5762018-03-21 19:33:13 +01004220 vc_conn.done;
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004221
4222 f_ctrs_bsc_and_bts_add(0, "assignment:attempted", 1);
4223 f_ctrs_bts_add(0, "assignment:attempted_speech", 1);
4224 f_ctrs_bsc_and_bts_add(0, "assignment:completed", 1);
4225 f_ctrs_bts_add(0, "assignment:completed_speech", 1);
4226 f_ctrs_bts_verify();
4227
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004228 f_shutdown_helper();
Harald Welte60aa5762018-03-21 19:33:13 +01004229}
4230
4231testcase TC_assignment_codec_hr() runs on test_CT {
Philipp Maier48604732018-10-09 15:00:37 +02004232 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte60aa5762018-03-21 19:33:13 +01004233 var MSC_ConnHdlr vc_conn;
4234
4235 f_init(1, true);
4236 f_sleep(1.0);
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004237 f_ctrs_bsc_and_bts_assignment_init(1);
Harald Welte60aa5762018-03-21 19:33:13 +01004238
4239 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR}));
Harald Welte8863fa12018-05-10 20:15:27 +02004240 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
Harald Welte60aa5762018-03-21 19:33:13 +01004241 vc_conn.done;
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004242
4243 f_ctrs_bsc_and_bts_add(0, "assignment:attempted", 1);
4244 f_ctrs_bts_add(0, "assignment:attempted_speech", 1);
4245 f_ctrs_bsc_and_bts_add(0, "assignment:completed", 1);
4246 f_ctrs_bts_add(0, "assignment:completed_speech", 1);
4247 f_ctrs_bts_verify();
4248
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004249 f_shutdown_helper();
Harald Welte60aa5762018-03-21 19:33:13 +01004250}
4251
4252testcase TC_assignment_codec_efr() runs on test_CT {
Philipp Maier48604732018-10-09 15:00:37 +02004253 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte60aa5762018-03-21 19:33:13 +01004254 var MSC_ConnHdlr vc_conn;
4255
4256 f_init(1, true);
4257 f_sleep(1.0);
4258
4259 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecEFR}));
Harald Welte8863fa12018-05-10 20:15:27 +02004260 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
Harald Welte60aa5762018-03-21 19:33:13 +01004261 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004262 f_shutdown_helper();
Harald Welte60aa5762018-03-21 19:33:13 +01004263}
4264
Philipp Maierd0e64b02019-03-13 14:15:23 +01004265/* Allow 5,90k only (current default config) */
4266private function f_allow_amr_rate_5_90k() runs on test_CT {
Neels Hofmeyr2a5670b2020-11-25 23:39:57 +00004267 f_vty_cfg_msc(BSCVTY, 0, {
4268 "amr-config 12_2k forbidden",
4269 "amr-config 10_2k forbidden",
4270 "amr-config 7_95k forbidden",
4271 "amr-config 7_40k forbidden",
4272 "amr-config 6_70k forbidden",
4273 "amr-config 5_90k allowed",
4274 "amr-config 5_15k forbidden",
4275 "amr-config 4_75k forbidden"
4276 });
Philipp Maierd0e64b02019-03-13 14:15:23 +01004277}
4278
4279/* Allow 4,75k, 5,90k, 4,70k and 12,2k, which are the most common rates
4280 * ("Config-NB-Code = 1") */
4281private function f_allow_amr_rate_4_75k_5_90k_7_40k_12_20k() runs on test_CT {
Neels Hofmeyr2a5670b2020-11-25 23:39:57 +00004282 f_vty_cfg_msc(BSCVTY, 0, {
4283 "amr-config 12_2k allowed",
4284 "amr-config 10_2k forbidden",
4285 "amr-config 7_95k forbidden",
4286 "amr-config 7_40k allowed",
4287 "amr-config 6_70k forbidden",
4288 "amr-config 5_90k allowed",
4289 "amr-config 5_15k forbidden",
4290 "amr-config 4_75k allowed"
4291 });
Philipp Maierd0e64b02019-03-13 14:15:23 +01004292}
4293
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004294private function f_vty_amr_start_mode_set(boolean fr, charstring startmode) runs on test_CT {
4295 var charstring tch;
4296 if (fr) {
4297 tch := "tch-f";
4298 } else {
4299 tch := "tch-h";
4300 }
4301 f_vty_cfg_bts(BSCVTY, 0, { "amr " & tch & " start-mode " & startmode });
4302}
4303
4304/* Set the AMR start-mode for this TCH back to the default configuration. */
4305private function f_vty_amr_start_mode_restore(boolean fr) runs on test_CT {
4306 f_vty_amr_start_mode_set(fr, "auto");
4307}
4308
Harald Welte60aa5762018-03-21 19:33:13 +01004309testcase TC_assignment_codec_amr_f() runs on test_CT {
Philipp Maier48604732018-10-09 15:00:37 +02004310 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte60aa5762018-03-21 19:33:13 +01004311 var MSC_ConnHdlr vc_conn;
Philipp Maier7695a0d2018-09-27 17:52:14 +02004312
4313 /* Note: This setups the codec configuration. The parameter payload in
4314 * mr_conf must be consistant with the parameter codecElements in pars
4315 * and also must match the amr-config in osmo-bsc.cfg! */
Neels Hofmeyrbcf62bc2018-07-04 00:24:33 +02004316 var RSL_IE_Body mr_conf := {
4317 other := {
4318 len := 2,
4319 payload := '2804'O
4320 }
4321 };
Harald Welte60aa5762018-03-21 19:33:13 +01004322
Philipp Maier7695a0d2018-09-27 17:52:14 +02004323 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_F}));
Philipp Maier806f8f12019-03-12 12:13:41 +01004324 pars.ass_codec_list.codecElements[0].s0_7 := '00000100'B; /* 5,90k */
Philipp Maier7695a0d2018-09-27 17:52:14 +02004325 pars.ass_codec_list.codecElements[0].s8_15 := '01010111'B;
4326 pars.expect_mr_conf_ie := mr_conf;
4327
Harald Welte60aa5762018-03-21 19:33:13 +01004328 f_init(1, true);
4329 f_sleep(1.0);
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004330 f_vty_amr_start_mode_set(true, "1");
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004331 f_ctrs_bsc_and_bts_assignment_init(1);
Harald Welte60aa5762018-03-21 19:33:13 +01004332
Harald Welte8863fa12018-05-10 20:15:27 +02004333 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
Harald Welte60aa5762018-03-21 19:33:13 +01004334 vc_conn.done;
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004335
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004336 f_ctrs_bsc_and_bts_add(0, "assignment:attempted", 1);
4337 f_ctrs_bts_add(0, "assignment:attempted_speech", 1);
4338 f_ctrs_bsc_and_bts_add(0, "assignment:completed", 1);
4339 f_ctrs_bts_add(0, "assignment:completed_speech", 1);
4340 f_ctrs_bts_verify();
4341
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004342 f_vty_amr_start_mode_restore(true);
Vadim Yanitskiy292e5962021-01-03 14:18:47 +01004343 f_shutdown_helper();
Harald Welte60aa5762018-03-21 19:33:13 +01004344}
4345
4346testcase TC_assignment_codec_amr_h() runs on test_CT {
Philipp Maier48604732018-10-09 15:00:37 +02004347 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte60aa5762018-03-21 19:33:13 +01004348 var MSC_ConnHdlr vc_conn;
Philipp Maier7695a0d2018-09-27 17:52:14 +02004349
4350 /* See note above */
Neels Hofmeyrbcf62bc2018-07-04 00:24:33 +02004351 var RSL_IE_Body mr_conf := {
4352 other := {
4353 len := 2,
4354 payload := '2804'O
4355 }
4356 };
Harald Welte60aa5762018-03-21 19:33:13 +01004357
Philipp Maier7695a0d2018-09-27 17:52:14 +02004358 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_H}));
Philipp Maier806f8f12019-03-12 12:13:41 +01004359 pars.ass_codec_list.codecElements[0].s0_7 := '00000100'B; /* 5,90k */
Philipp Maier7695a0d2018-09-27 17:52:14 +02004360 pars.ass_codec_list.codecElements[0].s8_15 := '00000111'B;
4361 pars.expect_mr_conf_ie := mr_conf;
4362
Harald Welte60aa5762018-03-21 19:33:13 +01004363 f_init(1, true);
4364 f_sleep(1.0);
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004365 f_vty_amr_start_mode_set(false, "1");
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004366 f_ctrs_bsc_and_bts_assignment_init(1);
Harald Welte60aa5762018-03-21 19:33:13 +01004367
Harald Welte8863fa12018-05-10 20:15:27 +02004368 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
Harald Welte60aa5762018-03-21 19:33:13 +01004369 vc_conn.done;
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004370
Neels Hofmeyrbcfc9442021-11-29 16:44:08 +01004371 f_ctrs_bsc_and_bts_add(0, "assignment:attempted", 1);
4372 f_ctrs_bts_add(0, "assignment:attempted_speech", 1);
4373 f_ctrs_bsc_and_bts_add(0, "assignment:completed", 1);
4374 f_ctrs_bts_add(0, "assignment:completed_speech", 1);
4375 f_ctrs_bts_verify();
4376
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004377 f_vty_amr_start_mode_restore(false);
Vadim Yanitskiy292e5962021-01-03 14:18:47 +01004378 f_shutdown_helper();
Harald Welte60aa5762018-03-21 19:33:13 +01004379}
4380
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004381/* Establish signalling on a TCH/F lchan, and then switch to speech mode without a new Assignment. */
4382testcase TC_assignment_codec_fr_by_mode_modify() runs on test_CT {
4383 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4384 var MSC_ConnHdlr vc_conn;
4385
4386 f_init(1, true);
4387 f_sleep(1.0);
4388
4389 /* By disabling all SDCCH, the MS should be given a TCH/F for signalling. Then activating an FR codec should
4390 * merely do a Channel Mode Modify, and not assign to a new lchan. f_establish_fully() already accounts for
4391 * expecting a Channel Mode Modify if the channel type is compatible. */
4392 f_disable_all_sdcch();
4393 f_disable_all_tch_h();
4394
4395 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
4396 pars.expect_channel_mode_modify := true;
4397 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
4398 vc_conn.done;
4399
4400 f_enable_all_sdcch();
4401 f_enable_all_tch();
4402 f_shutdown_helper();
4403}
4404
Neels Hofmeyr454d7922020-11-26 02:24:57 +00004405/* 'amr start-mode auto' should not keep the (unused) 'smod' bits from previous configuration */
4406testcase TC_assignment_codec_amr_startmode_cruft() runs on test_CT {
4407 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4408 var MSC_ConnHdlr vc_conn;
4409
4410 var RSL_IE_Body mr_conf := {
4411 other := {
4412 len := 2,
4413 payload := '2004'O /* <- expect ICMI=0, smod=00 */
4414 }
4415 };
4416
4417 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_F}));
4418 pars.ass_codec_list.codecElements[0].s0_7 := '00000100'B; /* 5,90k */
4419 pars.ass_codec_list.codecElements[0].s8_15 := '01010111'B;
4420 pars.expect_mr_conf_ie := mr_conf;
4421
4422 f_init(1, true);
4423 f_sleep(1.0);
4424
4425 /* First set nonzero start mode bits */
4426 f_vty_amr_start_mode_set(true, "4");
4427 /* Now set to auto, and expect the startmode bits to be zero in the message, i.e. ensure that osmo-bsc does not
4428 * let the startmode bits stick around and has deterministic MultiRate config for 'start-mode auto'; that is
4429 * ensured by above '2004'O, where 'x0xx'O indicates ICMI = 0, spare = 0, smod = 00. */
4430 f_vty_amr_start_mode_set(true, "auto");
4431
4432 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
4433 vc_conn.done;
Neels Hofmeyr454d7922020-11-26 02:24:57 +00004434
4435 /* Clear the startmode bits to not affect subsequent tests, in case the bits should indeed stick around. */
4436 f_vty_amr_start_mode_set(true, "1");
4437 f_vty_amr_start_mode_restore(true);
Vadim Yanitskiy292e5962021-01-03 14:18:47 +01004438 f_shutdown_helper();
Neels Hofmeyr454d7922020-11-26 02:24:57 +00004439}
4440
Neels Hofmeyr21863562020-11-26 00:34:33 +00004441function f_TC_assignment_codec_amr(boolean fr, octetstring mrconf, bitstring s8_s0, bitstring exp_s8_s0,
4442 charstring start_mode := "1")
Philipp Maierd0e64b02019-03-13 14:15:23 +01004443runs on test_CT {
4444
4445 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4446 var MSC_ConnHdlr vc_conn;
4447
4448 /* See note above */
4449 var RSL_IE_Body mr_conf := {
4450 other := {
4451 len := lengthof(mrconf),
4452 payload := mrconf
4453 }
4454 };
4455
4456 if (fr) {
4457 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_F}));
4458 } else {
4459 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_H}));
4460 }
4461 pars.ass_codec_list.codecElements[0].s0_7 := s8_s0;
4462 pars.ass_codec_list.codecElements[0].s8_15 := '00000111'B;
4463 pars.expect_mr_conf_ie := mr_conf;
4464 pars.expect_mr_s0_s7 := exp_s8_s0;
4465
4466 f_init(1, true);
4467 f_allow_amr_rate_4_75k_5_90k_7_40k_12_20k();
Neels Hofmeyr21863562020-11-26 00:34:33 +00004468 f_vty_amr_start_mode_set(fr, start_mode);
Philipp Maierd0e64b02019-03-13 14:15:23 +01004469 f_sleep(1.0);
4470
4471 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
4472 vc_conn.done;
4473 f_allow_amr_rate_5_90k();
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004474 f_vty_amr_start_mode_restore(fr);
Philipp Maierd0e64b02019-03-13 14:15:23 +01004475}
4476
4477function f_TC_assignment_codec_amr_fail(boolean fr, bitstring s8_s0)
4478runs on test_CT {
4479
4480 var TestHdlrParams pars := f_gen_test_hdlr_pars();
4481 var MSC_ConnHdlr vc_conn;
4482
4483 if (fr) {
4484 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_F}));
4485 } else {
4486 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_H}));
4487 }
4488 pars.ass_codec_list.codecElements[0].s0_7 := s8_s0;
4489 pars.ass_codec_list.codecElements[0].s8_15 := '00000111'B;
4490
4491 f_init(1, true);
4492 f_allow_amr_rate_4_75k_5_90k_7_40k_12_20k();
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004493 f_vty_amr_start_mode_set(fr, "1");
Philipp Maierd0e64b02019-03-13 14:15:23 +01004494 f_sleep(1.0);
4495
4496 vc_conn := f_start_handler(refers(f_TC_assignment_codec_fail), pars);
4497 vc_conn.done;
4498 f_allow_amr_rate_5_90k();
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00004499 f_vty_amr_start_mode_restore(fr);
Philipp Maierd0e64b02019-03-13 14:15:23 +01004500}
4501
4502
4503/* Set S1, we expect an AMR multirate configuration IE with all four rates
4504 * set. */
4505testcase TC_assignment_codec_amr_f_S1() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004506 f_TC_assignment_codec_amr(true, '289520882208'O, '00000010'B, '00000010'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004507 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004508}
4509
4510/* Set S1, we expect an AMR multirate configuration IE with the lower three
4511 * rates set. */
4512testcase TC_assignment_codec_amr_h_S1() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004513 f_TC_assignment_codec_amr(false, '2815208820'O, '00000010'B, '00000010'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004514 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004515}
4516
4517/* Set S1 and two other rates, we expect an AMR MULTIRATE CONFIGURATION IE with
4518 * all four rates (and only S1 set in the ASSIGNMENT COMPLETE) */
4519testcase TC_assignment_codec_amr_f_S124() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004520 f_TC_assignment_codec_amr(true, '289520882208'O, '00010110'B, '00000010'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004521 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004522}
4523
4524/* Set S1 and two other rates, we expect an AMR MULTIRATE CONFIGURATION IE with
4525 * all four rates (and only S1 set in the ASSIGNMENT COMPLETE) */
4526testcase TC_assignment_codec_amr_h_S124() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004527 f_TC_assignment_codec_amr(false, '2815208820'O, '00010110'B, '00000010'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004528 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004529}
4530
4531/* The following block of tests selects more and more rates until all four
4532 * possible rates are in the active set (full rate) */
4533testcase TC_assignment_codec_amr_f_S0() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004534 f_TC_assignment_codec_amr(true, '2801'O, '00000001'B, '00000001'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004535 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004536}
4537
4538testcase TC_assignment_codec_amr_f_S02() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004539 f_TC_assignment_codec_amr(true, '28052080'O, '00000101'B, '00000101'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004540 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004541}
4542
4543testcase TC_assignment_codec_amr_f_S024() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004544 f_TC_assignment_codec_amr(true, '2815208820'O, '00010101'B, '00010101'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004545 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004546}
4547
4548testcase TC_assignment_codec_amr_f_S0247() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004549 f_TC_assignment_codec_amr(true, '289520882208'O, '10010101'B, '10010101'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004550 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004551}
4552
4553/* The following block of tests selects more and more rates until all three
4554 * possible rates are in the active set (half rate) */
4555testcase TC_assignment_codec_amr_h_S0() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004556 f_TC_assignment_codec_amr(false, '2801'O, '00000001'B, '00000001'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004557 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004558}
4559
4560testcase TC_assignment_codec_amr_h_S02() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004561 f_TC_assignment_codec_amr(false, '28052080'O, '00000101'B, '00000101'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004562 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004563}
4564
4565testcase TC_assignment_codec_amr_h_S024() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004566 f_TC_assignment_codec_amr(false, '2815208820'O, '00010101'B, '00010101'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004567 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004568}
4569
4570/* The following block tests what happens when the MSC does offer rate
4571 * configurations that are not supported by the BSC. Normally such situations
4572 * should not happen because the MSC gets informed by the BSC in advance via
4573 * the L3 COMPLETE message which rates are applicable. The MSC should not try
4574 * to offer rates that are not applicable anyway. */
4575
4576testcase TC_assignment_codec_amr_h_S0247() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004577 /* Try to include 12,2k in into the active set even though the channel
4578 * is half rate only. The BSC is expected to remove the 12,0k */
4579 f_TC_assignment_codec_amr(false, '2815208820'O, '10010101'B, '00010101'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004580 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004581}
4582
4583testcase TC_assignment_codec_amr_f_S01234567() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004584 /* See what happens when all rates are selected at once. Since then
4585 * Also S1 is selected, this setting will be prefered and we should
4586 * get 12.2k, 7,40k, 5,90k, and 4,75k in the active set. */
4587 f_TC_assignment_codec_amr(true, '289520882208'O, '11111111'B, '00000010'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004588 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004589}
4590
4591testcase TC_assignment_codec_amr_f_S0234567() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004592 /* Same as above, but with S1 missing, the MSC is then expected to
4593 * select the currently supported rates, which are also 12.2k, 7,40k,
4594 * 5,90k, and 4,75k, into the active set. */
4595 f_TC_assignment_codec_amr(true, '289520882208'O, '11111101'B, '10010101'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004596 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004597}
4598
4599testcase TC_assignment_codec_amr_f_zero() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004600 /* Try to select no rates at all */
4601 f_TC_assignment_codec_amr_fail(true, '00000000'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004602 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004603}
4604
4605testcase TC_assignment_codec_amr_f_unsupp() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004606 /* Try to select only unsupported rates */
4607 f_TC_assignment_codec_amr_fail(true, '01101000'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004608 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004609}
4610
4611testcase TC_assignment_codec_amr_h_S7() runs on test_CT {
Pau Espin Pedrol00f40e82020-09-23 14:16:04 +02004612 /* Try to select 12,2k for half rate */
4613 f_TC_assignment_codec_amr_fail(false, '10000000'B);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004614 f_shutdown_helper();
Philipp Maierd0e64b02019-03-13 14:15:23 +01004615}
4616
Neels Hofmeyr21863562020-11-26 00:34:33 +00004617testcase TC_assignment_codec_amr_f_start_mode_auto() runs on test_CT {
4618 f_TC_assignment_codec_amr(true, '209520882208'O, '11111111'B, '00000010'B,
4619 start_mode := "auto");
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +01004620 f_shutdown_helper();
Neels Hofmeyr21863562020-11-26 00:34:33 +00004621}
4622
4623testcase TC_assignment_codec_amr_h_start_mode_auto() runs on test_CT {
4624 f_TC_assignment_codec_amr(false, '2015208820'O, '10010101'B, '00010101'B,
4625 start_mode := "auto");
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +01004626 f_shutdown_helper();
Neels Hofmeyr21863562020-11-26 00:34:33 +00004627}
4628
Neels Hofmeyr3eb94562020-11-26 02:40:26 +00004629testcase TC_assignment_codec_amr_f_start_mode_4() runs on test_CT {
Vadim Yanitskiy7815f482021-01-03 17:07:37 +01004630 /* "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 +00004631 f_TC_assignment_codec_amr(true, '2b9520882208'O, '11111111'B, '00000010'B,
4632 start_mode := "4");
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +01004633 f_shutdown_helper();
Neels Hofmeyr3eb94562020-11-26 02:40:26 +00004634}
4635
4636testcase TC_assignment_codec_amr_h_start_mode_4() runs on test_CT {
Vadim Yanitskiy7815f482021-01-03 17:07:37 +01004637 /* "amr tch-h modes 0 2 4" => total 3 modes and start mode 4 => '10'B on the wire */
4638 f_TC_assignment_codec_amr(false, '2a15208820'O, '10010101'B, '00010101'B,
Neels Hofmeyr3eb94562020-11-26 02:40:26 +00004639 start_mode := "4");
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +01004640 f_shutdown_helper();
Neels Hofmeyr3eb94562020-11-26 02:40:26 +00004641}
4642
Philipp Maierac09bfc2019-01-08 13:41:39 +01004643private function f_disable_all_tch_f() runs on test_CT {
Philipp Maierc704a882019-01-29 15:58:52 +01004644 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 1 sub-slot 0 borken");
4645 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 2 sub-slot 0 borken");
4646 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 3 sub-slot 0 borken");
4647 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 4 sub-slot 0 borken");
Philipp Maierac09bfc2019-01-08 13:41:39 +01004648}
4649
4650private function f_disable_all_tch_h() runs on test_CT {
Philipp Maierc704a882019-01-29 15:58:52 +01004651 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 5 sub-slot 0 borken");
4652 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 5 sub-slot 1 borken");
Philipp Maierac09bfc2019-01-08 13:41:39 +01004653}
4654
4655private function f_enable_all_tch() runs on test_CT {
Philipp Maierc704a882019-01-29 15:58:52 +01004656 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 1 sub-slot 0 unused");
4657 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 2 sub-slot 0 unused");
4658 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 3 sub-slot 0 unused");
4659 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 4 sub-slot 0 unused");
4660 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 5 sub-slot 0 unused");
4661 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 5 sub-slot 1 unused");
Philipp Maierac09bfc2019-01-08 13:41:39 +01004662}
4663
Neels Hofmeyr559d5d02021-04-16 16:50:49 +02004664private function f_disable_all_sdcch() runs on test_CT {
4665 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 0 borken");
4666 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 1 borken");
4667 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 2 borken");
4668 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 3 borken");
4669}
4670
4671private function f_enable_all_sdcch() runs on test_CT {
4672 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 0 unused");
4673 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 1 unused");
4674 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 2 unused");
4675 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 3 unused");
4676}
4677
Philipp Maierac09bfc2019-01-08 13:41:39 +01004678/* Allow HR only */
4679private function f_TC_assignment_codec_xr_exhausted_req_hr(charstring id) runs on MSC_ConnHdlr {
4680 g_pars := f_gen_test_hdlr_pars();
4681 var PDU_BSSAP ass_cmd := f_gen_ass_req();
4682 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
4683 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
4684 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '09'O;
4685 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '05'O;
4686 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR}));
4687 f_establish_fully(ass_cmd, exp_compl);
4688}
4689
4690/* Allow FR only */
4691private function f_TC_assignment_codec_xr_exhausted_req_fr(charstring id) runs on MSC_ConnHdlr {
4692 g_pars := f_gen_test_hdlr_pars();
4693 var PDU_BSSAP ass_cmd := f_gen_ass_req();
4694 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
4695 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
4696 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '08'O;
4697 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '01'O;
4698 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
4699 f_establish_fully(ass_cmd, exp_compl);
4700}
4701
4702/* Allow HR only (expect assignment failure) */
4703private function f_TC_assignment_codec_xr_exhausted_req_hr_fail(charstring id) runs on MSC_ConnHdlr {
4704 g_pars := f_gen_test_hdlr_pars();
4705 var PDU_BSSAP ass_cmd := f_gen_ass_req();
4706 var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
4707 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
4708 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '09'O;
4709 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '05'O;
4710 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR}));
4711 f_establish_fully(ass_cmd, exp_fail);
4712}
4713
4714/* Allow FR only (expect assignment failure) */
4715private function f_TC_assignment_codec_xr_exhausted_req_fr_fail(charstring id) runs on MSC_ConnHdlr {
4716 g_pars := f_gen_test_hdlr_pars();
4717 var PDU_BSSAP ass_cmd := f_gen_ass_req();
4718 var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
4719 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
4720 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '08'O;
4721 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '01'O;
4722 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
4723 f_establish_fully(ass_cmd, exp_fail);
4724}
4725
4726/* Allow FR and HR, but prefer FR */
4727private function f_TC_assignment_codec_fr_exhausted_req_fr_hr(charstring id) runs on MSC_ConnHdlr {
4728 g_pars := f_gen_test_hdlr_pars();
4729 var PDU_BSSAP ass_cmd := f_gen_ass_req();
4730 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
4731 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
4732 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '0A'O; /* Prefer FR */
4733 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '8105'O;
4734 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR, ts_CodecHR}));
4735 exp_compl.pdu.bssmap.assignmentComplete.speechVersion.speechVersionIdentifier := '0000101'B; /* Expect HR */
4736 f_establish_fully(ass_cmd, exp_compl);
4737}
4738
4739/* Allow FR and HR, but prefer HR */
4740private function f_TC_assignment_codec_fr_exhausted_req_hr_fr(charstring id) runs on MSC_ConnHdlr {
4741 g_pars := f_gen_test_hdlr_pars();
4742 var PDU_BSSAP ass_cmd := f_gen_ass_req();
4743 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
4744 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
4745 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '0B'O; /* Prefer HR */
4746 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '8501'O;
4747 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR, ts_CodecFR}));
4748 exp_compl.pdu.bssmap.assignmentComplete.speechVersion.speechVersionIdentifier := '0000101'B; /* Expect HR */
4749 f_establish_fully(ass_cmd, exp_compl);
4750}
4751
4752/* Allow FR and HR, but prefer FR */
4753private function f_TC_assignment_codec_hr_exhausted_req_fr_hr(charstring id) runs on MSC_ConnHdlr {
4754 g_pars := f_gen_test_hdlr_pars();
4755 var PDU_BSSAP ass_cmd := f_gen_ass_req();
4756 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
4757 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
4758 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '0A'O; /* Prefer FR */
4759 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '8105'O;
4760 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR, ts_CodecHR}));
4761 exp_compl.pdu.bssmap.assignmentComplete.speechVersion.speechVersionIdentifier := '0000001'B; /* Expect FR */
4762 f_establish_fully(ass_cmd, exp_compl);
4763}
4764
4765/* Allow FR and HR, but prefer HR */
4766private function f_TC_assignment_codec_hr_exhausted_req_hr_fr(charstring id) runs on MSC_ConnHdlr {
4767 g_pars := f_gen_test_hdlr_pars();
4768 var PDU_BSSAP ass_cmd := f_gen_ass_req();
4769 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
4770 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
4771 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '0B'O; /* Prefer HR */
4772 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '8501'O;
4773 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR, ts_CodecFR}));
4774 exp_compl.pdu.bssmap.assignmentComplete.speechVersion.speechVersionIdentifier := '0000001'B; /* Expect FR */
4775 f_establish_fully(ass_cmd, exp_compl);
4776}
4777
4778/* Request a HR channel while all FR channels are exhausted, this is expected
4779 * to work without conflicts */
4780testcase TC_assignment_codec_fr_exhausted_req_hr() runs on test_CT {
4781 var MSC_ConnHdlr vc_conn;
4782 f_init(1, true);
4783 f_sleep(1.0);
4784 f_enable_all_tch();
4785 f_disable_all_tch_f();
4786 vc_conn := f_start_handler(refers(f_TC_assignment_codec_xr_exhausted_req_hr));
4787 vc_conn.done;
4788 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004789 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01004790}
4791
4792/* Request a FR channel while all FR channels are exhausted, this is expected
4793 * to fail. */
4794testcase TC_assignment_codec_fr_exhausted_req_fr() runs on test_CT {
4795 var MSC_ConnHdlr vc_conn;
4796 f_init(1, true);
4797 f_sleep(1.0);
4798 f_enable_all_tch();
4799 f_disable_all_tch_f();
4800 vc_conn := f_start_handler(refers(f_TC_assignment_codec_xr_exhausted_req_fr_fail));
4801 vc_conn.done;
4802 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004803 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01004804}
4805
4806/* Request a FR (prefered) or alternatively a HR channel while all FR channels
4807 * are exhausted, this is expected to be resolved by selecting a HR channel. */
4808testcase TC_assignment_codec_fr_exhausted_req_fr_hr() runs on test_CT {
4809 var MSC_ConnHdlr vc_conn;
4810 f_init(1, true);
4811 f_sleep(1.0);
4812 f_enable_all_tch();
4813 f_disable_all_tch_f();
4814 vc_conn := f_start_handler(refers(f_TC_assignment_codec_fr_exhausted_req_fr_hr));
4815 vc_conn.done;
4816 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004817 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01004818}
4819
4820/* Request a HR (prefered) or alternatively a FR channel while all FR channels
4821 * are exhausted, this is expected to work without conflicts. */
4822testcase TC_assignment_codec_fr_exhausted_req_hr_fr() runs on test_CT {
4823 var MSC_ConnHdlr vc_conn;
4824 f_init(1, true);
4825 f_sleep(1.0);
4826 f_enable_all_tch();
4827 f_disable_all_tch_f();
4828 vc_conn := f_start_handler(refers(f_TC_assignment_codec_fr_exhausted_req_hr_fr));
4829 vc_conn.done;
4830 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004831 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01004832}
4833
4834/* Request a FR channel while all HR channels are exhausted, this is expected
4835 * to work without conflicts */
4836testcase TC_assignment_codec_hr_exhausted_req_fr() runs on test_CT {
4837 var MSC_ConnHdlr vc_conn;
4838 f_init(1, true);
4839 f_sleep(1.0);
4840 f_enable_all_tch();
4841 f_disable_all_tch_h();
4842 vc_conn := f_start_handler(refers(f_TC_assignment_codec_xr_exhausted_req_fr));
4843 vc_conn.done;
4844 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004845 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01004846}
4847
4848/* Request a HR channel while all HR channels are exhausted, this is expected
4849 * to fail. */
4850testcase TC_assignment_codec_hr_exhausted_req_hr() runs on test_CT {
4851 var MSC_ConnHdlr vc_conn;
4852 f_init(1, true);
4853 f_sleep(1.0);
4854 f_enable_all_tch();
4855 f_disable_all_tch_h();
4856 vc_conn := f_start_handler(refers(f_TC_assignment_codec_xr_exhausted_req_hr_fail));
4857 vc_conn.done;
4858 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004859 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01004860}
4861
4862/* Request a HR (prefered) or alternatively a FR channel while all HR channels
4863 * are exhausted, this is expected to be resolved by selecting a FR channel. */
4864testcase TC_assignment_codec_hr_exhausted_req_hr_fr() runs on test_CT {
4865 var MSC_ConnHdlr vc_conn;
4866 f_init(1, true);
4867 f_sleep(1.0);
4868 f_enable_all_tch();
4869 f_disable_all_tch_h();
4870 vc_conn := f_start_handler(refers(f_TC_assignment_codec_hr_exhausted_req_hr_fr));
4871 vc_conn.done;
4872 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004873 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01004874}
4875
4876/* Request a FR (prefered) or alternatively a HR channel while all HR channels
4877 * are exhausted, this is expected to work without conflicts. */
4878testcase TC_assignment_codec_hr_exhausted_req_fr_hr() runs on test_CT {
4879 var MSC_ConnHdlr vc_conn;
4880 f_init(1, true);
4881 f_sleep(1.0);
4882 f_enable_all_tch();
4883 f_disable_all_tch_h();
4884 vc_conn := f_start_handler(refers(f_TC_assignment_codec_hr_exhausted_req_fr_hr));
4885 vc_conn.done;
4886 f_enable_all_tch();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004887 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01004888}
4889
4890/* Allow FR and HR, but prefer HR */
4891private function f_TC_assignment_codec_req_hr_fr(charstring id) runs on MSC_ConnHdlr {
4892 g_pars := f_gen_test_hdlr_pars();
4893 var PDU_BSSAP ass_cmd := f_gen_ass_req();
4894 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
4895 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
4896 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '0B'O; /* Prefer HR */
4897 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '8501'O;
4898 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR, ts_CodecFR}));
4899 exp_compl.pdu.bssmap.assignmentComplete.speechVersion.speechVersionIdentifier := '0000101'B; /* Expect HR */
4900 f_establish_fully(ass_cmd, exp_compl);
4901}
4902
4903/* Allow FR and HR, but prefer FR */
4904private function f_TC_assignment_codec_req_fr_hr(charstring id) runs on MSC_ConnHdlr {
4905 g_pars := f_gen_test_hdlr_pars();
4906 var PDU_BSSAP ass_cmd := f_gen_ass_req();
4907 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
4908 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
4909 ass_cmd.pdu.bssmap.assignmentRequest.channelType.channelRateAndType := '0A'O; /* Prefer FR */
4910 ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '8105'O;
4911 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR, ts_CodecHR}));
4912 exp_compl.pdu.bssmap.assignmentComplete.speechVersion.speechVersionIdentifier := '0000001'B; /* Expect FR */
4913 f_establish_fully(ass_cmd, exp_compl);
4914}
4915
4916/* Request a HR (prefered) or alternatively a FR channel, it is expected that
4917 * HR, which is the prefered type, is selected. */
4918testcase TC_assignment_codec_req_hr_fr() runs on test_CT {
4919 var MSC_ConnHdlr vc_conn;
4920 f_init(1, true);
4921 f_sleep(1.0);
4922 f_enable_all_tch();
4923 vc_conn := f_start_handler(refers(f_TC_assignment_codec_req_hr_fr));
4924 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004925 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01004926}
4927
4928/* Request a FR (prefered) or alternatively a HR channel, it is expected that
4929 * FR, which is the prefered type, is selected. */
4930testcase TC_assignment_codec_req_fr_hr() runs on test_CT {
4931 var MSC_ConnHdlr vc_conn;
4932 f_init(1, true);
4933 f_sleep(1.0);
4934 f_enable_all_tch();
4935 vc_conn := f_start_handler(refers(f_TC_assignment_codec_req_fr_hr));
4936 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02004937 f_shutdown_helper();
Philipp Maierac09bfc2019-01-08 13:41:39 +01004938}
4939
Pau Espin Pedrol14475352021-07-22 15:48:16 +02004940/* request a signalling channel with all SDCCH exhausted, it is expected that a TCH will be selected */
4941private function f_TC_assignment_sdcch_exhausted_req_signalling(charstring id) runs on MSC_ConnHdlr {
4942 g_pars := f_gen_test_hdlr_pars();
4943 g_pars.ra := '02'O; /* RA containing reason=LU */
4944
4945 var MobileIdentityLV mi := valueof(ts_MI_IMSI_LV(g_pars.imsi));
4946 var PDU_ML3_MS_NW l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, mi));
4947 var octetstring l3_enc := enc_PDU_ML3_MS_NW(l3_info);
4948 var template uint3_t tsc := ?;
4949
4950 f_MscConnHdlr_init(g_pars.media_nr, host_bts, host_mgw_mgcp, FR_AMR);
4951 f_create_bssmap_exp(l3_enc);
4952 /* call helper function for CHAN_RQD -> IMM ASS ->EST_IND */
4953 RSL_Emulation.f_chan_est(g_pars.ra, l3_enc, g_pars.link_id, g_pars.fn, tsc);
4954
4955 /* we should now have a COMPL_L3 at the MSC */
4956 timer T := 10.0;
4957 T.start;
4958 alt {
4959 [] BSSAP.receive(tr_BSSMAP_ComplL3);
4960 [] T.timeout {
4961 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout waiting for COMPLETE LAYER 3 INFORMATION");
4962 }
4963 }
4964}
4965testcase TC_assignment_sdcch_exhausted_req_signalling() runs on test_CT {
4966 var MSC_ConnHdlr vc_conn;
4967 f_init(1, true);
4968 f_sleep(1.0);
4969 f_disable_all_sdcch();
4970 vc_conn := f_start_handler(refers(f_TC_assignment_sdcch_exhausted_req_signalling));
4971 vc_conn.done;
4972 f_enable_all_sdcch();
4973 f_shutdown_helper();
4974}
4975
4976/* Request a signalling channel with all SDCCH exhausted, it is
4977 expected that no TCH will be selected for signalling and assigment will fail
4978 because it's dictated by VTY config */
4979testcase TC_assignment_sdcch_exhausted_req_signalling_tch_forbidden() runs on test_CT {
4980 var RSL_Message rsl_unused, rsl_msg;
4981 var GsmRrMessage rr;
4982 f_init(1, false);
4983 f_sleep(1.0);
4984 f_vty_allow_tch_for_signalling(false, 0);
4985 f_disable_all_sdcch();
4986
4987 /* RA containing reason=LU */
4988 f_ipa_tx(0, ts_RSL_CHAN_RQD('02'O, 2342));
4989 rsl_msg := f_exp_ipa_rx(0, tr_RSL_IMM_ASSIGN(0));
4990 rr := dec_GsmRrMessage(rsl_msg.ies[1].body.full_imm_ass_info.payload);
4991 if (rr.header.message_type != IMMEDIATE_ASSIGNMENT_REJECT) {
4992 setverdict(fail, "Expected reject");
4993 }
4994
4995 f_vty_allow_tch_for_signalling(true, 0);
4996 f_enable_all_sdcch();
4997 f_shutdown_helper();
4998}
4999
5000/* Request a voice channel with all SDCCH exhausted, it is
5001 * expected that TCH channel will be allocated since the VTY option is only
5002 * aimed at signalling requests */
5003private function f_TC_assignment_sdcch_exhausted_req_voice_tch_forbidden(charstring id) runs on MSC_ConnHdlr {
5004 g_pars := f_gen_test_hdlr_pars();
5005 g_pars.ra := '43'O; /* RA containing reason=originating speech call*/
5006
5007 var MobileIdentityLV mi := valueof(ts_MI_IMSI_LV(g_pars.imsi));
5008 var PDU_ML3_MS_NW l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, mi));
5009 var octetstring l3_enc := enc_PDU_ML3_MS_NW(l3_info);
5010 var template uint3_t tsc := ?;
5011
5012 f_MscConnHdlr_init(g_pars.media_nr, host_bts, host_mgw_mgcp, FR_AMR);
5013 f_create_bssmap_exp(l3_enc);
5014 /* call helper function for CHAN_RQD -> IMM ASS ->EST_IND */
5015 RSL_Emulation.f_chan_est(g_pars.ra, l3_enc, g_pars.link_id, g_pars.fn, tsc);
5016
5017 /* we should now have a COMPL_L3 at the MSC */
5018 timer T := 10.0;
5019 T.start;
5020 alt {
5021 [] BSSAP.receive(tr_BSSMAP_ComplL3);
5022 [] T.timeout {
5023 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout waiting for COMPLETE LAYER 3 INFORMATION");
5024 }
5025 }
5026}
5027testcase TC_assignment_sdcch_exhausted_req_voice_tch_forbidden() runs on test_CT {
5028 var MSC_ConnHdlr vc_conn;
5029 f_init(1, true);
5030 f_sleep(1.0);
5031 f_vty_allow_tch_for_signalling(false, 0);
5032 f_disable_all_sdcch();
5033
5034 vc_conn := f_start_handler(refers(f_TC_assignment_sdcch_exhausted_req_voice_tch_forbidden));
5035 vc_conn.done;
5036
5037 f_vty_allow_tch_for_signalling(true, 0);
5038 f_enable_all_sdcch();
5039 f_shutdown_helper();
5040}
5041
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02005042testcase TC_assignment_osmux() runs on test_CT {
5043 var TestHdlrParams pars := f_gen_test_hdlr_pars();
5044 var MSC_ConnHdlr vc_conn;
5045
5046 /* See note above */
5047 var RSL_IE_Body mr_conf := {
5048 other := {
5049 len := 2,
5050 payload := '2804'O
5051 }
5052 };
5053
5054 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_H}));
5055 pars.ass_codec_list.codecElements[0].s0_7 := '00000100'B; /* 5,90k */
5056 pars.ass_codec_list.codecElements[0].s8_15 := '00000111'B;
5057 pars.expect_mr_conf_ie := mr_conf;
5058 pars.use_osmux := true;
5059
5060 f_init(1, true, true);
5061 f_sleep(1.0);
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00005062 f_vty_amr_start_mode_set(false, "1");
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02005063
5064 vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
5065 vc_conn.done;
Neels Hofmeyra6ab8212020-11-25 23:57:47 +00005066
5067 f_vty_amr_start_mode_restore(false);
Vadim Yanitskiy292e5962021-01-03 14:18:47 +01005068 f_shutdown_helper();
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +02005069}
5070
Neels Hofmeyr92b12b72018-09-18 14:30:23 +02005071/* test the procedure of the MSC requesting a Classmark Update:
5072 * a) BSSMAP Classmark Request should result in RR CLASSMARK ENQUIRY,
5073 * b) L3 RR CLASSMARK CHANGE should result in BSSMAP CLASSMARK UPDATE */
Harald Welte898113b2018-01-31 18:32:21 +01005074private function f_tc_classmark(charstring id) runs on MSC_ConnHdlr {
Philipp Maier48604732018-10-09 15:00:37 +02005075 g_pars := f_gen_test_hdlr_pars();
5076
Harald Weltea0630032018-03-20 21:09:55 +01005077 f_create_chan_and_exp();
Harald Welte898113b2018-01-31 18:32:21 +01005078 /* we should now have a COMPL_L3 at the MSC */
Harald Welte898113b2018-01-31 18:32:21 +01005079
Neels Hofmeyr92b12b72018-09-18 14:30:23 +02005080 BSSAP.send(ts_BSSMAP_ClassmarkRequest);
5081 RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_CM_ENQUIRY));
5082
Harald Welte898113b2018-01-31 18:32:21 +01005083 f_rsl_send_l3(ts_RRM_CM_CHG(valueof(ts_CM2)));
5084 BSSAP.receive(tr_BSSMAP_ClassmarkUpd(?, omit));
5085 setverdict(pass);
5086}
5087testcase TC_classmark() runs on test_CT {
5088 var MSC_ConnHdlr vc_conn;
5089 f_init(1, true);
5090 f_sleep(1.0);
Harald Welte8863fa12018-05-10 20:15:27 +02005091 vc_conn := f_start_handler(refers(f_tc_classmark));
Harald Welte898113b2018-01-31 18:32:21 +01005092 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005093 f_shutdown_helper();
Harald Welte898113b2018-01-31 18:32:21 +01005094}
5095
Harald Welteeddf0e92020-06-21 19:42:15 +02005096/* Send a CommonID from the simulated MSC and verify that the information is used to
5097 * fill BSC-internal data structures (specifically, bsc_subscr associated with subscr_conn) */
5098private function f_tc_common_id(charstring id) runs on MSC_ConnHdlr {
5099 g_pars := f_gen_test_hdlr_pars();
5100 f_MscConnHdlr_init_vty();
5101
5102 f_create_chan_and_exp();
5103 /* we should now have a COMPL_L3 at the MSC */
Harald Welteeddf0e92020-06-21 19:42:15 +02005104
5105 /* Send CommonID */
5106 BSSAP.send(ts_BSSMAP_CommonId(g_pars.imsi));
5107
5108 /* Use VTY to verify that the IMSI of the subscr_conn is set */
5109 var charstring regex := "*(IMSI: " & hex2str(g_pars.imsi) & ")*";
5110 f_vty_transceive_match_regexp_retry(BSCVTY, "show conns", regex, 0, 4, 1.0);
5111
5112 setverdict(pass);
5113}
5114testcase TC_common_id() runs on test_CT {
5115 var MSC_ConnHdlr vc_conn;
5116 f_init(1, true);
5117 f_sleep(1.0);
5118 vc_conn := f_start_handler(refers(f_tc_common_id));
5119 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005120 f_shutdown_helper();
Harald Welteeddf0e92020-06-21 19:42:15 +02005121}
5122
Harald Weltee3bd6582018-01-31 22:51:25 +01005123private function f_est_single_l3(template PDU_ML3_MS_NW l3) runs on MSC_ConnHdlr {
Philipp Maier48604732018-10-09 15:00:37 +02005124 g_pars := f_gen_test_hdlr_pars();
Harald Weltea0630032018-03-20 21:09:55 +01005125 f_create_chan_and_exp();
Harald Welte898113b2018-01-31 18:32:21 +01005126 /* we should now have a COMPL_L3 at the MSC */
Harald Welte898113b2018-01-31 18:32:21 +01005127
Harald Weltee3bd6582018-01-31 22:51:25 +01005128 /* send the single message we want to send */
5129 f_rsl_send_l3(l3);
5130}
5131
5132private function f_bssap_expect_nothing(float sec := 5.00) runs on MSC_ConnHdlr {
5133 timer T := sec;
5134 var PDU_BSSAP bssap;
Harald Welte898113b2018-01-31 18:32:21 +01005135 T.start;
5136 alt {
Harald Weltee3bd6582018-01-31 22:51:25 +01005137 [] BSSAP.receive(PDU_BSSAP:?) -> value bssap {
5138 setverdict(fail, "Unexpected BSSMAP ", bssap);
Daniel Willmannafce8662018-07-06 23:11:32 +02005139 mtc.stop;
Harald Welte898113b2018-01-31 18:32:21 +01005140 }
5141 [] T.timeout {
5142 setverdict(pass);
5143 }
5144 }
5145}
5146
Harald Weltee3bd6582018-01-31 22:51:25 +01005147/* unsolicited ASSIGNMENT FAIL (without ASSIGN) from MS shouldn't bring BSC down */
5148private function f_tc_unsol_ass_fail(charstring id) runs on MSC_ConnHdlr {
5149 f_est_single_l3(ts_RRM_AssignmentFailure('00'O));
5150 f_bssap_expect_nothing();
5151}
Harald Welte898113b2018-01-31 18:32:21 +01005152testcase TC_unsol_ass_fail() runs on test_CT {
5153 var MSC_ConnHdlr vc_conn;
5154 f_init(1, true);
5155 f_sleep(1.0);
Harald Welte8863fa12018-05-10 20:15:27 +02005156 vc_conn := f_start_handler(refers(f_tc_unsol_ass_fail));
Harald Welte898113b2018-01-31 18:32:21 +01005157 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005158 f_shutdown_helper();
Harald Welte898113b2018-01-31 18:32:21 +01005159}
Harald Welte552620d2017-12-16 23:21:36 +01005160
Harald Welteea99a002018-01-31 20:46:43 +01005161
5162/* unsolicited ASSIGNMENT COMPLETE (without ASSIGN) from MS shouldn't bring BSC down */
5163private function f_tc_unsol_ass_compl(charstring id) runs on MSC_ConnHdlr {
Harald Weltee3bd6582018-01-31 22:51:25 +01005164 f_est_single_l3(ts_RRM_AssignmentComplete('00'O));
5165 f_bssap_expect_nothing();
Harald Welteea99a002018-01-31 20:46:43 +01005166}
5167testcase TC_unsol_ass_compl() runs on test_CT {
5168 var MSC_ConnHdlr vc_conn;
5169 f_init(1, true);
5170 f_sleep(1.0);
Harald Welte8863fa12018-05-10 20:15:27 +02005171 vc_conn := f_start_handler(refers(f_tc_unsol_ass_compl));
Harald Welteea99a002018-01-31 20:46:43 +01005172 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005173 f_shutdown_helper();
Harald Welteea99a002018-01-31 20:46:43 +01005174}
5175
5176
Harald Weltefbf9b5e2018-01-31 20:41:23 +01005177/* unsolicited HANDOVER FAIL (without ASSIGN) from MS shouldn't bring BSC down */
5178private function f_tc_unsol_ho_fail(charstring id) runs on MSC_ConnHdlr {
Harald Weltee3bd6582018-01-31 22:51:25 +01005179 f_est_single_l3(ts_RRM_HandoverFailure('00'O));
5180 f_bssap_expect_nothing();
Harald Weltefbf9b5e2018-01-31 20:41:23 +01005181}
Harald Weltefbf9b5e2018-01-31 20:41:23 +01005182testcase TC_unsol_ho_fail() runs on test_CT {
5183 var MSC_ConnHdlr vc_conn;
5184 f_init(1, true);
5185 f_sleep(1.0);
Harald Welte8863fa12018-05-10 20:15:27 +02005186 vc_conn := f_start_handler(refers(f_tc_unsol_ho_fail));
Harald Weltefbf9b5e2018-01-31 20:41:23 +01005187 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005188 f_shutdown_helper();
Harald Weltefbf9b5e2018-01-31 20:41:23 +01005189}
5190
5191
Harald Weltee3bd6582018-01-31 22:51:25 +01005192/* short message from MS should be ignored */
5193private function f_tc_err_82_short_msg(charstring id) runs on MSC_ConnHdlr {
Philipp Maier48604732018-10-09 15:00:37 +02005194 g_pars := f_gen_test_hdlr_pars();
Harald Weltea0630032018-03-20 21:09:55 +01005195 f_create_chan_and_exp();
Harald Weltee3bd6582018-01-31 22:51:25 +01005196 /* we should now have a COMPL_L3 at the MSC */
Harald Weltee3bd6582018-01-31 22:51:25 +01005197
5198 /* send short message */
5199 RSL.send(ts_RSL_DATA_IND(g_chan_nr, valueof(ts_RslLinkID_DCCH(0)), ''O));
5200 f_bssap_expect_nothing();
5201}
5202testcase TC_err_82_short_msg() runs on test_CT {
5203 var MSC_ConnHdlr vc_conn;
5204 f_init(1, true);
5205 f_sleep(1.0);
Harald Welte8863fa12018-05-10 20:15:27 +02005206 vc_conn := f_start_handler(refers(f_tc_err_82_short_msg));
Harald Weltee3bd6582018-01-31 22:51:25 +01005207 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005208 f_shutdown_helper();
Harald Weltee3bd6582018-01-31 22:51:25 +01005209}
5210
5211
Harald Weltee9e02e42018-01-31 23:36:25 +01005212/* 24.008 8.4 Unknown message must trigger RR STATUS */
5213private function f_tc_err_84_unknown_msg(charstring id) runs on MSC_ConnHdlr {
5214 f_est_single_l3(ts_RRM_UL_REL('00'O));
5215 timer T := 3.0
5216 alt {
5217 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_STATUS)) {
5218 setverdict(pass);
5219 }
5220 [] BSSAP.receive { setverdict(fail, "unexpected BSSAP"); }
Harald Welte458fd372018-03-21 11:26:23 +01005221 [] T.timeout { setverdict(fail, "Timeout waiting for RR STATUS"); }
Harald Weltee9e02e42018-01-31 23:36:25 +01005222 }
5223}
5224testcase TC_err_84_unknown_msg() runs on test_CT {
5225 var MSC_ConnHdlr vc_conn;
5226 f_init(1, true);
5227 f_sleep(1.0);
Harald Welte8863fa12018-05-10 20:15:27 +02005228 vc_conn := f_start_handler(refers(f_tc_err_84_unknown_msg));
Harald Weltee9e02e42018-01-31 23:36:25 +01005229 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005230 f_shutdown_helper();
Harald Weltee9e02e42018-01-31 23:36:25 +01005231}
5232
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01005233/***********************************************************************
5234 * Handover
5235 ***********************************************************************/
5236
Harald Welte94e0c342018-04-07 11:33:23 +02005237/* execute a "bts <0-255> trx <0-255> timeslot <0-7> " command on given Dchan */
5238private function f_vty_ts_action(charstring suffix, integer bts_nr, integer trx_nr, integer ts_nr)
5239runs on test_CT {
5240 var charstring cmd := "bts "&int2str(bts_nr)&" trx "&int2str(trx_nr)&
5241 " timeslot "&int2str(ts_nr)&" ";
5242 f_vty_transceive(BSCVTY, cmd & suffix);
5243}
5244
Harald Welte261af4b2018-02-12 21:20:39 +01005245/* 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 +07005246private function f_vty_ss_action(TELNETasp_PT pt, charstring suffix,
5247 uint8_t bts_nr, uint8_t trx_nr,
5248 in RslChannelNr chan_nr)
5249{
Harald Welte261af4b2018-02-12 21:20:39 +01005250 /* FIXME: resolve those from component-global state */
5251 var integer ts_nr := chan_nr.tn;
5252 var integer ss_nr;
5253 if (ischosen(chan_nr.u.ch0)) {
5254 ss_nr := 0;
5255 } else if (ischosen(chan_nr.u.lm)) {
5256 ss_nr := chan_nr.u.lm.sub_chan;
5257 } else if (ischosen(chan_nr.u.sdcch4)) {
5258 ss_nr := chan_nr.u.sdcch4.sub_chan;
5259 } else if (ischosen(chan_nr.u.sdcch8)) {
5260 ss_nr := chan_nr.u.sdcch8.sub_chan;
5261 } else {
5262 setverdict(fail, "Invalid ChanNr ", chan_nr);
Daniel Willmannafce8662018-07-06 23:11:32 +02005263 mtc.stop;
Harald Welte261af4b2018-02-12 21:20:39 +01005264 }
5265
5266 var charstring cmd := "bts "&int2str(bts_nr)&" trx "&int2str(trx_nr)&
5267 " timeslot "&int2str(ts_nr)&" sub-slot "&int2str(ss_nr)&" ";
Vadim Yanitskiy00070722020-09-02 17:27:57 +07005268 f_vty_transceive(pt, cmd & suffix);
Harald Welte261af4b2018-02-12 21:20:39 +01005269}
5270
Neels Hofmeyr91401012019-07-11 00:42:35 +02005271/* Even though the VTY command to trigger handover takes a new BTS number as argument, behind the scenes osmo-bsc always
5272 * translates that to a target ARFCN+BSIC first. See bsc_vty.c trigger_ho_or_as(), which puts the selected BTS' neighbor
5273 * ident key (ARFCN + BSIC) in the struct passed on to handover_request(). handover_start() then resolves that to a
5274 * viable actual neighbor cell. So from the internal osmo-bsc perspective, we always request handover to an ARFCN + BSIC
5275 * pair, not really to a specific BTS number. */
Vadim Yanitskiy00070722020-09-02 17:27:57 +07005276private function f_vty_handover(TELNETasp_PT pt, uint8_t bts_nr, uint8_t trx_nr,
5277 in RslChannelNr chan_nr, uint8_t new_bts_nr)
5278{
5279 f_vty_ss_action(pt, "handover " & int2str(new_bts_nr), bts_nr, trx_nr, chan_nr);
Harald Welte261af4b2018-02-12 21:20:39 +01005280}
5281
5282/* intra-BSC hand-over between BTS0 and BTS1 */
5283private function f_tc_ho_int(charstring id) runs on MSC_ConnHdlr {
Harald Welteed848512018-05-24 22:27:58 +02005284 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5285 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Harald Welte261af4b2018-02-12 21:20:39 +01005286
5287 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5288 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
5289
Harald Weltea0630032018-03-20 21:09:55 +01005290 f_establish_fully(ass_cmd, exp_compl);
Neels Hofmeyr666f0432020-07-04 00:53:07 +02005291 f_bts_0_cfg(BSCVTY, {"neighbor bts 1"});
Harald Welte261af4b2018-02-12 21:20:39 +01005292
5293 var HandoverState hs := {
5294 rr_ho_cmpl_seen := false,
5295 handover_done := false,
Neels Hofmeyrc741fcb2021-10-02 14:52:28 +02005296 old_chan_nr := -,
5297 expect_target_tsc := BTS_TSC[1]
Harald Welte261af4b2018-02-12 21:20:39 +01005298 };
Neels Hofmeyrc2cf4542021-10-02 12:26:38 +02005299 /* issue hand-over command on VTY, from BTS 0 to BTS 1 */
Vadim Yanitskiy00070722020-09-02 17:27:57 +07005300 f_vty_handover(BSCVTY, 0, 0, g_chan_nr, 1);
Harald Welte261af4b2018-02-12 21:20:39 +01005301 /* temporarily suspend DChan processing on BTS1 to avoid race with RSLEM_register */
5302 f_rslem_suspend(RSL1_PROC);
Philipp Maier3e2af5d2018-07-11 17:01:05 +02005303
5304 /* From the MGW perspective, a handover is is characterized by
5305 * performing one MDCX operation with the MGW. So we expect to see
5306 * one more MDCX during handover. */
5307 g_media.mgcp_conn[0].mdcx_seen_exp := g_media.mgcp_conn[0].crcx_seen_exp + 1;
5308
Harald Welte261af4b2018-02-12 21:20:39 +01005309 alt {
5310 [] as_handover(hs);
Harald Welte261af4b2018-02-12 21:20:39 +01005311 }
Philipp Maier3e2af5d2018-07-11 17:01:05 +02005312
Philipp Maier4dae0652018-11-12 12:03:26 +01005313 /* Since this is an internal handover we expect the BSC to inform the
5314 * MSC about the event */
5315 BSSAP.receive(tr_BSSMAP_HandoverPerformed);
5316
Philipp Maier3e2af5d2018-07-11 17:01:05 +02005317 /* Check the amount of MGCP transactions is still consistant with the
5318 * test expectation */
5319 f_check_mgcp_expectations()
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005320
Neels Hofmeyrc2cf4542021-10-02 12:26:38 +02005321 var RSL_Message chan_act := f_rslem_get_last_act(RSL1_PROC, 0, g_chan_nr);
5322
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005323 /* Ensure the Channel Activation for the new channel contained the right encryption params. as_handover() set
5324 * 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 +02005325 f_verify_encr_info(chan_act);
5326
5327 f_chan_act_verify_tsc(chan_act, BTS_TSC[1]);
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005328
Neels Hofmeyr861a4c12018-11-07 01:23:17 +01005329 f_sleep(0.5);
Harald Welte261af4b2018-02-12 21:20:39 +01005330}
5331
5332testcase TC_ho_int() runs on test_CT {
Neels Hofmeyr5f7a9df2021-06-21 01:30:43 +02005333 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Harald Welte261af4b2018-02-12 21:20:39 +01005334 var MSC_ConnHdlr vc_conn;
5335 f_init(2, true);
5336 f_sleep(1.0);
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00005337
Neels Hofmeyrc2cf4542021-10-02 12:26:38 +02005338 pars.expect_tsc := BTS_TSC[0];
5339
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01005340 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00005341
Neels Hofmeyr5f7a9df2021-06-21 01:30:43 +02005342 vc_conn := f_start_handler(refers(f_tc_ho_int), pars);
Harald Welte261af4b2018-02-12 21:20:39 +01005343 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00005344
5345 /* from f_establish_fully() */
5346 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
5347 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
5348 /* from handover */
5349 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
5350 f_ctrs_bsc_and_bts_add(0, "handover:completed");
5351 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
5352 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:completed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01005353 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:attempted");
5354 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:completed");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00005355 f_ctrs_bsc_and_bts_verify();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005356 f_shutdown_helper();
Harald Welte261af4b2018-02-12 21:20:39 +01005357}
Harald Weltee9e02e42018-01-31 23:36:25 +01005358
Oliver Smith7eabd312021-07-12 14:18:56 +02005359function 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 +02005360 var MSC_ConnHdlr vc_conn;
5361 var TestHdlrParams pars := f_gen_test_hdlr_pars();
5362 pars.encr := valueof(t_EncrParams(encr_alg, f_rnd_octstring(8), f_rnd_octstring(16)));
5363
5364 f_init(2, true);
Oliver Smith7eabd312021-07-12 14:18:56 +02005365 f_vty_encryption_a5(enc_a5);
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005366 f_sleep(1.0);
5367
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01005368 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005369
5370 vc_conn := f_start_handler(refers(f_tc_ho_int), pars);
5371 vc_conn.done;
5372
5373 /* from f_establish_fully() */
5374 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
5375 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
5376 /* from handover */
5377 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
5378 f_ctrs_bsc_and_bts_add(0, "handover:completed");
5379 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
5380 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:completed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01005381 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:attempted");
5382 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:completed");
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005383 f_ctrs_bsc_and_bts_verify();
Oliver Smith7eabd312021-07-12 14:18:56 +02005384 f_vty_encryption_a5_reset();
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005385 f_shutdown_helper();
5386}
5387
5388testcase TC_ho_int_a5_0() runs on test_CT {
5389 f_tc_ho_int_a5('01'O);
5390}
5391
5392testcase TC_ho_int_a5_1() runs on test_CT {
5393 f_tc_ho_int_a5('02'O);
5394}
5395
5396testcase TC_ho_int_a5_3() runs on test_CT {
5397 f_tc_ho_int_a5('08'O);
5398}
5399
5400testcase TC_ho_int_a5_4() runs on test_CT {
Oliver Smith7eabd312021-07-12 14:18:56 +02005401 f_tc_ho_int_a5('10'O, "0 1 3 4");
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +02005402}
5403
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005404/* intra-BSC hand-over with CONNection FAILure and cause Radio Link Failure: check RR release cause */
5405private function f_tc_ho_int_radio_link_failure(charstring id) runs on MSC_ConnHdlr {
5406 g_pars := f_gen_test_hdlr_pars();
5407 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5408 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005409
5410 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5411 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
5412
5413 f_establish_fully(ass_cmd, exp_compl);
5414 f_bts_0_cfg(BSCVTY, {"neighbor bts 1"});
5415
5416 var HandoverState hs := {
5417 rr_ho_cmpl_seen := false,
5418 handover_done := false,
Neels Hofmeyrc741fcb2021-10-02 14:52:28 +02005419 old_chan_nr := -,
5420 expect_target_tsc := BTS_TSC[1]
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005421 };
5422 /* issue hand-over command on VTY */
5423 f_vty_handover(BSCVTY, 0, 0, g_chan_nr, 1);
5424 /* temporarily suspend DChan processing on BTS1 to avoid race with RSLEM_register */
5425 f_rslem_suspend(RSL1_PROC);
5426
5427 /* From the MGW perspective, a handover is is characterized by
5428 * performing one MDCX operation with the MGW. So we expect to see
5429 * one more MDCX during handover. */
5430 g_media.mgcp_conn[0].mdcx_seen_exp := g_media.mgcp_conn[0].crcx_seen_exp + 1;
5431
5432 var RSL_Message rsl;
5433 var PDU_ML3_NW_MS l3;
5434 var RslChannelNr new_chan_nr;
5435 var GsmArfcn arfcn;
5436 RSL.receive(tr_RSL_DATA_REQ(g_chan_nr)) -> value rsl {
5437 l3 := dec_PDU_ML3_NW_MS(rsl.ies[2].body.l3_info.payload);
5438 if (not ischosen(l3.msgs.rrm.handoverCommand)) {
5439 setverdict(fail, "Expected handoverCommand");
5440 mtc.stop;
5441 }
5442 }
5443 f_ChDesc2RslChanNr(l3.msgs.rrm.handoverCommand.channelDescription2,
5444 new_chan_nr, arfcn);
5445
5446 f_rslem_register(0, new_chan_nr, RSL1_PROC);
5447
5448 /* resume processing of RSL DChan messages, which was temporarily suspended
5449 * before performing a hand-over */
5450 f_rslem_resume(RSL1_PROC);
5451 RSL1.receive(tr_RSL_IPA_CRCX(new_chan_nr));
5452
5453 f_sleep(1.0);
5454
5455 /* Handover fails because no HANDO DET appears on the new lchan,
5456 * and the old lchan reports a Radio Link Failure. */
5457 RSL.send(ts_RSL_CONN_FAIL_IND(g_chan_nr, RSL_ERR_RADIO_LINK_FAIL));
5458
5459 var PDU_BSSAP rx_clear_request;
5460 BSSAP.receive(tr_BSSMAP_ClearRequest) -> value rx_clear_request;
5461 var BssmapCause cause := bit2int(rx_clear_request.pdu.bssmap.clearRequest.cause.causeValue);
5462 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
5463
5464 var RR_Cause rr_cause := GSM48_RR_CAUSE_ABNORMAL_UNSPEC;
5465
5466 var MgcpCommand mgcp;
5467 interleave {
5468 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_RELEASE(int2oct(enum2int(rr_cause), 1)))) {}
5469 [] RSL.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {}
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +02005470 [] RSL.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005471 RSL.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
Neels Hofmeyre680b012021-07-22 19:19:09 +02005472 f_rslem_unregister(0, g_chan_nr);
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005473 }
5474 [] RSL1.receive(tr_RSL_DEACT_SACCH(new_chan_nr)) {}
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +02005475 [] RSL1.receive(tr_RSL_RF_CHAN_REL(new_chan_nr)) {
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005476 RSL1.send(ts_RSL_RF_CHAN_REL_ACK(new_chan_nr));
Neels Hofmeyre680b012021-07-22 19:19:09 +02005477 f_rslem_unregister(0, g_chan_nr, PT := RSL1_PROC);
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005478 }
5479 [] BSSAP.receive(tr_BSSMAP_ClearComplete) {}
5480 }
5481
5482 f_sleep(0.5);
5483 setverdict(pass);
5484}
5485testcase TC_ho_int_radio_link_failure() runs on test_CT {
5486 var MSC_ConnHdlr vc_conn;
5487 f_init(2, true);
5488 f_sleep(1.0);
5489
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01005490 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005491
5492 vc_conn := f_start_handler(refers(f_tc_ho_int_radio_link_failure));
5493 vc_conn.done;
5494
5495 /* from f_establish_fully() */
5496 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
5497 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
5498 /* from handover */
5499 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
5500 f_ctrs_bsc_and_bts_add(0, "handover:stopped");
5501 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
5502 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:stopped");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01005503 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:attempted");
5504 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:stopped");
Neels Hofmeyr5f144212020-11-03 15:41:58 +00005505 f_ctrs_bsc_and_bts_verify();
5506 f_shutdown_helper();
5507}
5508
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005509/* Expecting MGCP to DLCX the endpoint's two connections: towards BTS and towards MSC */
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02005510private function f_expect_dlcx_conns() runs on MSC_ConnHdlr {
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005511 var MgcpCommand mgcp;
Pau Espin Pedrolfd02ad42019-06-18 17:45:20 +02005512 var template MgcpResponse mgcp_resp;
5513 var MGCP_RecvFrom mrf;
5514 var template MgcpMessage msg_resp;
5515 var template MgcpMessage msg_dlcx := {
5516 command := tr_DLCX()
5517 }
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005518
Pau Espin Pedrolfd02ad42019-06-18 17:45:20 +02005519 if (g_pars.aoip) {
5520 MGCP.receive(tr_DLCX()) -> value mgcp {
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005521 log("Got first DLCX: ", mgcp);
5522 MGCP.send(ts_DLCX_ACK2(mgcp.line.trans_id));
Pau Espin Pedrolfd02ad42019-06-18 17:45:20 +02005523 };
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005524
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005525 MGCP.receive(tr_DLCX()) -> value mgcp {
5526 log("Got second DLCX: ", mgcp);
5527 MGCP.send(ts_DLCX_ACK2(mgcp.line.trans_id));
5528 };
Pau Espin Pedrolfd02ad42019-06-18 17:45:20 +02005529 } else {
5530 /* For SCCPLite, BSC doesn't handle the MSC-side */
5531 MGCP_MULTI.receive(tr_MGCP_RecvFrom_any(msg_dlcx)) -> value mrf {
5532 log("Got first DLCX: ", mrf.msg.command);
5533 msg_resp := {
5534 response := ts_DLCX_ACK2(mrf.msg.command.line.trans_id)
5535 }
5536 MGCP_MULTI.send(t_MGCP_SendToMrf(mrf, msg_resp));
5537 };
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005538 }
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005539}
5540
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02005541private 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 +01005542
Neels Hofmeyrafe2ea52021-11-24 15:16:12 +01005543 var NcellReports neighbor_rep := {
5544 { rxlev := 20, bcch_freq := 0, bsic := 11 }
5545 };
5546 var octetstring l3_mr := enc_GsmRrL3Message(valueof(ts_MEAS_REP(true, 8, 8, reps := neighbor_rep)));
5547 RSL.send(ts_RSL_MEAS_RES(g_chan_nr, 0, ts_RSL_IE_UplinkMeas, ts_RSL_IE_BS_Power(0), ts_RSL_IE_L1Info,
5548 l3_mr, 0));
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01005549
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02005550 BSSAP.receive(tr_BSSMAP_HandoverRequired(exp_oldToNewBSSIEs));
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01005551
5552 f_sleep(0.5);
5553 /* The MSC negotiates Handover Request and Handover Request Ack with
5554 * the other BSS and comes back with a BSSMAP Handover Command
5555 * containing an RR Handover Command coming from the target BSS... */
5556
5557 var PDU_ML3_NW_MS rr_ho_cmd := valueof(ts_RR_HandoverCommand);
5558 log("Remote cell's RR Handover Command passed through as L3 Info: ", rr_ho_cmd);
5559 var octetstring rr_ho_cmd_enc := enc_PDU_ML3_NW_MS(rr_ho_cmd);
5560 log("Remote cell's RR Handover Command passed through as L3 Info, encoded: ", rr_ho_cmd_enc);
5561 BSSAP.send(ts_BSSMAP_HandoverCommand(rr_ho_cmd_enc));
5562
5563 /* expect the Handover Command to go out on RR */
5564 var RSL_Message rsl_ho_cmd
5565 RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, ?)) -> value rsl_ho_cmd;
5566 log("RSL Data Req went out to first BTS: ", rsl_ho_cmd);
5567 var RSL_IE_Body rsl_ho_cmd_l3;
5568 if (not f_rsl_find_ie(rsl_ho_cmd, RSL_IE_L3_INFO, rsl_ho_cmd_l3)) {
5569 log("RSL message contains no L3 Info IE, expected RR Handover Command");
5570 setverdict(fail);
5571 } else {
5572 log("Found L3 Info: ", rsl_ho_cmd_l3);
5573 if (rsl_ho_cmd_l3.l3_info.payload != rr_ho_cmd_enc) {
5574 log("FAIL: the BSC sent out a different L3 Info, not matching the RR Handover Command the other BSS forwarded.");
5575 setverdict(fail);
5576 } else {
5577 log("Success: the BSC sent out the same RR Handover Command the other BSS forwarded.");
5578 setverdict(pass);
5579 }
5580 }
5581
5582 /* When the other BSS has reported a completed handover, this side is
5583 * torn down. */
5584
5585 var myBSSMAP_Cause cause_val := GSM0808_CAUSE_HANDOVER_SUCCESSFUL;
5586 var BssmapCause cause := enum2int(cause_val);
5587 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
5588
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02005589 f_expect_dlcx_conns();
Pau Espin Pedrol06199952021-06-15 11:30:00 +02005590
5591 interleave {
5592 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_RELEASE));
5593 [] RSL.receive(tr_RSL_DEACT_SACCH(g_chan_nr));
5594 [] RSL.receive(tr_RSL_RF_CHAN_REL(g_chan_nr));
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02005595 [] BSSAP.receive(tr_BSSMAP_ClearComplete);
Pau Espin Pedrol06199952021-06-15 11:30:00 +02005596 }
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01005597 setverdict(pass);
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02005598}
5599
5600private function f_tc_ho_out_of_this_bsc(charstring id) runs on MSC_ConnHdlr {
5601 g_pars := f_gen_test_hdlr_pars();
5602 var PDU_BSSAP ass_req := f_gen_ass_req();
5603 ass_req.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5604 ass_req.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
5605 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5606 f_establish_fully(ass_req, exp_compl);
5607
5608 f_ho_out_of_this_bsc();
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01005609}
5610testcase TC_ho_out_of_this_bsc() runs on test_CT {
5611 var MSC_ConnHdlr vc_conn;
5612
Neels Hofmeyrafe2ea52021-11-24 15:16:12 +01005613 f_init_vty();
5614 f_bts_0_cfg(BSCVTY,
5615 {"neighbor-list mode automatic",
5616 "handover 1",
5617 "handover algorithm 2",
5618 "handover2 window rxlev averaging 1",
Neels Hofmeyr6cc90eb2021-12-15 12:49:39 +01005619 "no neighbors",
Neels Hofmeyrafe2ea52021-11-24 15:16:12 +01005620 "neighbor lac 99 arfcn 123 bsic any"});
5621 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
5622
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01005623 f_init(1, true);
5624 f_sleep(1.0);
5625
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01005626 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00005627
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01005628 vc_conn := f_start_handler(refers(f_tc_ho_out_of_this_bsc));
5629 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00005630
5631 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
5632 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
5633 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
5634 f_ctrs_bsc_and_bts_add(0, "handover:completed");
5635 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
5636 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:completed");
5637 f_ctrs_bsc_and_bts_verify();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005638 f_shutdown_helper();
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01005639}
5640
Neels Hofmeyr0aa719b2020-10-12 18:43:09 +00005641private function f_mo_l3_transceive(RSL_DCHAN_PT rsl := RSL,
5642 template (value) RslLinkId link_id := ts_RslLinkID_DCCH(0),
Vadim Yanitskiy2ef6a2f2020-10-08 23:17:32 +07005643 template (present) OCT1 dlci := ?,
Vadim Yanitskiyb93aa432020-10-01 14:23:11 +07005644 octetstring l3 := '0123456789'O)
5645runs on MSC_ConnHdlr {
Neels Hofmeyr43654812020-09-25 01:35:35 +02005646 /* The old lchan and conn should still be active. See that arbitrary L3
5647 * is still going through. */
Neels Hofmeyr0aa719b2020-10-12 18:43:09 +00005648 rsl.send(ts_RSL_DATA_IND(g_chan_nr, link_id, l3));
Neels Hofmeyr43654812020-09-25 01:35:35 +02005649 var template PDU_BSSAP exp_data := {
5650 discriminator := '1'B,
5651 spare := '0000000'B,
Vadim Yanitskiyb93aa432020-10-01 14:23:11 +07005652 dlci := dlci,
5653 lengthIndicator := lengthof(l3),
Neels Hofmeyr43654812020-09-25 01:35:35 +02005654 pdu := {
5655 dtap := l3
5656 }
5657 };
5658 BSSAP.receive(exp_data);
5659 setverdict(pass);
5660}
5661
Neels Hofmeyr0aa719b2020-10-12 18:43:09 +00005662private function f_mt_l3_transceive(RSL_DCHAN_PT rsl := RSL,
5663 template (present) RslLinkId link_id := tr_RslLinkID_DCCH(0),
Vadim Yanitskiy0033a3b2020-10-01 22:21:16 +07005664 template (value) OCT1 dlci := '00'O,
5665 octetstring l3 := '0123456789'O)
5666runs on MSC_ConnHdlr {
5667 BSSAP.send(PDU_BSSAP:{
5668 discriminator := '1'B,
5669 spare := '0000000'B,
5670 dlci := dlci,
5671 lengthIndicator := lengthof(l3),
5672 pdu := {
5673 dtap := l3
5674 }
5675 });
Neels Hofmeyr0aa719b2020-10-12 18:43:09 +00005676 rsl.receive(tr_RSL_DATA_REQ(g_chan_nr, link_id, l3));
Vadim Yanitskiy0033a3b2020-10-01 22:21:16 +07005677 setverdict(pass);
5678}
5679
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02005680/* BSC asks for inter-BSC HO, but the MSC decides that it won't happen and
5681 * simply never sends a BSSMAP Handover Command. */
5682private function f_tc_ho_out_fail_no_msc_response(charstring id) runs on MSC_ConnHdlr {
Daniel Willmann3b59eb52018-10-29 15:40:55 +01005683 g_pars := f_gen_test_hdlr_pars();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02005684
5685 var PDU_BSSAP ass_req := f_gen_ass_req();
5686 ass_req.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5687 ass_req.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
5688 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5689 f_establish_fully(ass_req, exp_compl);
5690
Neels Hofmeyr6cc90eb2021-12-15 12:49:39 +01005691 f_bts_0_cfg(BSCVTY, {"no neighbor lac 99", "neighbor lac 99 arfcn 123 bsic any"});
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02005692 f_vty_transceive(BSCVTY, "handover any to arfcn 123 bsic any");
5693
5694 BSSAP.receive(tr_BSSMAP_HandoverRequired);
5695
5696 /* osmo-bsc should time out 10 seconds after the handover started.
5697 * Let's give it a bit extra. */
5698 f_sleep(15.0);
5699
Vadim Yanitskiy74ae5eb2020-10-01 22:13:29 +07005700 f_mo_l3_transceive();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02005701 f_sleep(1.0);
5702}
5703testcase TC_ho_out_fail_no_msc_response() runs on test_CT {
5704 var MSC_ConnHdlr vc_conn;
5705
5706 f_init(1, true);
5707 f_sleep(1.0);
5708
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01005709 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00005710
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02005711 vc_conn := f_start_handler(refers(f_tc_ho_out_fail_no_msc_response));
5712 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00005713
5714 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
5715 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
5716 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
5717 f_ctrs_bsc_and_bts_add(0, "handover:timeout");
5718 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
5719 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:timeout");
5720 f_ctrs_bsc_and_bts_verify();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005721 f_shutdown_helper();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02005722}
5723
5724/* BSC asks for inter-BSC HO, receives BSSMAP Handover Command, but MS reports
5725 * RR Handover Failure. */
5726private function f_tc_ho_out_fail_rr_ho_failure(charstring id) runs on MSC_ConnHdlr {
Daniel Willmann3b59eb52018-10-29 15:40:55 +01005727 g_pars := f_gen_test_hdlr_pars();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02005728
5729 var PDU_BSSAP ass_req := f_gen_ass_req();
5730 ass_req.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5731 ass_req.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
5732 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5733 f_establish_fully(ass_req, exp_compl);
5734
Neels Hofmeyr6cc90eb2021-12-15 12:49:39 +01005735 f_bts_0_cfg(BSCVTY, {"no neighbor lac 99", "neighbor lac 99 arfcn 123 bsic any"});
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02005736 f_vty_transceive(BSCVTY, "handover any to arfcn 123 bsic any");
5737
5738 BSSAP.receive(tr_BSSMAP_HandoverRequired);
5739
5740 f_sleep(0.5);
5741 /* The MSC negotiates Handover Request and Handover Request Ack with
5742 * the other BSS and comes back with a BSSMAP Handover Command
5743 * containing an RR Handover Command coming from the target BSS... */
5744
5745 var PDU_ML3_NW_MS rr_ho_cmd := valueof(ts_RR_HandoverCommand);
5746 log("Remote cell's RR Handover Command passed through as L3 Info: ", rr_ho_cmd);
5747 var octetstring rr_ho_cmd_enc := enc_PDU_ML3_NW_MS(rr_ho_cmd);
5748 log("Remote cell's RR Handover Command passed through as L3 Info, encoded: ", rr_ho_cmd_enc);
5749 BSSAP.send(ts_BSSMAP_HandoverCommand(rr_ho_cmd_enc));
5750
5751 /* expect the Handover Command to go out on RR */
5752 var RSL_Message rsl_ho_cmd
5753 RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, ?)) -> value rsl_ho_cmd;
5754 log("RSL Data Req went out to first BTS: ", rsl_ho_cmd);
5755 var RSL_IE_Body rsl_ho_cmd_l3;
5756 if (not f_rsl_find_ie(rsl_ho_cmd, RSL_IE_L3_INFO, rsl_ho_cmd_l3)) {
5757 log("RSL message contains no L3 Info IE, expected RR Handover Command");
5758 setverdict(fail);
5759 } else {
5760 log("Found L3 Info: ", rsl_ho_cmd_l3);
5761 if (rsl_ho_cmd_l3.l3_info.payload != rr_ho_cmd_enc) {
5762 log("FAIL: the BSC sent out a different L3 Info, not matching the RR Handover Command the other BSS forwarded.");
5763 setverdict(fail);
5764 } else {
5765 log("Success: the BSC sent out the same RR Handover Command the other BSS forwarded.");
5766 setverdict(pass);
5767 }
5768 }
5769
5770 f_sleep(0.2);
5771 f_rsl_send_l3(ts_RRM_HandoverFailure('00'O));
5772
5773 /* Should tell the MSC about the failure */
5774 BSSAP.receive(tr_BSSMAP_HandoverFailure);
5775
5776 f_sleep(1.0);
5777
Vadim Yanitskiy74ae5eb2020-10-01 22:13:29 +07005778 f_mo_l3_transceive();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02005779 f_sleep(1.0);
5780
5781 setverdict(pass);
5782 f_sleep(1.0);
5783}
5784testcase TC_ho_out_fail_rr_ho_failure() runs on test_CT {
5785 var MSC_ConnHdlr vc_conn;
5786
5787 f_init(1, true);
5788 f_sleep(1.0);
5789
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01005790 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00005791
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02005792 vc_conn := f_start_handler(refers(f_tc_ho_out_fail_rr_ho_failure));
5793 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00005794
5795 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
5796 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
5797 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
5798 f_ctrs_bsc_and_bts_add(0, "handover:failed");
5799 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
5800 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:failed");
5801 f_ctrs_bsc_and_bts_verify();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005802 f_shutdown_helper();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02005803}
5804
Neels Hofmeyr10f2bfa2019-07-09 19:33:29 +02005805/* BSC asks for inter-BSC-out HO, receives BSSMAP Handover Command, but then no reply is received about HO outcome
5806 * (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 +02005807 * and the lchan is released. */
5808private function f_tc_ho_out_fail_no_result_after_ho_cmd(charstring id) runs on MSC_ConnHdlr {
Daniel Willmann3b59eb52018-10-29 15:40:55 +01005809 g_pars := f_gen_test_hdlr_pars();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02005810
5811 var PDU_BSSAP ass_req := f_gen_ass_req();
5812 ass_req.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
5813 ass_req.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
5814 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
5815 f_establish_fully(ass_req, exp_compl);
5816
Neels Hofmeyr6cc90eb2021-12-15 12:49:39 +01005817 f_bts_0_cfg(BSCVTY, {"no neighbor lac 99", "neighbor lac 99 arfcn 123 bsic any"});
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02005818 f_vty_transceive(BSCVTY, "handover any to arfcn 123 bsic any");
5819
5820 BSSAP.receive(tr_BSSMAP_HandoverRequired);
5821
5822 f_sleep(0.5);
5823 /* The MSC negotiates Handover Request and Handover Request Ack with
5824 * the other BSS and comes back with a BSSMAP Handover Command
5825 * containing an RR Handover Command coming from the target BSS... */
5826
5827 var PDU_ML3_NW_MS rr_ho_cmd := valueof(ts_RR_HandoverCommand);
5828 log("Remote cell's RR Handover Command passed through as L3 Info: ", rr_ho_cmd);
5829 var octetstring rr_ho_cmd_enc := enc_PDU_ML3_NW_MS(rr_ho_cmd);
5830 log("Remote cell's RR Handover Command passed through as L3 Info, encoded: ", rr_ho_cmd_enc);
5831 BSSAP.send(ts_BSSMAP_HandoverCommand(rr_ho_cmd_enc));
5832
5833 /* expect the Handover Command to go out on RR */
5834 var RSL_Message rsl_ho_cmd
5835 RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, ?)) -> value rsl_ho_cmd;
5836 log("RSL Data Req went out to first BTS: ", rsl_ho_cmd);
5837 var RSL_IE_Body rsl_ho_cmd_l3;
5838 if (not f_rsl_find_ie(rsl_ho_cmd, RSL_IE_L3_INFO, rsl_ho_cmd_l3)) {
5839 log("RSL message contains no L3 Info IE, expected RR Handover Command");
5840 setverdict(fail);
5841 } else {
5842 log("Found L3 Info: ", rsl_ho_cmd_l3);
5843 if (rsl_ho_cmd_l3.l3_info.payload != rr_ho_cmd_enc) {
5844 log("FAIL: the BSC sent out a different L3 Info, not matching the RR Handover Command the other BSS forwarded.");
5845 setverdict(fail);
5846 } else {
5847 log("Success: the BSC sent out the same RR Handover Command the other BSS forwarded.");
5848 setverdict(pass);
5849 }
5850 }
5851
Neels Hofmeyr10f2bfa2019-07-09 19:33:29 +02005852 /* We get neither success nor failure report from the remote BSS. Eventually T8 times out and we run into 3GPP
5853 * TS 48.008 3.1.5.3.3 "Abnormal Conditions": Clear Request should go to the MSC, and RR should be released
5854 * after Clear Command */
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02005855
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02005856 var PDU_BSSAP rx_clear_request;
Neels Hofmeyre1797aa2019-07-09 19:34:04 +02005857 BSSAP.receive(tr_BSSMAP_ClearRequest) -> value rx_clear_request;
5858 log("Got BSSMAP Clear Request");
5859 /* Instruct BSC to clear channel */
5860 var BssmapCause cause := bit2int(rx_clear_request.pdu.bssmap.clearRequest.cause.causeValue);
5861 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
5862
5863 var MgcpCommand mgcp;
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02005864 interleave {
Neels Hofmeyr861a4c12018-11-07 01:23:17 +01005865 [] RSL.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {
5866 log("Got Deact SACCH");
5867 }
Harald Welte924b6ea2019-02-04 01:05:34 +01005868 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_RELEASE)) {
Neels Hofmeyr211169d2018-11-07 00:37:29 +01005869 log("Got RR Release");
5870 }
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +02005871 [] RSL.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02005872 log("Got RF Chan Rel");
5873 RSL.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
Neels Hofmeyre680b012021-07-22 19:19:09 +02005874 f_rslem_unregister(0, g_chan_nr);
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02005875 }
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02005876 }
5877
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02005878 f_expect_dlcx_conns();
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02005879 BSSAP.receive(tr_BSSMAP_ClearComplete);
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02005880
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02005881 setverdict(pass);
5882 f_sleep(1.0);
5883}
Neels Hofmeyrd8a602c2019-07-09 19:46:01 +02005884testcase TC_ho_out_fail_no_result_after_ho_cmd() runs on test_CT {
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02005885 var MSC_ConnHdlr vc_conn;
5886
5887 f_init(1, true);
5888 f_sleep(1.0);
5889
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01005890 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00005891
Neels Hofmeyrd8a602c2019-07-09 19:46:01 +02005892 vc_conn := f_start_handler(refers(f_tc_ho_out_fail_no_result_after_ho_cmd));
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02005893 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00005894
5895 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
5896 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
5897 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
5898 f_ctrs_bsc_and_bts_add(0, "handover:timeout");
5899 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
5900 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:timeout");
5901 f_ctrs_bsc_and_bts_verify();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02005902 f_shutdown_helper();
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +02005903}
5904
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02005905private 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 +01005906 /* Hack: the proper way would be to wait for the BSSMAP Handover Request ACK and extract the
5907 * actual assigned chan_nr from its L3 (RR Handover Command) message. But osmo-bsc starts acting
5908 * on the lchan even before we get a chance to evaluate the BSSMAP Handover Request ACK. So we
5909 * need to assume that osmo-bsc will activate TS 1 and already set up this lchan's RSL emulation
5910 * before we get started. */
5911 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
5912 f_rslem_register(0, new_chan_nr);
5913 g_chan_nr := new_chan_nr;
Neels Hofmeyr34174bd2021-10-02 14:52:57 +02005914 var uint3_t expect_target_tsc := BTS_TSC[0];
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01005915 f_sleep(1.0);
5916
5917 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
5918 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
5919 activate(as_Media());
5920
Neels Hofmeyr90f80962020-06-12 16:16:55 +02005921 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02005922 f_gen_handover_req(aoip_tla := g_pars.host_aoip_tla,
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02005923 oldToNewBSSIEs := oldToNewBSSIEs,
5924 enc := g_pars.encr)));
Harald Welte6811d102019-04-14 22:23:14 +02005925 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01005926
5927 /* The RSL Emulation magically accepts the Chan Activ behind the scenes. */
5928
5929 var PDU_BSSAP rx_bssap;
5930 var octetstring ho_command_str;
5931
5932 BSSAP.receive(tr_BSSMAP_HandoverRequestAcknowledge(?)) -> value rx_bssap;
Pau Espin Pedrol76ba5412019-06-10 11:00:33 +02005933
Neels Hofmeyr34174bd2021-10-02 14:52:57 +02005934 /* we're sure that the channel activation is done now, verify the parameters in it */
5935 var RSL_Message chan_act := f_rslem_get_last_act(RSL_PROC, 0, g_chan_nr);
5936 f_verify_encr_info(chan_act);
5937 f_chan_act_verify_tsc(chan_act, expect_target_tsc);
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02005938
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01005939 ho_command_str := rx_bssap.pdu.bssmap.handoverRequestAck.layer3Information.layer3info;
5940 log("Received L3 Info in HO Request Ack: ", ho_command_str);
5941 var PDU_ML3_NW_MS ho_command := dec_PDU_ML3_NW_MS(ho_command_str);
5942 log("L3 Info in HO Request Ack is ", ho_command);
5943
5944 var GsmArfcn arfcn;
5945 var RslChannelNr actual_new_chan_nr;
5946 f_ChDesc2RslChanNr(ho_command.msgs.rrm.handoverCommand.channelDescription2,
5947 actual_new_chan_nr, arfcn);
5948
5949 if (actual_new_chan_nr != new_chan_nr) {
5950 log("ERROR: osmo-bsc assigned a different lchan than we assumed above -- this test will fail now.",
5951 " Assumed: ", new_chan_nr, " Assigned: ", actual_new_chan_nr);
5952 setverdict(fail);
5953 return;
5954 }
5955 log("Handover Command chan_nr is", actual_new_chan_nr);
5956
Neels Hofmeyr34174bd2021-10-02 14:52:57 +02005957 var uint3_t got_tsc := rr_chan_desc_tsc(ho_command.msgs.rrm.handoverCommand.channelDescription2);
5958 if (not match(got_tsc, expect_target_tsc)) {
5959 setverdict(fail, "RR Handover Command: unexpected TSC in Channel Description: expected ",
5960 expect_target_tsc, " got ", got_tsc);
5961 mtc.stop;
5962 } else {
5963 log("handoverCommand: verified TSC = ", got_tsc);
5964 }
5965
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01005966 /* Now the MSC forwards the RR Handover Command to the other BSC, which
5967 * tells the MS to handover to the new lchan. Here comes the new MS on
5968 * the new lchan with a Handover RACH: */
5969
5970 /* send handover detect */
5971
5972 RSL.send(ts_RSL_HANDO_DET(new_chan_nr));
5973
5974 BSSAP.receive(tr_BSSMAP_HandoverDetect);
5975
5976 /* send handover complete over the new channel */
5977
5978 var PDU_ML3_MS_NW l3_tx := valueof(ts_RRM_HandoverComplete('00'O));
5979 RSL.send(ts_RSL_EST_IND(new_chan_nr, valueof(ts_RslLinkID_DCCH(0)),
5980 enc_PDU_ML3_MS_NW(l3_tx)));
5981
5982 BSSAP.receive(tr_BSSMAP_HandoverComplete);
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02005983 setverdict(pass);
5984}
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02005985
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02005986private function f_tc_ho_into_this_bsc(charstring id) runs on MSC_ConnHdlr {
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02005987 var template PDU_ML3_NW_MS exp_rr_rel_tmpl;
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02005988 var template (omit) BSSMAP_oldToNewBSSIEs oldToNewBSSIEs := omit;
5989 if (not istemplatekind(g_pars.last_used_eutran_plmn, "omit")) {
5990 oldToNewBSSIEs := f_ts_BSSMAP_oldToNewBSSIEs(ts_BSSMAP_LastUsedEUTRANPLMNId(g_pars.last_used_eutran_plmn));
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02005991 }
5992 if (g_pars.exp_fast_return) {
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02005993 exp_rr_rel_tmpl := tr_RRM_RR_RELEASE_CellSelectInd;
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02005994 } else {
5995 exp_rr_rel_tmpl := tr_RRM_RR_RELEASE;
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02005996 }
5997 f_ho_into_this_bsc(id, oldToNewBSSIEs);
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02005998 f_perform_clear(exp_rr_rel_tmpl := exp_rr_rel_tmpl);
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01005999 setverdict(pass);
6000}
Pau Espin Pedrol07866632020-09-03 19:10:55 +02006001function f_tc_ho_into_this_bsc_main(TestHdlrParams pars) runs on test_CT {
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006002 var MSC_ConnHdlr vc_conn;
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006003
6004 f_init(1, true);
6005 f_sleep(1.0);
6006
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006007 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006008
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006009 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
6010 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006011
6012 vc_conn := f_start_handler(refers(f_tc_ho_into_this_bsc), pars);
6013 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006014
6015 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6016 f_ctrs_bsc_and_bts_add(0, "handover:completed");
6017 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:attempted");
6018 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:completed");
6019 f_ctrs_bsc_and_bts_verify();
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006020}
6021
Pau Espin Pedrol07866632020-09-03 19:10:55 +02006022testcase TC_ho_into_this_bsc() runs on test_CT {
6023 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6024 f_tc_ho_into_this_bsc_main(pars);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02006025 f_shutdown_helper();
Pau Espin Pedrol07866632020-09-03 19:10:55 +02006026}
6027
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +02006028function f_tc_ho_into_this_bsc_a5(OCT1 encr_alg) runs on test_CT {
6029 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6030 pars.encr := valueof(t_EncrParams(encr_alg, f_rnd_octstring(8), f_rnd_octstring(16)));
6031 f_tc_ho_into_this_bsc_main(pars);
6032 f_shutdown_helper();
6033}
6034
6035testcase TC_ho_into_this_bsc_a5_0() runs on test_CT {
6036 f_tc_ho_into_this_bsc_a5('01'O);
6037}
6038
6039testcase TC_ho_into_this_bsc_a5_1() runs on test_CT {
6040 f_tc_ho_into_this_bsc_a5('02'O);
6041}
6042
6043testcase TC_ho_into_this_bsc_a5_3() runs on test_CT {
6044 f_tc_ho_into_this_bsc_a5('08'O);
6045}
6046
6047testcase TC_ho_into_this_bsc_a5_4() runs on test_CT {
6048 f_tc_ho_into_this_bsc_a5('10'O);
6049}
6050
Pau Espin Pedrol07866632020-09-03 19:10:55 +02006051testcase TC_ho_into_this_bsc_tla_v6() runs on test_CT {
6052 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6053 pars.host_aoip_tla := "::6";
6054 f_tc_ho_into_this_bsc_main(pars);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02006055 f_shutdown_helper();
Pau Espin Pedrol07866632020-09-03 19:10:55 +02006056}
6057
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02006058/* Similar to TC_ho_into_this_bsc, but when in SRVCC, HO Req contains "Old BSS
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006059 to New BSS Information" IE with "Last Used E-UTRAN PLMN Id", which, when the
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02006060 channel is later released (RR CHannel Release), should trigger inclusion of
6061 IE "Cell Selection Indicator after Release of all TCH and SDCCH" with E-UTRAN
6062 neighbors. */
6063testcase TC_srvcc_eutran_to_geran() runs on test_CT {
6064 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6065 pars.last_used_eutran_plmn := '323454'O;
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006066 pars.exp_fast_return := true;
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02006067 f_tc_ho_into_this_bsc_main(pars);
Pau Espin Pedrol211a7142021-06-15 16:43:03 +02006068
6069 f_ctrs_bsc_and_bts_add(0, "srvcc:attempted");
6070 f_ctrs_bsc_and_bts_add(0, "srvcc:completed");
6071 f_ctrs_bsc_and_bts_verify();
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02006072 f_shutdown_helper();
6073}
6074
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006075/* Same as TC_srvcc_eutran_to_geran, but test explicitly forbiding fast return
6076 on the BTS. As a result, RR Release shouldn't contain the EUTRAN neighbor
6077 list when the channel is released. */
6078testcase TC_srvcc_eutran_to_geran_forbid_fast_return() runs on test_CT {
6079 f_init_vty();
6080 f_vty_allow_srvcc_fast_return(true, 0)
6081
6082 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6083 pars.last_used_eutran_plmn := '323454'O;
6084 pars.exp_fast_return := false;
6085 f_tc_ho_into_this_bsc_main(pars);
6086 f_vty_allow_srvcc_fast_return(false, 0);
6087 f_shutdown_helper();
6088}
6089
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006090private function f_tc_srvcc_eutran_to_geran_ho_out(charstring id) runs on MSC_ConnHdlr {
6091 var template (omit) BSSMAP_oldToNewBSSIEs oldToNewBSSIEs;
6092 oldToNewBSSIEs := f_ts_BSSMAP_oldToNewBSSIEs(ts_BSSMAP_LastUsedEUTRANPLMNId(g_pars.last_used_eutran_plmn));
6093 f_ho_into_this_bsc(id, oldToNewBSSIEs);
6094 f_ho_out_of_this_bsc(oldToNewBSSIEs);
6095 setverdict(pass);
6096}
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006097
6098private function f_tc_srvcc_eutran_to_geran_ho_out_main(boolean disable_fast_return)
6099 runs on test_CT {
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006100 var MSC_ConnHdlr vc_conn;
6101 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6102
Neels Hofmeyr6cc90eb2021-12-15 12:49:39 +01006103 f_init_vty();
6104 f_bts_0_cfg(BSCVTY,
6105 {"neighbor-list mode automatic",
6106 "handover 1",
6107 "handover algorithm 2",
6108 "handover2 window rxlev averaging 1",
6109 "no neighbors",
6110 "neighbor lac 99 arfcn 123 bsic any"});
6111 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
6112
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006113 f_init(1, true);
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006114 if (disable_fast_return) {
6115 f_vty_allow_srvcc_fast_return(true, 0);
6116 }
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006117 f_sleep(1.0);
6118
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006119 f_ctrs_bsc_and_bts_handover_init();
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006120
6121 pars.last_used_eutran_plmn := '323454'O;
6122 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
6123 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
6124
6125 vc_conn := f_start_handler(refers(f_tc_srvcc_eutran_to_geran_ho_out), pars);
6126 vc_conn.done;
6127
6128 f_ctrs_bsc_and_bts_add(0, "handover:attempted", 2);
6129 f_ctrs_bsc_and_bts_add(0, "handover:completed", 2);
6130 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:attempted", 1);
6131 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:completed", 1);
6132 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted", 1);
6133 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:completed", 1);
Pau Espin Pedrol211a7142021-06-15 16:43:03 +02006134
6135 f_ctrs_bsc_and_bts_add(0, "srvcc:attempted", 1);
6136 f_ctrs_bsc_and_bts_add(0, "srvcc:completed", 1);
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006137 f_ctrs_bsc_and_bts_verify();
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006138
6139 if (disable_fast_return) {
6140 f_vty_allow_srvcc_fast_return(false, 0);
6141 }
Pau Espin Pedrol35801c32021-04-19 13:03:20 +02006142 f_shutdown_helper();
6143}
6144
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02006145/* First, HO into BSC from EUTRAN (SRVCC): HO Request contains "Old BSS to New
6146 BSS Information" IE with "Last Used E-UTRAN PLMN Id".
6147 Second, HO to another BSC: HO Required contains "Old BSS to New BSS Information"
6148 IE with "Last Used E-UTRAN PLMN Id" from first step. */
6149testcase TC_srvcc_eutran_to_geran_ho_out() runs on test_CT {
6150 f_tc_srvcc_eutran_to_geran_ho_out_main(false);
6151}
6152/* Validate subsequent intra-GSM-HO works the same (with OldBSSToNewBSSInfo IE)
6153 * independently of fast-reture allowed/forbidden in local BTS */
6154testcase TC_srvcc_eutran_to_geran_ho_out_forbid_fast_return() runs on test_CT {
6155 f_tc_srvcc_eutran_to_geran_ho_out_main(true);
6156}
6157
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006158private function f_tc_ho_in_fail_msc_clears(charstring id) runs on MSC_ConnHdlr {
6159 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
6160 f_rslem_register(0, new_chan_nr);
6161 g_chan_nr := new_chan_nr;
6162 f_sleep(1.0);
6163
6164 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
6165 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
6166 activate(as_Media());
6167
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006168 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006169 f_gen_handover_req()));
Harald Welte6811d102019-04-14 22:23:14 +02006170 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006171
6172 /* The RSL Emulation magically accepts the Chan Activ behind the scenes. */
6173
6174 var PDU_BSSAP rx_bssap;
6175 var octetstring ho_command_str;
6176
6177 BSSAP.receive(tr_BSSMAP_HandoverRequestAcknowledge(?)) -> value rx_bssap;
6178
6179 ho_command_str := rx_bssap.pdu.bssmap.handoverRequestAck.layer3Information.layer3info;
6180 log("Received L3 Info in HO Request Ack: ", ho_command_str);
6181 var PDU_ML3_NW_MS ho_command := dec_PDU_ML3_NW_MS(ho_command_str);
6182 log("L3 Info in HO Request Ack is ", ho_command);
6183
6184 var GsmArfcn arfcn;
6185 var RslChannelNr actual_new_chan_nr;
6186 f_ChDesc2RslChanNr(ho_command.msgs.rrm.handoverCommand.channelDescription2,
6187 actual_new_chan_nr, arfcn);
6188
6189 if (actual_new_chan_nr != new_chan_nr) {
6190 log("ERROR: osmo-bsc assigned a different lchan than we assumed above -- this test will fail now.",
6191 " Assumed: ", new_chan_nr, " Assigned: ", actual_new_chan_nr);
6192 setverdict(fail);
6193 return;
6194 }
6195 log("Handover Command chan_nr is", actual_new_chan_nr);
6196
Neels Hofmeyr61ca08d2019-05-06 23:52:22 +02006197 /* For deterministic test results, give some time for the MGW endpoint to be configured */
6198 f_sleep(1.0);
6199
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006200 /* Now the MSC forwards the RR Handover Command to the other BSC, which
6201 * tells the MS to handover to the new lchan. In this case, the MS
6202 * reports a Handover Failure to the old BSS, which forwards a BSSMAP
6203 * Handover Failure to the MSC. The procedure according to 3GPP TS
6204 * 48.008 3.1.5.3.2 "Handover Failure" is then that the MSC sends a
6205 * BSSMAP Clear Command: */
6206
6207 var myBSSMAP_Cause cause_val := GSM0808_CAUSE_RADIO_INTERFACE_FAILURE_REVERSION;
6208 var BssmapCause cause := enum2int(cause_val);
6209 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
6210
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02006211 f_expect_dlcx_conns();
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02006212 BSSAP.receive(tr_BSSMAP_ClearComplete);
6213
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006214 setverdict(pass);
6215 f_sleep(1.0);
6216
6217 setverdict(pass);
6218}
6219testcase TC_ho_in_fail_msc_clears() runs on test_CT {
6220 var MSC_ConnHdlr vc_conn;
6221 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6222
6223 f_init(1, true);
6224 f_sleep(1.0);
6225
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006226 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006227
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006228 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
6229 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006230
6231 vc_conn := f_start_handler(refers(f_tc_ho_in_fail_msc_clears), pars);
6232 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006233
6234 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6235 f_ctrs_bsc_and_bts_add(0, "handover:stopped");
6236 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:attempted");
6237 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:stopped");
6238 f_ctrs_bsc_and_bts_verify();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02006239 f_shutdown_helper();
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006240}
6241
6242private function f_tc_ho_in_fail_msc_clears_after_ho_detect(charstring id) runs on MSC_ConnHdlr {
6243 /* Hack: the proper way would be to wait for the BSSMAP Handover Request ACK and extract the
6244 * actual assigned chan_nr from its L3 (RR Handover Command) message. But osmo-bsc starts acting
6245 * on the lchan even before we get a chance to evaluate the BSSMAP Handover Request ACK. So we
6246 * need to assume that osmo-bsc will activate TS 1 and already set up this lchan's RSL emulation
6247 * before we get started. */
6248 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
6249 f_rslem_register(0, new_chan_nr);
6250 g_chan_nr := new_chan_nr;
6251 f_sleep(1.0);
6252
6253 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
6254 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
6255 activate(as_Media());
6256
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006257 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006258 f_gen_handover_req()));
Harald Welte6811d102019-04-14 22:23:14 +02006259 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006260
6261 /* The RSL Emulation magically accepts the Chan Activ behind the scenes. */
6262
6263 var PDU_BSSAP rx_bssap;
6264 var octetstring ho_command_str;
6265
6266 BSSAP.receive(tr_BSSMAP_HandoverRequestAcknowledge(?)) -> value rx_bssap;
6267
6268 ho_command_str := rx_bssap.pdu.bssmap.handoverRequestAck.layer3Information.layer3info;
6269 log("Received L3 Info in HO Request Ack: ", ho_command_str);
6270 var PDU_ML3_NW_MS ho_command := dec_PDU_ML3_NW_MS(ho_command_str);
6271 log("L3 Info in HO Request Ack is ", ho_command);
6272
6273 var GsmArfcn arfcn;
6274 var RslChannelNr actual_new_chan_nr;
6275 f_ChDesc2RslChanNr(ho_command.msgs.rrm.handoverCommand.channelDescription2,
6276 actual_new_chan_nr, arfcn);
6277
6278 if (actual_new_chan_nr != new_chan_nr) {
6279 log("ERROR: osmo-bsc assigned a different lchan than we assumed above -- this test will fail now.",
6280 " Assumed: ", new_chan_nr, " Assigned: ", actual_new_chan_nr);
6281 setverdict(fail);
6282 return;
6283 }
6284 log("Handover Command chan_nr is", actual_new_chan_nr);
6285
6286 /* Now the MSC forwards the RR Handover Command to the other BSC, which
6287 * tells the MS to handover to the new lchan. Here comes the new MS on
6288 * the new lchan with a Handover RACH: */
6289
6290 /* send handover detect */
6291
6292 RSL.send(ts_RSL_HANDO_DET(new_chan_nr));
6293
6294 BSSAP.receive(tr_BSSMAP_HandoverDetect);
6295
6296 /* The MSC chooses to clear the connection now, maybe we got the
6297 * Handover RACH on the new cell but the MS still signaled Handover
6298 * Failure to the old BSS? */
6299
6300 var myBSSMAP_Cause cause_val := GSM0808_CAUSE_RADIO_INTERFACE_FAILURE_REVERSION;
6301 var BssmapCause cause := enum2int(cause_val);
6302 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
6303
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02006304 f_expect_dlcx_conns();
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02006305 BSSAP.receive(tr_BSSMAP_ClearComplete);
6306
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006307 f_sleep(1.0);
6308}
6309testcase TC_ho_in_fail_msc_clears_after_ho_detect() runs on test_CT {
6310 var MSC_ConnHdlr vc_conn;
6311 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6312
6313 f_init(1, true);
6314 f_sleep(1.0);
6315
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006316 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006317
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006318 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
6319 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006320
6321 vc_conn := f_start_handler(refers(f_tc_ho_in_fail_msc_clears_after_ho_detect), pars);
6322 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006323
6324 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6325 f_ctrs_bsc_and_bts_add(0, "handover:stopped");
6326 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:attempted");
6327 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:stopped");
6328 f_ctrs_bsc_and_bts_verify();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02006329 f_shutdown_helper();
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006330}
6331
6332/* The new BSS's lchan times out before the MSC decides that handover failed. */
6333private function f_tc_ho_in_fail_no_detect(charstring id) runs on MSC_ConnHdlr {
6334 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
6335 f_rslem_register(0, new_chan_nr);
6336 g_chan_nr := new_chan_nr;
6337 f_sleep(1.0);
6338
6339 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
6340 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
6341 activate(as_Media());
6342
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006343 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006344 f_gen_handover_req()));
Harald Welte6811d102019-04-14 22:23:14 +02006345 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006346
6347 /* The RSL Emulation magically accepts the Chan Activ behind the scenes. */
6348
6349 var PDU_BSSAP rx_bssap;
6350 var octetstring ho_command_str;
6351
6352 BSSAP.receive(tr_BSSMAP_HandoverRequestAcknowledge(?)) -> value rx_bssap;
6353
6354 ho_command_str := rx_bssap.pdu.bssmap.handoverRequestAck.layer3Information.layer3info;
6355 log("Received L3 Info in HO Request Ack: ", ho_command_str);
6356 var PDU_ML3_NW_MS ho_command := dec_PDU_ML3_NW_MS(ho_command_str);
6357 log("L3 Info in HO Request Ack is ", ho_command);
6358
6359 var GsmArfcn arfcn;
6360 var RslChannelNr actual_new_chan_nr;
6361 f_ChDesc2RslChanNr(ho_command.msgs.rrm.handoverCommand.channelDescription2,
6362 actual_new_chan_nr, arfcn);
6363
6364 if (actual_new_chan_nr != new_chan_nr) {
6365 log("ERROR: osmo-bsc assigned a different lchan than we assumed above -- this test will fail now.",
6366 " Assumed: ", new_chan_nr, " Assigned: ", actual_new_chan_nr);
6367 setverdict(fail);
6368 return;
6369 }
6370 log("Handover Command chan_nr is", actual_new_chan_nr);
6371
6372 /* Now the MSC forwards the RR Handover Command to the other BSC, which
6373 * tells the MS to handover to the new lchan. But the MS never shows up
6374 * on the new lchan. */
6375
6376 BSSAP.receive(tr_BSSMAP_HandoverFailure);
6377
6378 /* Did osmo-bsc also send a Clear Request? */
6379 timer T := 0.5;
6380 T.start;
6381 alt {
6382 [] BSSAP.receive(tr_BSSMAP_ClearRequest);
6383 [] T.timeout { }
6384 }
6385
6386 /* MSC plays along with a Clear Command (no matter whether osmo-bsc
6387 * asked for it, this is a Handover Failure after all). */
6388
6389 var myBSSMAP_Cause cause_val := GSM0808_CAUSE_RADIO_INTERFACE_FAILURE_REVERSION;
6390 var BssmapCause cause := enum2int(cause_val);
6391 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
6392
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02006393 f_expect_dlcx_conns();
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02006394 BSSAP.receive(tr_BSSMAP_ClearComplete);
6395
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006396 f_sleep(1.0);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006397}
6398testcase TC_ho_in_fail_no_detect() runs on test_CT {
6399 var MSC_ConnHdlr vc_conn;
6400 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6401
6402 f_init(1, true);
6403 f_sleep(1.0);
6404
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006405 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006406
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006407 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
6408 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006409
6410 vc_conn := f_start_handler(refers(f_tc_ho_in_fail_no_detect), pars);
6411 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006412
6413 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6414 f_ctrs_bsc_and_bts_add(0, "handover:error");
6415 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:attempted");
6416 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:error");
6417 f_ctrs_bsc_and_bts_verify();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02006418 f_shutdown_helper();
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006419}
6420
6421/* Same as f_tc_ho_in_fail_no_detect, but MSC fails to send a Clear Command */
6422private function f_tc_ho_in_fail_no_detect2(charstring id) runs on MSC_ConnHdlr {
6423 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
6424 f_rslem_register(0, new_chan_nr);
6425 g_chan_nr := new_chan_nr;
6426 f_sleep(1.0);
6427
6428 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
6429 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
6430 activate(as_Media());
6431
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006432 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006433 f_gen_handover_req()));
Harald Welte6811d102019-04-14 22:23:14 +02006434 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006435
6436 /* The RSL Emulation magically accepts the Chan Activ behind the scenes. */
6437
6438 var PDU_BSSAP rx_bssap;
6439 var octetstring ho_command_str;
6440
6441 BSSAP.receive(tr_BSSMAP_HandoverRequestAcknowledge(?)) -> value rx_bssap;
6442
6443 ho_command_str := rx_bssap.pdu.bssmap.handoverRequestAck.layer3Information.layer3info;
6444 log("Received L3 Info in HO Request Ack: ", ho_command_str);
6445 var PDU_ML3_NW_MS ho_command := dec_PDU_ML3_NW_MS(ho_command_str);
6446 log("L3 Info in HO Request Ack is ", ho_command);
6447
6448 var GsmArfcn arfcn;
6449 var RslChannelNr actual_new_chan_nr;
6450 f_ChDesc2RslChanNr(ho_command.msgs.rrm.handoverCommand.channelDescription2,
6451 actual_new_chan_nr, arfcn);
6452
6453 if (actual_new_chan_nr != new_chan_nr) {
6454 log("ERROR: osmo-bsc assigned a different lchan than we assumed above -- this test will fail now.",
6455 " Assumed: ", new_chan_nr, " Assigned: ", actual_new_chan_nr);
6456 setverdict(fail);
6457 return;
6458 }
6459 log("Handover Command chan_nr is", actual_new_chan_nr);
6460
6461 /* Now the MSC forwards the RR Handover Command to the other BSC, which
6462 * tells the MS to handover to the new lchan. But the MS never shows up
6463 * on the new lchan. */
6464
6465 BSSAP.receive(tr_BSSMAP_HandoverFailure);
6466
6467 /* MSC plays dumb and sends no Clear Command */
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006468 var PDU_BSSAP rx_clear_request;
Pau Espin Pedrol1fc30b92019-06-18 13:08:22 +02006469
6470 BSSAP.receive(tr_BSSMAP_ClearRequest) -> value rx_clear_request {
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006471 var BssmapCause cause := bit2int(rx_clear_request.pdu.bssmap.clearRequest.cause.causeValue);
6472 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
6473 };
Pau Espin Pedrol7aa02742019-06-26 16:30:14 +02006474 f_expect_dlcx_conns();
Neels Hofmeyr8fcd8772021-07-22 16:12:57 +02006475 BSSAP.receive(tr_BSSMAP_ClearComplete);
6476
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006477 f_sleep(1.0);
6478}
6479testcase TC_ho_in_fail_no_detect2() runs on test_CT {
6480 var MSC_ConnHdlr vc_conn;
6481 var TestHdlrParams pars := f_gen_test_hdlr_pars();
6482
6483 f_init(1, true);
6484 f_sleep(1.0);
6485
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006486 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006487
Neels Hofmeyr90f80962020-06-12 16:16:55 +02006488 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
6489 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006490
6491 vc_conn := f_start_handler(refers(f_tc_ho_in_fail_no_detect2), pars);
6492 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006493
6494 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6495 f_ctrs_bsc_and_bts_add(0, "handover:error");
6496 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:attempted");
6497 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:error");
6498 f_ctrs_bsc_and_bts_verify();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02006499 f_shutdown_helper();
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +01006500}
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +01006501
Neels Hofmeyr91401012019-07-11 00:42:35 +02006502type record of charstring Commands;
6503
Neels Hofmeyr666f0432020-07-04 00:53:07 +02006504private function f_bts_0_cfg(TELNETasp_PT pt, Commands cmds := {})
Neels Hofmeyr91401012019-07-11 00:42:35 +02006505{
Neels Hofmeyr666f0432020-07-04 00:53:07 +02006506 f_vty_enter_cfg_bts(pt, 0);
Neels Hofmeyr91401012019-07-11 00:42:35 +02006507 for (var integer i := 0; i < sizeof(cmds); i := i+1) {
Neels Hofmeyr666f0432020-07-04 00:53:07 +02006508 f_vty_transceive(pt, cmds[i]);
Neels Hofmeyr91401012019-07-11 00:42:35 +02006509 }
Neels Hofmeyr666f0432020-07-04 00:53:07 +02006510 f_vty_transceive(pt, "end");
Neels Hofmeyr91401012019-07-11 00:42:35 +02006511}
6512
Pau Espin Pedrolc675b612020-01-09 19:55:40 +01006513private function f_cs7_inst_0_cfg(TELNETasp_PT pt, Commands cmds := {})
6514{
6515 f_vty_enter_cfg_cs7_inst(pt, 0);
6516 for (var integer i := 0; i < sizeof(cmds); i := i+1) {
6517 f_vty_transceive(pt, cmds[i]);
6518 }
6519 f_vty_transceive(pt, "end");
6520}
6521
Neels Hofmeyr91401012019-07-11 00:42:35 +02006522private function f_probe_for_handover(charstring log_label,
6523 charstring log_descr,
6524 charstring handover_vty_cmd,
6525 boolean expect_handover,
Neels Hofmeyr6a955cc2021-10-02 14:53:48 +02006526 boolean is_inter_bsc_handover := false,
6527 template uint3_t expect_target_tsc := ?)
Neels Hofmeyr91401012019-07-11 00:42:35 +02006528runs on MSC_ConnHdlr
6529{
Neels Hofmeyrb3fc8982020-05-11 00:16:42 +02006530 /* We're going to thwart any and all handover attempts, just be ready to handle (and ignore) handover target
6531 * lchans to be established on bts 1 or bts 2. */
6532 f_rslem_suspend(RSL1_PROC);
6533 f_rslem_suspend(RSL2_PROC);
6534
Neels Hofmeyr91401012019-07-11 00:42:35 +02006535 var RSL_Message rsl;
6536
6537 var charstring log_msg := " (expecting handover)"
6538 if (not expect_handover) {
6539 log_msg := " (expecting NO handover)";
6540 }
6541 log("f_probe_for_handover starting: " & log_label & ": " & log_descr & log_msg);
6542 f_vty_transceive(BSCVTY, handover_vty_cmd);
6543
Neels Hofmeyr91401012019-07-11 00:42:35 +02006544 timer T := 2.0;
6545 T.start;
6546
6547 alt {
6548 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr)) -> value rsl {
6549 var PDU_ML3_NW_MS l3 := dec_PDU_ML3_NW_MS(rsl.ies[2].body.l3_info.payload);
6550 log("Rx L3 from net: ", l3);
6551 if (ischosen(l3.msgs.rrm.handoverCommand)) {
6552 var RslChannelNr new_chan_nr;
6553 var GsmArfcn arfcn;
6554 f_ChDesc2RslChanNr(l3.msgs.rrm.handoverCommand.channelDescription2,
6555 new_chan_nr, arfcn);
6556 log("Handover to new chan ", new_chan_nr, " on ARFCN ", arfcn);
6557 log(l3.msgs.rrm.handoverCommand);
6558
Neels Hofmeyr6a955cc2021-10-02 14:53:48 +02006559 /* Verify correct TSC in handoverCommand */
6560 var uint3_t got_tsc := rr_chan_desc_tsc(l3.msgs.rrm.handoverCommand.channelDescription2);
6561 if (not match(got_tsc, expect_target_tsc)) {
6562 setverdict(fail, "RR Handover Command: unexpected TSC in Channel Description: expected ",
6563 expect_target_tsc, " got ", got_tsc);
6564 mtc.stop;
6565 } else {
6566 log("handoverCommand: verified TSC = ", got_tsc, " (matches ",
6567 expect_target_tsc, ")");
6568 }
6569
Neels Hofmeyr91401012019-07-11 00:42:35 +02006570 /* Need to register for new lchan on new BTS -- it's either bts 1 or bts 2. It doesn't really
6571 * matter on which BTS it really is, we're not going to follow through an entire handover
6572 * anyway. */
6573 f_rslem_register(0, new_chan_nr, RSL1_PROC);
6574 f_rslem_resume(RSL1_PROC);
6575 f_rslem_register(0, new_chan_nr, RSL2_PROC);
6576 f_rslem_resume(RSL2_PROC);
6577
6578 if (expect_handover and not is_inter_bsc_handover) {
6579 setverdict(pass);
6580 log("f_probe_for_handover(" & log_label & "): Got RSL Handover Command as expected.");
6581 } else {
6582 setverdict(fail, "f_probe_for_handover(" & log_label & "): Expected none, but got RSL Handover Command. "
6583 & log_label & ": " & log_descr);
6584 }
6585
6586 log("f_probe_for_handover(" & log_label & "): Ending the test: Handover Failure stops the procedure.");
6587 /* osmo-bsc has triggered Handover. That's all we need to know for this test, reply with
6588 * Handover Failure. */
6589 f_rsl_send_l3(ts_RRM_HandoverFailure('00'O));
6590
6591 /* target BTS is told to release lchan again; don't care which BTS nor what messages. */
6592 f_sleep(0.5);
6593 RSL1.clear;
6594 RSL2.clear;
6595 log("f_probe_for_handover(" & log_label & "): done (got RSL Handover Command)");
6596 break;
6597 } else {
6598 repeat;
6599 }
6600 }
6601 [] BSSAP.receive(tr_BSSMAP_HandoverRequired) {
6602 if (expect_handover and is_inter_bsc_handover) {
6603 setverdict(pass);
6604 log("f_probe_for_handover(" & log_label & "): Got BSSMAP Handover Required as expected.");
6605 } else {
6606 setverdict(fail, "f_probe_for_handover(" & log_label & "): Expected none, but got BSSMAP Handover Required. "
6607 & log_label & ": " & log_descr);
6608 }
6609
6610 log("f_probe_for_handover(" & log_label & "): done (got BSSMAP Handover Required)");
6611
6612 /* Note: f_tc_ho_neighbor_config_start() sets T7, the timeout for BSSMAP Handover Required, to
6613 * 1 second. There is no legal way to quickly abort a handover after a BSSMAP Handover Required,
6614 * setting a short timeout and waiting is the only way. */
6615 log("f_probe_for_handover(" & log_label & "): waiting for inter-BSC HO to time out...");
6616 f_sleep(1.5);
6617 log("f_probe_for_handover(" & log_label & "): ...done");
6618
6619 break;
6620 }
6621 [] T.timeout {
6622 if (expect_handover) {
6623 setverdict(fail, "f_probe_for_handover(" & log_label & "): Expected Handover, but got none. "
6624 & log_label & ": " & log_descr);
6625 } else {
6626 setverdict(pass);
6627 log("f_probe_for_handover(" & log_label & "): Got no Handover, as expected.");
6628 }
6629 log("f_probe_for_handover(" & log_label & "): done (got no Handover)");
6630 break;
6631 }
6632 }
6633
6634 f_rslem_resume(RSL1_PROC);
6635 f_rslem_resume(RSL2_PROC);
6636 f_sleep(3.0);
6637 RSL.clear;
6638
6639 log("f_probe_for_handover(" & log_label & "): done clearing");
6640}
6641
6642/* Test the effect of various neighbor configuration scenarios:
6643 *
6644 * To avoid complexity, block off any actual handover operation, and always remain on the lchan at bts 0.
6645 * Reconfigure the neighbors for bts 0, trigger a Handover, and probe whether osmo-bsc does or doesn't start HO.
6646 */
6647private function f_tc_ho_neighbor_config_start() runs on MSC_ConnHdlr {
6648 g_pars := f_gen_test_hdlr_pars();
6649 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
6650 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Neels Hofmeyr91401012019-07-11 00:42:35 +02006651
6652 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
6653 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
6654
6655 /* Establish lchan at bts 0 */
6656 f_establish_fully(ass_cmd, exp_compl);
6657
6658 /* Shorten the inter-BSC Handover timeout, to not wait so long for inter-BSC Handovers */
6659 f_vty_enter_cfg_network(BSCVTY);
6660 f_vty_transceive(BSCVTY, "timer T7 1");
6661 f_vty_transceive(BSCVTY, "end");
6662}
6663
6664private function f_tc_ho_neighbor_config_1(charstring id) runs on MSC_ConnHdlr {
6665 f_tc_ho_neighbor_config_start();
6666
6667 /*
6668 * bts 0 ARFCN 871 BSIC 10
6669 * bts 1 ARFCN 871 BSIC 11
6670 * bts 2 ARFCN 871 BSIC 12
6671 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
6672 */
6673
6674 log("f_tc_ho_neighbor_config: 1. No 'neighbor' config");
Neels Hofmeyr666f0432020-07-04 00:53:07 +02006675 f_bts_0_cfg(BSCVTY, {"no neighbors"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02006676 f_probe_for_handover("1.a", "HO to bts 1 works, implicitly listed as neighbor (legacy behavior when none are configured)",
6677 "handover any to arfcn 871 bsic 11",
Neels Hofmeyr6a955cc2021-10-02 14:53:48 +02006678 true, expect_target_tsc := BTS_TSC[1]);
Neels Hofmeyr91401012019-07-11 00:42:35 +02006679
6680 f_probe_for_handover("1.b", "HO to unknown cell does not start",
6681 "handover any to arfcn 13 bsic 39",
6682 false);
6683
6684 f_probe_for_handover("1.c", "HO to 871-12 is ambiguous = error",
6685 "handover any to arfcn 871 bsic 12",
6686 false);
6687
6688 f_probe_for_handover("1.d", "HO to 871-11 still works (verify that this test properly cleans up)",
6689 "handover any to arfcn 871 bsic 11",
Neels Hofmeyr6a955cc2021-10-02 14:53:48 +02006690 true, expect_target_tsc := BTS_TSC[1]);
Neels Hofmeyr91401012019-07-11 00:42:35 +02006691}
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006692testcase TC_ho_neighbor_config_1() runs on test_CT {
6693 var MSC_ConnHdlr vc_conn;
6694 f_init(3, true, guard_timeout := 60.0);
6695 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006696 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006697 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_1));
6698 vc_conn.done;
6699
6700 /* f_tc_ho_neighbor_config_start() */
6701 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
6702 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
6703
6704 /* 1.a */
6705 /* "failed" means a handover was triggered and started (which is all this test aims for) and the test ended the
6706 * handover quickly by sending a Handover Failure message. */
6707 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6708 f_ctrs_bsc_and_bts_add(0, "handover:failed");
6709 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
6710 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:failed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006711 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:attempted");
6712 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:failed");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006713
6714 /* 1.b */
6715 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6716 f_ctrs_bsc_and_bts_add(0, "handover:error");
6717
6718 /* 1.c */
6719 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6720 f_ctrs_bsc_and_bts_add(0, "handover:error");
6721
6722 /* 1.d */
6723 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6724 f_ctrs_bsc_and_bts_add(0, "handover:failed");
6725 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
6726 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:failed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006727 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:attempted");
6728 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:failed");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006729
6730 f_ctrs_bsc_and_bts_verify();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02006731 f_shutdown_helper();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006732}
6733
Neels Hofmeyr91401012019-07-11 00:42:35 +02006734private function f_tc_ho_neighbor_config_2(charstring id) runs on MSC_ConnHdlr {
6735 f_tc_ho_neighbor_config_start();
6736
6737 /*
6738 * bts 0 ARFCN 871 BSIC 10
6739 * bts 1 ARFCN 871 BSIC 11
6740 * bts 2 ARFCN 871 BSIC 12
6741 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
6742 */
6743
6744 log("f_tc_ho_neighbor_config: 2. explicit local neighbor: 'neighbor bts 1'");
Neels Hofmeyr666f0432020-07-04 00:53:07 +02006745 f_bts_0_cfg(BSCVTY, {"neighbor bts 1"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02006746 f_sleep(0.5);
6747
6748 f_probe_for_handover("2.a", "HO to bts 1 works, explicitly listed as neighbor",
6749 "handover any to arfcn 871 bsic 11",
Neels Hofmeyr6a955cc2021-10-02 14:53:48 +02006750 true, expect_target_tsc := BTS_TSC[1]);
Neels Hofmeyr91401012019-07-11 00:42:35 +02006751
6752 f_probe_for_handover("2.b", "HO to bts 2 doesn't work, not listed as neighbor",
6753 "handover any to arfcn 871 bsic 12",
6754 false);
6755}
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006756testcase TC_ho_neighbor_config_2() runs on test_CT {
6757 var MSC_ConnHdlr vc_conn;
6758 f_init(3, true, guard_timeout := 50.0);
6759 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006760 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006761 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_2));
6762 vc_conn.done;
6763
6764 /* f_tc_ho_neighbor_config_start() */
6765 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
6766 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
6767
6768 /* 2.a */
6769 /* "failed" means a handover was triggered and started (which is all this test aims for) and the test ended the
6770 * handover quickly by sending a Handover Failure message. */
6771 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6772 f_ctrs_bsc_and_bts_add(0, "handover:failed");
6773 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
6774 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:failed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006775 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:attempted");
6776 f_ctrs_bts_add(1, "incoming_intra_bsc_ho:failed");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006777
6778 /* 2.b */
6779 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6780 f_ctrs_bsc_and_bts_add(0, "handover:error");
6781
6782 f_ctrs_bsc_and_bts_verify();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02006783 f_shutdown_helper();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006784}
6785
Neels Hofmeyr91401012019-07-11 00:42:35 +02006786private function f_tc_ho_neighbor_config_3(charstring id) runs on MSC_ConnHdlr {
6787 f_tc_ho_neighbor_config_start();
6788
6789 /*
6790 * bts 0 ARFCN 871 BSIC 10
6791 * bts 1 ARFCN 871 BSIC 11
6792 * bts 2 ARFCN 871 BSIC 12
6793 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
6794 */
6795
6796 log("f_tc_ho_neighbor_config: 3. explicit local neighbor: 'neighbor bts 2'");
Neels Hofmeyr666f0432020-07-04 00:53:07 +02006797 f_bts_0_cfg(BSCVTY, {"no neighbors", "neighbor bts 2"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02006798 f_sleep(0.5);
6799
6800 f_probe_for_handover("3.a", "HO to bts 1 doesn't work, not listed as neighbor",
6801 "handover any to arfcn 871 bsic 11",
6802 false);
6803 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",
6804 "handover any to arfcn 871 bsic 12",
Neels Hofmeyr6a955cc2021-10-02 14:53:48 +02006805 true, expect_target_tsc := BTS_TSC[2]);
Neels Hofmeyr91401012019-07-11 00:42:35 +02006806}
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006807testcase TC_ho_neighbor_config_3() runs on test_CT {
6808 var MSC_ConnHdlr vc_conn;
6809 f_init(3, true, guard_timeout := 50.0);
6810 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006811 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006812 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_3));
6813 vc_conn.done;
6814
6815 /* f_tc_ho_neighbor_config_start() */
6816 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
6817 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
6818
6819 /* 3.a */
6820 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6821 f_ctrs_bsc_and_bts_add(0, "handover:error");
6822
6823 /* 3.b */
6824 /* "failed" means a handover was triggered and started (which is all this test aims for) and the test ended the
6825 * handover quickly by sending a Handover Failure message. */
6826 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6827 f_ctrs_bsc_and_bts_add(0, "handover:failed");
6828 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
6829 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:failed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006830 f_ctrs_bts_add(2, "incoming_intra_bsc_ho:attempted");
6831 f_ctrs_bts_add(2, "incoming_intra_bsc_ho:failed");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006832
6833 f_ctrs_bsc_and_bts_verify();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02006834 f_shutdown_helper();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006835}
6836
Neels Hofmeyr91401012019-07-11 00:42:35 +02006837private function f_tc_ho_neighbor_config_4(charstring id) runs on MSC_ConnHdlr {
6838 f_tc_ho_neighbor_config_start();
6839
6840 /*
6841 * bts 0 ARFCN 871 BSIC 10
6842 * bts 1 ARFCN 871 BSIC 11
6843 * bts 2 ARFCN 871 BSIC 12
6844 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
6845 */
6846
6847 log("f_tc_ho_neighbor_config: 4. explicit remote neighbor: 'neighbor lac 99 arfcn 123 bsic 45'");
Neels Hofmeyr666f0432020-07-04 00:53:07 +02006848 f_bts_0_cfg(BSCVTY, {"no neighbors", "neighbor lac 99 arfcn 123 bsic 45"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02006849 f_sleep(0.5);
6850
6851 f_probe_for_handover("4.a", "HO to bts 1 doesn't work, not listed as neighbor",
6852 "handover any to arfcn 871 bsic 11",
6853 false);
6854 f_probe_for_handover("4.b", "HO to bts 2 doesn't work, not listed as neighbor",
6855 "handover any to arfcn 871 bsic 12",
6856 false);
6857 f_probe_for_handover("4.c", "HO to 123-45 triggers inter-BSC HO",
6858 "handover any to arfcn 123 bsic 45",
6859 true, true);
6860}
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006861testcase TC_ho_neighbor_config_4() runs on test_CT {
6862 var MSC_ConnHdlr vc_conn;
6863 f_init(3, true, guard_timeout := 50.0);
6864 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006865 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006866 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_4));
6867 vc_conn.done;
6868
6869 /* f_tc_ho_neighbor_config_start() */
6870 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
6871 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
6872
6873 /* 4.a */
6874 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6875 f_ctrs_bsc_and_bts_add(0, "handover:error");
6876
6877 /* 4.b */
6878 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6879 f_ctrs_bsc_and_bts_add(0, "handover:error");
6880
6881 /* 4.c */
6882 /* "timeout" means a handover was triggered and started (which is all this test aims for) and the test ended the
6883 * handover quickly by timing out after the Handover Required message */
6884 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6885 f_ctrs_bsc_and_bts_add(0, "handover:timeout");
6886 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
6887 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:timeout");
6888
6889 f_ctrs_bsc_and_bts_verify();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02006890 f_shutdown_helper();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006891}
6892
Neels Hofmeyr91401012019-07-11 00:42:35 +02006893private function f_tc_ho_neighbor_config_5(charstring id) runs on MSC_ConnHdlr {
6894 f_tc_ho_neighbor_config_start();
6895
6896 /*
6897 * bts 0 ARFCN 871 BSIC 10
6898 * bts 1 ARFCN 871 BSIC 11
6899 * bts 2 ARFCN 871 BSIC 12
6900 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
6901 */
6902
6903 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 +02006904 f_bts_0_cfg(BSCVTY, {"no neighbors", "neighbor lac 99 arfcn 871 bsic 12"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02006905 f_sleep(0.5);
6906
6907 f_probe_for_handover("5.a", "HO to 871-12 triggers inter-BSC HO (ignoring local cells with same ARFCN+BSIC)",
6908 "handover any to arfcn 871 bsic 12",
6909 true, true);
6910}
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006911testcase TC_ho_neighbor_config_5() runs on test_CT {
6912 var MSC_ConnHdlr vc_conn;
6913 f_init(3, true);
6914 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006915 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006916 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_5));
6917 vc_conn.done;
6918
6919 /* f_tc_ho_neighbor_config_start() */
6920 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
6921 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
6922
6923 /* 5 */
6924 /* "timeout" means a handover was triggered and started (which is all this test aims for) and the test ended the
6925 * handover quickly by timing out after the Handover Required message */
6926 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6927 f_ctrs_bsc_and_bts_add(0, "handover:timeout");
6928 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
6929 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:timeout");
6930
6931 f_ctrs_bsc_and_bts_verify();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02006932 f_shutdown_helper();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006933}
6934
Neels Hofmeyr91401012019-07-11 00:42:35 +02006935private function f_tc_ho_neighbor_config_6(charstring id) runs on MSC_ConnHdlr {
6936 f_tc_ho_neighbor_config_start();
6937
6938 /*
6939 * bts 0 ARFCN 871 BSIC 10
6940 * bts 1 ARFCN 871 BSIC 11
6941 * bts 2 ARFCN 871 BSIC 12
6942 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
6943 */
6944
6945 log("f_tc_ho_neighbor_config: 6. config error: explicit local and remote neighbors with ambiguous ARFCN+BSIC:"
6946 & " 'neighbor bts 2; neighbor lac 99 arfcn 871 bsic 12'");
Neels Hofmeyr666f0432020-07-04 00:53:07 +02006947 f_bts_0_cfg(BSCVTY, {"no neighbors", "neighbor bts 2", "neighbor lac 99 arfcn 871 bsic 12"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02006948 f_sleep(0.5);
6949
6950 f_probe_for_handover("6.a", "HO to 871-12 is ambiguous = error",
6951 "handover any to arfcn 871 bsic 12",
6952 false);
6953}
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006954testcase TC_ho_neighbor_config_6() runs on test_CT {
6955 var MSC_ConnHdlr vc_conn;
6956 f_init(3, true);
6957 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01006958 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006959 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_6));
6960 vc_conn.done;
6961
6962 /* f_tc_ho_neighbor_config_start() */
6963 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
6964 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
6965
6966 /* 6.a */
6967 /* "timeout" means a handover was triggered and started (which is all this test aims for) and the test ended the
6968 * handover quickly by timing out after the Handover Required message */
6969 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
6970 f_ctrs_bsc_and_bts_add(0, "handover:error");
6971
6972 f_ctrs_bsc_and_bts_verify();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02006973 f_shutdown_helper();
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00006974}
6975
Neels Hofmeyr91401012019-07-11 00:42:35 +02006976private function f_tc_ho_neighbor_config_7(charstring id) runs on MSC_ConnHdlr {
6977 f_tc_ho_neighbor_config_start();
6978
6979 /*
6980 * bts 0 ARFCN 871 BSIC 10
6981 * bts 1 ARFCN 871 BSIC 11
6982 * bts 2 ARFCN 871 BSIC 12
6983 * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC
6984 */
6985
6986 log("f_tc_ho_neighbor_config: 7. explicit local and remote neighbors:"
6987 & " 'neighbor bts 2; neighbor lac 99 arfcn 123 bsic 45'");
Neels Hofmeyr666f0432020-07-04 00:53:07 +02006988 f_bts_0_cfg(BSCVTY, {"no neighbors", "neighbor bts 2", "neighbor lac 99 arfcn 123 bsic 45"});
Neels Hofmeyr91401012019-07-11 00:42:35 +02006989 f_sleep(0.5);
6990
6991 f_probe_for_handover("7.a", "HO to 871-12 does HO to bts 2",
6992 "handover any to arfcn 871 bsic 12",
Neels Hofmeyr6a955cc2021-10-02 14:53:48 +02006993 true, expect_target_tsc := BTS_TSC[2]);
Neels Hofmeyr91401012019-07-11 00:42:35 +02006994 f_probe_for_handover("7.b", "HO to 123-45 triggers inter-BSC HO",
6995 "handover any to arfcn 123 bsic 45",
6996 true, true);
6997}
Neels Hofmeyr91401012019-07-11 00:42:35 +02006998testcase TC_ho_neighbor_config_7() runs on test_CT {
6999 var MSC_ConnHdlr vc_conn;
Neels Hofmeyrf2b88032020-06-16 00:35:04 +02007000 f_init(3, true, guard_timeout := 50.0);
Neels Hofmeyr91401012019-07-11 00:42:35 +02007001 f_sleep(1.0);
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007002 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007003 vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_7));
7004 vc_conn.done;
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007005
7006 /* f_tc_ho_neighbor_config_start() */
7007 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
7008 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
7009
7010 /* 7.a */
7011 /* "failed" means a handover was triggered and started (which is all this test aims for) and the test ended the
7012 * handover quickly by sending a Handover Failure message. */
7013 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7014 f_ctrs_bsc_and_bts_add(0, "handover:failed");
7015 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
7016 f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:failed");
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01007017 f_ctrs_bts_add(2, "incoming_intra_bsc_ho:attempted");
7018 f_ctrs_bts_add(2, "incoming_intra_bsc_ho:failed");
Neels Hofmeyr12941bd2020-08-29 03:21:26 +00007019
7020 /* 7.b */
7021 /* "timeout" means a handover was triggered and started (which is all this test aims for) and the test ended the
7022 * handover quickly by timing out after the Handover Required message */
7023 f_ctrs_bsc_and_bts_add(0, "handover:attempted");
7024 f_ctrs_bsc_and_bts_add(0, "handover:timeout");
7025 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
7026 f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:timeout");
7027
7028 f_ctrs_bsc_and_bts_verify();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02007029 f_shutdown_helper();
Neels Hofmeyr91401012019-07-11 00:42:35 +02007030}
7031
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +01007032/* OS#3041: Open and close N connections in a normal fashion, and expect no
7033 * BSSMAP Reset just because of that. */
7034testcase TC_bssap_rlsd_does_not_cause_bssmap_reset() runs on test_CT {
7035 var default d;
7036 var integer i;
7037 var DchanTuple dt;
7038
7039 f_init();
7040
7041 /* Wait for initial BSSMAP Reset to pass */
7042 f_sleep(4.0);
7043
7044 d := activate(no_bssmap_reset());
7045
7046 /* Setup up a number of connections and RLSD them again from the MSC
7047 * side. In the buggy behavior, the fourth one triggers BSSMAP Reset.
7048 * Let's do it some more times for good measure. */
Harald Weltec3260d92018-06-11 17:48:16 +02007049 for (i := 0; i < 4; i := i+1) {
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +01007050 /* Since we're doing a lot of runs, give each one a fresh
7051 * T_guard from the top. */
7052 T_guard.start;
7053
7054 /* Setup a BSSAP connection and clear it right away. This is
7055 * the MSC telling the BSC about a planned release, it's not an
7056 * erratic loss of a connection. */
Harald Weltea1897182018-06-11 13:53:09 +02007057 dt := f_est_dchan(int2oct(i,1), 23+i, '00010203040506'O);
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +01007058
7059 /* MSC disconnects (RLSD). */
7060 BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
7061 }
7062
7063 /* In the buggy behavior, a timeout of 2 seconds happens between above
7064 * trigger (logs "SIGTRAN connection down, reconnecting...") and the
7065 * actual BSSMAP Reset. Wait a bit longer just to make sure. */
7066 f_sleep(4.0);
7067
7068 deactivate(d);
7069 f_shutdown_helper();
7070}
Harald Welte552620d2017-12-16 23:21:36 +01007071
Neels Hofmeyr4ff93282018-03-12 04:25:35 +01007072/* OS#3041: Open and close N connections in a normal fashion, and expect no
7073 * BSSMAP Reset just because of that. Invoke the release by a BSSMAP Clear from
7074 * the MSC. */
7075testcase TC_bssmap_clear_does_not_cause_bssmap_reset() runs on test_CT {
7076 var default d;
7077 var integer i;
7078 var DchanTuple dt;
7079 var BSSAP_N_DATA_ind rx_di;
Neels Hofmeyr4ff93282018-03-12 04:25:35 +01007080 var myBSSMAP_Cause cause_val := GSM0808_CAUSE_CALL_CONTROL;
7081 var BssmapCause cause := enum2int(cause_val);
7082
7083 f_init();
7084
7085 /* Wait for initial BSSMAP Reset to pass */
7086 f_sleep(4.0);
7087
7088 d := activate(no_bssmap_reset());
7089
7090 /* Setup up a number of connections and RLSD them again from the MSC
7091 * side. In the buggy behavior, the fourth one triggers BSSMAP Reset.
7092 * Let's do it some more times for good measure. */
7093 for (i := 0; i < 8; i := i+1) {
7094 /* Since we're doing a lot of runs, give each one a fresh
7095 * T_guard from the top. */
7096 T_guard.start;
7097
7098 /* Setup a BSSAP connection and clear it right away. This is
7099 * the MSC telling the BSC about a planned release, it's not an
7100 * erratic loss of a connection. */
Harald Weltea1897182018-06-11 13:53:09 +02007101 dt := f_est_dchan(int2oct(i,1), 23+i, '00010203040506'O);
Neels Hofmeyr4ff93282018-03-12 04:25:35 +01007102
7103 /* Instruct BSC to clear channel */
7104 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
7105
7106 /* expect BSC to disable the channel */
Harald Welte641fcbe2018-06-14 10:58:35 +02007107 f_exp_chan_rel_and_clear(dt, 0);
Neels Hofmeyr4ff93282018-03-12 04:25:35 +01007108 }
7109
7110 /* In the buggy behavior, a timeout of 2 seconds happens between above
7111 * trigger (logs "SIGTRAN connection down, reconnecting...") and the
7112 * actual BSSMAP Reset. Wait a bit longer just to make sure. */
7113 f_sleep(4.0);
7114
7115 deactivate(d);
7116 f_shutdown_helper();
7117}
7118
Neels Hofmeyrfd445c32018-03-09 15:39:31 +01007119/* OS#3041: Open and close N connections in a normal fashion, and expect no
7120 * BSSMAP Reset just because of that. Close connections from the MS side with a
7121 * Release Ind on RSL. */
7122testcase TC_ms_rel_ind_does_not_cause_bssmap_reset() runs on test_CT {
7123 var default d;
7124 var integer i;
7125 var DchanTuple dt;
7126 var BSSAP_N_DATA_ind rx_di;
Neels Hofmeyrfd445c32018-03-09 15:39:31 +01007127 var integer j;
7128
7129 f_init();
7130
7131 /* Wait for initial BSSMAP Reset to pass */
7132 f_sleep(4.0);
7133
7134 d := activate(no_bssmap_reset());
7135
7136 /* Setup up a number of connections and RLSD them again from the MSC
7137 * side. In the buggy behavior, the fourth one triggers BSSMAP Reset.
7138 * Let's do it some more times for good measure. */
7139 for (i := 0; i < 8; i := i+1) {
7140 /* Since we're doing a lot of runs, give each one a fresh
7141 * T_guard from the top. */
7142 T_guard.start;
7143
7144 /* Setup a BSSAP connection and clear it right away. This is
7145 * the MSC telling the BSC about a planned release, it's not an
7146 * erratic loss of a connection. */
7147 dt := f_est_dchan('23'O, 23, '00010203040506'O);
7148
7149 /* simulate RLL REL IND */
7150 f_ipa_tx(0, ts_RSL_REL_IND(dt.rsl_chan_nr, valueof(ts_RslLinkID_DCCH(0))));
7151
7152 /* expect Clear Request on MSC side */
7153 BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearRequest)) -> value rx_di;
7154
7155 /* Instruct BSC to clear channel */
7156 var BssmapCause cause := bit2int(rx_di.userData.pdu.bssmap.clearRequest.cause.causeValue);
7157 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
7158
7159 /* expect BSC to disable the channel */
Harald Welte641fcbe2018-06-14 10:58:35 +02007160 f_exp_chan_rel_and_clear(dt, 0);
Neels Hofmeyrfd445c32018-03-09 15:39:31 +01007161 }
7162
7163 /* In the buggy behavior, a timeout of 2 seconds happens between above
7164 * trigger (logs "SIGTRAN connection down, reconnecting...") and the
7165 * actual BSSMAP Reset. Wait a bit longer just to make sure. */
7166 f_sleep(4.0);
7167
7168 deactivate(d);
7169 f_shutdown_helper();
7170}
7171
Harald Welte94e0c342018-04-07 11:33:23 +02007172/***********************************************************************
7173 * IPA style dynamic PDCH
7174 ***********************************************************************/
7175
7176private function f_dyn_ipa_pdch_act(integer bts_nr, integer trx_nr, integer ts_nr,
7177 template (omit) RSL_Cause nack := omit)
7178runs on test_CT {
7179 var RslChannelNr chan_nr := valueof(t_RslChanNr_Bm(ts_nr));
7180 var RSL_Message rsl_unused;
7181 /* ask BSC via VTY to activate a given IPA style chan as PDCH */
7182 f_vty_ts_action("pdch activate", bts_nr, trx_nr, ts_nr);
7183 /* expect the BSC to issue the related RSL command */
7184 rsl_unused := f_exp_ipa_rx(0, tr_RSL_IPA_PDCH_ACT(chan_nr));
7185 if (istemplatekind(nack, "omit")) {
7186 /* respond with a related acknowledgement */
7187 f_ipa_tx(0, ts_RSL_IPA_PDCH_ACT_ACK(chan_nr, ts_RSL_IE_FrameNumber(2342)));
7188 } else {
7189 f_ipa_tx(0, ts_RSL_IPA_PDCH_ACT_NACK(chan_nr, valueof(nack)));
7190 }
7191}
7192
7193private function f_dyn_ipa_pdch_deact(integer bts_nr, integer trx_nr, integer ts_nr,
7194 template (omit) RSL_Cause nack := omit)
7195runs on test_CT {
7196 var RslChannelNr chan_nr := valueof(t_RslChanNr_Bm(ts_nr));
7197 var RSL_Message rsl_unused;
7198 /* ask BSC via VTY to activate a given IPA style chan as PDCH */
7199 f_vty_ts_action("pdch deactivate", bts_nr, trx_nr, ts_nr);
7200 /* expect the BSC to issue the related RSL command */
7201 rsl_unused := f_exp_ipa_rx(0, tr_RSL_IPA_PDCH_DEACT(chan_nr));
7202 if (istemplatekind(nack, "omit")) {
7203 /* respond with a related acknowledgement */
7204 f_ipa_tx(0, ts_RSL_IPA_PDCH_DEACT_ACK(chan_nr));
7205 } else {
7206 f_ipa_tx(0, ts_RSL_IPA_PDCH_DEACT_NACK(chan_nr, valueof(nack)));
7207 }
7208}
7209
7210private function f_ts_dyn_mode_get(integer bts_nr, integer trx_nr, integer ts_nr)
7211runs on test_CT return charstring {
7212 var charstring cmd, resp;
7213 cmd := "show timeslot "&int2str(bts_nr)&" "&int2str(trx_nr)&" "&int2str(ts_nr);
Stefan Sperlingcff13562018-11-13 15:24:06 +01007214 return f_vty_transceive_match_regexp_retry(BSCVTY, cmd, "*\((*)\)*", 0, 4, 1.0);
Harald Welte94e0c342018-04-07 11:33:23 +02007215}
7216
7217private function f_ts_dyn_mode_assert(integer bts_nr, integer trx_nr, integer ts_nr,
7218 template charstring exp)
7219runs on test_CT {
7220 var charstring mode := f_ts_dyn_mode_get(bts_nr, trx_nr, ts_nr);
7221 if (not match(mode, exp)) {
7222 setverdict(fail, "Unexpected TS Mode: ", mode);
Daniel Willmannafce8662018-07-06 23:11:32 +02007223 mtc.stop;
Harald Welte94e0c342018-04-07 11:33:23 +02007224 }
7225}
7226
7227private function f_ts_set_chcomb(integer bts_nr, integer trx_nr, integer ts_nr, charstring chcomb)
7228runs on test_CT {
7229 f_vty_enter_cfg_ts(BSCVTY, bts_nr, trx_nr, ts_nr);
7230 f_vty_transceive(BSCVTY, "phys_chan_config " & chcomb);
7231 f_vty_transceive(BSCVTY, "end");
7232}
7233
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02007234
7235private function f_ts_reset_chcomb(integer bts_nr) runs on test_CT {
7236 var integer i;
7237 for (i := 0; i < 8; i := i + 1) {
7238 f_ts_set_chcomb(bts_nr, 0, i, phys_chan_config[i]);
7239 }
7240}
7241
Harald Welte94e0c342018-04-07 11:33:23 +02007242private const charstring TCHF_MODE := "TCH/F mode";
7243private const charstring TCHH_MODE := "TCH/H mode";
7244private const charstring PDCH_MODE := "PDCH mode";
7245private const charstring NONE_MODE := "NONE mode";
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02007246private const charstring SDCCH8_MODE := "SDCCH8 mode";
Harald Welte94e0c342018-04-07 11:33:23 +02007247
7248/* Test IPA PDCH activation / deactivation triggered by VTY */
7249testcase TC_dyn_pdch_ipa_act_deact() runs on test_CT {
7250 var RSL_Message rsl_unused;
7251
7252 /* change Timeslot 6 before f_init() starts RSL */
7253 f_init_vty();
7254 f_ts_set_chcomb(0, 0, 6, "TCH/F_PDCH");
7255 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
7256
7257 f_init(1, false);
7258 f_sleep(1.0);
7259
7260 var RslChannelNr chan_nr := valueof(t_RslChanNr_Bm(6));
7261
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02007262 log("TCH/F_PDCH pchan starts out in TCH/F mode:");
Harald Welte94e0c342018-04-07 11:33:23 +02007263 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, TCHF_MODE);
7264 /* The BSC will activate the dynamic PDCH by default, so confirm that */
7265 rsl_unused := f_exp_ipa_rx(0, tr_RSL_IPA_PDCH_ACT(chan_nr));
7266 f_ipa_tx(0, ts_RSL_IPA_PDCH_ACT_ACK(chan_nr, ts_RSL_IE_FrameNumber(2342)));
7267 f_sleep(1.0);
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02007268 log("TCH/F_PDCH pchan, PDCH ACT was ACKed, so now in PDCH mode:");
Harald Welte94e0c342018-04-07 11:33:23 +02007269 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, PDCH_MODE);
7270
7271 /* De-activate it via VTY */
7272 f_dyn_ipa_pdch_deact(0, 0, chan_nr.tn);
7273 f_sleep(1.0);
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02007274 log("TCH/F_PDCH pchan, PDCH DEACT via VTY, so now back in TCH/F mode:");
Harald Welte94e0c342018-04-07 11:33:23 +02007275 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, TCHF_MODE);
7276
7277 /* re-activate it via VTY */
7278 f_dyn_ipa_pdch_act(0, 0, chan_nr.tn);
7279 f_sleep(1.0);
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02007280 log("TCH/F_PDCH pchan, PDCH ACT via VTY, so now in PDCH mode:");
Harald Welte94e0c342018-04-07 11:33:23 +02007281 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, PDCH_MODE);
7282
7283 /* and finally de-activate it again */
7284 f_dyn_ipa_pdch_deact(0, 0, chan_nr.tn);
7285 f_sleep(1.0);
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02007286 log("TCH/F_PDCH pchan, PDCH DEACT via VTY, so now back in TCH/F mode:");
Harald Welte94e0c342018-04-07 11:33:23 +02007287 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, TCHF_MODE);
7288
Neels Hofmeyr887e8f12018-06-27 01:01:55 +02007289 /* clean up config */
7290 f_ts_set_chcomb(0, 0, 6, "PDCH");
7291
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02007292 f_shutdown_helper();
Harald Welte94e0c342018-04-07 11:33:23 +02007293}
7294
7295/* Test IPA PDCH activation NACK */
7296testcase TC_dyn_pdch_ipa_act_nack() runs on test_CT {
7297 var RSL_Message rsl_unused;
7298
7299 /* change Timeslot 6 before f_init() starts RSL */
7300 f_init_vty();
7301 f_ts_set_chcomb(0, 0, 6, "TCH/F_PDCH");
7302 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
7303
7304 f_init(1, false);
7305 f_sleep(1.0);
7306
7307 var RslChannelNr chan_nr := valueof(t_RslChanNr_Bm(6));
7308
7309 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, TCHF_MODE);
7310 /* The BSC will activate the dynamic PDCH by default, so confirm that */
7311 rsl_unused := f_exp_ipa_rx(0, tr_RSL_IPA_PDCH_ACT(chan_nr));
7312 f_ipa_tx(0, ts_RSL_IPA_PDCH_ACT_ACK(chan_nr, ts_RSL_IE_FrameNumber(2342)));
7313 f_sleep(1.0);
7314 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, PDCH_MODE);
7315
7316 /* De-activate it via VTY */
7317 f_dyn_ipa_pdch_deact(0, 0, chan_nr.tn);
7318 f_sleep(1.0);
7319 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, TCHF_MODE);
7320
7321 /* re-activate it via VTY, but fail that; check BSC still assumes TCH/F mode */
7322 f_dyn_ipa_pdch_act(0, 0, chan_nr.tn, RSL_ERR_EQUIPMENT_FAIL);
7323 f_sleep(1.0);
7324 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, TCHF_MODE);
7325
Neels Hofmeyr887e8f12018-06-27 01:01:55 +02007326 /* clean up config */
7327 f_ts_set_chcomb(0, 0, 6, "PDCH");
7328
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02007329 f_shutdown_helper();
Harald Welte94e0c342018-04-07 11:33:23 +02007330}
7331
7332
7333/***********************************************************************
7334 * Osmocom style dynamic PDCH
7335 ***********************************************************************/
7336
7337private function f_dyn_osmo_pdch_act(integer bts_nr, integer trx_nr, integer ts_nr,
7338 template (omit) RSL_Cause nack := omit)
7339runs on test_CT {
7340 var RslChannelNr chan_nr := valueof(t_RslChanNr_PDCH(ts_nr));
7341 var RSL_Message rsl_unused;
Pau Espin Pedrol64adf372021-06-28 16:25:47 +02007342 /* ask BSC via VTY to activate a given OSMO style chan as PDCH */
Harald Welte94e0c342018-04-07 11:33:23 +02007343 /* FIXME: no VTY command to activate Osmocom PDCH !! */
7344 /* expect the BSC to issue the related RSL command */
7345 rsl_unused := f_exp_ipa_rx(0, tr_RSL_CHAN_ACT(chan_nr, ?));
7346 if (istemplatekind(nack, "omit")) {
7347 /* respond with a related acknowledgement */
7348 f_ipa_tx(0, ts_RSL_CHAN_ACT_ACK(chan_nr, 2342));
7349 } else {
7350 f_ipa_tx(0, ts_RSL_CHAN_ACT_NACK(chan_nr, valueof(nack)));
7351 }
7352}
7353
7354private function f_dyn_osmo_pdch_deact(integer bts_nr, integer trx_nr, integer ts_nr,
7355 template (omit) RSL_Cause nack := omit)
7356runs on test_CT {
7357 var RslChannelNr chan_nr := valueof(t_RslChanNr_PDCH(ts_nr));
7358 var RSL_Message rsl_unused;
Pau Espin Pedrol64adf372021-06-28 16:25:47 +02007359 /* ask BSC via VTY to activate a given OSMO style chan as PDCH */
Harald Welte94e0c342018-04-07 11:33:23 +02007360 /* FIXME: no VTY command to activate Osmocom PDCH !! */
7361 /* expect the BSC to issue the related RSL command */
7362 rsl_unused := f_exp_ipa_rx(0, tr_RSL_RF_CHAN_REL(chan_nr));
7363 if (istemplatekind(nack, "omit")) {
7364 /* respond with a related acknowledgement */
7365 f_ipa_tx(0, ts_RSL_RF_CHAN_REL_ACK(chan_nr));
7366 } else {
7367 //f_ipa_tx(0, ts_RSL_RF_CHAN_REL_NACK(chan_nr, valueof(nack)));
7368 }
7369}
7370
7371/* Test Osmocom dyn PDCH activation / deactivation triggered by VTY */
7372testcase TC_dyn_pdch_osmo_act_deact() runs on test_CT {
7373 var RSL_Message rsl_unused;
7374
7375 /* change Timeslot 6 before f_init() starts RSL */
7376 f_init_vty();
7377 f_ts_set_chcomb(0, 0, 6, "TCH/F_TCH/H_PDCH");
7378 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
7379
7380 f_init(1, false);
7381 f_sleep(1.0);
7382
7383 var RslChannelNr chan_nr := valueof(t_RslChanNr_PDCH(6));
7384
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02007385 log("TCH/F_TCH/H_PDCH pchan starts out in disabled mode:");
Harald Welte94e0c342018-04-07 11:33:23 +02007386 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, NONE_MODE);
7387 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiy58b16532021-10-09 20:27:39 +06007388 rsl_unused := f_exp_ipa_rx(0, tr_RSL_CHAN_ACT_PDCH(chan_nr));
Harald Welte94e0c342018-04-07 11:33:23 +02007389
7390 f_ipa_tx(0, ts_RSL_CHAN_ACT_ACK(chan_nr, 2342));
7391 f_sleep(1.0);
Neels Hofmeyrda4a6952018-06-14 04:02:49 +02007392 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 +02007393 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, PDCH_MODE);
7394
Neels Hofmeyr887e8f12018-06-27 01:01:55 +02007395 /* clean up config */
7396 f_ts_set_chcomb(0, 0, 6, "PDCH");
7397
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02007398 f_shutdown_helper();
Harald Welte94e0c342018-04-07 11:33:23 +02007399}
7400
7401/* Test Osmocom dyn PDCH activation NACK behavior */
7402testcase TC_dyn_pdch_osmo_act_nack() runs on test_CT {
7403 var RSL_Message rsl_unused;
7404
7405 /* change Timeslot 6 before f_init() starts RSL */
7406 f_init_vty();
7407 f_ts_set_chcomb(0, 0, 6, "TCH/F_TCH/H_PDCH");
7408 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
7409
7410 f_init(1, false);
7411 f_sleep(1.0);
7412
7413 var RslChannelNr chan_nr := valueof(t_RslChanNr_PDCH(6));
7414
7415 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, NONE_MODE);
7416 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiy58b16532021-10-09 20:27:39 +06007417 rsl_unused := f_exp_ipa_rx(0, tr_RSL_CHAN_ACT_PDCH(chan_nr));
Harald Welte94e0c342018-04-07 11:33:23 +02007418
7419 /* NACK this activation and expect the "show timeslot" mode still to be NONE */
7420 f_ipa_tx(0, ts_RSL_CHAN_ACT_NACK(chan_nr, RSL_ERR_EQUIPMENT_FAIL));
7421 f_sleep(1.0);
7422 f_ts_dyn_mode_assert(0, 0, chan_nr.tn, NONE_MODE);
7423
Neels Hofmeyr887e8f12018-06-27 01:01:55 +02007424 /* clean up config */
7425 f_ts_set_chcomb(0, 0, 6, "PDCH");
7426
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02007427 f_shutdown_helper();
Harald Welte94e0c342018-04-07 11:33:23 +02007428}
7429
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02007430/* Test Osmocom dyn TS SDCCH8 activation / deactivation */
7431testcase TC_dyn_ts_sdcch8_act_deact() runs on test_CT {
7432 var RSL_Message rsl_unused, rsl_msg;
7433 var DchanTuple dt;
7434 var BSSAP_N_CONNECT_ind rx_c_ind;
7435
7436 /* change Timeslot 6 before f_init() starts RSL */
7437 f_init_vty();
7438 f_ts_set_chcomb(0, 0, 6, "TCH/F_TCH/H_SDCCH8_PDCH");
7439 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
7440
7441 f_init(1, false);
7442 f_sleep(1.0);
7443
7444 var RslChannelNr pdch_chan_nr := valueof(t_RslChanNr_PDCH(6));
7445
7446 log("TCH/F_TCH/H_SDCCH8_PDCH pchan starts out in disabled mode:");
7447 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, NONE_MODE);
7448 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiy58b16532021-10-09 20:27:39 +06007449 rsl_unused := f_exp_ipa_rx(0, tr_RSL_CHAN_ACT_PDCH(pdch_chan_nr));
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02007450
7451 f_ipa_tx(0, ts_RSL_CHAN_ACT_ACK(pdch_chan_nr, 2342));
7452 f_sleep(1.0);
7453 log("TCH/F_TCH/H_SDCCH8_PDC requested to PDCH ACT on startup, which was ACKed, so now in PDCH:");
7454 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, PDCH_MODE);
7455
7456 /* Fill TS0 SDCCH channels (NOTE: only 3 SDCCH/4 channels are available
7457 * on CCCH+SDCCH4+CBCH) */
7458 var integer i;
Pau Espin Pedrolce4d5bb2021-10-25 13:31:25 +02007459 for (i := 0; i < NUM_SDCCH_PER_BTS; i := i + 1) {
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02007460 dt := f_est_dchan('23'O, i, '00010203040506'O);
7461 }
7462
7463 /* Now the dyn ts is selected. First PDCH is released, then sdcch chan is activated */
7464 f_ipa_tx(0, ts_RSL_CHAN_RQD(int2oct(oct2int('23'O) + i, 1), 2342));
7465 rsl_unused := f_exp_ipa_rx(0, tr_RSL_RF_CHAN_REL(pdch_chan_nr));
7466 f_ipa_tx(0, ts_RSL_RF_CHAN_REL_ACK(pdch_chan_nr));
7467
7468 rsl_msg := f_exp_ipa_rx(0, tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
7469 dt.rsl_chan_nr := rsl_msg.ies[0].body.chan_nr;
7470
7471 f_ts_dyn_mode_assert(0, 0, dt.rsl_chan_nr.tn, SDCCH8_MODE);
7472 f_ipa_tx(0, ts_RSL_CHAN_ACT_ACK(dt.rsl_chan_nr, 2342));
7473 rsl_msg := f_exp_ipa_rx(0, tr_RSL_IMM_ASSIGN(0));
7474 f_ts_dyn_mode_assert(0, 0, dt.rsl_chan_nr.tn, SDCCH8_MODE);
7475
7476 f_ipa_tx(0, ts_RSL_EST_IND(dt.rsl_chan_nr, valueof(ts_RslLinkID_DCCH(0)), '1234'O));
7477 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3('1234'O))) -> value rx_c_ind;
7478 dt.sccp_conn_id := rx_c_ind.connectionId;
7479 BSSAP.send(ts_BSSAP_CONNECT_res(dt.sccp_conn_id));
7480
7481 /* Instruct BSC to clear channel */
7482 var BssmapCause cause := 0;
7483 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
7484 f_exp_chan_rel_and_clear(dt, 0);
7485
7486 /* The BSC will switch the TS back to PDCH once the only lchan using it is released: */
Vadim Yanitskiy58b16532021-10-09 20:27:39 +06007487 rsl_unused := f_exp_ipa_rx(0, tr_RSL_CHAN_ACT_PDCH(pdch_chan_nr));
Pau Espin Pedrol5b381082021-06-28 17:14:03 +02007488 f_ipa_tx(0, ts_RSL_CHAN_ACT_ACK(pdch_chan_nr, 2342));
7489 f_sleep(1.0);
7490 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, PDCH_MODE);
7491
7492 /* clean up config */
7493 f_ts_set_chcomb(0, 0, 6, "PDCH");
7494
7495 f_shutdown_helper();
7496}
7497
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02007498/* Validate all 8 subslots of a dynamics TS configured as SDCCH8 are used */
7499testcase TC_dyn_ts_sdcch8_all_subslots_used() runs on test_CT {
7500 var ASP_RSL_Unitdata rsl_ud;
7501 var integer i;
7502 var integer chreq_total, chreq_nochan;
7503
7504 f_init_vty();
7505 for (i := 1; i < 8; i := i + 1) {
7506 if (i == 2) {
7507 f_ts_set_chcomb(0, 0, i, "TCH/F_TCH/H_SDCCH8_PDCH");
7508 } else {
7509 f_ts_set_chcomb(0, 0, i, "PDCH");
7510 }
7511 }
7512 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
7513
7514 f_init(1);
7515
7516 /* The dyn TS want to activate PDCH mode, ACK that. */
7517 var RslChannelNr chan_nr;
7518 chan_nr := valueof(t_RslChanNr_PDCH(2));
Vadim Yanitskiy58b16532021-10-09 20:27:39 +06007519 f_exp_ipa_rx(0, tr_RSL_CHAN_ACT_PDCH(chan_nr));
Neels Hofmeyre1a7c4d2021-10-23 23:13:01 +02007520 f_ipa_tx(0, ts_RSL_CHAN_ACT_ACK(chan_nr, 2342));
7521
7522 f_sleep(1.0);
7523
7524 /* Exhaust all dedicated SDCCH lchans.
7525 /* GSM 44.018 Table 9.1.8.2:
7526 * RA = '13'O -> Establishment cause = 0001xxxx (MS dual rate capable and asks for "SDCCH").
7527 */
7528 for (i := 0; i < NUM_SDCCH_PER_BTS; i := i+1) {
7529 f_est_dchan('13'O, NUM_SDCCH_PER_BTS + i, '00010203040506'O);
7530 }
7531
7532 /* Only the dyn TS is still available. Its first lchan gets converted to SDCCH8 */
7533 f_est_dchan_dyn('33'O, NUM_SDCCH_PER_BTS + i, '00010203040506'O);
7534 /* Also occupy the seven other SDCCH of the dyn TS */
7535 for (i := 0; i < 7; i := i+1) {
7536 f_est_dchan('33'O, NUM_SDCCH_PER_BTS + i, '00010203040506'O);
7537 }
7538
7539 /* clean up config */
7540 f_ts_reset_chcomb(0);
7541
7542 f_shutdown_helper();
7543}
7544
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02007545/* Test Osmocom dyn TS SDCCH8 activation / deactivation: If activating dyn TS as
7546 SDCCH8 would end up in having no free TCH, then BSC should decide to activate
7547 it as TCH directly instead. SYS#5309. */
7548testcase TC_dyn_ts_sdcch8_tch_call_act_deact() runs on test_CT {
7549 var RSL_Message rsl_unused, rsl_msg;
7550 var DchanTuple dt;
7551 var BSSAP_N_CONNECT_ind rx_c_ind;
7552 var integer i;
7553
7554 /* change Timeslot 6 before f_init() starts RSL */
7555 f_init_vty();
7556 for (i := 1; i < 8; i := i + 1) {
7557 if (i == 6) {
7558 f_ts_set_chcomb(0, 0, i, "TCH/F_TCH/H_SDCCH8_PDCH");
7559 } else {
7560 f_ts_set_chcomb(0, 0, i, "PDCH");
7561 }
7562 }
7563 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
7564
7565 f_init(1, false);
7566 f_sleep(1.0);
7567
7568 var RslChannelNr pdch_chan_nr := valueof(t_RslChanNr_PDCH(6));
7569
7570 log("TCH/F_TCH/H_SDCCH8_PDCH pchan starts out in disabled mode:");
7571 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, NONE_MODE);
7572 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiy58b16532021-10-09 20:27:39 +06007573 rsl_unused := f_exp_ipa_rx(0, tr_RSL_CHAN_ACT_PDCH(pdch_chan_nr));
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02007574
7575 f_ipa_tx(0, ts_RSL_CHAN_ACT_ACK(pdch_chan_nr, 2342));
7576 f_sleep(1.0);
7577 log("TCH/F_TCH/H_SDCCH8_PDC requested to PDCH ACT on startup, which was ACKed, so now in PDCH:");
7578 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, PDCH_MODE);
7579
7580 /* Fill TS0 SDCCH channels (NOTE: only 3 SDCCH/4 channels are available
7581 * on CCCH+SDCCH4+CBCH) */
Pau Espin Pedrol2ebbe7c2021-07-23 16:17:09 +02007582 var OCT1 ra := '43'O; /* RA containing reason=originating speech call*/
Pau Espin Pedrolce4d5bb2021-10-25 13:31:25 +02007583 for (i := 0; i < NUM_SDCCH_PER_BTS; i := i + 1) {
Pau Espin Pedrol2ebbe7c2021-07-23 16:17:09 +02007584 dt := f_est_dchan(ra, i, '00010203040506'O);
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02007585 }
7586
7587 /* Now the dyn ts is selected. First PDCH is released, then TCH chan is activated */
Pau Espin Pedrol2ebbe7c2021-07-23 16:17:09 +02007588 f_ipa_tx(0, ts_RSL_CHAN_RQD(int2oct(oct2int(ra) + i, 1), 2342));
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02007589 rsl_unused := f_exp_ipa_rx(0, tr_RSL_RF_CHAN_REL(pdch_chan_nr));
7590 f_ipa_tx(0, ts_RSL_RF_CHAN_REL_ACK(pdch_chan_nr));
7591
7592 rsl_msg := f_exp_ipa_rx(0, tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
7593 dt.rsl_chan_nr := rsl_msg.ies[0].body.chan_nr;
7594
7595 f_ts_dyn_mode_assert(0, 0, dt.rsl_chan_nr.tn, TCHH_MODE);
7596 f_ipa_tx(0, ts_RSL_CHAN_ACT_ACK(dt.rsl_chan_nr, 2342));
7597 rsl_msg := f_exp_ipa_rx(0, tr_RSL_IMM_ASSIGN(0));
7598 f_ts_dyn_mode_assert(0, 0, dt.rsl_chan_nr.tn, TCHH_MODE);
7599
7600 f_ipa_tx(0, ts_RSL_EST_IND(dt.rsl_chan_nr, valueof(ts_RslLinkID_DCCH(0)), '1234'O));
7601 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3('1234'O))) -> value rx_c_ind;
7602 dt.sccp_conn_id := rx_c_ind.connectionId;
7603 BSSAP.send(ts_BSSAP_CONNECT_res(dt.sccp_conn_id));
7604
7605 /* Instruct BSC to clear channel */
7606 var BssmapCause cause := 0;
7607 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
7608 f_exp_chan_rel_and_clear(dt, 0);
7609
7610 /* The BSC will switch the TS back to PDCH once the only lchan using it is released: */
Vadim Yanitskiy58b16532021-10-09 20:27:39 +06007611 rsl_unused := f_exp_ipa_rx(0, tr_RSL_CHAN_ACT_PDCH(pdch_chan_nr));
Pau Espin Pedrol0953bf82021-07-09 13:20:19 +02007612 f_ipa_tx(0, ts_RSL_CHAN_ACT_ACK(pdch_chan_nr, 2342));
7613 f_sleep(1.0);
7614 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, PDCH_MODE);
7615
7616 /* clean up config */
7617 f_ts_reset_chcomb(0);
7618 /* TODO: clean up other channels? */
7619
7620 f_shutdown_helper();
7621}
7622
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02007623/* Test Osmocom dyn TS SDCCH8 activation / deactivation when SDCCH fails at BTS */
7624testcase TC_dyn_ts_sdcch8_act_nack() runs on test_CT {
7625 var RSL_Message rsl_unused, rsl_msg;
7626 var DchanTuple dt;
7627 var BSSAP_N_CONNECT_ind rx_c_ind;
7628 var GsmRrMessage rr;
7629
7630 /* change Timeslot 6 before f_init() starts RSL */
7631 f_init_vty();
7632 f_ts_set_chcomb(0, 0, 6, "TCH/F_TCH/H_SDCCH8_PDCH");
7633 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
7634
7635 f_init(1, false);
7636 f_sleep(1.0);
7637
7638 var RslChannelNr pdch_chan_nr := valueof(t_RslChanNr_PDCH(6));
7639
7640 log("TCH/F_TCH/H_SDCCH8_PDCH pchan starts out in disabled mode:");
7641 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, NONE_MODE);
7642 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiy58b16532021-10-09 20:27:39 +06007643 rsl_unused := f_exp_ipa_rx(0, tr_RSL_CHAN_ACT_PDCH(pdch_chan_nr));
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02007644
7645 f_ipa_tx(0, ts_RSL_CHAN_ACT_ACK(pdch_chan_nr, 2342));
7646 f_sleep(1.0);
7647 log("TCH/F_TCH/H_SDCCH8_PDC requested to PDCH ACT on startup, which was ACKed, so now in PDCH:");
7648 f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, PDCH_MODE);
7649
7650 /* Fill TS0 SDCCH channels (NOTE: only 3 SDCCH/4 channels are available
7651 * on CCCH+SDCCH4+CBCH) */
7652 var integer i;
Pau Espin Pedrolce4d5bb2021-10-25 13:31:25 +02007653 for (i := 0; i < NUM_SDCCH_PER_BTS; i := i + 1) {
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02007654 dt := f_est_dchan('23'O, i, '00010203040506'O);
7655 }
7656
7657 /* Now the dyn ts is selected. First PDCH is released, then sdcch chan is activated */
7658 f_ipa_tx(0, ts_RSL_CHAN_RQD(int2oct(oct2int('23'O) + i, 1), 2342));
7659 rsl_unused := f_exp_ipa_rx(0, tr_RSL_RF_CHAN_REL(pdch_chan_nr));
7660 f_ipa_tx(0, ts_RSL_RF_CHAN_REL_ACK(pdch_chan_nr));
7661
7662 rsl_msg := f_exp_ipa_rx(0, tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
7663 dt.rsl_chan_nr := rsl_msg.ies[0].body.chan_nr;
7664
7665 f_ts_dyn_mode_assert(0, 0, dt.rsl_chan_nr.tn, SDCCH8_MODE);
7666 f_ipa_tx(0, ts_RSL_CHAN_ACT_NACK(dt.rsl_chan_nr, RSL_ERR_EQUIPMENT_FAIL));
7667 rsl_msg := f_exp_ipa_rx(0, tr_RSL_IMM_ASSIGN(0));
7668 rr := dec_GsmRrMessage(rsl_msg.ies[1].body.full_imm_ass_info.payload);
7669 if (rr.header.message_type != IMMEDIATE_ASSIGNMENT_REJECT) {
7670 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Expected reject");
7671 }
7672
7673 /* FIXME? Currently the TS stays in state BORKEN: */
7674
7675 /* The BSC will switch the TS back to PDCH once the only lchan using it is released: */
Vadim Yanitskiy58b16532021-10-09 20:27:39 +06007676 /* rsl_unused := f_exp_ipa_rx(0, tr_RSL_CHAN_ACT_PDCH(pdch_chan_nr));
Pau Espin Pedrolcdf26142021-06-28 17:14:03 +02007677 * f_ipa_tx(0, ts_RSL_CHAN_ACT_ACK(pdch_chan_nr, 2342));
7678 * f_sleep(1.0);
7679 * f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, PDCH_MODE)
7680 */
7681
7682 /* clean up config */
7683 f_ts_set_chcomb(0, 0, 6, "PDCH");
7684
7685 f_shutdown_helper();
7686}
7687
Stefan Sperling0796a822018-10-05 13:01:39 +02007688testcase TC_chopped_ipa_ping() runs on test_CT {
Stefan Sperling554123f2018-10-09 14:12:30 +02007689 const Integers bsc_ipa_ports := {mp_bsc_rsl_port, mp_bsc_oml_port, mp_bsc_ctrl_port};
Stefan Sperling0796a822018-10-05 13:01:39 +02007690 for (var integer i := 0; i < lengthof(bsc_ipa_ports); i := i + 1) {
7691 IPA_Testing.f_run_TC_chopped_ipa_ping(mp_bsc_ip, bsc_ipa_ports[i], CONNECT_TO_SERVER);
7692 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02007693 f_shutdown_helper();
Stefan Sperling0796a822018-10-05 13:01:39 +02007694}
7695
Stefan Sperlingaa1e60f2018-10-15 16:34:07 +02007696testcase TC_chopped_ipa_payload() runs on test_CT {
7697 const Integers bsc_ipa_ports := {mp_bsc_rsl_port, mp_bsc_oml_port
7698 /* TODO: mp_bsc_ctrl_port does not work yet */};
7699 for (var integer i := 0; i < lengthof(bsc_ipa_ports); i := i + 1) {
7700 IPA_Testing.f_run_TC_chopped_ipa_payload(mp_bsc_ip, bsc_ipa_ports[i], CONNECT_TO_SERVER);
7701 }
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02007702 f_shutdown_helper();
Stefan Sperlingaa1e60f2018-10-15 16:34:07 +02007703}
7704
Pau Espin Pedrol8f773632019-11-05 11:46:53 +01007705/* Verify the BSC sends the MS Power Parameters IE during CHAN ACT to make sure
7706 the BTS does autonomous MS power control loop */
7707testcase TC_assignment_verify_ms_power_params_ie() runs on test_CT {
7708 var MSC_ConnHdlr vc_conn;
7709 var TestHdlrParams pars := f_gen_test_hdlr_pars();
7710 //pars.encr := valueof(t_EncrParams('01'O, f_rnd_octstring(8)));
7711 pars.exp_ms_power_params := true;
7712
7713 f_init(1, true);
7714 f_sleep(1.0);
7715 vc_conn := f_start_handler(refers(f_tc_assignment_fr_a5), pars);
7716 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02007717 f_shutdown_helper();
Pau Espin Pedrol8f773632019-11-05 11:46:53 +01007718}
Stefan Sperlingaa1e60f2018-10-15 16:34:07 +02007719
Vadim Yanitskiy4b233042021-06-30 00:58:43 +02007720/* Verify activation and deactivation of the BCCH carrier power reduction mode */
7721testcase TC_c0_power_red_mode() runs on test_CT {
7722 f_init(1);
7723
7724 for (var integer red := 6; red >= 0; red := red - 2) {
7725 /* Configure BCCH carrier power reduction mode via the VTY */
7726 f_vty_transceive(BSCVTY, "bts 0 c0-power-reduction " & int2str(red));
7727
7728 /* Expect Osmocom specific BS Power Control message on the RSL */
7729 var template RSL_Message tr_rsl_pdu := tr_RSL_BS_PWR_CTRL(
7730 chan_nr := t_RslChanNr_BCCH(0),
7731 bs_power := tr_RSL_IE_BS_Power(red / 2));
7732 tr_rsl_pdu.msg_disc := tr_RSL_MsgDisc(RSL_MDISC_CCHAN, false);
7733 var RSL_Message unused := f_exp_ipa_rx(0, tr_rsl_pdu);
7734
7735 /* Additionally verify the applied value over the CTRL interface */
7736 var CtrlValue cred := f_ctrl_get_bts(IPA_CTRL, 0, "c0-power-reduction");
7737 if (cred != int2str(red)) {
7738 setverdict(fail, "Unexpected BCCH carrier power reduction value ",
7739 cred, " (expected ", red, ")");
7740 }
7741 }
7742
7743 f_shutdown_helper();
7744}
7745
Neels Hofmeyr4f118412020-06-04 15:25:10 +02007746/***********************************************************************
7747 * MSC Pooling
7748 ***********************************************************************/
7749
Neels Hofmeyr4f118412020-06-04 15:25:10 +02007750template MobileIdentityLV ts_MI_TMSI_NRI_LV(integer nri_v, integer nri_bitlen := 10) :=
Harald Weltebf397612021-01-14 20:39:46 +01007751 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 +02007752
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02007753private 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 +02007754runs on MSC_ConnHdlr {
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02007755 interleave {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02007756 [] rsl_pt.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch exp_rr_rel_tmpl)) {
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02007757 f_logp(BSCVTY, "Got RSL RR Release");
7758 }
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02007759 [] rsl_pt.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02007760 f_logp(BSCVTY, "Got RSL Deact SACCH");
7761 }
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +02007762 [] rsl_pt.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02007763 f_logp(BSCVTY, "Got RSL RF Chan Rel, sending Rel Ack");
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02007764 rsl_pt.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
7765 f_rslem_unregister(0, g_chan_nr, PT := rsl_proc_pt);
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02007766 break;
7767 }
7768 }
7769}
7770
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02007771friend function f_perform_clear(RSL_DCHAN_PT rsl_pt := RSL, RSLEM_PROC_PT rsl_proc_pt := RSL_PROC,
7772 template PDU_ML3_NW_MS exp_rr_rel_tmpl := tr_RRM_RR_RELEASE)
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +02007773runs on MSC_ConnHdlr {
Neels Hofmeyr767548a2020-08-09 20:26:07 +00007774 f_logp(BSCVTY, "MSC instructs BSC to clear channel");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02007775 BSSAP.send(ts_BSSMAP_ClearCommand(0));
7776 interleave {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02007777 [] rsl_pt.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch exp_rr_rel_tmpl)) {
Neels Hofmeyr767548a2020-08-09 20:26:07 +00007778 f_logp(BSCVTY, "Got RSL RR Release");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02007779 }
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02007780 [] rsl_pt.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {
Neels Hofmeyr767548a2020-08-09 20:26:07 +00007781 f_logp(BSCVTY, "Got RSL Deact SACCH");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02007782 }
7783 [] BSSAP.receive(tr_BSSMAP_ClearComplete) {
Neels Hofmeyr767548a2020-08-09 20:26:07 +00007784 f_logp(BSCVTY, "Got BSSMAP Clear Complete");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02007785 /* Also drop the SCCP connection */
7786 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
7787 }
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +02007788 [] rsl_pt.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
Neels Hofmeyr767548a2020-08-09 20:26:07 +00007789 f_logp(BSCVTY, "Got RSL RF Chan Rel, sending Rel Ack");
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02007790 rsl_pt.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
7791 f_rslem_unregister(0, g_chan_nr, PT := rsl_proc_pt);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02007792 }
7793 }
7794}
7795
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02007796private function f_perform_compl_l3(RSL_DCHAN_PT rsl_pt, RSLEM_PROC_PT rsl_proc_pt,
7797 template PDU_ML3_MS_NW l3_info, boolean do_clear := true, boolean expect_bssmap_l3 := true)
Neels Hofmeyr4f118412020-06-04 15:25:10 +02007798runs on MSC_ConnHdlr {
7799 timer T := 10.0;
7800 var octetstring l3_enc := enc_PDU_ML3_MS_NW(valueof(l3_info));
7801
Neels Hofmeyr767548a2020-08-09 20:26:07 +00007802 f_logp(BSCVTY, "establish channel, send Complete Layer 3 Info");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02007803 f_create_bssmap_exp(l3_enc);
7804
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02007805 /* RSL_Emulation.f_chan_est() on rsl_pt:
7806 * This is basically code dup with s/RSL/rsl_pt from:
Neels Hofmeyr4f118412020-06-04 15:25:10 +02007807 * RSL_Emulation.f_chan_est(g_pars.ra, l3_enc, g_pars.link_id, g_pars.fn);
7808 */
7809 var RSL_Message rx_rsl;
7810 var GsmRrMessage rr;
7811
7812 /* request a channel to be established */
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02007813 rsl_pt.send(ts_RSLDC_ChanRqd(g_pars.ra, g_pars.fn));
Neels Hofmeyr4f118412020-06-04 15:25:10 +02007814 /* expect immediate assignment.
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02007815 * Code dup with s/RSL/rsl_pt from:
Neels Hofmeyr4f118412020-06-04 15:25:10 +02007816 * rx_rsl := f_rx_or_fail(tr_RSL_IMM_ASSIGN);
7817 */
7818 timer Tt := 10.0;
7819
7820 /* request a channel to be established */
7821 Tt.start;
7822 alt {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02007823 [] rsl_pt.receive(tr_RSL_IMM_ASSIGN) -> value rx_rsl {
Neels Hofmeyr4f118412020-06-04 15:25:10 +02007824 Tt.stop;
7825 }
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02007826 [] rsl_pt.receive {
Neels Hofmeyr4f118412020-06-04 15:25:10 +02007827 setverdict(fail, "Unexpected RSL message on DCHAN");
7828 mtc.stop;
7829 }
7830 [] Tt.timeout {
7831 setverdict(fail, "Timeout waiting for RSL on DCHAN");
7832 mtc.stop;
7833 }
7834 }
7835 rr := dec_GsmRrMessage(rx_rsl.ies[1].body.full_imm_ass_info.payload);
7836 g_chan_nr := rr.payload.imm_ass.chan_desc.chan_nr;
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02007837 rsl_pt.send(ts_RSL_EST_IND(g_chan_nr, valueof(g_pars.link_id), l3_enc));
Neels Hofmeyr4f118412020-06-04 15:25:10 +02007838
7839
Neels Hofmeyr66e15092020-10-12 18:44:41 +00007840 if (expect_bssmap_l3) {
7841 f_logp(BSCVTY, "expect BSSAP Complete Layer 3 Info at MSC");
7842 var template PDU_BSSAP exp_l3_compl;
7843 exp_l3_compl := tr_BSSMAP_ComplL3()
7844 if (g_pars.aoip == false) {
7845 exp_l3_compl.pdu.bssmap.completeLayer3Information.codecList := omit;
7846 } else {
7847 exp_l3_compl.pdu.bssmap.completeLayer3Information.codecList := ?;
7848 }
Neels Hofmeyr4f118412020-06-04 15:25:10 +02007849
Neels Hofmeyr66e15092020-10-12 18:44:41 +00007850 var PDU_BSSAP bssap;
7851 T.start;
7852 alt {
7853 [] BSSAP.receive(exp_l3_compl) -> value bssap {
7854 f_logp(BSCVTY, "received expected Complete Layer 3 Info at MSC");
7855 log("rx exp_l3_compl = ", bssap);
7856 }
7857 [] BSSAP.receive(tr_BSSMAP_ComplL3) {
7858 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Received non-matching COMPLETE LAYER 3 INFORMATION");
7859 }
7860 [] T.timeout {
7861 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout waiting for COMPLETE LAYER 3 INFORMATION");
7862 }
Neels Hofmeyr4f118412020-06-04 15:25:10 +02007863 }
Neels Hofmeyr4f118412020-06-04 15:25:10 +02007864
Neels Hofmeyr66e15092020-10-12 18:44:41 +00007865 /* start ciphering, if requested */
7866 if (ispresent(g_pars.encr)) {
7867 f_logp(BSCVTY, "start ciphering");
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02007868 f_cipher_mode(g_pars.encr, rsl_pt := rsl_pt, rsl_proc_pt := rsl_proc_pt);
Neels Hofmeyr66e15092020-10-12 18:44:41 +00007869 }
Neels Hofmeyr4f118412020-06-04 15:25:10 +02007870 }
7871
7872 if (do_clear) {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02007873 f_perform_clear(rsl_pt, rsl_proc_pt);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02007874 }
7875 setverdict(pass);
7876 f_sleep(1.0);
7877}
7878
7879private function f_tc_mscpool_compl_l3(charstring id) runs on MSC_ConnHdlr {
7880 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
7881 if (g_pars.mscpool.rsl_idx == 0) {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02007882 f_perform_compl_l3(RSL, RSL_PROC, g_pars.mscpool.l3_info);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02007883 } else if (g_pars.mscpool.rsl_idx == 1) {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02007884 f_perform_compl_l3(RSL1, RSL1_PROC, g_pars.mscpool.l3_info);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02007885 } else if (g_pars.mscpool.rsl_idx == 2) {
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02007886 f_perform_compl_l3(RSL2, RSL2_PROC, g_pars.mscpool.l3_info);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02007887 }
7888}
7889
7890/* Various Complete Layer 3 by IMSI all end up with the first MSC, because the other MSCs are not connected. */
7891private function f_tc_mscpool_L3Compl_on_1_msc(charstring id) runs on MSC_ConnHdlr {
7892 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02007893 f_perform_compl_l3(RSL, RSL_PROC, ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_IMSI_LV('001010000000001'H)), '00F110'O) );
7894 f_perform_compl_l3(RSL, RSL_PROC, ts_CM_SERV_REQ(CM_TYPE_MO_SMS, valueof(ts_MI_IMSI_LV('001010000000002'H))) );
7895 f_perform_compl_l3(RSL, RSL_PROC, ts_PAG_RESP(valueof(ts_MI_IMSI_LV('001010000000003'H))) );
7896 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 +02007897}
7898testcase TC_mscpool_L3Compl_on_1_msc() runs on test_CT {
7899
7900 f_init(1, true);
7901 f_sleep(1.0);
7902 var MSC_ConnHdlr vc_conn;
7903 var TestHdlrParams pars := f_gen_test_hdlr_pars();
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02007904
7905 f_ctrs_msc_init();
7906
Neels Hofmeyr4f118412020-06-04 15:25:10 +02007907 vc_conn := f_start_handler(refers(f_tc_mscpool_L3Compl_on_1_msc), pars);
7908 vc_conn.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02007909
7910 f_ctrs_msc_expect(0, "mscpool:subscr:new", 4);
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02007911 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02007912}
7913
7914/* Three Layer 3 Complete by IMSI are round-robin'ed across two connected MSCs */
7915/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
7916 * just as well using only RSL. */
7917testcase TC_mscpool_L3Complete_by_imsi_round_robin() runs on test_CT {
7918
7919 f_init(nr_bts := 3, handler_mode := true, nr_msc := 2);
7920 f_sleep(1.0);
7921
7922 /* Control which MSC gets chosen next by the round-robin, otherwise
7923 * would be randomly affected by which other tests ran before this. */
7924 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
7925
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02007926 f_ctrs_msc_init();
7927
Neels Hofmeyr4f118412020-06-04 15:25:10 +02007928 var MSC_ConnHdlr vc_conn1;
7929 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
7930 pars1.mscpool.rsl_idx := 0;
7931 pars1.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_IMSI_LV('001010000000001'H)), '00F110'O));
7932 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
7933 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02007934 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02007935
7936 var MSC_ConnHdlr vc_conn2;
7937 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 1);
7938 pars2.mscpool.rsl_idx := 1;
7939 pars2.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, valueof(ts_MI_IMSI_LV('001010000000002'H))));
7940 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
7941 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02007942 f_ctrs_msc_expect(1, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02007943
7944 /* Test round-robin wrap to the first MSC */
7945 var MSC_ConnHdlr vc_conn3;
7946 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 0);
7947 pars3.mscpool.rsl_idx := 2;
7948 pars3.mscpool.l3_info := valueof(ts_PAG_RESP(valueof(ts_MI_IMSI_LV('001010000000003'H))));
7949 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
7950 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02007951 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02007952 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02007953}
7954
7955/* Three LU by TMSI are round-robin'ed across two connected MSCs, because they contain the NULL-NRI 0
7956 * (configured in osmo-bsc.cfg). */
7957/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
7958 * just as well using only RSL. */
7959testcase TC_mscpool_LU_by_tmsi_null_nri_0_round_robin() runs on test_CT {
7960
7961 f_init(nr_bts := 3, handler_mode := true, nr_msc := 2);
7962 f_sleep(1.0);
7963
7964 /* Control which MSC gets chosen next by the round-robin, otherwise
7965 * would be randomly affected by which other tests ran before this. */
7966 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
7967
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02007968 f_ctrs_msc_init();
7969
Neels Hofmeyr4f118412020-06-04 15:25:10 +02007970 var MSC_ConnHdlr vc_conn1;
7971 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
7972 pars1.mscpool.rsl_idx := 0;
7973 pars1.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(0)), '00F110'O));
7974 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
7975 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02007976 f_ctrs_msc_expect(0, "mscpool:subscr:reattach");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02007977
7978 var MSC_ConnHdlr vc_conn2;
7979 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 1);
7980 pars2.mscpool.rsl_idx := 1;
7981 pars2.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(0)), '00F110'O));
7982 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
7983 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02007984 f_ctrs_msc_expect(1, "mscpool:subscr:reattach");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02007985
7986 /* Test round-robin wrap to the first MSC */
7987 var MSC_ConnHdlr vc_conn3;
7988 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 0);
7989 pars3.mscpool.rsl_idx := 2;
7990 pars3.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(0)), '00F110'O));
7991 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
7992 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02007993 f_ctrs_msc_expect(0, "mscpool:subscr:reattach");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02007994 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02007995}
7996
7997/* Three LU by TMSI are round-robin'ed across two connected MSCs, because they contain the NULL-NRI 1
7998 * (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
7999 * NULL-NRI setting is stronger than that. */
8000/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8001 * just as well using only RSL. */
8002testcase TC_mscpool_LU_by_tmsi_null_nri_1_round_robin() runs on test_CT {
8003
8004 f_init(nr_bts := 3, handler_mode := true, nr_msc := 2);
8005 f_sleep(1.0);
8006
8007 /* Control which MSC gets chosen next by the round-robin, otherwise
8008 * would be randomly affected by which other tests ran before this. */
8009 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
8010
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008011 f_ctrs_msc_init();
8012
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008013 var MSC_ConnHdlr vc_conn1;
8014 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
8015 pars1.mscpool.rsl_idx := 0;
8016 pars1.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(1)), '00F110'O));
8017 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8018 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008019 f_ctrs_msc_expect(0, "mscpool:subscr:reattach");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008020
8021 var MSC_ConnHdlr vc_conn2;
8022 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 1);
8023 pars2.mscpool.rsl_idx := 1;
8024 pars2.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(1)), '00F110'O));
8025 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8026 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008027 f_ctrs_msc_expect(1, "mscpool:subscr:reattach");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008028
8029 /* Test round-robin wrap to the first MSC */
8030 var MSC_ConnHdlr vc_conn3;
8031 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 0);
8032 pars3.mscpool.rsl_idx := 2;
8033 pars3.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(1)), '00F110'O));
8034 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8035 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008036 f_ctrs_msc_expect(0, "mscpool:subscr:reattach");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008037 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008038}
8039
8040/* Three Layer 3 Complete by TMSI are round-robin'ed across two connected MSCs, because they contain an NRI not
8041 * assigned to any MSC (configured in osmo-bsc.cfg). */
8042/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8043 * just as well using only RSL. */
8044testcase TC_mscpool_L3Complete_by_tmsi_unassigned_nri_round_robin() runs on test_CT {
8045
8046 f_init(nr_bts := 3, handler_mode := true, nr_msc := 2);
8047 f_sleep(1.0);
8048
8049 /* Control which MSC gets chosen next by the round-robin, otherwise
8050 * would be randomly affected by which other tests ran before this. */
8051 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
8052
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008053 f_ctrs_msc_init();
8054
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008055 var MSC_ConnHdlr vc_conn1;
8056 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
8057 pars1.mscpool.rsl_idx := 0;
8058 /* An NRI that is not assigned to any MSC */
8059 pars1.mscpool.l3_info := valueof(ts_ML3_MO_MM_IMSI_DET_Ind(valueof(ts_MI_TMSI_NRI_LV(1023))));
8060 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8061 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008062 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008063
8064 var MSC_ConnHdlr vc_conn2;
8065 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 1);
8066 pars2.mscpool.rsl_idx := 1;
8067 /* An NRI that is not assigned to any MSC */
8068 pars2.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(768)), '00F110'O));
8069 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8070 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008071 f_ctrs_msc_expect(1, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008072
8073 /* Test round-robin wrap to the first MSC */
8074 var MSC_ConnHdlr vc_conn3;
8075 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 0);
8076 pars3.mscpool.rsl_idx := 2;
8077 /* An NRI that is not assigned to any MSC */
8078 pars3.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_SS_ACT, valueof(ts_MI_TMSI_NRI_LV(819))));
8079 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8080 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008081 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008082 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008083}
8084
8085/* Three Layer 3 Complete by TMSI are round-robin'ed across two connected MSCs, because they contain an NRI
8086 * assigned to an MSC that is currently not connected (configured in osmo-bsc.cfg). */
8087/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8088 * just as well using only RSL. */
8089testcase TC_mscpool_L3Complete_by_tmsi_valid_nri_msc_not_connected_round_robin() runs on test_CT {
8090
8091 f_init(nr_bts := 3, handler_mode := true, nr_msc := 2);
8092 f_sleep(1.0);
8093
8094 /* Control which MSC gets chosen next by the round-robin, otherwise
8095 * would be randomly affected by which other tests ran before this. */
8096 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
8097
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008098 f_ctrs_msc_init();
8099
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008100 var MSC_ConnHdlr vc_conn1;
8101 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
8102 pars1.mscpool.rsl_idx := 0;
8103 /* An NRI that is assigned to an unconnected MSC */
8104 pars1.mscpool.l3_info := valueof(ts_PAG_RESP(valueof(ts_MI_TMSI_NRI_LV(512))));
8105 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8106 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008107 f_ctrs_msc_add(2, "mscpool:subscr:attach_lost");
8108 f_ctrs_msc_add(0, "mscpool:subscr:new");
8109 f_ctrs_msc_verify();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008110
8111 var MSC_ConnHdlr vc_conn2;
8112 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 1);
8113 pars2.mscpool.rsl_idx := 1;
8114 /* An NRI that is assigned to an unconnected MSC */
8115 pars2.mscpool.l3_info := valueof(ts_ML3_MO_MM_IMSI_DET_Ind(valueof(ts_MI_TMSI_NRI_LV(767))));
8116 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8117 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008118 f_ctrs_msc_add(2, "mscpool:subscr:attach_lost");
8119 f_ctrs_msc_add(1, "mscpool:subscr:new");
8120 f_ctrs_msc_verify();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008121
8122 /* Test round-robin wrap to the first MSC */
8123 var MSC_ConnHdlr vc_conn3;
8124 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 0);
8125 pars3.mscpool.rsl_idx := 2;
8126 /* An NRI that is assigned to an unconnected MSC */
8127 pars3.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(750)), '00F110'O));
8128 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8129 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008130 f_ctrs_msc_add(2, "mscpool:subscr:attach_lost");
8131 f_ctrs_msc_add(0, "mscpool:subscr:new");
8132 f_ctrs_msc_verify();
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008133 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008134}
8135
8136/* Three Layer 3 Complete by TMSI with valid NRI for the second MSC are all directed to the second MSC (configured in
8137 * osmo-bsc.cfg). */
8138/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8139 * just as well using only RSL. */
8140testcase TC_mscpool_L3Complete_by_tmsi_valid_nri_1() runs on test_CT {
8141
8142 f_init(nr_bts := 3, handler_mode := true, nr_msc := 2);
8143 f_sleep(1.0);
8144
8145 /* All TMSIs in this test point at the second MSC, set the round robin to point at the first MSC to make sure
8146 * this is not using round-robin. */
8147 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
8148
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008149 f_ctrs_msc_init();
8150
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008151 var MSC_ConnHdlr vc_conn1;
8152 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 1);
8153 pars1.mscpool.rsl_idx := 0;
8154 /* An NRI of the second MSC's range (256-511) */
8155 pars1.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_SMS, valueof(ts_MI_TMSI_NRI_LV(256))));
8156 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8157 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008158 f_ctrs_msc_expect(1, "mscpool:subscr:known");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008159
8160 var MSC_ConnHdlr vc_conn2;
8161 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 1);
8162 pars2.mscpool.rsl_idx := 1;
8163 /* An NRI of the second MSC's range (256-511) */
8164 pars2.mscpool.l3_info := valueof(ts_PAG_RESP(valueof(ts_MI_TMSI_NRI_LV(260))));
8165 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8166 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008167 f_ctrs_msc_expect(1, "mscpool:subscr:known");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008168
8169 var MSC_ConnHdlr vc_conn3;
8170 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 1);
8171 pars3.mscpool.rsl_idx := 2;
8172 /* An NRI of the second MSC's range (256-511) */
8173 pars3.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(511)), '00F110'O));
8174 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8175 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008176 f_ctrs_msc_expect(1, "mscpool:subscr:known");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008177 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008178}
8179
8180/* Layer 3 Complete by TMSI with valid NRI for the third MSC are directed to the third MSC (configured in osmo-bsc.cfg),
8181 * while a round-robin remains unaffected by that. */
8182/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8183 * just as well using only RSL. */
8184testcase TC_mscpool_L3Complete_by_tmsi_valid_nri_2() runs on test_CT {
8185
8186 f_init(nr_bts := 3, handler_mode := true, nr_msc := 3);
8187 f_sleep(1.0);
8188
8189 /* All TMSIs in this test point at the third MSC, set the round robin to point at the second MSC to make sure
8190 * this is not using round-robin. */
8191 f_vty_transceive(BSCVTY, "mscpool roundrobin next 1");
8192
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008193 f_ctrs_msc_init();
8194
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008195 var MSC_ConnHdlr vc_conn1;
8196 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 2);
8197 pars1.mscpool.rsl_idx := 0;
8198 /* An NRI of the third MSC's range (512-767) */
8199 pars1.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_SMS, valueof(ts_MI_TMSI_NRI_LV(512))));
8200 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8201 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008202 f_ctrs_msc_expect(2, "mscpool:subscr:known");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008203
8204 var MSC_ConnHdlr vc_conn2;
8205 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 2);
8206 pars2.mscpool.rsl_idx := 1;
8207 /* An NRI of the third MSC's range (512-767) */
8208 pars2.mscpool.l3_info := valueof(ts_PAG_RESP(valueof(ts_MI_TMSI_NRI_LV(678))));
8209 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8210 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008211 f_ctrs_msc_expect(2, "mscpool:subscr:known");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008212
8213 /* The above forwardings to third MSC have not affected the round robin, which still points at the second MSC */
8214 var MSC_ConnHdlr vc_conn3;
8215 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 1);
8216 pars3.mscpool.rsl_idx := 2;
8217 pars3.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_IMSI_LV('001010000000013'H)), '00F110'O));
8218 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8219 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008220 f_ctrs_msc_expect(1, "mscpool:subscr:new");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008221 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008222}
8223
8224/* LU with a TMSI but indicating a different PLMN in its previous LAI: ignore the NRI. */
8225/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8226 * just as well using only RSL. */
8227testcase TC_mscpool_LU_by_tmsi_from_other_PLMN() runs on test_CT {
8228
8229 f_init(nr_bts := 3, handler_mode := true, nr_msc := 3);
8230 f_sleep(1.0);
8231
8232 /* The TMSIs in this test points at the second MSC, but since it is from a different PLMN, round-robin is used
8233 * instead, and hits msc 0. */
8234 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
8235
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008236 f_ctrs_msc_init();
8237
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008238 /* An NRI of the second MSC's range (256-511), but a PLMN that doesn't match with osmo-bsc.cfg */
8239 var MSC_ConnHdlr vc_conn1;
8240 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
8241 pars1.mscpool.rsl_idx := 0;
8242 pars1.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(260)), '99F999'O));
8243 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8244 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008245 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008246
8247 /* An NRI of the third MSC's range (512-767) and a matching PLMN gets directed by NRI. */
8248 var MSC_ConnHdlr vc_conn2;
8249 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 2);
8250 pars2.mscpool.rsl_idx := 1;
8251 pars2.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_TMSI_NRI_LV(555)), '00F110'O));
8252 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8253 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008254 f_ctrs_msc_expect(2, "mscpool:subscr:known");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008255 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008256}
8257
8258/* Make sure that whichever MSC paged a subscriber will also get the Paging Response. Page by IMSI, which would be
8259 * round-robined to another MSC, to make sure the Paging->Response relation is stronger than the NRI->MSC mapping. */
8260private function f_tc_mscpool_paging_imsi(charstring id) runs on MSC_ConnHdlr {
8261 var template BSSMAP_FIELD_CellIdentificationList cid_list := { cIl_CI := { ts_BSSMAP_CI_CI(0) } };
8262 //cid_list := { cIl_allInBSS := ''O };
8263 var RSL_ChanNeeded rsl_chneed := RSL_CHANNEED_SDCCH;
8264 var template BSSMAP_IE_ChannelNeeded bssmap_chneed := ts_BSSMAP_IE_ChanNeeded(int2bit(enum2int(valueof(rsl_chneed)),2));
8265 var BSSAP_N_UNITDATA_req paging;
8266 var hexstring imsi := '001010000000123'H;
8267
8268 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
8269
Neels Hofmeyr90f80962020-06-12 16:16:55 +02008270 paging := valueof(ts_BSSAP_UNITDATA_req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008271 valueof(ts_BSSMAP_Paging(imsi, cid_list, omit, bssmap_chneed))));
8272 BSSAP.send(paging);
8273
8274 /* Register any RSL conn so that the Paging Command gets received here. With the current RSL_Emulation's main()
8275 * handling of '[bts_role] IPA_PT.receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD()))' it doesn't matter at all which
8276 * channel number is picked here. */
8277 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(0, RSL_CHAN_NR_INVALID));
8278 f_rslem_register(0, new_chan_nr);
8279 RSL.receive(tr_RSL_PAGING_CMD(tr_MI_IMSI(imsi)));
8280 f_rslem_unregister(0, new_chan_nr);
8281
8282 /* Despite the round robin pointing at the second MSC ('roundrobin next 1'), the earlier Paging for the same IMSI
8283 * causes this Paging Response to go to the first MSC (bssap_idx := 0). */
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008284 f_perform_compl_l3(RSL, RSL_PROC, ts_PAG_RESP(valueof(ts_MI_IMSI_LV(imsi))) );
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008285 f_sleep(1.0);
8286}
8287testcase TC_mscpool_paging_and_response_imsi() runs on test_CT {
8288 f_init(nr_bts := 1, handler_mode := true, nr_msc := 3);
8289 f_sleep(1.0);
8290
8291 /* Testing a Paging on the first MSC to get a Paging Response back to the first MSC. Set round robin to the
8292 * second MSC to make sure we're getting the Paging logic, not a coincidental round robin match. */
8293 f_vty_transceive(BSCVTY, "mscpool roundrobin next 1");
8294
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008295 f_ctrs_msc_init();
8296
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008297 var MSC_ConnHdlr vc_conn1;
8298 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
8299 pars1.mscpool.rsl_idx := 0;
Neels Hofmeyr90f80962020-06-12 16:16:55 +02008300 pars1.sccp_addr_bsc := g_bssap[pars1.mscpool.bssap_idx].sccp_addr_peer;
8301 pars1.sccp_addr_msc := g_bssap[pars1.mscpool.bssap_idx].sccp_addr_own;
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008302 vc_conn1 := f_start_handler(refers(f_tc_mscpool_paging_imsi), pars1);
8303 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008304 f_ctrs_msc_expect(0, "mscpool:subscr:paged");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008305 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008306}
8307
8308/* Make sure that whichever MSC paged a subscriber will also get the Paging Response. Page by TMSI with an NRI value
8309 * that matches a different MSC, to make sure the Paging->Response relation is stronger than the NRI->MSC mapping. */
8310private function f_tc_mscpool_paging_tmsi(charstring id) runs on MSC_ConnHdlr {
8311 var template BSSMAP_FIELD_CellIdentificationList cid_list := { cIl_CI := { ts_BSSMAP_CI_CI(0) } };
8312 //cid_list := { cIl_allInBSS := ''O };
8313 var RSL_ChanNeeded rsl_chneed := RSL_CHANNEED_SDCCH;
8314 var template BSSMAP_IE_ChannelNeeded bssmap_chneed := ts_BSSMAP_IE_ChanNeeded(int2bit(enum2int(valueof(rsl_chneed)),2));
8315 var integer nri_v := 300; /* <-- second MSC's NRI */
Harald Weltebf397612021-01-14 20:39:46 +01008316 var octetstring tmsi := f_gen_tmsi(suffix := 0, nri_v := nri_v);
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008317 var BSSAP_N_UNITDATA_req paging;
8318
8319 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
8320
Neels Hofmeyr90f80962020-06-12 16:16:55 +02008321 paging := valueof(ts_BSSAP_UNITDATA_req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008322 valueof(ts_BSSMAP_Paging('001010000000011'H, cid_list, tmsi, bssmap_chneed))));
8323 BSSAP.send(paging);
8324
8325 /* Register any RSL conn so that the Paging Command gets received here. With the current RSL_Emulation's main()
8326 * handling of '[bts_role] IPA_PT.receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD()))' it doesn't matter at all which
8327 * channel number is picked here. */
8328 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(0, RSL_CHAN_NR_INVALID));
8329 f_rslem_register(0, new_chan_nr);
8330 RSL.receive(tr_RSL_PAGING_CMD(t_MI_TMSI(tmsi)));
8331 f_rslem_unregister(0, new_chan_nr);
8332
8333 /* Despite the NRI matching the second MSC (NRI from 'msc 1' in osmo-bsc.cfg) and round robin pointing at the
8334 * third MSC ('roundrobin next 2'), the earlier Paging for the same TMSI causes this Paging Response to go to
8335 * the first MSC (bssap_idx := 0). */
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02008336 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 +02008337 f_sleep(1.0);
8338}
8339testcase TC_mscpool_paging_and_response_tmsi() runs on test_CT {
8340 f_init(nr_bts := 1, handler_mode := true, nr_msc := 3);
8341 f_sleep(1.0);
8342
8343 /* Testing a Paging on the first MSC to get a Paging Response back to the first MSC. Set round robin to the
8344 * third MSC to make sure we're getting the Paging logic, not a coincidental round robin match. */
8345 f_vty_transceive(BSCVTY, "mscpool roundrobin next 2");
8346
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008347 f_ctrs_msc_init();
8348
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008349 var MSC_ConnHdlr vc_conn1;
8350 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
8351 pars1.mscpool.rsl_idx := 0;
Neels Hofmeyr90f80962020-06-12 16:16:55 +02008352 pars1.sccp_addr_bsc := g_bssap[pars1.mscpool.bssap_idx].sccp_addr_peer;
8353 pars1.sccp_addr_msc := g_bssap[pars1.mscpool.bssap_idx].sccp_addr_own;
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008354 vc_conn1 := f_start_handler(refers(f_tc_mscpool_paging_tmsi), pars1);
8355 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008356 f_ctrs_msc_expect(0, "mscpool:subscr:paged");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008357 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008358}
8359
8360/* For round-robin, skip an MSC that has 'no allow-attach' set. */
8361/* FIXME: each run is using a separate RSLem: RSL, RSL1, RSL2. It should work
8362 * just as well using only RSL. */
8363testcase TC_mscpool_no_allow_attach_round_robin() runs on test_CT {
8364
8365 f_init(nr_bts := 3, handler_mode := true, nr_msc := 3);
8366 f_sleep(1.0);
Neels Hofmeyra460f1f2020-08-09 20:17:03 +00008367 /* Mark the second MSC as offloading, round-robin should skip this MSC now. */
8368 f_vty_msc_allow_attach(BSCVTY, {true, false, true});
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008369
8370 /* Control which MSC gets chosen next by the round-robin, otherwise
8371 * would be randomly affected by which other tests ran before this. */
8372 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
8373
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008374 f_ctrs_msc_init();
8375
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008376 var MSC_ConnHdlr vc_conn1;
8377 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
8378 pars1.mscpool.rsl_idx := 0;
8379 pars1.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_IMSI_LV('001010000000001'H)), '00F110'O));
8380 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8381 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008382 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008383
8384 var MSC_ConnHdlr vc_conn2;
8385 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 2);
8386 pars2.mscpool.rsl_idx := 1;
8387 pars2.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, valueof(ts_MI_IMSI_LV('001010000000002'H))));
8388 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8389 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008390 f_ctrs_msc_expect(2, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008391
8392 var MSC_ConnHdlr vc_conn3;
8393 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 0);
8394 pars3.mscpool.rsl_idx := 2;
8395 pars3.mscpool.l3_info := valueof(ts_PAG_RESP(valueof(ts_MI_IMSI_LV('001010000000003'H))));
8396 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8397 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008398 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008399 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008400}
8401
8402/* An MSC that has 'no allow-attach' set should still serve subscribers that are already attached according to their
8403 * TMSI NRI. */
8404testcase TC_mscpool_no_allow_attach_valid_nri() runs on test_CT {
8405
8406 f_init(nr_bts := 3, handler_mode := true, nr_msc := 3);
8407 f_sleep(1.0);
8408
Neels Hofmeyra460f1f2020-08-09 20:17:03 +00008409 /* Mark the second MSC as offloading, round-robin should skip this MSC now. */
8410 f_vty_msc_allow_attach(BSCVTY, {true, false, true});
8411
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008412 /* Control which MSC gets chosen next by the round-robin, otherwise
8413 * would be randomly affected by which other tests ran before this. */
8414 f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
8415
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008416 f_ctrs_msc_init();
8417
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008418 /* Round robin points at msc 0, but the valid NRI directs to msc 1, even though msc 1 has 'no allow-attach'. */
8419 var MSC_ConnHdlr vc_conn1;
8420 var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 1);
8421 pars1.mscpool.rsl_idx := 0;
8422 /* An NRI of the second MSC's range (256-511) */
8423 pars1.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, valueof(ts_MI_TMSI_NRI_LV(260))));
8424 vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
8425 vc_conn1.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008426 f_ctrs_msc_expect(1, "mscpool:subscr:known");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008427
8428 var MSC_ConnHdlr vc_conn2;
8429 var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 0);
8430 pars2.mscpool.rsl_idx := 1;
8431 pars2.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, valueof(ts_MI_IMSI_LV('001010000000002'H))));
8432 vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
8433 vc_conn2.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008434 f_ctrs_msc_expect(0, "mscpool:subscr:new");
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008435
8436 var MSC_ConnHdlr vc_conn3;
8437 var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 2);
8438 pars3.mscpool.rsl_idx := 2;
8439 pars3.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, valueof(ts_MI_IMSI_LV('001010000000003'H))));
8440 vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
8441 vc_conn3.done;
Neels Hofmeyr22c3f792020-06-17 02:49:28 +02008442 f_ctrs_msc_expect(2, "mscpool:subscr:new");
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008443 f_shutdown_helper();
Neels Hofmeyr4f118412020-06-04 15:25:10 +02008444}
8445
Philipp Maier783681c2020-07-16 16:47:06 +02008446/* Allow/Deny emergency calls globally via VTY */
8447private function f_vty_allow_emerg_msc(boolean allow) runs on test_CT {
8448 f_vty_enter_cfg_msc(BSCVTY, 0);
8449 if (allow) {
8450 f_vty_transceive(BSCVTY, "allow-emergency allow");
8451 } else {
8452 f_vty_transceive(BSCVTY, "allow-emergency deny");
8453 }
8454 f_vty_transceive(BSCVTY, "exit");
8455 f_vty_transceive(BSCVTY, "exit");
8456}
8457
8458/* Allow/Deny emergency calls per BTS via VTY */
8459private function f_vty_allow_emerg_bts(boolean allow, integer bts_nr) runs on test_CT {
8460 f_vty_enter_cfg_bts(BSCVTY, bts_nr);
8461 if (allow) {
8462 f_vty_transceive(BSCVTY, "rach emergency call allowed 1");
8463 } else {
8464 f_vty_transceive(BSCVTY, "rach emergency call allowed 0");
8465 }
8466 f_vty_transceive(BSCVTY, "exit");
8467 f_vty_transceive(BSCVTY, "exit");
Neels Hofmeyrb6ed80c2020-10-12 22:52:39 +00008468 f_vty_transceive(BSCVTY, "exit");
Philipp Maier783681c2020-07-16 16:47:06 +02008469}
8470
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +02008471/* Allow/Forbid Fast Return after SRVCC on a given BTS via VTY */
8472private function f_vty_allow_srvcc_fast_return(boolean allow, integer bts_nr) runs on test_CT {
8473 f_vty_enter_cfg_bts(BSCVTY, bts_nr);
8474 if (allow) {
8475 f_vty_transceive(BSCVTY, "srvcc fast-return allow");
8476 } else {
8477 f_vty_transceive(BSCVTY, "srvcc fast-return forbid");
8478 }
8479 f_vty_transceive(BSCVTY, "exit");
8480 f_vty_transceive(BSCVTY, "exit");
8481 f_vty_transceive(BSCVTY, "exit");
8482}
8483
Pau Espin Pedrol14475352021-07-22 15:48:16 +02008484/* Allow/Forbid TCH for signalling if SDCCH exhausted on a given BTS via VTY */
8485private function f_vty_allow_tch_for_signalling(boolean allow, integer bts_nr) runs on test_CT {
8486 f_vty_enter_cfg_bts(BSCVTY, bts_nr);
8487 if (allow) {
8488 f_vty_transceive(BSCVTY, "channel allocator allow-tch-for-signalling 1");
8489 } else {
8490 f_vty_transceive(BSCVTY, "channel allocator allow-tch-for-signalling 0");
8491 }
8492 f_vty_transceive(BSCVTY, "exit");
8493 f_vty_transceive(BSCVTY, "exit");
8494 f_vty_transceive(BSCVTY, "exit");
8495}
8496
Philipp Maier783681c2020-07-16 16:47:06 +02008497/* Begin assignmet procedure and send an EMERGENCY SETUP (RR) */
8498private function f_assignment_emerg_setup() runs on MSC_ConnHdlr {
8499 var PDU_ML3_MS_NW emerg_setup;
8500 var octetstring emerg_setup_enc;
8501 var RSL_Message emerg_setup_data_ind;
8502
8503 f_establish_fully(omit, omit);
8504
8505 emerg_setup := valueof(ts_ML3_MO_CC_EMERG_SETUP(1, valueof(ts_Bcap_voice)));
8506 emerg_setup_enc := enc_PDU_ML3_MS_NW(emerg_setup);
8507 emerg_setup_data_ind := valueof(ts_RSL_DATA_IND(g_chan_nr, valueof(ts_RslLinkID_DCCH(0)), emerg_setup_enc));
8508
8509 RSL.send(emerg_setup_data_ind);
8510}
8511
8512/* Test if the EMERGENCY SETUP gets passed on to the MSC via A when EMERGENCY
8513 * CALLS are permitted by the BSC config. */
8514private function f_TC_assignment_emerg_setup_allow(charstring id) runs on MSC_ConnHdlr {
8515 var PDU_BSSAP emerg_setup_data_ind_bssap;
8516 var PDU_ML3_MS_NW emerg_setup;
8517 timer T := 3.0;
8518
8519 f_assignment_emerg_setup()
8520
8521 T.start;
8522 alt {
8523 [] BSSAP.receive(tr_BSSAP_DTAP) -> value emerg_setup_data_ind_bssap {
8524 emerg_setup := dec_PDU_ML3_MS_NW(emerg_setup_data_ind_bssap.pdu.dtap);
8525 if (not isbound(emerg_setup.msgs.cc.emergencySetup)) {
8526 setverdict(fail, "no emergency setup");
8527 }
8528 }
8529 [] BSSAP.receive {
8530 setverdict(fail, "unexpected BSSAP message!");
8531 }
8532 [] T.timeout {
8533 setverdict(fail, "timout waiting for EMERGENCY SETUP!");
8534 }
8535 }
8536
8537 setverdict(pass);
8538}
8539
8540/* Test if the EMERGENCY SETUP gets blocked by the BSC if EMERGENCY CALLS are
8541 * forbidden by the BSC config. */
8542private function f_TC_assignment_emerg_setup_deny(charstring id) runs on MSC_ConnHdlr {
8543 var PDU_BSSAP emerg_setup_data_ind_bssap;
8544 timer T := 3.0;
8545
8546 f_assignment_emerg_setup()
8547
8548 T.start;
8549 alt {
8550 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_RELEASE)) {
8551 setverdict(pass);
8552 }
8553 [] RSL.receive {
8554 setverdict(fail, "unexpected RSL message!");
8555 }
8556 [] T.timeout {
8557 setverdict(fail, "timout waiting for RR CHANNEL RELEASE!");
8558 }
8559 }
8560}
8561
8562/* EMERGENCY CALL situation #1, allowed globally and by BTS */
8563testcase TC_assignment_emerg_setup_allow() runs on test_CT {
8564 var TestHdlrParams pars := f_gen_test_hdlr_pars();
8565 var MSC_ConnHdlr vc_conn;
8566
8567 f_init(1, true);
8568 f_sleep(1.0);
8569
8570 f_vty_allow_emerg_msc(true);
8571 f_vty_allow_emerg_bts(true, 0);
8572 vc_conn := f_start_handler(refers(f_TC_assignment_emerg_setup_allow), pars);
8573 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008574 f_shutdown_helper();
Philipp Maier783681c2020-07-16 16:47:06 +02008575}
8576
8577/* EMERGENCY CALL situation #2, forbidden globally but allowed by BTS */
8578testcase TC_assignment_emerg_setup_deny_msc() runs on test_CT {
8579 var TestHdlrParams pars := f_gen_test_hdlr_pars();
8580 var MSC_ConnHdlr vc_conn;
8581
8582 f_init(1, true);
8583 f_sleep(1.0);
8584
8585 f_vty_allow_emerg_msc(false);
8586 f_vty_allow_emerg_bts(true, 0);
8587 vc_conn := f_start_handler(refers(f_TC_assignment_emerg_setup_deny), pars);
8588 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008589 f_shutdown_helper();
Philipp Maier783681c2020-07-16 16:47:06 +02008590}
8591
8592/* EMERGENCY CALL situation #3, allowed globally but forbidden by BTS */
8593testcase TC_assignment_emerg_setup_deny_bts() runs on test_CT {
8594 var TestHdlrParams pars := f_gen_test_hdlr_pars();
8595 var MSC_ConnHdlr vc_conn;
8596
8597 /* Note: This simulates a spec violation by the MS, correct MS
8598 * implementations would not try to establish an emergency call because
8599 * the system information tells in advance that emergency calls are
8600 * not forbidden */
8601
8602 f_init(1, true);
8603 f_sleep(1.0);
8604
8605 f_vty_allow_emerg_msc(true);
8606 f_vty_allow_emerg_bts(false, 0);
8607 vc_conn := f_start_handler(refers(f_TC_assignment_emerg_setup_deny), pars);
8608 vc_conn.done;
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008609 f_shutdown_helper();
Philipp Maier783681c2020-07-16 16:47:06 +02008610}
8611
Philipp Maier82812002020-08-13 18:48:27 +02008612/* Test what happens when an emergency call arrives while all TCH channels are
8613 * busy, the BSC is expected to terminate one call in favor of the incoming
8614 * emergency call */
8615testcase TC_emerg_premption() runs on test_CT {
8616 var ASP_RSL_Unitdata rsl_ud;
8617 var integer i;
8618 var integer chreq_total, chreq_nochan;
8619 var RSL_Message rx_rsl;
8620 var RslChannelNr chan_nr;
8621
8622 f_init(1);
8623 f_sleep(1.0);
8624
8625 f_vty_allow_emerg_msc(true);
8626 f_vty_allow_emerg_bts(true, 0);
8627
8628 /* Fill up all channels on the BTS */
8629 chreq_total := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:total");
8630 chreq_nochan := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:no_channel");
8631 for (i := 0; i < NUM_TCHF_PER_BTS + NUM_TCHH_PER_BTS + NUM_SDCCH_PER_BTS; i := i+1) {
8632 chan_nr := f_chreq_act_ack('33'O, i);
8633 }
8634 IPA_RSL[0].clear;
8635 f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:total",
8636 chreq_total + NUM_TCHF_PER_BTS + NUM_TCHH_PER_BTS + NUM_SDCCH_PER_BTS);
8637
8638 /* Send Channel request for emegergency call */
8639 f_ipa_tx(0, ts_RSL_CHAN_RQD('A5'O, 23));
8640
8641 /* Expect the BSC to release one (the first) TCH/F on the BTS */
8642 chan_nr := valueof(t_RslChanNr_Bm(1));
8643 f_expect_chan_rel(0, chan_nr, expect_rr_chan_rel := false, expect_rll_rel_req := false);
8644
8645 /* Expect the BSC to send activate/assign the a channel for the emergency call */
8646 rx_rsl := f_exp_ipa_rx(0, tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
8647 chan_nr := rx_rsl.ies[0].body.chan_nr;
8648 f_ipa_tx(0, ts_RSL_CHAN_ACT_ACK(chan_nr, 33));
8649 rx_rsl := f_exp_ipa_rx(0, tr_RSL_IMM_ASSIGN(0));
Philipp Maier104f4c02020-09-11 18:12:18 +02008650
Pau Espin Pedrol6ed083c2020-09-23 14:16:58 +02008651 f_shutdown_helper();
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07008652}
8653
8654/* Hopping parameters per a timeslot */
Vadim Yanitskiybc6654a2020-09-13 01:27:40 +07008655private type record length(0..64) of GsmArfcn ArfcnList;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07008656private type record FHParamsTs {
8657 boolean enabled,
8658 uint6_t hsn,
8659 uint6_t maio,
8660 ArfcnList ma
8661};
8662
8663/* Hopping parameters per a transceiver */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07008664private type record FHParamsTrx {
Philipp Maier798d8952021-10-19 14:43:19 +02008665 GsmBandArfcn arfcn,
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07008666 FHParamsTs ts[8]
8667};
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07008668
8669/* Randomly generate the hopping parameters for the given timeslot numbers */
8670private function f_TC_fh_params_gen(template integer tr_tn := (1, 3, 5))
8671runs on test_CT return FHParamsTrx {
8672 var FHParamsTrx fhp;
8673
Philipp Maier798d8952021-10-19 14:43:19 +02008674 /* Generate a random ARFCN in the range of 0 - 3. This ARFCN will
8675 * fall in the GSM900 band. */
8676 fhp.arfcn.arfcn := f_rnd_int(3);
8677 fhp.arfcn.pcs := false;
Vadim Yanitskiye7c8c6e2020-09-13 14:33:03 +07008678
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07008679 for (var integer tn := 0; tn < 8; tn := tn + 1) {
8680 if (not match(tn, tr_tn)) {
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07008681 fhp.ts[tn].enabled := false;
8682 fhp.ts[tn].ma := { };
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07008683 continue;
8684 }
8685
8686 /* Random HSN / MAIO values: 0..63 */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07008687 fhp.ts[tn].hsn := f_rnd_int(64);
8688 fhp.ts[tn].maio := f_rnd_int(64);
8689 fhp.ts[tn].ma := { };
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07008690
8691 /* Random Mobile Allocation (hopping channels) */
8692 var integer ma_len := 2 + f_rnd_int(9); /* 2..10 channels */
8693 var integer step := 3 + f_rnd_int(4); /* 3..6 stepping */
8694 for (var integer i := 1; i <= ma_len; i := i + 1) {
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07008695 fhp.ts[tn].ma := fhp.ts[tn].ma & { i * step };
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07008696 }
8697
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07008698 fhp.ts[tn].enabled := true;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07008699 }
8700
8701 log("f_TC_fh_params_gen(): ", fhp);
8702 return fhp;
8703}
8704
8705/* Make sure that the given Channel Description IE matches the hopping configuration */
8706private function f_TC_fh_params_match_chan_desc(in FHParamsTrx fhp, in ChannelDescription cd)
8707{
8708 var template (present) ChannelDescription tr_cd;
8709 var template (present) MaioHsn tr_maio_hsn;
8710 var uint3_t tn := cd.chan_nr.tn;
8711
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07008712 if (fhp.ts[tn].enabled) {
8713 tr_maio_hsn := tr_HsnMaio(fhp.ts[tn].hsn, fhp.ts[tn].maio);
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07008714 tr_cd := tr_ChanDescH1(cd.chan_nr, tr_maio_hsn);
8715 } else {
Philipp Maier798d8952021-10-19 14:43:19 +02008716 tr_cd := tr_ChanDescH0(cd.chan_nr, fhp.arfcn.arfcn);
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07008717 }
8718
8719 if (not match(cd, tr_cd)) {
8720 setverdict(fail, "Channel Description IE does not match: ",
8721 cd, " vs expected ", tr_cd);
8722 }
8723}
8724
8725/* Make sure that the given Mobile Allocation IE matches the hopping configuration */
8726private function f_TC_fh_params_match_ma(in FHParamsTrx fhp, uint3_t tn,
8727 in MobileAllocationLV ma)
8728{
8729 var template MobileAllocationLV tr_ma := f_TC_fh_params_gen_tr_ma(fhp, tn, ma);
8730
8731 if (not match(ma, tr_ma)) {
8732 setverdict(fail, "Mobile Allocation IE does not match (tn := ",
8733 tn, "): ", ma, " vs expected: ", tr_ma);
8734 } else {
8735 setverdict(pass);
8736 }
8737}
8738
8739private function f_TC_fh_params_gen_tr_ma(in FHParamsTrx fhp, uint3_t tn,
8740 in MobileAllocationLV ma)
8741return template MobileAllocationLV {
8742 /* Mobile Allocation IE is expected to be empty if hopping is not enabled */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07008743 if (not fhp.ts[tn].enabled) {
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07008744 return { len := 0, ma := ''B };
8745 }
8746
8747 var bitstring full_mask := f_pad_bit(''B, 1024, '0'B);
8748 var bitstring slot_mask := f_pad_bit(''B, 1024, '0'B);
8749 var bitstring ma_mask := ''B;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07008750
8751 /* Compose the full bit-mask (all channels, up to 1024 entries) */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07008752 for (var integer i := 0; i < lengthof(fhp.ts); i := i + 1) {
8753 for (var integer j := 0; j < lengthof(fhp.ts[i].ma); j := j + 1) {
8754 if (full_mask[fhp.ts[i].ma[j]] == '1'B)
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07008755 { continue; }
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07008756 full_mask[fhp.ts[i].ma[j]] := '1'B;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07008757 }
8758 }
8759
Vadim Yanitskiye7c8c6e2020-09-13 14:33:03 +07008760 /* Take ARFCN of the TRX itself into account */
Philipp Maier798d8952021-10-19 14:43:19 +02008761 full_mask[fhp.arfcn.arfcn] := '1'B;
Vadim Yanitskiye7c8c6e2020-09-13 14:33:03 +07008762
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07008763 /* Compose a bit-mask for the given timeslot number */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07008764 for (var integer i := 0; i < lengthof(fhp.ts[tn].ma); i := i + 1) {
8765 slot_mask[fhp.ts[tn].ma[i]] := '1'B;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07008766 }
8767
8768 /* Finally, compose the Mobile Allocation bit-mask */
Vadim Yanitskiy3e997362020-09-05 21:08:34 +07008769 for (var integer i := 1; i < lengthof(full_mask); i := i + 1) {
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07008770 if (full_mask[i] != '1'B)
8771 { continue; }
8772
8773 /* FIXME: ma_mask := ma_mask & slot_mask[i]; // triggers a bug in TITAN */
8774 if (slot_mask[i] == '1'B) {
8775 ma_mask := ma_mask & '1'B;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07008776 } else {
8777 ma_mask := ma_mask & '0'B;
8778 }
8779 }
8780
Vadim Yanitskiy3e997362020-09-05 21:08:34 +07008781 /* ARFCN 0 (if present) goes to the last position of the bit-mask */
8782 if (full_mask[0] == '1'B) {
8783 /* FIXME: ma_mask := ma_mask & slot_mask[0]; // triggers a bug in TITAN */
8784 if (slot_mask[0] == '1'B) {
8785 ma_mask := ma_mask & '1'B;
8786 } else {
8787 ma_mask := ma_mask & '0'B;
8788 }
8789 }
8790
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07008791 /* Ensure that ma_mask is octet-aligned */
Vadim Yanitskiy2aa02522020-09-06 14:05:23 +07008792 var integer ma_mask_len := (lengthof(ma_mask) + 8 - 1) / 8;
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07008793 ma_mask := f_pad_bit(ma_mask, ma_mask_len * 8, '0'B);
8794
8795 return { len := ma_mask_len, ma := ma_mask };
8796}
8797
Philipp Maier798d8952021-10-19 14:43:19 +02008798/* Configure the appropriate band for a given arfcn, exc */
8799private function f_TC_set_band_by_arfcn(integer bts_nr, GsmBandArfcn arfcn) runs on test_CT
8800{
8801 var charstring band;
8802 var GsmBandArfcn arfcn_ := valueof(ts_GsmBandArfcn(arfcn.arfcn, arfcn.pcs, false));
8803
8804 select (arfcn_) {
8805 case (tr_GsmBandArfcn((259..293), false, ?)) { band := "GSM450"; }
8806 case (tr_GsmBandArfcn((306..340), false, ?)) { band := "GSM480"; }
8807 case (tr_GsmBandArfcn((438..511), false, ?)) { band := "GSM750"; }
8808 case (tr_GsmBandArfcn((128..251), false, ?)) { band := "GSM850"; }
8809 case (tr_GsmBandArfcn((0..124), false, ?)) { band := "GSM900"; }
8810 case (tr_GsmBandArfcn((955..1023), false, ?)) { band := "GSM900"; }
8811 case (tr_GsmBandArfcn((512..885), false, ?)) { band := "DCS1800"; }
8812 case (tr_GsmBandArfcn((512..810), true, ?)) { band := "PCS1900"; }
8813 case else { return; }
8814 }
8815
8816 f_vty_enter_cfg_bts(BSCVTY, bts_nr);
8817 f_vty_transceive(BSCVTY, "band " & band);
8818 f_vty_transceive(BSCVTY, "end");
8819}
8820
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07008821/* Configure the hopping parameters in accordance with the given record */
8822private function f_TC_fh_params_set(in FHParamsTrx fhp,
8823 uint8_t bts_nr := 0,
8824 uint8_t trx_nr := 0)
8825runs on test_CT {
Philipp Maier798d8952021-10-19 14:43:19 +02008826
8827 f_TC_set_band_by_arfcn(bts_nr, fhp.arfcn);
8828
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07008829 /* Enter the configuration node for the given BTS/TRX numbers */
8830 f_vty_enter_cfg_trx(BSCVTY, bts_nr, trx_nr);
8831
Philipp Maier798d8952021-10-19 14:43:19 +02008832 f_vty_transceive(BSCVTY, "arfcn " & int2str(fhp.arfcn.arfcn));
Vadim Yanitskiye7c8c6e2020-09-13 14:33:03 +07008833
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07008834 for (var integer tn := 0; tn < lengthof(fhp.ts); tn := tn + 1) {
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07008835 f_vty_transceive(BSCVTY, "timeslot " & int2str(tn));
8836
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07008837 if (not fhp.ts[tn].enabled) {
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07008838 f_vty_transceive(BSCVTY, "hopping enabled 0");
8839 f_vty_transceive(BSCVTY, "exit"); /* go back */
8840 continue;
8841 }
8842
8843 /* Configure HSN / MAIO values */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07008844 f_vty_transceive(BSCVTY, "hopping sequence-number " & int2str(fhp.ts[tn].hsn));
8845 f_vty_transceive(BSCVTY, "hopping maio " & int2str(fhp.ts[tn].maio));
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07008846
8847 /* Configure the Mobile Allocation (hopping channels) */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07008848 for (var integer i := 0; i < lengthof(fhp.ts[tn].ma); i := i + 1) {
8849 f_vty_transceive(BSCVTY, "hopping arfcn add " & int2str(fhp.ts[tn].ma[i]));
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07008850 }
8851
8852 f_vty_transceive(BSCVTY, "hopping enabled 1");
8853 f_vty_transceive(BSCVTY, "exit"); /* go back */
8854 }
8855
8856 f_vty_transceive(BSCVTY, "end");
8857}
8858
8859/* Disable frequency hopping on all timeslots */
8860private function f_TC_fh_params_unset(in FHParamsTrx fhp,
8861 uint8_t bts_nr := 0,
Vadim Yanitskiye7c8c6e2020-09-13 14:33:03 +07008862 uint8_t trx_nr := 0,
Philipp Maier798d8952021-10-19 14:43:19 +02008863 GsmBandArfcn arfcn := {pcs := false, arfcn := 871})
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07008864runs on test_CT {
Philipp Maier798d8952021-10-19 14:43:19 +02008865
8866 f_TC_set_band_by_arfcn(bts_nr, arfcn);
8867
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07008868 /* Enter the configuration node for the given BTS/TRX numbers */
8869 f_vty_enter_cfg_trx(BSCVTY, bts_nr, trx_nr);
8870
Philipp Maier798d8952021-10-19 14:43:19 +02008871 f_vty_transceive(BSCVTY, "arfcn " & int2str(arfcn.arfcn));
Vadim Yanitskiye7c8c6e2020-09-13 14:33:03 +07008872
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07008873 for (var integer tn := 0; tn < lengthof(fhp.ts); tn := tn + 1) {
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07008874 f_vty_transceive(BSCVTY, "timeslot " & int2str(tn));
8875
8876 /* Delete all ARFCNs from the Mobile Allocation (if any) */
Vadim Yanitskiy1b996612020-09-13 13:22:34 +07008877 for (var integer i := 0; i < lengthof(fhp.ts[tn].ma); i := i + 1) {
8878 f_vty_transceive(BSCVTY, "hopping arfcn del " & int2str(fhp.ts[tn].ma[i]));
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07008879 }
8880
8881 f_vty_transceive(BSCVTY, "hopping enabled 0");
8882 f_vty_transceive(BSCVTY, "exit"); /* go back */
8883 }
8884
8885 f_vty_transceive(BSCVTY, "end");
8886 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
8887}
8888
8889/* Verify presence and correctness of the hopping parameters (HSN, MAIO)
8890 * in the Channel Identification IE of the RSL CHANnel ACTIVation message. */
8891testcase TC_fh_params_chan_activ() runs on test_CT {
8892 var FHParamsTrx fhp := f_TC_fh_params_gen();
8893 var RSL_Message rsl_msg;
8894 var RSL_IE_Body ie;
8895
8896 f_init_vty();
8897
8898 f_TC_fh_params_set(fhp); /* Enable frequency hopping */
8899 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
8900
8901 f_init(1);
8902
8903 /* CS domain: 3 (SDCCH/4+CBCH) + 4 (TCH/F) + 2 (TCH/H) channels available */
8904 for (var integer i := 0; i < 9; i := i + 1) {
8905 f_ipa_tx(0, ts_RSL_CHAN_RQD(f_rnd_ra_cs(), 23));
8906 rsl_msg := f_exp_ipa_rx(0, tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
8907
8908 /* Make sure that Channel Identification IE is present */
8909 if (not f_rsl_find_ie(rsl_msg, RSL_IE_CHAN_IDENT, ie)) {
8910 setverdict(fail, "RSL Channel Identification IE is absent");
8911 continue;
8912 }
8913
8914 /* Make sure that hopping parameters (HSN/MAIO) match */
8915 f_TC_fh_params_match_chan_desc(fhp, ie.chan_ident.ch_desc.v);
8916
8917 /* "Mobile Allocation shall be included but empty" - let's check this */
8918 if (ie.chan_ident.ma.v.len != 0) {
8919 setverdict(fail, "Mobile Allocation IE is not empty: ",
8920 ie.chan_ident.ma, ", despite it shall be");
8921 continue;
8922 }
8923 }
8924
8925 /* Disable frequency hopping */
8926 f_TC_fh_params_unset(fhp);
8927
Vadim Yanitskiy21726312020-09-04 01:45:36 +07008928 f_shutdown_helper();
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +07008929}
8930
8931/* Verify the hopping parameters (HSN, MAIO, MA) in (RR) Immediate Assignment */
8932testcase TC_fh_params_imm_ass() runs on test_CT {
8933 var FHParamsTrx fhp := f_TC_fh_params_gen();
8934 var RSL_Message rsl_msg;
8935 var RSL_IE_Body ie;
8936
8937 f_init_vty();
8938
8939 f_TC_fh_params_set(fhp); /* Enable frequency hopping */
8940 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
8941
8942 f_init(1);
8943
8944 /* CS domain: 3 (SDCCH/4+CBCH) + 4 (TCH/F) + 2 (TCH/H) channels available */
8945 for (var integer i := 0; i < 9; i := i + 1) {
8946 f_ipa_tx(0, ts_RSL_CHAN_RQD(f_rnd_ra_cs(), 23));
8947 rsl_msg := f_exp_ipa_rx(0, tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
8948
8949 f_ipa_tx(0, ts_RSL_CHAN_ACT_ACK(rsl_msg.ies[0].body.chan_nr, 33));
8950 rsl_msg := f_exp_ipa_rx(0, tr_RSL_MsgTypeC(RSL_MT_IMMEDIATE_ASSIGN_CMD));
8951
8952 /* Make sure that Full Immediate Assign Info IE is present */
8953 if (not f_rsl_find_ie(rsl_msg, RSL_IE_FULL_IMM_ASS_INFO, ie)) {
8954 setverdict(fail, "RSL Full Immediate Assign Info IE is absent");
8955 continue;
8956 }
8957
8958 /* Decode the actual Immediate Assignment message */
8959 var GsmRrMessage rr_msg := dec_GsmRrMessage(ie.full_imm_ass_info.payload);
8960 if (not match(rr_msg.header, t_RrHeader(IMMEDIATE_ASSIGNMENT, ?))) {
8961 setverdict(fail, "Failed to match Immediate Assignment: ", rr_msg);
8962 continue;
8963 }
8964
8965 /* Make sure that hopping parameters (HSN/MAIO) match */
8966 f_TC_fh_params_match_chan_desc(fhp, rr_msg.payload.imm_ass.chan_desc);
8967
8968 /* Make sure that the Mobile Allocation IE matches */
8969 f_TC_fh_params_match_ma(fhp, rr_msg.payload.imm_ass.chan_desc.chan_nr.tn,
8970 rr_msg.payload.imm_ass.mobile_allocation);
8971 }
8972
8973 /* Disable frequency hopping */
8974 f_TC_fh_params_unset(fhp);
Philipp Maier82812002020-08-13 18:48:27 +02008975
Vadim Yanitskiy21726312020-09-04 01:45:36 +07008976 f_shutdown_helper();
Philipp Maier82812002020-08-13 18:48:27 +02008977}
8978
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +07008979/* Verify the hopping parameters (HSN, MAIO, MA) in (RR) Assignment Command */
8980testcase TC_fh_params_assignment_cmd() runs on test_CT {
8981 var FHParamsTrx fhp := f_TC_fh_params_gen();
8982 var RSL_Message rsl_msg;
8983 var RSL_IE_Body ie;
8984
8985 f_init_vty();
8986
8987 f_TC_fh_params_set(fhp); /* Enable frequency hopping */
8988 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
8989
8990 f_init(1);
8991
8992 /* HACK: work around "Couldn't find Expect for CRCX" */
8993 vc_MGCP.stop;
8994
8995 var template PDU_BSSAP ass_cmd := f_gen_ass_req();
8996 ass_cmd.pdu.bssmap.assignmentRequest.codecList := ts_BSSMAP_IE_CodecList({ts_CodecFR});
8997
8998 /* CS domain (TCH): 4 (TCH/F) + 2 (TCH/H) channels available
8999 * NOTE: only 3 SDCCH/4 channels are available on CCCH+SDCCH4+CBCH */
9000 for (var integer i := 0; i < 3; i := i + 1) {
9001 /* Establish a dedicated channel, so we can trigger (late) TCH assignment */
9002 var DchanTuple dt := f_est_dchan(f_rnd_ra_cs(), 23, f_rnd_octstring(16));
9003
9004 /* Send a BSSMAP Assignment Command, expect CHANnel ACTIVation */
9005 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ass_cmd));
9006 rsl_msg := f_exp_ipa_rx(0, tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
9007
9008 /* ACKnowledge CHANnel ACTIVation, expect RSL DATA REQuest */
9009 f_ipa_tx(0, ts_RSL_CHAN_ACT_ACK(rsl_msg.ies[0].body.chan_nr, 33));
9010 rsl_msg := f_exp_ipa_rx(0, tr_RSL_MsgTypeR(RSL_MT_DATA_REQ));
9011
9012 /* Make sure that L3 Information IE is present */
9013 if (not f_rsl_find_ie(rsl_msg, RSL_IE_L3_INFO, ie)) {
9014 setverdict(fail, "RSL L3 Information IE is absent");
9015 continue;
9016 }
9017
9018 /* Decode the L3 message and make sure it is (RR) Assignment Command */
9019 var GsmRrL3Message l3_msg := dec_GsmRrL3Message(ie.l3_info.payload);
9020 if (not match(l3_msg.header, t_RrL3Header(ASSIGNMENT_COMMAND))) {
9021 setverdict(fail, "Failed to match Assignment Command: ", l3_msg);
9022 continue;
9023 }
9024
9025 /* Make sure that hopping parameters (HSN/MAIO) match */
9026 var ChannelDescription chan_desc := l3_msg.payload.ass_cmd.chan_desc;
9027 f_TC_fh_params_match_chan_desc(fhp, chan_desc);
9028
9029 /* Make sure that Cell Channel Description IE is present if FH is enabled */
9030 if (chan_desc.h and not ispresent(l3_msg.payload.ass_cmd.cell_chan_desc)) {
Vadim Yanitskiy38d069d2020-09-02 17:18:57 +07009031 setverdict(fail, "FH enabled, but Cell Channel Description IE is absent");
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +07009032 continue;
9033 }
9034
9035 /* Make sure that the Mobile Allocation IE matches (if present) */
9036 var boolean ma_present := ispresent(l3_msg.payload.ass_cmd.mobile_allocation);
9037 if (chan_desc.h and ma_present) {
9038 f_TC_fh_params_match_ma(fhp, chan_desc.chan_nr.tn,
9039 l3_msg.payload.ass_cmd.mobile_allocation.v);
9040 } else if (chan_desc.h and not ma_present) {
9041 setverdict(fail, "FH enabled, but Mobile Allocation IE is absent");
9042 continue;
9043 } else if (not chan_desc.h and ma_present) {
9044 setverdict(fail, "FH disabled, but Mobile Allocation IE is present");
9045 continue;
9046 }
9047 }
9048
9049 /* Give the IUT some time to release all channels */
9050 f_sleep(3.0);
9051
9052 /* Disable frequency hopping */
9053 f_TC_fh_params_unset(fhp);
9054
Vadim Yanitskiy21726312020-09-04 01:45:36 +07009055 f_shutdown_helper();
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +07009056}
9057
Vadim Yanitskiy8f5430d2020-09-02 18:51:38 +07009058/* Verify the hopping parameters (HSN, MAIO, MA) in (RR) Handover Command */
9059private function f_TC_fh_params_handover_cmd(in FHParamsTrx fhp)
9060runs on test_CT {
9061 var RSL_Message rsl_msg;
9062 var RSL_IE_Body ie;
9063 var DchanTuple dt;
9064
9065 /* Establish a dedicated channel, so we can trigger handover */
9066 dt := f_est_dchan(f_rnd_ra_cs(), 23, f_rnd_octstring(16));
Vadim Yanitskiyc18ff472021-11-18 20:15:37 +03009067 f_sleep(0.5);
Vadim Yanitskiy8f5430d2020-09-02 18:51:38 +07009068
9069 /* Trigger handover from BTS0 to BTS1 */
9070 f_bts_0_cfg(BSCVTY, { "neighbor bts 1" });
9071 f_vty_handover(BSCVTY, 0, 0, dt.rsl_chan_nr, 1);
9072
9073 /* Expect RSL CHANnel ACTIVation on BTS1/TRX0/TS1 */
9074 rsl_msg := f_exp_ipa_rx(1, tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
9075
9076 /* ACKnowledge channel activation and expect (RR) Handover Command */
9077 f_ipa_tx(1, ts_RSL_CHAN_ACT_ACK(rsl_msg.ies[0].body.chan_nr, 33));
9078 rsl_msg := f_exp_ipa_rx(0, tr_RSL_MsgTypeR(RSL_MT_DATA_REQ));
9079
9080 /* Make sure that L3 Information IE is present */
9081 if (not f_rsl_find_ie(rsl_msg, RSL_IE_L3_INFO, ie)) {
9082 setverdict(fail, "RSL L3 Information IE is absent");
9083 return;
9084 }
9085
9086 /* Decode the L3 message and make sure it is (RR) Handover Command */
9087 var GsmRrL3Message l3_msg := dec_GsmRrL3Message(ie.l3_info.payload);
9088 if (not match(l3_msg.header, t_RrL3Header(HANDOVER_COMMAND))) {
9089 setverdict(fail, "Failed to match Handover Command: ", l3_msg);
9090 return;
9091 }
9092
9093 /* Make sure that we've got SDCCH/8 on TS1 (expected to be hopping) */
9094 var ChannelDescription chan_desc := l3_msg.payload.ho_cmd.chan_desc;
9095 if (not match(chan_desc.chan_nr, t_RslChanNr_SDCCH8(1, ?))) {
9096 setverdict(fail, "Unexpected channel number: ", chan_desc.chan_nr);
9097 return;
9098 }
9099
9100 /* Make sure that hopping parameters (HSN/MAIO) match */
9101 f_TC_fh_params_match_chan_desc(fhp, chan_desc);
9102
9103 /* Make sure that Cell Channel Description IE is present */
9104 if (not ispresent(l3_msg.payload.ho_cmd.cell_chan_desc)) {
9105 setverdict(fail, "FH enabled, but Cell Channel Description IE is absent");
9106 return;
9107 }
9108
9109 /* Make sure that the Mobile Allocation (after time) IE is present and matches */
9110 var boolean ma_present := ispresent(l3_msg.payload.ho_cmd.mobile_allocation);
9111 if (ma_present) {
9112 f_TC_fh_params_match_ma(fhp, chan_desc.chan_nr.tn,
9113 l3_msg.payload.ho_cmd.mobile_allocation.v);
9114 } else {
9115 setverdict(fail, "FH enabled, but Mobile Allocation IE is absent");
9116 return;
9117 }
9118}
9119testcase TC_fh_params_handover_cmd() runs on test_CT {
9120 var FHParamsTrx fhp := f_TC_fh_params_gen();
9121
9122 f_init_vty();
9123
9124 /* (Re)configure TS0 as BCCH and TS1 as SDCCH8 on BTS1/TRX0 */
9125 f_vty_enter_cfg_trx(BSCVTY, bts := 1, trx := 0);
9126
9127 f_vty_transceive(BSCVTY, "timeslot 0");
9128 f_vty_transceive(BSCVTY, "phys_chan_config ccch");
9129 f_vty_transceive(BSCVTY, "exit"); /* go back */
9130
9131 f_vty_transceive(BSCVTY, "timeslot 1");
9132 f_vty_transceive(BSCVTY, "phys_chan_config sdcch8");
9133 f_vty_transceive(BSCVTY, "end"); /* we're done */
9134
9135 f_TC_fh_params_set(fhp, 1); /* Enable frequency hopping on BTS1 */
9136 f_vty_transceive(BSCVTY, "drop bts connection 1 oml");
9137
9138 f_init(2);
9139
9140 f_TC_fh_params_handover_cmd(fhp);
9141
9142 /* Disable frequency hopping on BTS1 */
9143 f_TC_fh_params_unset(fhp, 1);
9144
9145 /* (Re)configure TS0 as CCCH+SDCCH4+CBCH and TS1 as TCH/F */
9146 f_vty_enter_cfg_trx(BSCVTY, bts := 1, trx := 0);
9147
9148 f_vty_transceive(BSCVTY, "timeslot 0");
9149 f_vty_transceive(BSCVTY, "phys_chan_config ccch+sdcch4+cbch");
9150 f_vty_transceive(BSCVTY, "exit"); /* go back */
9151
9152 f_vty_transceive(BSCVTY, "timeslot 1");
9153 f_vty_transceive(BSCVTY, "phys_chan_config tch/f");
9154 f_vty_transceive(BSCVTY, "end"); /* we're done */
9155
9156 f_shutdown_helper();
9157}
9158
Vadim Yanitskiyca974032020-09-01 07:20:39 +07009159/* Verify the hopping parameters in System Information Type 4 */
9160testcase TC_fh_params_si4_cbch() runs on test_CT {
9161 var FHParamsTrx fhp := f_TC_fh_params_gen(tr_tn := 1);
9162 var ASP_RSL_Unitdata rx_rsl_ud;
9163 timer T := 5.0;
9164
9165 f_init_vty();
9166
9167 /* (Re)configure TS0 as BCCH and TS1 as SDCCH8+CBCH */
9168 f_vty_enter_cfg_trx(BSCVTY, trx := 0);
9169
9170 f_vty_transceive(BSCVTY, "timeslot 0");
9171 f_vty_transceive(BSCVTY, "phys_chan_config ccch");
9172 f_vty_transceive(BSCVTY, "exit"); /* go back */
9173
9174 f_vty_transceive(BSCVTY, "timeslot 1");
9175 f_vty_transceive(BSCVTY, "phys_chan_config sdcch8+cbch");
9176 f_vty_transceive(BSCVTY, "end"); /* we're done */
9177
9178 f_TC_fh_params_set(fhp); /* Enable frequency hopping */
9179 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
9180
9181 f_init(1);
9182
9183 T.start;
9184 alt {
9185 [] IPA_RSL[0].receive(tr_ASP_RSL_UD(tr_RSL_BCCH_INFO(RSL_SYSTEM_INFO_4))) -> value rx_rsl_ud {
9186 var RSL_IE_Body ie := rx_rsl_ud.rsl.ies[2].body; /* FULL BCCH Information IE */
9187 var SystemInformation si := dec_SystemInformation(ie.other.payload);
9188
9189 /* Make sure that what we decoded is System Information Type 4 */
9190 if (si.header.message_type != SYSTEM_INFORMATION_TYPE_4) {
9191 setverdict(fail, "RSL FULL BCCH Information IE contains: ", si);
9192 repeat;
9193 }
9194
9195 /* Make sure that CBCH Channel Description IE is present */
9196 if (not ispresent(si.payload.si4.cbch_chan_desc)) {
9197 setverdict(fail, "CBCH Channel Description IE is absent");
9198 break;
9199 }
9200
9201 /* Finally, check the hopping parameters (HSN, MAIO) */
9202 var ChannelDescription chan_desc := si.payload.si4.cbch_chan_desc.v;
9203 f_TC_fh_params_match_chan_desc(fhp, chan_desc);
9204
9205 /* 3GPP TS 44.018, section 9.1.36.2 "CBCH Mobile Allocation":
9206 * The CBCH Mobile Allocation IE *shall* be present if FH is enabled. */
9207 if (chan_desc.h and not ispresent(si.payload.si4.cbch_mobile_alloc)) {
9208 setverdict(fail, "FH enabled, but Mobile Allocation IE is absent");
9209 break;
9210 } else if (chan_desc.h and ispresent(si.payload.si4.cbch_mobile_alloc)) {
9211 f_TC_fh_params_match_ma(fhp, chan_desc.chan_nr.tn,
9212 si.payload.si4.cbch_mobile_alloc.v);
9213 }
9214 }
9215 [] IPA_RSL[0].receive { repeat; }
9216 [] T.timeout {
9217 setverdict(fail, "Timeout waiting for RSL BCCH INFOrmation (SI4)");
9218 }
9219 }
9220
9221 /* Disable frequency hopping */
9222 f_TC_fh_params_unset(fhp);
9223
Vadim Yanitskiy8bc46012020-09-06 12:38:01 +07009224 /* (Re)configure TS0 as CCCH+SDCCH4+CBCH and TS1 as TCH/F */
Vadim Yanitskiyca974032020-09-01 07:20:39 +07009225 f_vty_enter_cfg_trx(BSCVTY, trx := 0);
9226
9227 f_vty_transceive(BSCVTY, "timeslot 0");
Vadim Yanitskiy8bc46012020-09-06 12:38:01 +07009228 f_vty_transceive(BSCVTY, "phys_chan_config ccch+sdcch4+cbch");
Vadim Yanitskiyca974032020-09-01 07:20:39 +07009229 f_vty_transceive(BSCVTY, "exit"); /* go back */
9230
9231 f_vty_transceive(BSCVTY, "timeslot 1");
9232 f_vty_transceive(BSCVTY, "phys_chan_config tch/f");
9233 f_vty_transceive(BSCVTY, "end"); /* we're done */
9234
Vadim Yanitskiy21726312020-09-04 01:45:36 +07009235 f_shutdown_helper();
Vadim Yanitskiyca974032020-09-01 07:20:39 +07009236}
9237
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02009238template (value) PDU_BSSAP_LE ts_BSSMAP_LE_BSSLAP(template (value) BSSLAP_PDU bsslap)
9239 := ts_BSSMAP_LE_ConnInfo(BSSMAP_LE_PROT_BSSLAP, data := enc_BSSLAP_PDU(valueof(bsslap)));
9240
9241private function f_match_bsslap(PDU_BSSAP_LE got_bsslap_msg,
9242 template (present) BSSLAP_PDU expect_bsslap)
9243{
9244 var BSSLAP_PDU bsslap := dec_BSSLAP_PDU(got_bsslap_msg.pdu.bssmap.co_info.bsslap_apdu.data);
9245 if (not match(bsslap, expect_bsslap)) {
9246 log("EXPECTING BSSLAP: ", expect_bsslap);
9247 log("GOT BSSLAP: ", bsslap);
9248 setverdict(fail, "BSSLAP is not as expected");
9249 mtc.stop;
9250 }
9251 setverdict(pass);
9252}
9253
9254/* GAD: this is an Ellipsoid point with uncertainty circle, encoded as in 3GPP TS 23.032 §7.3.2. */
9255const octetstring gad_ell_point_unc_circle := '10b0646d0d5f6627'O;
9256
9257private function f_expect_bsslap(template (present) BSSLAP_PDU expect_rx_bsslap) runs on MSC_ConnHdlr {
9258 var PDU_BSSAP_LE rx_bsslap;
9259 BSSAP_LE.receive(tr_BSSMAP_LE_ConnInfo(BSSMAP_LE_PROT_BSSLAP, ?)) -> value(rx_bsslap);
9260 f_match_bsslap(rx_bsslap, expect_rx_bsslap);
9261}
9262
9263/* With an active lchan, start BSSMAP Perform Location Request on A interface, starting BSSMAP-LE Perform Location
9264 * Request on Lb interface. Either with or without the SMLC doing a BSSLAP TA Request. */
9265private function f_lcs_loc_req_for_active_ms(boolean do_ta_request := false) runs on MSC_ConnHdlr {
9266 f_sleep(1.0);
9267
9268 f_establish_fully(omit, omit);
9269 f_bssap_le_register_imsi(g_pars.imsi, omit);
9270
9271 BSSAP.send(valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
9272 ts_CellId_CGI('262'H, '42'H, 23, 42))));
9273
9274 var PDU_BSSAP_LE plr;
9275 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?)) -> value(plr);
9276
9277 if (not do_ta_request) {
9278 /* verify TA Layer 3 in APDU. First the APDU type (BSSLAP), then the BSSLAP data contents. */
9279 var template BSSMAP_LE_IE_APDU expect_apdu := tr_BSSMAP_LE_APDU(BSSMAP_LE_PROT_BSSLAP, ?);
9280 if (not match(plr.pdu.bssmap.perf_loc_req.bsslap_apdu, expect_apdu)) {
9281 log("EXPECTING BSSMAP-LE APDU IE ", expect_apdu);
9282 log("GOT BSSMAP-LE APDU IE ", plr.pdu.bssmap.perf_loc_req.bsslap_apdu);
9283 setverdict(fail, "BSSMAP-LE APDU IE is not as expected");
9284 mtc.stop;
9285 }
9286 var template BSSLAP_PDU expect_ta_layer3 := tr_BSSLAP_TA_Layer3(tr_BSSLAP_IE_TA(0));
9287 var BSSLAP_PDU bsslap := dec_BSSLAP_PDU(plr.pdu.bssmap.perf_loc_req.bsslap_apdu.data);
9288 if (not match(bsslap, expect_ta_layer3)) {
9289 log("EXPECTING BSSLAP TA Layer 3: ", expect_ta_layer3);
9290 log("GOT BSSLAP: ", bsslap);
9291 setverdict(fail, "BSSLAP is not as expected");
9292 mtc.stop;
9293 }
9294 /* OsmoBSC directly sent the TA as BSSLAP APDU in the BSSMAP-LE Perform Location Request to the SMLC. The SMLC
9295 * has no need to request the TA from the BSC and directly responds. */
9296 } else {
9297 /* SMLC wants to ask the TA from the BSC explicitly in a BSSLAP TA Request message */
9298 BSSAP_LE.send(ts_BSSMAP_LE_BSSLAP(ts_BSSLAP_TA_Req));
9299 f_expect_bsslap(tr_BSSLAP_TA_Resp(?, ?));
9300 }
9301
9302 /* SMLC got the TA from the BSC, now responds with geo information data. */
9303 BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(gad_ell_point_unc_circle, omit));
9304 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
9305 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(tr_BSSMAP_IE_LocationEstimate(gad_ell_point_unc_circle)));
9306
9307 /* The LCS was using an active A-interface conn. It should still remain active after this. */
9308 f_mo_l3_transceive();
9309
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02009310 f_perform_clear();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02009311
9312 f_sleep(2.0);
9313 setverdict(pass);
9314}
9315
9316/* With an active lchan, start BSSMAP Perform Location Request on A interface, starting BSSMAP-LE Perform Location
9317 * Request on Lb interface. Without the SMLC doing a BSSLAP TA Request. */
9318private function f_tc_lcs_loc_req_for_active_ms(charstring id) runs on MSC_ConnHdlr {
9319 f_lcs_loc_req_for_active_ms(false);
9320}
9321testcase TC_lcs_loc_req_for_active_ms() runs on test_CT {
9322 var MSC_ConnHdlr vc_conn;
9323 var TestHdlrParams pars := f_gen_test_hdlr_pars();
9324
9325 f_init(1, true);
9326 f_sleep(1.0);
9327 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_for_active_ms), pars);
9328 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +01009329 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02009330}
9331
9332/* With an active lchan, start BSSMAP Perform Location Request on A interface, starting BSSMAP-LE Perform Location
9333 * Request on Lb interface. With the SMLC doing a BSSLAP TA Request. */
9334private function f_tc_lcs_loc_req_for_active_ms_ta_req(charstring id) runs on MSC_ConnHdlr {
9335 f_lcs_loc_req_for_active_ms(true);
9336}
9337testcase TC_lcs_loc_req_for_active_ms_ta_req() runs on test_CT {
9338 var MSC_ConnHdlr vc_conn;
9339 var TestHdlrParams pars := f_gen_test_hdlr_pars();
9340
9341 f_init(1, true);
9342 f_sleep(1.0);
9343 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_for_active_ms_ta_req), pars);
9344 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +01009345 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02009346}
9347
9348/* Clear the A-interface conn only, without doing anything on Abis. Useful for LCS, for cases where there is only an A
9349 * conn without an active lchan. */
9350private function f_clear_A_conn() runs on MSC_ConnHdlr
9351{
9352 var BssmapCause cause := 0;
9353 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
9354 BSSAP.receive(tr_BSSMAP_ClearComplete);
9355 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
9356
9357 timer no_more_bssap := 5.0;
9358 no_more_bssap.start;
9359 alt {
9360 [] no_more_bssap.timeout { break; }
9361 [] BSSAP.receive(tr_BSSAP_BSSMAP) {
9362 setverdict(fail, "Expected no more BSSAP after Clear Complete");
9363 mtc.stop;
9364 }
9365 }
9366 setverdict(pass);
9367}
9368
9369/* Verify that the A-interface connection is still working, and then clear it, without doing anything on Abis. Useful
9370 * for LCS, for cases where there is only an A conn without an active lchan. */
9371private function f_verify_active_A_conn_and_clear() runs on MSC_ConnHdlr
9372{
9373 f_logp(BSCVTY, "f_verify_active_A_conn_and_clear: test A link, then clear");
9374
9375 /* When an lchan is active, we can send some L3 data from the BTS side and verify that it shows up on the other
9376 * side towards the MSC. When there is no lchan, this is not possible. To probe whether the A-interface
9377 * connection is still up, we need something that echos back on the A-interface. Another LCS request! */
9378 BSSAP.send(valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
9379 ts_CellId_CGI('262'H, '42'H, 23, 42))));
9380 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?));
9381
9382 /* Right, the Perform Location Request showed up on Lb, now we can clear the A conn. */
9383 f_clear_A_conn();
9384 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocAbort(BSSMAP_LE_LCS_CAUSE_REQUEST_ABORTED));
9385 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
9386}
9387
9388/* With *no* active lchan, start BSSMAP Perform Location Request on A interface, starting BSSMAP-LE Perform Location
9389 * Request on Lb interface. BSC will Page for the subscriber as soon as we (virtual SMLC) request the TA via BSSLAP.
9390 */
9391private function f_tc_lcs_loc_req_for_idle_ms(charstring id) runs on MSC_ConnHdlr {
9392 f_sleep(1.0);
9393
9394 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
9395 f_bssap_le_register_imsi(g_pars.imsi, omit);
9396
9397 /* Register to receive the Paging Command */
9398 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
9399 g_chan_nr := new_chan_nr;
9400 f_rslem_register(0, g_chan_nr);
9401
9402 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
9403 valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
9404 ts_CellId_CGI('001'H, '01'H, 1, 0)))));
9405 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
9406
9407 var PDU_BSSAP_LE plr;
9408 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?)) -> value(plr);
9409
9410 /* SMLC wants to ask the TA from the BSC explicitly in a BSSLAP TA Request message */
9411 BSSAP_LE.send(ts_BSSMAP_LE_BSSLAP(ts_BSSLAP_TA_Req));
9412
9413 /* OsmoBSC needs to Page */
9414 RSL.receive(tr_RSL_PAGING_CMD(tr_MI_IMSI(g_pars.imsi)));
9415 f_logp(BSCVTY, "got Paging Command");
9416
9417 /* MS requests channel. Since the Paging was for LCS, the Paging Response does not trigger a Complete Layer 3 to
9418 * the MSC, and releases the lchan directly. */
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02009419 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);
9420 f_expect_lchan_rel(RSL, RSL_PROC);
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02009421
9422 /* From the Paging Response, the TA is now known to the BSC, and it responds to the SMLC. */
9423
9424 f_expect_bsslap(tr_BSSLAP_TA_Resp(?, ?));
9425
9426 /* SMLC got the TA from the BSC, now responds with geo information data. */
9427 BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(gad_ell_point_unc_circle, omit));
9428 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
9429
9430 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(tr_BSSMAP_IE_LocationEstimate(gad_ell_point_unc_circle)));
9431
9432 /* The lchan is gone, the A-interface conn was created for the LCS only.
9433 * Still it is clearly the MSC's job to decide whether to tear down the conn or not. */
9434 f_verify_active_A_conn_and_clear();
9435
9436 f_sleep(2.0);
9437 setverdict(pass);
9438}
9439testcase TC_lcs_loc_req_for_idle_ms() runs on test_CT {
9440 var MSC_ConnHdlr vc_conn;
9441 var TestHdlrParams pars := f_gen_test_hdlr_pars();
9442
9443 f_init(1, true);
9444 f_sleep(1.0);
9445
9446 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
9447 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
9448
9449 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_for_idle_ms), pars);
9450 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +01009451 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02009452}
9453
9454/* With no active lchan, start BSSMAP Perform Location Request on A interface, but omit IMSI; expect failure response.
9455 */
9456private function f_tc_lcs_loc_req_no_subscriber(charstring id) runs on MSC_ConnHdlr {
9457 f_sleep(1.0);
9458
9459 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
9460 f_bssap_le_register_imsi(g_pars.imsi, omit);
9461
9462 /* provoke an abort by omitting both IMSI and IMEI */
9463 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
9464 valueof(ts_BSSMAP_Perform_Location_Request(omit,
9465 ts_CellId_CGI('262'H, '42'H, 23, 42)))));
9466 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
9467
9468 /* BSC tells MSC about failure */
9469 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(
9470 locationEstimate := omit, positioningData := omit,
9471 lCS_Cause := tr_BSSMAP_LcsCause(BSSMAP_LCS_CAUSE_DATA_MISSING_IN_REQ)));
9472
9473 /* There is no lchan. Still the MSC's job to decide whether to tear down the conn or not. */
9474 f_verify_active_A_conn_and_clear();
9475
9476 f_sleep(2.0);
9477 setverdict(pass);
9478}
9479testcase TC_lcs_loc_req_no_subscriber() runs on test_CT {
9480 var MSC_ConnHdlr vc_conn;
9481 var TestHdlrParams pars := f_gen_test_hdlr_pars();
9482
9483 f_init(1, true);
9484 f_sleep(1.0);
9485
9486 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
9487 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
9488
9489 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_no_subscriber), pars);
9490 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +01009491 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02009492}
9493
9494/* With an active lchan, start a Perform Location Request on the A-interface, but virtual SMLC does not answer with
9495 * BSSMAP-LE Perform Location Response (before or after sending a BSSLAP TA Request) */
9496private function f_lcs_loc_req_for_active_ms_le_timeout(boolean do_ta) runs on MSC_ConnHdlr {
9497 f_sleep(1.0);
9498
9499 f_establish_fully(omit, omit);
9500 f_bssap_le_register_imsi(g_pars.imsi, omit);
9501
9502 BSSAP.send(valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
9503 ts_CellId_CGI('262'H, '42'H, 23, 42))));
9504
9505 var PDU_BSSAP_LE plr;
9506 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?)) -> value(plr);
9507
9508 if (do_ta) {
9509 /* SMLC wants to ask the TA from the BSC explicitly in a BSSLAP TA Request message */
9510 BSSAP_LE.send(ts_BSSMAP_LE_BSSLAP(ts_BSSLAP_TA_Req));
9511 f_expect_bsslap(tr_BSSLAP_TA_Resp(?, ?));
9512 }
9513
9514 /* SMLC fails to respond, BSC runs into timeout */
9515 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocAbort(BSSMAP_LE_LCS_CAUSE_SYSTEM_FAILURE));
9516 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
9517
9518 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(
9519 locationEstimate := omit, positioningData := omit,
9520 lCS_Cause := tr_BSSMAP_LcsCause(BSSMAP_LCS_CAUSE_SYSTEM_FAILURE)));
9521
9522 /* There is no lchan. Still the MSC's job to decide whether to tear down the conn or not. */
9523 f_verify_active_A_conn_and_clear();
9524
9525 f_sleep(2.0);
9526 setverdict(pass);
9527}
9528
9529/* With an active lchan, start a Perform Location Request on the A-interface, but virtual SMLC does not answer with
9530 * BSSMAP-LE Perform Location Response, without sending a BSSLAP TA Request. */
9531private function f_tc_lcs_loc_req_for_active_ms_le_timeout(charstring id) runs on MSC_ConnHdlr {
9532 f_lcs_loc_req_for_active_ms_le_timeout(false);
9533}
9534
9535testcase TC_lcs_loc_req_for_active_ms_le_timeout() runs on test_CT {
9536 var MSC_ConnHdlr vc_conn;
9537 var TestHdlrParams pars := f_gen_test_hdlr_pars();
9538
9539 f_init(1, true);
9540 f_sleep(1.0);
9541 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_for_active_ms_le_timeout), pars);
9542 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +01009543 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02009544}
9545
9546/* With an active lchan, start a Perform Location Request on the A-interface, but virtual SMLC does not answer with
9547 * BSSMAP-LE Perform Location Response, after sending a BSSLAP TA Request. */
9548private function f_tc_lcs_loc_req_for_active_ms_le_timeout2(charstring id) runs on MSC_ConnHdlr {
9549 f_lcs_loc_req_for_active_ms_le_timeout(true);
9550}
9551
9552testcase TC_lcs_loc_req_for_active_ms_le_timeout2() runs on test_CT {
9553 var MSC_ConnHdlr vc_conn;
9554 var TestHdlrParams pars := f_gen_test_hdlr_pars();
9555
9556 f_init(1, true);
9557 f_sleep(1.0);
9558 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_for_active_ms_le_timeout2), pars);
9559 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +01009560 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02009561}
9562
9563/* With *no* active lchan, start a Perform Location Request, expecting that the MS will be Paged. */
9564private function f_tc_lcs_loc_req_for_idle_ms_no_pag_resp(charstring id) runs on MSC_ConnHdlr {
9565 f_sleep(1.0);
9566
9567 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
9568 f_bssap_le_register_imsi(g_pars.imsi, omit);
9569
9570 /* Register to receive the Paging Command */
9571 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
9572 g_chan_nr := new_chan_nr;
9573 f_rslem_register(0, g_chan_nr);
9574
9575 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
9576 valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
9577 ts_CellId_CGI('001'H, '01'H, 1, 0)))));
9578 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
9579
9580 var PDU_BSSAP_LE plr;
9581 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?)) -> value(plr);
9582
9583 /* SMLC wants to ask the TA from the BSC explicitly in a BSSLAP TA Request message */
9584 BSSAP_LE.send(ts_BSSMAP_LE_BSSLAP(ts_BSSLAP_TA_Req));
9585
9586 /* OsmoBSC needs to Page */
9587 var PDU_BSSAP_LE rx_bsslap;
9588 alt {
9589 [] RSL.receive(tr_RSL_PAGING_CMD(tr_MI_IMSI(g_pars.imsi))) {
9590 f_logp(BSCVTY, "got Paging Command");
9591 repeat;
9592 }
9593 [] BSSAP_LE.receive(tr_BSSMAP_LE_ConnInfo(BSSMAP_LE_PROT_BSSLAP, ?)) -> value(rx_bsslap) {
9594 /* MS does not respond to Paging, TA Req runs into timeout. */
9595 f_match_bsslap(rx_bsslap, tr_BSSLAP_Abort(?));
9596 }
9597 }
9598
9599 /* SMLC responds with failure */
9600 BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(omit, BSSMAP_LE_LCS_CAUSE_REQUEST_ABORTED));
9601 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
9602
9603 /* BSC tells MSC about failure */
9604 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(
9605 locationEstimate := omit, positioningData := omit,
9606 lCS_Cause := tr_BSSMAP_LcsCause(BSSMAP_LCS_CAUSE_REQUEST_ABORTED)));
9607
9608 /* There is no lchan. Still the MSC's job to decide whether to tear down the conn or not. */
9609 f_verify_active_A_conn_and_clear();
9610
9611 f_sleep(2.0);
9612 setverdict(pass);
9613}
9614testcase TC_lcs_loc_req_for_idle_ms_no_pag_resp() runs on test_CT {
9615 var MSC_ConnHdlr vc_conn;
9616 var TestHdlrParams pars := f_gen_test_hdlr_pars();
9617
9618 f_init(1, true);
9619 f_sleep(1.0);
9620
9621 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
9622 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
9623
9624 vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_for_idle_ms_no_pag_resp), pars);
9625 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +01009626 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02009627}
9628
9629/* During an ongoing Location Request, the MS sends a CM Service Request. Expect the same A-conn to be re-used / taken
9630 * over. */
9631private function f_tc_cm_service_during_lcs_loc_req(charstring id) runs on MSC_ConnHdlr {
9632 f_sleep(1.0);
9633
9634 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
9635 f_bssap_le_register_imsi(g_pars.imsi, omit);
9636
9637 /* Register to receive the Paging Command */
9638 var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
9639 g_chan_nr := new_chan_nr;
9640 f_rslem_register(0, g_chan_nr);
9641
9642 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
9643 valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
9644 ts_CellId_CGI('001'H, '01'H, 1, 0)))));
9645 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
9646
9647 var PDU_BSSAP_LE plr;
9648 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?)) -> value(plr);
9649
9650 /* As the A-interface conn was established for LCS, the MS coincidentally decides to issue a CM Service Request
9651 * and establish Layer 3. It should use the existing A-interface conn. */
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02009652 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 +02009653 do_clear := false, expect_bssmap_l3 := true);
9654
9655 /* SMLC wants to ask the TA from the BSC explicitly in a BSSLAP TA Request message */
9656 BSSAP_LE.send(ts_BSSMAP_LE_BSSLAP(ts_BSSLAP_TA_Req));
9657
9658 /* OsmoBSC already has an lchan, no need to Page, just returns the TA */
9659 f_expect_bsslap(tr_BSSLAP_TA_Resp(?, ?));
9660
9661 /* SMLC got the TA from the BSC, now responds with geo information data. */
9662 BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(gad_ell_point_unc_circle, omit));
9663 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
9664 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(tr_BSSMAP_IE_LocationEstimate(gad_ell_point_unc_circle)));
9665
9666 /* The lchan should still exist, it was from a CM Service Request. */
9667 f_mo_l3_transceive();
9668
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02009669 f_perform_clear();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02009670
9671 f_sleep(2.0);
9672 setverdict(pass);
9673}
9674testcase TC_cm_service_during_lcs_loc_req() runs on test_CT {
9675 var MSC_ConnHdlr vc_conn;
9676 var TestHdlrParams pars := f_gen_test_hdlr_pars();
9677
9678 f_init(1, true);
9679 f_sleep(1.0);
9680
9681 pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
9682 pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
9683
9684 vc_conn := f_start_handler(refers(f_tc_cm_service_during_lcs_loc_req), pars);
9685 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +01009686 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02009687}
9688
9689/* During an ongoing Perform Location Request, do a Handover, an expect a BSSLAP Reset message from the BSC to indicate
9690 * the new lchan after handover. */
9691private function f_tc_ho_during_lcs_loc_req(charstring id) runs on MSC_ConnHdlr {
9692 f_sleep(1.0);
9693
9694 f_establish_fully(omit, omit);
9695 f_bssap_le_register_imsi(g_pars.imsi, omit);
9696
9697 BSSAP.send(valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
9698 ts_CellId_CGI('262'H, '42'H, 23, 42))));
9699
9700 var PDU_BSSAP_LE plr;
9701 BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?)) -> value(plr);
9702
9703 /* SMLC ponders the Location Request, in the meantime the BSC decides to handover */
9704 f_bts_0_cfg(BSCVTY, {"neighbor bts 1"});
9705
9706 var HandoverState hs := {
9707 rr_ho_cmpl_seen := false,
9708 handover_done := false,
Neels Hofmeyrc741fcb2021-10-02 14:52:28 +02009709 old_chan_nr := -,
9710 expect_target_tsc := BTS_TSC[1]
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02009711 };
9712 /* issue hand-over command on VTY */
9713 f_vty_handover(BSCVTY, 0, 0, g_chan_nr, 1);
9714 /* temporarily suspend DChan processing on BTS1 to avoid race with RSLEM_register */
9715 f_rslem_suspend(RSL1_PROC);
9716
9717 /* From the MGW perspective, a handover is is characterized by
9718 * performing one MDCX operation with the MGW. So we expect to see
9719 * one more MDCX during handover. */
9720 g_media.mgcp_conn[0].mdcx_seen_exp := g_media.mgcp_conn[0].crcx_seen_exp + 1;
9721
9722 alt {
9723 [] as_handover(hs);
9724 }
9725
9726 var PDU_BSSAP_LE rx_bsslap;
9727
9728 interleave {
9729 /* Expect the BSC to inform the MSC about the handover */
9730 [] BSSAP.receive(tr_BSSMAP_HandoverPerformed);
9731
9732 /* Expect the BSC to inform the SMLC about the handover */
9733 [] BSSAP_LE.receive(tr_BSSMAP_LE_ConnInfo(BSSMAP_LE_PROT_BSSLAP, ?)) -> value(rx_bsslap) {
9734 f_match_bsslap(rx_bsslap, tr_BSSLAP_Reset(BSSLAP_CAUSE_INTRA_BSS_HO));
9735 }
9736 }
9737
9738 /* SMLC now responds with geo information data. */
9739 BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(gad_ell_point_unc_circle, omit));
9740 BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
9741 BSSAP.receive(tr_BSSMAP_Perform_Location_Response(tr_BSSMAP_IE_LocationEstimate(gad_ell_point_unc_circle)));
9742
9743 /* lchan still active */
9744 f_mo_l3_transceive(RSL1);
9745
9746 /* MSC decides it is done now. */
Neels Hofmeyr85bcd272021-07-22 19:14:48 +02009747 f_perform_clear(RSL1, RSL1_PROC);
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02009748
9749 f_sleep(2.0);
9750 setverdict(pass);
9751}
9752testcase TC_ho_during_lcs_loc_req() runs on test_CT {
9753 var MSC_ConnHdlr vc_conn;
9754 var TestHdlrParams pars := f_gen_test_hdlr_pars();
9755
9756 f_init(2, true);
9757 f_sleep(1.0);
9758 vc_conn := f_start_handler(refers(f_tc_ho_during_lcs_loc_req), pars);
9759 vc_conn.done;
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +01009760 f_shutdown_helper();
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +02009761}
9762
Neels Hofmeyrbf037052020-10-28 22:52:02 +00009763/* Attempt Complete Layer 3 without any MSC available (OS#4832) */
9764private function f_tc_no_msc(charstring id) runs on MSC_ConnHdlr {
9765 f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
9766
9767 /* Also disable attach for the single connected MSC */
9768 f_vty_msc_allow_attach(BSCVTY, { false });
9769
9770 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) ));
9771 f_chan_est(g_pars.ra, l3_enc, g_pars.link_id, g_pars.fn);
9772
9773 /* No MSC is found, expecting a proper release on RSL */
9774 interleave {
9775 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_RELEASE)) {
9776 f_logp(BSCVTY, "Got RSL RR Release");
9777 }
9778 [] RSL.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {
9779 f_logp(BSCVTY, "Got RSL Deact SACCH");
9780 }
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +02009781 [] RSL.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
Neels Hofmeyrbf037052020-10-28 22:52:02 +00009782 f_logp(BSCVTY, "Got RSL RF Chan Rel, sending Rel Ack");
9783 RSL.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
Neels Hofmeyre680b012021-07-22 19:19:09 +02009784 f_rslem_unregister(0, g_chan_nr);
Neels Hofmeyrbf037052020-10-28 22:52:02 +00009785 }
9786 }
9787 setverdict(pass);
9788}
9789testcase TC_no_msc() runs on test_CT {
9790
9791 f_init(1, true);
9792 f_sleep(1.0);
9793 var MSC_ConnHdlr vc_conn;
9794 var TestHdlrParams pars := f_gen_test_hdlr_pars();
9795
9796 f_ctrs_bsc_init(counternames_bsc_mscpool);
9797
9798 vc_conn := f_start_handler(refers(f_tc_no_msc), pars);
9799 vc_conn.done;
9800
9801 f_ctrs_bsc_add("mscpool:subscr:no_msc");
9802 f_ctrs_bsc_verify();
Vadim Yanitskiy8ca840e2021-01-03 14:16:35 +01009803 f_shutdown_helper();
Neels Hofmeyrbf037052020-10-28 22:52:02 +00009804}
9805
Harald Welte0ea2d5e2018-04-07 21:40:29 +02009806/* Dyn PDCH todo:
9807 * activate OSMO as TCH/F
9808 * activate OSMO as TCH/H
9809 * does the BSC-located PCU socket get the updated INFO?
9810 * what if no PCU is connected at the time?
9811 * is the info correct on delayed PCU (re)connect?
9812 */
Harald Welte94e0c342018-04-07 11:33:23 +02009813
Neels Hofmeyr87857ec2021-04-25 16:17:47 +00009814private function f_TC_refuse_mode_modif_to_vamos(charstring id) runs on MSC_ConnHdlr {
9815 var PDU_BSSAP ass_cmd := f_gen_ass_req(g_pars.use_osmux);
9816 var template PDU_BSSAP exp_compl := f_gen_exp_compl(g_pars.use_osmux);
9817
9818 /* puzzle together the ASSIGNMENT REQ for given codec[s] */
9819 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
9820 ass_cmd.pdu.bssmap.assignmentRequest.codecList := g_pars.ass_codec_list;
9821 exp_compl.pdu.bssmap.assignmentComplete.speechCodec.codecElements[0] :=
9822 g_pars.ass_codec_list.codecElements[0];
9823 if (isvalue(g_pars.expect_mr_s0_s7)) {
9824 exp_compl.pdu.bssmap.assignmentComplete.speechCodec.codecElements[0].s0_7 :=
9825 g_pars.expect_mr_s0_s7;
9826 }
9827 }
9828 ass_cmd.pdu.bssmap.assignmentRequest.channelType :=
9829 f_BSSMAP_chtype_from_codec(g_pars.ass_codec_list.codecElements[0]);
9830 log("expecting ASS COMPL like this: ", exp_compl);
9831
9832 f_establish_fully(ass_cmd, exp_compl);
9833
Neels Hofmeyr8746b0d2021-06-01 17:25:39 +02009834 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 +00009835
9836 var RSL_Message rsl;
9837
9838 timer T := 5.0;
9839 T.start;
9840 alt {
9841 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr)) -> value rsl {
9842 var PDU_ML3_NW_MS l3 := dec_PDU_ML3_NW_MS(rsl.ies[2].body.l3_info.payload);
9843 log("Rx L3 from net: ", l3);
9844 if (ischosen(l3.msgs.rrm.channelModeModify)) {
9845 setverdict(fail, "Mode Modify to VAMOS succeeded even though BTS does not support VAMOS");
9846 mtc.stop;
9847 }
9848 }
9849 [] RSL.receive(tr_RSL_MODE_MODIFY_REQ(g_chan_nr, ?)) -> value rsl {
9850 setverdict(fail, "Mode Modify to VAMOS succeeded even though BTS does not support VAMOS");
9851 mtc.stop;
9852 }
9853 [] T.timeout {
9854 /* The BTS does not exhibit BTS_FEAT_VAMOS, so no VAMOS related Mode Modify should happen. */
9855 setverdict(pass);
9856 }
9857 }
9858 T.stop;
9859}
9860
9861/* The BSC does *not* indicate BTS_FEAT_VAMOS; make sure that a channel Mode Modify to VAMOS mode is refused by
9862 * osmo-bsc. */
9863testcase TC_refuse_mode_modif_to_vamos() runs on test_CT {
9864 var TestHdlrParams pars := f_gen_test_hdlr_pars();
9865 var MSC_ConnHdlr vc_conn;
9866
9867 f_init(1, true);
9868 f_sleep(1.0);
9869
9870 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
9871 vc_conn := f_start_handler(refers(f_TC_refuse_mode_modif_to_vamos), pars);
9872 vc_conn.done;
9873 f_shutdown_helper();
9874}
9875
9876/* The BSC does *not* indicate BTS_FEAT_VAMOS; make sure that a channel activation to VAMOS mode is refused by osmo-bsc.
9877 */
9878testcase TC_refuse_chan_act_to_vamos() runs on test_CT {
9879 f_init_vty();
9880
9881 f_init(1, false);
9882 f_sleep(1.0);
9883
9884 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 1 sub-slot 0 activate-vamos fr");
9885
9886 var ASP_RSL_Unitdata rx_rsl_ud;
9887 timer T := 5.0;
9888
9889 T.start;
9890 alt {
9891 [] IPA_RSL[0].receive(tr_ASP_RSL_UD(?, IPAC_PROTO_RSL_TRX0)) -> value rx_rsl_ud {
9892 if (rx_rsl_ud.rsl.msg_type == RSL_MT_CHAN_ACTIV) {
9893 T.stop;
9894 setverdict(fail, "CHANnel ACTivate in VAMOS mode succeeded even though BTS does not support VAMOS");
9895 mtc.stop;
9896 }
9897 repeat;
9898 }
9899 [] T.timeout {
9900 /* The BTS does not exhibit BTS_FEAT_VAMOS, so no VAMOS related CHANnel ACTivate should happen. */
9901 setverdict(pass);
9902 }
9903 }
9904}
9905
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +00009906private function f_TC_reassignment_codec(charstring id) runs on MSC_ConnHdlr {
9907 /* First fully set up a speech lchan */
9908 f_TC_assignment_codec(id);
9909
9910 /* Trigger re-assignment to another lchan */
9911 var AssignmentState assignment_st := valueof(ts_AssignmentStateInit);
9912
9913 /* Re-Assignment should tell the MGW endpoint the new lchan's RTP address and port, so expecting to see exactly
9914 * one MDCX on MGCP. */
9915 g_media.mgcp_conn[0].mdcx_seen_exp := g_media.mgcp_conn[0].mdcx_seen_exp + 1;
9916
9917 /* The new lchan will see all-new IPAC_CRCX and IPAC_MDCX messages telling the BTS the same RTP address and port
9918 * as the old lchan used. */
9919 g_media.bts.ipa_crcx_seen := false;
9920 g_media.bts.ipa_mdcx_seen := false;
9921
9922 /* Send different BTS side RTP port number for the new lchan */
9923 g_media.bts.bts.port_nr := 4223;
9924
9925 f_rslem_register(0, valueof(ts_RslChanNr_Bm(2))); /* <-- FIXME: can we somehow infer the timeslot that will be used? */
9926
9927 /* Trigger re-assignment. */
9928 f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot " & int2str(g_chan_nr.tn) & " sub-slot 0 assignment");
9929
9930 timer T := 5.0;
9931 T.start;
9932 alt {
9933 [] as_assignment(assignment_st);
9934 [] as_Media();
9935 [] T.timeout {
9936 break;
9937 }
9938 }
9939
9940 if (not assignment_st.assignment_done) {
9941 setverdict(fail, "Assignment did not complete");
9942 mtc.stop;
9943 }
9944
9945 f_check_mgcp_expectations()
9946 setverdict(pass);
9947
9948 f_sleep(2.0);
9949 log("show lchan summary: ", f_vty_transceive_ret(BSCVTY, "show lchan summary"));
9950
9951 /* Instruct BSC to clear channel */
9952 var BssmapCause cause := 0;
9953 BSSAP.send(ts_BSSMAP_ClearCommand(cause));
9954 interleave {
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +00009955 [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_RELEASE)) {}
9956 [] RSL.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {}
Neels Hofmeyr3c5127e2021-07-22 19:18:40 +02009957 [] RSL.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +00009958 RSL.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
Neels Hofmeyre680b012021-07-22 19:19:09 +02009959 f_rslem_unregister(0, g_chan_nr);
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +00009960 }
9961 [] BSSAP.receive(tr_BSSMAP_ClearComplete) {
9962 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
9963 }
9964 }
Neels Hofmeyr40a45d12021-09-23 22:57:12 +02009965 f_expect_dlcx_conns();
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +00009966
9967 f_sleep(0.5);
9968}
9969
9970testcase TC_reassignment_fr() runs on test_CT {
9971 var TestHdlrParams pars := f_gen_test_hdlr_pars();
9972 var MSC_ConnHdlr vc_conn;
9973
9974 f_init(1, true);
9975 f_sleep(1.0);
9976
Neels Hofmeyrac432fa2021-11-02 16:45:56 +01009977 f_ctrs_bsc_and_bts_handover_init();
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +00009978
9979 pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
9980 vc_conn := f_start_handler(refers(f_TC_reassignment_codec), pars);
9981 vc_conn.done;
9982
9983 /* from f_establish_fully() */
9984 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
9985 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
9986 /* from re-assignment */
9987 f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
9988 f_ctrs_bsc_and_bts_add(0, "assignment:completed");
9989 f_ctrs_bsc_and_bts_verify();
9990 f_shutdown_helper();
9991}
9992
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +02009993const charstring REEST_LOST_CONNECTION := "REEST_LOST_CONNECTION";
9994const charstring REEST_CLEAR := "REEST_CLEAR";
9995const charstring REEST_CLEAR_DONE := "REEST_CLEAR_DONE";
9996
9997/* CM Re-Establishment, 3GPP TS 24.008 4.5.1.6.
9998 * The MS <-> BTS loses radio connection, MS shows up on second BTS and asks for CM Re-Establishment.
9999 * BSC should establish a separate A conn for the same MS, the original A conn is then cleared by
10000 * the MSC as the CM Re-Establishment is handled.
10001 *
10002 * MS bts0 bts1 bsc msc test-component
10003 * |<----->|<----------------->|<-0-->| _1 Establish channel on bts 0
10004 * | | _1 wait a bit, to settle down
10005 * |<-x x--| | _1 "lose connection"
10006 * | | REEST_LOST_CONNECTION
10007 * |----------------->|------->|--1-->| _2 new A-conn: Chan Rqd, Imm Ass, Compl L3 with CM Re-Establishment Req
10008 * | | REEST_CLEAR
10009 * | |<-0---| _1 Clear Command on first A-conn
10010 * | |--0-->| _1 Clear Complete
10011 * | |<----------------->| | _1 Release first channel
10012 * | | REEST_CLEAR_DONE
10013 * |<-----------------|<-------|<-1---| _2 Chan Activ, Assignment Command
10014 * |<-----------------|<-------|<-1---| _2 Clear Command, Release
10015 *
10016 */
10017private function f_tc_cm_reestablishment_1(charstring id) runs on MSC_ConnHdlr {
10018 var template PDU_BSSAP exp_compl := f_gen_exp_compl();
10019 var PDU_BSSAP ass_cmd := f_gen_ass_req();
10020
10021 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
10022 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
10023
10024 f_establish_fully(ass_cmd, exp_compl);
10025
10026 /* The original channel loses connection, MS attemts CM Re-Establishment on another cell, see
10027 * f_tc_cm_reestablishment_2(). This established channel stays active until MSC sends a Clear Command. The time
10028 * when exactly that happens is determined by f_tc_cm_reestablishment_2(). */
10029 f_sleep(2.0);
10030 COORD.send(REEST_LOST_CONNECTION);
10031
10032 alt {
10033 [] COORD.receive(REEST_CLEAR);
10034 [] RSL.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {
10035 setverdict(fail, "Unexpected channel release");
10036 mtc.stop;
10037 }
10038 [] RSL.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
10039 setverdict(fail, "Unexpected channel release");
10040 mtc.stop;
10041 }
10042 }
10043 f_perform_clear()
10044 f_expect_dlcx_conns();
Neels Hofmeyr969abd02021-09-23 22:24:08 +020010045 f_create_mgcp_delete_ep(g_media.mgcp_ep);
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020010046 COORD.send(REEST_CLEAR_DONE);
10047}
10048
10049private function f_tc_cm_reestablishment_2(charstring id) runs on MSC_ConnHdlr {
10050 f_MscConnHdlr_init(g_pars.media_nr, host_bts, host_mgw_mgcp, FR_AMR);
10051
10052 /* The MS lost the connection on the first channel, now establishes another one */
10053 COORD.receive(REEST_LOST_CONNECTION);
10054
10055 var MobileIdentityLV mi := valueof(ts_MI_IMSI_LV(g_pars.imsi));
10056 var PDU_ML3_MS_NW l3_info := valueof(ts_CM_REESTABL_REQ(mi));
10057 var octetstring l3_enc := enc_PDU_ML3_MS_NW(l3_info);
10058
10059 f_create_bssmap_exp(l3_enc);
Neels Hofmeyrc7b1f6d2021-07-20 23:21:36 +020010060 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 +020010061 BSSAP.receive(tr_BSSMAP_ComplL3(l3_enc));
10062
10063 /* MSC got the CM Re-Establishment request and first off clears the previous conn. */
10064 COORD.send(REEST_CLEAR);
10065 COORD.receive(REEST_CLEAR_DONE);
10066
10067 f_sleep(2.0);
10068
10069 /* Answer the CM Re-Establishment with an Assignment Command. */
10070 var template PDU_BSSAP expect_assignment_compl := f_gen_exp_compl();
10071 var PDU_BSSAP ass_cmd := f_gen_ass_req();
10072 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
10073 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
10074
10075 var AssignmentState st := valueof(ts_AssignmentStateInit);
10076 st.voice_call := true;
10077 st.is_assignment := true;
10078
10079 var ExpectCriteria mgcpcrit := {
10080 connid := omit,
10081 endpoint := omit,
10082 transid := omit
10083 };
10084 f_create_mgcp_expect(mgcpcrit);
10085
Neels Hofmeyrc7b1f6d2021-07-20 23:21:36 +020010086 f_rslem_dchan_queue_enable(RSL1_PROC);
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020010087
10088 BSSAP.send(ass_cmd);
10089
10090 var PDU_BSSAP bssap;
10091
10092 alt {
Neels Hofmeyrc7b1f6d2021-07-20 23:21:36 +020010093 [] as_assignment(st, rsl_pt := RSL1, rsl_proc_pt := RSL1_PROC);
10094 [] as_Media_ipacc(RSL1, RSL2);
10095 [] as_Media_mgw();
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020010096 [st.assignment_done] BSSAP.receive(expect_assignment_compl) {
10097 break;
10098 }
10099 }
10100
10101 f_sleep(3.0);
10102
10103 f_logp(BSCVTY, "f_tc_cm_reestablishment_2 clearing");
Neels Hofmeyrc7b1f6d2021-07-20 23:21:36 +020010104 f_perform_clear(RSL1, RSL1_PROC);
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020010105 f_expect_dlcx_conns();
10106}
10107
10108testcase TC_cm_reestablishment() runs on test_CT {
10109 var TestHdlrParams pars1 := f_gen_test_hdlr_pars();
10110 var MSC_ConnHdlr vc_conn1;
10111
10112 var TestHdlrParams pars2 := f_gen_test_hdlr_pars();
10113 var MSC_ConnHdlr vc_conn2;
10114 pars2.imsi := pars1.imsi;
10115 pars2.media_nr := 2;
Neels Hofmeyrbf720202021-10-02 12:58:24 +020010116 pars2.expect_tsc := BTS_TSC[1];
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020010117
10118 f_init(2, true, guard_timeout := 40.0);
10119 f_sleep(1.0);
10120
10121 vc_conn1 := f_start_handler_create(pars1);
10122 vc_conn2 := f_start_handler_create(pars2);
10123 connect(vc_conn1:COORD, vc_conn2:COORD);
10124 f_start_handler_run(vc_conn1, refers(f_tc_cm_reestablishment_1), pars1);
10125 f_start_handler_run(vc_conn2, refers(f_tc_cm_reestablishment_2), pars2);
10126 vc_conn1.done;
10127 vc_conn2.done;
10128
10129 f_shutdown_helper();
10130}
Neels Hofmeyr87857ec2021-04-25 16:17:47 +000010131
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020010132function f_exp_ipa_rx_nonfatal(integer bts_nr, template (present) RSL_Message t_rx, float t_secs := 2.0,
10133 IpaStreamId sid := IPAC_PROTO_RSL_TRX0, boolean ignore_other_rx := true)
10134runs on test_CT return template (omit) RSL_Message {
10135 var ASP_RSL_Unitdata rx_rsl_ud;
10136 timer T := t_secs;
10137
10138 T.start;
10139 alt {
10140 [] IPA_RSL[bts_nr].receive(tr_ASP_RSL_UD(t_rx, sid)) -> value rx_rsl_ud {
10141 T.stop;
10142 }
10143 [ignore_other_rx] IPA_RSL[bts_nr].receive { repeat; }
10144 [not ignore_other_rx] IPA_RSL[bts_nr].receive {
10145 log("f_exp_ipa_rx_nonfatal(): Got different message than ", t_rx);
10146 T.stop;
10147 return omit;
10148 }
10149 [] T.timeout {
10150 return omit;
10151 }
10152 }
10153 return rx_rsl_ud.rsl;
10154}
10155
10156private function f_vty_set_imm_ass(TELNETasp_PT pt, BtsNr bts_nr := 0, charstring imm_ass_setting := "post-chan-ack") {
10157 f_vty_enter_cfg_bts(pt, bts_nr);
10158 f_vty_transceive(pt, "immediate-assignment " & imm_ass_setting);
10159 f_vty_transceive(pt, "exit");
10160 f_vty_transceive(pt, "exit");
10161 f_vty_transceive(pt, "exit");
10162}
10163
10164private function f_verify_imm_ass(RSL_Message imm_ass, template uint8_t ra := ?, template GsmFrameNumber fn := ?,
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020010165 template RslChannelNr chan_nr := ?,
10166 template (present) uint12_t arfcn := ?,
10167 template (present) uint3_t tsc := ?)
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020010168{
10169 var RSL_IE_Body full_imm_ass_info;
10170 if (not f_rsl_find_ie(imm_ass, RSL_IE_FULL_IMM_ASS_INFO, full_imm_ass_info)) {
10171 setverdict(fail, "RSL Full Immediate Assign Info IE is absent");
10172 mtc.stop;
10173 }
10174
10175 var GsmRrMessage rr_imm_ass := dec_GsmRrMessage(full_imm_ass_info.full_imm_ass_info.payload);
10176 var template GsmRrMessage expect_imm_ass := tr_IMM_ASS(ra := ra,
10177 fn := fn,
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020010178 ch_desc := tr_ChanDescH0(chan_nr, arfcn, tsc),
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020010179 page_mode := ?);
10180 if (not match(rr_imm_ass, expect_imm_ass)) {
10181 log("Error: expected ", expect_imm_ass, " got ", rr_imm_ass);
10182 setverdict(fail, "Failed to match Immediate Assignment");
10183 mtc.stop;
10184 }
10185}
10186
10187testcase TC_imm_ass_post_chan_ack() runs on test_CT {
10188 var RSL_Message chan_act;
10189 var RSL_Message imm_ass;
10190
10191 f_init(1, false);
10192 f_sleep(1.0);
10193
10194 /* (should be the default anyway, just to make things clear) */
10195 f_vty_set_imm_ass(BSCVTY, 0, "post-chan-ack");
10196
10197 /* RA containing reason=LU */
10198 var GsmFrameNumber fn := 2342;
10199 var uint8_t ra := 2;
10200 f_ipa_tx(0, ts_RSL_CHAN_RQD(int2oct(ra, 1), fn));
10201
10202 chan_act := f_exp_ipa_rx(0, tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
10203
10204 /* First send the Chan Act ACK */
10205 var RslChannelNr chan_nr := chan_act.ies[0].body.chan_nr;
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020010206 var RSL_IE_Body chan_ident_ie;
10207 if (not f_rsl_find_ie(chan_act, RSL_IE_CHAN_IDENT, chan_ident_ie)) {
10208 setverdict(fail, "RSL Channel Identification IE is absent");
10209 mtc.stop;
10210 }
10211
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020010212 f_ipa_tx(0, ts_RSL_CHAN_ACT_ACK(chan_nr, fn + 10));
10213
10214 /* Then expect the Immediate Assignment, after we ACKed the chan act */
10215 imm_ass := f_exp_ipa_rx(0, tr_RSL_IMM_ASSIGN(0));
10216
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020010217 f_verify_imm_ass(imm_ass, ra, fn, chan_nr, chan_ident_ie.chan_ident.ch_desc.v.arfcn,
10218 chan_ident_ie.chan_ident.ch_desc.v.tsc);
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020010219
10220 /* Check that the lchan is working */
10221 var octetstring l3 := '00010203040506'O;
10222 f_ipa_tx(0, ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3));
10223
10224 var BSSAP_N_CONNECT_ind rx_c_ind;
10225 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3))) -> value rx_c_ind;
10226 BSSAP.send(ts_BSSAP_CONNECT_res(rx_c_ind.connectionId));
10227
10228 f_sleep(1.0);
10229 f_shutdown_helper();
10230}
10231
10232testcase TC_imm_ass_pre_chan_ack() runs on test_CT {
10233 var RSL_Message chan_act;
10234 var RSL_Message imm_ass;
10235
10236 f_init(1, false);
10237 f_sleep(1.0);
10238
10239 f_vty_set_imm_ass(BSCVTY, 0, "pre-chan-ack");
10240
10241 /* RA containing reason=LU */
10242 var GsmFrameNumber fn := 2342;
10243 var uint8_t ra := 2;
10244 f_ipa_tx(0, ts_RSL_CHAN_RQD(int2oct(ra, 1), fn));
10245
10246 /* (set bts 0 cfg back to default) */
10247 f_vty_set_imm_ass(BSCVTY);
10248
10249 chan_act := f_exp_ipa_rx(0, tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
10250 var RslChannelNr chan_nr := chan_act.ies[0].body.chan_nr;
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020010251 var RSL_IE_Body chan_ident_ie;
10252 if (not f_rsl_find_ie(chan_act, RSL_IE_CHAN_IDENT, chan_ident_ie)) {
10253 setverdict(fail, "RSL Channel Identification IE is absent");
10254 mtc.stop;
10255 }
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020010256
10257 /* *FIRST* expect the Immediate Assignment, before we ACK the chan act */
10258 imm_ass := f_exp_ipa_rx(0, tr_RSL_IMM_ASSIGN(0));
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020010259 f_verify_imm_ass(imm_ass, ra, fn, chan_nr, chan_ident_ie.chan_ident.ch_desc.v.arfcn,
10260 chan_ident_ie.chan_ident.ch_desc.v.tsc);
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020010261
10262 /* Only now send the Chan Act ACK */
10263 f_ipa_tx(0, ts_RSL_CHAN_ACT_ACK(chan_nr, fn+10));
10264
10265 /* Check that the lchan is working */
10266 var octetstring l3 := '00010203040506'O;
10267 f_ipa_tx(0, ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3));
10268
10269 var BSSAP_N_CONNECT_ind rx_c_ind;
10270 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3))) -> value rx_c_ind;
10271 BSSAP.send(ts_BSSAP_CONNECT_res(rx_c_ind.connectionId));
10272
10273 f_sleep(1.0);
10274 f_shutdown_helper();
10275}
10276
Neels Hofmeyr23158742021-09-07 19:08:07 +020010277testcase TC_imm_ass_pre_ts_ack() runs on test_CT {
10278 var RSL_Message chan_act;
10279 var RSL_Message imm_ass;
10280
10281 f_init(1, false);
10282 f_sleep(1.0);
10283
10284 f_vty_set_imm_ass(BSCVTY, 0, "pre-ts-ack");
10285
10286 /* RA containing reason=LU */
10287 var GsmFrameNumber fn := 2342;
10288 var uint8_t ra := 2;
10289 f_ipa_tx(0, ts_RSL_CHAN_RQD(int2oct(ra, 1), fn));
10290
10291 /* (set bts 0 cfg back to default) */
10292 f_vty_set_imm_ass(BSCVTY);
10293
10294 chan_act := f_exp_ipa_rx(0, tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
10295 var RslChannelNr chan_nr := chan_act.ies[0].body.chan_nr;
10296 var RSL_IE_Body chan_ident_ie;
10297 if (not f_rsl_find_ie(chan_act, RSL_IE_CHAN_IDENT, chan_ident_ie)) {
10298 setverdict(fail, "RSL Channel Identification IE is absent");
10299 mtc.stop;
10300 }
10301
10302 /* *FIRST* expect the Immediate Assignment, before we ACK the chan act */
10303 imm_ass := f_exp_ipa_rx(0, tr_RSL_IMM_ASSIGN(0));
10304 f_verify_imm_ass(imm_ass, ra, fn, chan_nr, chan_ident_ie.chan_ident.ch_desc.v.arfcn,
10305 chan_ident_ie.chan_ident.ch_desc.v.tsc);
10306
10307 /* Only now send the Chan Act ACK */
10308 f_ipa_tx(0, ts_RSL_CHAN_ACT_ACK(chan_nr, fn+10));
10309
10310 /* Check that the lchan is working */
10311 var octetstring l3 := '00010203040506'O;
10312 f_ipa_tx(0, ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3));
10313
10314 var BSSAP_N_CONNECT_ind rx_c_ind;
10315 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3))) -> value rx_c_ind;
10316 BSSAP.send(ts_BSSAP_CONNECT_res(rx_c_ind.connectionId));
10317
10318 f_sleep(1.0);
10319 f_shutdown_helper();
10320}
10321
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020010322testcase TC_imm_ass_pre_chan_ack_dyn_ts() runs on test_CT {
10323 /* change Timeslot 6 before f_init() starts RSL */
10324 f_init_vty();
10325 f_ts_set_chcomb(0, 0, 6, "TCH/F_TCH/H_PDCH");
10326 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
10327
10328 f_init(1, false);
10329 f_sleep(1.0);
10330
10331 var RslChannelNr chan_nr := valueof(t_RslChanNr_PDCH(6));
10332 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiy58b16532021-10-09 20:27:39 +060010333 f_exp_ipa_rx(0, tr_RSL_CHAN_ACT_PDCH(chan_nr));
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020010334 f_ipa_tx(0, ts_RSL_CHAN_ACT_ACK(chan_nr, 2323));
10335
10336 /* clean up timeslot 6 config, will only take effect when the OML drops the next time */
10337 f_ts_set_chcomb(0, 0, 6, "PDCH");
10338
10339 /* block all static timeslots so that the dyn TS will be used */
10340 f_disable_all_tch_f();
10341 f_disable_all_tch_h();
10342 f_disable_all_sdcch();
10343
10344 var RSL_Message chan_act;
10345 var RSL_Message imm_ass;
10346
10347 f_init(1, false);
10348 f_sleep(1.0);
10349
10350 f_vty_set_imm_ass(BSCVTY, 0, "pre-chan-ack");
10351
10352 /* RA containing reason=LU */
10353 var GsmFrameNumber fn := 2342;
10354 var uint8_t ra := 2;
10355 f_ipa_tx(0, ts_RSL_CHAN_RQD(int2oct(ra, 1), fn));
10356
10357 /* (set bts 0 cfg back to default) */
10358 f_vty_set_imm_ass(BSCVTY);
10359
10360 /* Expect the dyn TS to deactivate PDCH first */
10361 f_exp_ipa_rx(0, tr_RSL_RF_CHAN_REL(chan_nr));
10362 f_ipa_tx(0, ts_RSL_RF_CHAN_REL_ACK(chan_nr));
10363
10364 /* Now activation as SDCCH8 */
10365 chan_nr := valueof(t_RslChanNr_SDCCH8(tn := 6, sub_slot := 0));
10366
10367 chan_act := f_exp_ipa_rx(0, tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020010368 var RSL_IE_Body chan_ident_ie;
10369 if (not f_rsl_find_ie(chan_act, RSL_IE_CHAN_IDENT, chan_ident_ie)) {
10370 setverdict(fail, "RSL Channel Identification IE is absent");
10371 mtc.stop;
10372 }
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020010373
10374 /* *FIRST* expect the Immediate Assignment, before we ACK the chan act */
10375 imm_ass := f_exp_ipa_rx(0, tr_RSL_IMM_ASSIGN(0));
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020010376 f_verify_imm_ass(imm_ass, ra, fn, chan_nr, chan_ident_ie.chan_ident.ch_desc.v.arfcn,
10377 chan_ident_ie.chan_ident.ch_desc.v.tsc);
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020010378
10379 /* Only now send the Chan Act ACK */
10380 f_ipa_tx(0, ts_RSL_CHAN_ACT_ACK(chan_nr, fn+10));
10381
10382 /* Check that the lchan is working */
10383 var octetstring l3 := '00010203040506'O;
10384 f_ipa_tx(0, ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3));
10385
10386 var BSSAP_N_CONNECT_ind rx_c_ind;
10387 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3))) -> value rx_c_ind;
10388 BSSAP.send(ts_BSSAP_CONNECT_res(rx_c_ind.connectionId));
10389
10390 f_sleep(1.0);
10391 f_shutdown_helper();
10392}
10393
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020010394testcase TC_imm_ass_pre_ts_ack_dyn_ts() runs on test_CT {
10395 /* change Timeslot 6 before f_init() starts RSL */
10396 f_init_vty();
10397 f_ts_set_chcomb(0, 0, 6, "TCH/F_TCH/H_PDCH");
10398 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
10399
10400 f_init(1, false);
10401 f_sleep(1.0);
10402
10403 var RslChannelNr chan_nr := valueof(t_RslChanNr_PDCH(6));
10404 /* The BSC will activate the dynamic PDCH by default, so confirm that */
Vadim Yanitskiy58b16532021-10-09 20:27:39 +060010405 f_exp_ipa_rx(0, tr_RSL_CHAN_ACT_PDCH(chan_nr));
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020010406 f_ipa_tx(0, ts_RSL_CHAN_ACT_ACK(chan_nr, 2323));
10407
10408 /* clean up timeslot 6 config, will only take effect when the OML drops the next time */
10409 f_ts_set_chcomb(0, 0, 6, "PDCH");
10410
10411 /* block all static timeslots so that the dyn TS will be used */
10412 f_disable_all_tch_f();
10413 f_disable_all_tch_h();
10414 f_disable_all_sdcch();
10415
10416 var RSL_Message chan_act;
10417 var RSL_Message imm_ass;
10418
10419 f_init(1, false);
10420 f_sleep(1.0);
10421
10422 f_vty_set_imm_ass(BSCVTY, 0, "pre-ts-ack");
10423
10424 /* RA containing reason=LU */
10425 var GsmFrameNumber fn := 2342;
10426 var uint8_t ra := 2;
10427 f_ipa_tx(0, ts_RSL_CHAN_RQD(int2oct(ra, 1), fn));
10428
10429 /* (set bts 0 cfg back to default) */
10430 f_vty_set_imm_ass(BSCVTY);
10431
10432 /* Expect the dyn TS to deactivate PDCH first */
10433 f_exp_ipa_rx(0, tr_RSL_RF_CHAN_REL(chan_nr));
10434
10435 /* And already the Immediate Assignment even before the PDCH Deact ACK */
10436 imm_ass := f_exp_ipa_rx(0, tr_RSL_IMM_ASSIGN(0));
10437
10438 /* continue the Osmo style PDCH Deact (usual chan rel) */
10439 f_ipa_tx(0, ts_RSL_RF_CHAN_REL_ACK(chan_nr));
10440
10441 /* Now activation as SDCCH8 */
10442 chan_nr := valueof(t_RslChanNr_SDCCH8(tn := 6, sub_slot := 0));
10443
10444 chan_act := f_exp_ipa_rx(0, tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020010445 var RSL_IE_Body chan_ident_ie;
10446 if (not f_rsl_find_ie(chan_act, RSL_IE_CHAN_IDENT, chan_ident_ie)) {
10447 setverdict(fail, "RSL Channel Identification IE is absent");
10448 mtc.stop;
10449 }
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020010450 f_ipa_tx(0, ts_RSL_CHAN_ACT_ACK(chan_nr, fn+10));
10451
Neels Hofmeyr07603cf2021-09-07 19:05:52 +020010452 f_verify_imm_ass(imm_ass, ra, fn, chan_nr, chan_ident_ie.chan_ident.ch_desc.v.arfcn,
10453 chan_ident_ie.chan_ident.ch_desc.v.tsc);
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020010454
10455 /* Check that the lchan is working */
10456 var octetstring l3 := '00010203040506'O;
10457 f_ipa_tx(0, ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3));
10458
10459 var BSSAP_N_CONNECT_ind rx_c_ind;
10460 BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3))) -> value rx_c_ind;
10461 BSSAP.send(ts_BSSAP_CONNECT_res(rx_c_ind.connectionId));
10462
10463 f_sleep(1.0);
10464 f_shutdown_helper();
10465}
10466
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020010467/* GET and SET the bts.N.trx.M.rf_locked CTRL variable */
10468testcase TC_ctrl_trx_rf_locked() runs on test_CT {
10469 var MSC_ConnHdlr vc_conn;
10470
10471 f_init(nr_bts := 2, handler_mode := true, nr_msc := 1);
10472 f_sleep(1.0);
10473
10474 /* BTS 0, 1, 2 are OML unlocked, only BTS 0, 1 are actually connected to RSL. */
10475 f_ctrl_get_exp(IPA_CTRL, "rf_states",
10476 "0,0,operational,unlocked,on,rsl-up;" &
10477 "1,0,operational,unlocked,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 BTS 1 TRX 0");
10482 f_ctrl_set(IPA_CTRL, "bts.1.trx.0.rf_locked", "1");
10483 /* give it a moment to settle the FSM status */
10484 f_sleep(1.0);
10485
10486 /* Now BTS 1 TRX 0 should reflect "locked". Note the RF policy stays "on", because this is still handled
10487 * globally in osmo-bsc. Probably after sending "rf_locked 1" for a TRX, that TRX should reflect an RF policy
10488 * of "off"? But that's for a future patch if at all. */
10489 f_ctrl_get_exp(IPA_CTRL, "rf_states",
10490 "0,0,operational,unlocked,on,rsl-up;" &
10491 "1,0,operational,locked,on,rsl-up;" &
10492 "2,0,operational,unlocked,on,rsl-down;" &
10493 "3,0,inoperational,locked,on,rsl-down;");
10494
10495 f_logp(BSCVTY, "TC_ctrl_trx_rf_locked: lock the already locked TRX, nothing should change");
10496 f_ctrl_set(IPA_CTRL, "bts.1.trx.0.rf_locked", "1");
10497 f_sleep(1.0);
10498 f_ctrl_get_exp(IPA_CTRL, "rf_states",
10499 "0,0,operational,unlocked,on,rsl-up;" &
10500 "1,0,operational,locked,on,rsl-up;" &
10501 "2,0,operational,unlocked,on,rsl-down;" &
10502 "3,0,inoperational,locked,on,rsl-down;");
10503
10504 f_logp(BSCVTY, "TC_ctrl_trx_rf_locked: unlock BTS 1 TRX 0");
10505 f_ctrl_set(IPA_CTRL, "bts.1.trx.0.rf_locked", "0");
10506 f_sleep(1.0);
10507 f_ctrl_get_exp(IPA_CTRL, "rf_states",
10508 "0,0,operational,unlocked,on,rsl-up;" &
10509 "1,0,operational,unlocked,on,rsl-up;" &
10510 "2,0,operational,unlocked,on,rsl-down;" &
10511 "3,0,inoperational,locked,on,rsl-down;");
10512
10513 f_logp(BSCVTY, "TC_ctrl_trx_rf_locked: unlock an already unlocked TRX, nothing should change");
10514 f_ctrl_set(IPA_CTRL, "bts.0.trx.0.rf_locked", "0");
10515 f_sleep(1.0);
10516 f_ctrl_get_exp(IPA_CTRL, "rf_states",
10517 "0,0,operational,unlocked,on,rsl-up;" &
10518 "1,0,operational,unlocked,on,rsl-up;" &
10519 "2,0,operational,unlocked,on,rsl-down;" &
10520 "3,0,inoperational,locked,on,rsl-down;");
10521
10522 f_logp(BSCVTY, "TC_ctrl_trx_rf_locked: unlock an inoperational TRX");
10523 f_ctrl_set(IPA_CTRL, "bts.3.trx.0.rf_locked", "0");
10524 f_sleep(1.0);
10525 f_ctrl_get_exp(IPA_CTRL, "rf_states",
10526 "0,0,operational,unlocked,on,rsl-up;" &
10527 "1,0,operational,unlocked,on,rsl-up;" &
10528 "2,0,operational,unlocked,on,rsl-down;" &
10529 "3,0,inoperational,locked,on,rsl-down;");
10530
10531 f_shutdown_helper();
10532}
10533
Neels Hofmeyrb7581872021-11-07 14:02:49 +010010534const CounterNameVals counternames_cm_serv_rej := {
10535 { "cm_serv_rej", 0 },
10536 { "cm_serv_rej:imsi_unknown_in_hlr", 0 },
10537 { "cm_serv_rej:illegal_ms", 0 },
10538 { "cm_serv_rej:imsi_unknown_in_vlr", 0 },
10539 { "cm_serv_rej:imei_not_accepted", 0 },
10540 { "cm_serv_rej:illegal_me", 0 },
10541 { "cm_serv_rej:plmn_not_allowed", 0 },
10542 { "cm_serv_rej:loc_not_allowed", 0 },
10543 { "cm_serv_rej:roaming_not_allowed", 0 },
10544 { "cm_serv_rej:network_failure", 0 },
10545 { "cm_serv_rej:synch_failure", 0 },
10546 { "cm_serv_rej:congestion", 0 },
10547 { "cm_serv_rej:srv_opt_not_supported", 0 },
10548 { "cm_serv_rej:rqd_srv_opt_not_supported", 0 },
10549 { "cm_serv_rej:srv_opt_tmp_out_of_order", 0 },
10550 { "cm_serv_rej:call_can_not_be_identified", 0 },
10551 { "cm_serv_rej:incorrect_message", 0 },
10552 { "cm_serv_rej:invalid_mandantory_inf", 0 },
10553 { "cm_serv_rej:msg_type_not_implemented", 0 },
10554 { "cm_serv_rej:msg_type_not_compatible", 0 },
10555 { "cm_serv_rej:inf_eleme_not_implemented", 0 },
10556 { "cm_serv_rej:condtional_ie_error", 0 },
10557 { "cm_serv_rej:msg_not_compatible", 0 },
10558 { "cm_serv_rej:protocol_error", 0 },
10559 { "cm_serv_rej:retry_in_new_cell", 0 }
10560};
10561
10562private function f_TC_cm_serv_rej(charstring id) runs on MSC_ConnHdlr
10563{
10564 f_create_chan_and_exp();
Vadim Yanitskiya7fc5a62021-12-04 20:10:08 +030010565 /* we should now have a COMPL_L3 at the MSC */
Neels Hofmeyrb7581872021-11-07 14:02:49 +010010566 BSSAP.send(ts_PDU_DTAP_MT(ts_CM_SERV_REJ('02'O), '00'O));
Neels Hofmeyr87a65612021-11-16 15:56:45 +010010567 f_sleep(1.0);
Neels Hofmeyrb7581872021-11-07 14:02:49 +010010568}
10569testcase TC_cm_serv_rej() runs on test_CT {
10570 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10571 var MSC_ConnHdlr vc_conn;
10572
10573 f_init(1, true);
10574 f_sleep(1.0);
10575
10576 f_ctrs_bts_init(1, counternames_cm_serv_rej);
10577
10578 vc_conn := f_start_handler(refers(f_TC_cm_serv_rej), pars);
10579 vc_conn.done;
10580
10581 f_ctrs_bts_add(0, "cm_serv_rej", 1);
10582 f_ctrs_bts_add(0, "cm_serv_rej:imsi_unknown_in_hlr", 1);
10583 f_ctrs_bts_verify();
10584
Neels Hofmeyr87a65612021-11-16 15:56:45 +010010585 f_sleep(1.0);
Neels Hofmeyrb7581872021-11-07 14:02:49 +010010586 f_shutdown_helper();
10587}
10588
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020010589/* Reproduce a segfault happening when the SDCCH (primary) lchan is lost in-between a TCH Channel Activ and its Channel
10590 * Activ Ack (SYS#5627). */
10591private function f_TC_lost_sdcch_during_assignment(charstring id) runs on MSC_ConnHdlr {
10592 var PDU_BSSAP ass_cmd := f_gen_ass_req();
Vadim Yanitskiyf0310e32021-10-26 00:30:59 +030010593
10594 ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
10595 ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020010596
10597 var BSSMAP_FIELD_CodecType codecType;
10598 codecType := valueof(ass_cmd.pdu.bssmap.assignmentRequest.codecList.codecElements[0].codecType);
10599
10600 f_MscConnHdlr_init(g_pars.media_nr, host_bts, host_mgw_mgcp, codecType);
10601
10602 /* First establish a signalling lchan */
10603 f_create_chan_and_exp();
10604 f_rslem_dchan_queue_enable();
10605
10606 /* we should now have a COMPL_L3 at the MSC */
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020010607
10608 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
10609 activate(as_Media_mgw());
10610
10611 var RslChannelNr chan_nr := { u := { ch0 := RSL_CHAN_NR_Bm_ACCH }, tn := 1 };
10612 f_rslem_register(0, chan_nr);
10613
10614 f_rslem_set_auto_chan_act_ack(RSL_PROC, false);
10615 BSSAP.send(ass_cmd);
10616
10617
10618 /* Wait for the Channel Activ for the TCH channel */
10619 var ASP_RSL_Unitdata rx_rsl_ud;
10620 RSL.receive(tr_ASP_RSL_UD(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV), sid := ?)) -> value rx_rsl_ud;
10621
10622 /* make the original SDCCH disappear */
10623 RSL.send(ts_RSL_REL_IND(g_chan_nr, valueof(ts_RslLinkID_DCCH(0))));
10624
10625 /* and ACK the TCH channel activation. This caused a segfault up to OsmoBSC 1.7.0 (SYS#5627) */
10626 RSL.send(ts_ASP_RSL_UD(ts_RSL_CHAN_ACT_ACK(chan_nr, 23), rx_rsl_ud.streamId));
10627
10628 interleave {
10629 [] BSSAP.receive(tr_BSSMAP_AssignmentFail);
10630 [] BSSAP.receive(tr_BSSMAP_ClearRequest);
10631 }
10632
10633 BSSAP.send(ts_BSSMAP_ClearCommand(0));
10634 BSSAP.receive(tr_BSSMAP_ClearComplete);
10635 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
10636
10637 var MgcpCommand mgcp;
10638 MGCP.receive(tr_DLCX()) -> value mgcp {
10639 MGCP.send(ts_DLCX_ACK2(mgcp.line.trans_id));
10640 };
10641
10642 f_sleep(0.5);
10643}
10644testcase TC_lost_sdcch_during_assignment() runs on test_CT {
10645 var TestHdlrParams pars := f_gen_test_hdlr_pars();
10646 var MSC_ConnHdlr vc_conn;
10647
10648 f_init(1, true);
10649 f_sleep(1.0);
10650
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020010651 vc_conn := f_start_handler(refers(f_TC_lost_sdcch_during_assignment), pars);
10652 vc_conn.done;
10653
10654 f_shutdown_helper();
10655}
10656
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020010657const CounterNameVals counternames_bsc_bts_all_available_allocated := {
10658 { "all_allocated:sdcch", 0 },
10659 { "all_allocated:static_sdcch", 0 },
10660 { "all_allocated:tch", 0 },
10661 { "all_allocated:static_tch", 0 }
10662}
10663
10664private function f_all_allocated_expect_counter_change(charstring_list expect_changed) runs on test_CT
10665{
10666 /* Make sure counters settle first */
10667 f_sleep(1.0);
10668
10669 /* Take a baseline of counters */
10670 f_ctrs_bsc_and_bts_init(1, counternames_bsc_bts_all_available_allocated);
10671
10672 /* Elapse some time so that we see changes in counters, hopefully where expected */
10673 f_sleep(2.0);
10674
10675 /* Get new counters */
10676 var charstring_list all_changed := {};
10677 all_changed := all_changed & f_counter_name_vals_get_changed_n(IPA_CTRL, "bsc", g_ctr_bsc);
10678 all_changed := all_changed & f_counter_name_vals_get_changed_n(IPA_CTRL, "bts", g_ctr_bts);
10679
10680 /* Compare with expectations */
10681 var charstring_list all_expect_changed := {};
10682 for (var integer i := 0; i < lengthof(expect_changed); i := i + 1) {
10683 all_expect_changed := all_expect_changed & { "bsc.0." & expect_changed[i], "bts.0." & expect_changed[i] };
10684 }
10685 f_counter_name_vals_expect_changed_list(all_changed, all_expect_changed);
10686}
10687
10688testcase TC_ratectr_all_available_allocated() runs on test_CT {
10689 var ASP_RSL_Unitdata rsl_ud;
10690 var integer i;
10691 var integer chreq_total, chreq_nochan;
10692
10693 f_init(1);
10694 f_sleep(1.0);
10695
10696 /* Exhaust all dedicated SDCCH lchans.
10697 /* GSM 44.018 Table 9.1.8.2:
10698 * RA = '13'O -> Establishment cause = 0001xxxx (MS dual rate capable and asks for "SDCCH").
10699 */
10700 for (i := 0; i < NUM_SDCCH_PER_BTS; i := i+1) {
10701 f_est_dchan('13'O, NUM_SDCCH_PER_BTS + i, '00010203040506'O);
10702 }
10703
10704 /* Since only bts 0 is connected, expecting all_allocated to become true for both bts 0 and the "global" bsc
10705 * level.
10706 * All SDCCH are now occupied. */
10707 f_all_allocated_expect_counter_change({"all_allocated:sdcch", "all_allocated:static_sdcch"});
10708
10709 /* Also fill up all remaining (TCH) channels */
10710 for (i := 0; i < NUM_TCHF_PER_BTS + NUM_TCHH_PER_BTS; i := i+1) {
10711 f_est_dchan('33'O, NUM_SDCCH_PER_BTS + i, '00010203040506'O);
10712 }
10713
10714 /* All TCH are now also occupied */
10715 f_all_allocated_expect_counter_change({"all_allocated:sdcch", "all_allocated:static_sdcch",
10716 "all_allocated:tch", "all_allocated:static_tch"});
10717
10718 f_shutdown_helper();
10719}
10720
10721testcase TC_ratectr_all_available_allocated_dyn() runs on test_CT {
10722 var ASP_RSL_Unitdata rsl_ud;
10723 var integer i;
10724 var integer chreq_total, chreq_nochan;
10725
10726 f_init_vty();
10727 f_ts_set_chcomb(0, 0, 2, "TCH/F_TCH/H_PDCH");
10728 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
10729 /* Now we have 3 TCH/F, 1 OSMO_DYN, 1 TCH/H */
10730
10731 f_init(1, guard_timeout := 60.0);
10732 f_sleep(1.0);
10733
10734 /* The dyn TS wants to activate PDCH mode, ACK that. */
10735 var RslChannelNr chan_nr;
10736 chan_nr := valueof(t_RslChanNr_PDCH(2));
Vadim Yanitskiy58b16532021-10-09 20:27:39 +060010737 f_exp_ipa_rx(0, tr_RSL_CHAN_ACT_PDCH(chan_nr));
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020010738 f_ipa_tx(0, ts_RSL_CHAN_ACT_ACK(chan_nr, 2342));
10739
10740 /* Exhaust all dedicated SDCCH lchans.
10741 /* GSM 44.018 Table 9.1.8.2:
10742 * RA = '13'O -> Establishment cause = 0001xxxx (MS dual rate capable and asks for "SDCCH").
10743 */
10744 for (i := 0; i < NUM_SDCCH_PER_BTS; i := i+1) {
10745 f_est_dchan('13'O, NUM_SDCCH_PER_BTS + i, '00010203040506'O);
10746 }
10747
10748 /* The static SDCCH should now be occupied, while still 3x8 dynamic SDCCH potentially remain. So only
10749 * all_allocated:static_sdcch is counted, all_allocated:sdcch remains zero. */
10750 f_all_allocated_expect_counter_change({"all_allocated:static_sdcch"});
10751
10752 /* Request more SDCCH, hence convert the first dyn TS to SDCCH8.
10753 * Will release them later, so remember all the DchanTuples. */
10754 var DchanTuples dyn_sddch := {};
10755 dyn_sddch := dyn_sddch & { f_est_dchan_dyn('33'O, NUM_SDCCH_PER_BTS + i, '00010203040506'O) };
10756
10757 /* Also occupy the seven other SDCCH of the dyn TS */
10758 for (i := 0; i < 7; i := i+1) {
10759 dyn_sddch := dyn_sddch & { f_est_dchan('33'O, NUM_SDCCH_PER_BTS + i, '00010203040506'O) };
10760 }
10761
10762 /* Now all dynamic SDCCH are also occupied, so for the first time all_allocated:sdcch will trigger... */
10763 f_all_allocated_expect_counter_change({"all_allocated:sdcch", "all_allocated:static_sdcch"});
10764
10765 /* occupy the remaining TCH, three TCH/F and two TCH/H lchans */
10766 for (i := 0; i < 5; i := i+1) {
10767 f_est_dchan('33'O, NUM_SDCCH_PER_BTS + i, '00010203040506'O);
10768 }
10769
10770 /* All TCH lchans are now also occupied, both static and dynamic */
10771 f_all_allocated_expect_counter_change({"all_allocated:sdcch", "all_allocated:static_sdcch",
10772 "all_allocated:tch", "all_allocated:static_tch"});
10773
10774 /* Starting to release the dyn TS: as soon as the first SDCCH gets released, all_allocated:sdcch stops
10775 * incrementing. */
10776 var BssmapCause cause := 0;
10777 var DchanTuple dt := dyn_sddch[0];
10778 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
10779 f_exp_chan_rel_and_clear(dt, 0);
10780
10781 /* one dyn TS SDCCH is free again, so only the static_sdcch should increment. For tch, both static and dynamic
10782 * count as occupied, so those still both increment. */
10783 f_all_allocated_expect_counter_change({"all_allocated:static_sdcch",
10784 "all_allocated:tch", "all_allocated:static_tch"});
10785
10786 /* Release the remaining SDCCH of the dyn TS, so it becomes available as TCH again */
10787 for (i := 1; i < lengthof(dyn_sddch); i := i+1) {
10788 dt := dyn_sddch[i];
10789 BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
10790 f_exp_chan_rel_and_clear(dt, 0);
10791 }
10792
10793 /* All SDCCH on the dyn TS are released, the dyn TS wants to activate PDCH again */
10794 chan_nr := valueof(t_RslChanNr_PDCH(2));
Vadim Yanitskiy58b16532021-10-09 20:27:39 +060010795 f_exp_ipa_rx(0, tr_RSL_CHAN_ACT_PDCH(chan_nr));
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020010796 f_ipa_tx(0, ts_RSL_CHAN_ACT_ACK(chan_nr, 2342));
10797
10798 /* Now all channels are occupied except the dyn TS, so expecting only the static counters to increment */
10799 f_all_allocated_expect_counter_change({"all_allocated:static_sdcch", "all_allocated:static_tch"});
10800
10801 /* clean up config */
10802 f_ts_reset_chcomb(0);
10803
10804 f_shutdown_helper();
10805}
10806
Harald Welte28d943e2017-11-25 15:00:50 +010010807control {
Harald Welte898113b2018-01-31 18:32:21 +010010808 /* CTRL interface testing */
Harald Welte4003d112017-12-09 22:35:39 +010010809 execute( TC_ctrl_msc_connection_status() );
Stefan Sperlingb041b3d2018-01-03 17:14:55 +010010810 execute( TC_ctrl_msc0_connection_status() );
Neels Hofmeyrf65ce872021-09-23 18:40:10 +020010811 /* In SCCPlite tests, only one MSC is configured. These tests assume that three MSCs are configured, so only run
10812 * these in the AoIP test suite. */
10813 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
10814 execute( TC_stat_num_msc_connected_1() );
10815 execute( TC_stat_num_msc_connected_2() );
10816 execute( TC_stat_num_msc_connected_3() );
10817 }
Neels Hofmeyr5ce3ae42021-08-29 15:32:00 +020010818 execute( TC_stat_num_bts_connected_1() );
10819 execute( TC_stat_num_bts_connected_2() );
10820 execute( TC_stat_num_bts_connected_3() );
Harald Welte96c94412017-12-09 03:12:45 +010010821 execute( TC_ctrl() );
Neels Hofmeyrf246a922020-05-13 02:27:10 +020010822 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_SCCPlite_SERVER) {
Pau Espin Pedrol5a2d7432019-06-07 19:43:45 +020010823 execute( TC_ctrl_location() );
10824 }
Harald Welte898113b2018-01-31 18:32:21 +010010825
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +020010826 execute( TC_si_default() );
Neels Hofmeyr66aeba42020-07-06 02:21:21 +020010827 execute( TC_si2quater_2_earfcns() );
10828 execute( TC_si2quater_3_earfcns() );
10829 execute( TC_si2quater_4_earfcns() );
10830 execute( TC_si2quater_5_earfcns() );
10831 execute( TC_si2quater_6_earfcns() );
Neels Hofmeyrad132f22020-07-08 02:20:16 +020010832 execute( TC_si2quater_12_earfcns() );
10833 execute( TC_si2quater_23_earfcns() );
10834 execute( TC_si2quater_32_earfcns() );
10835 execute( TC_si2quater_33_earfcns() );
10836 execute( TC_si2quater_42_earfcns() );
10837 execute( TC_si2quater_48_earfcns() );
10838 execute( TC_si2quater_49_earfcns() );
Pau Espin Pedrol85a84432020-07-20 18:45:03 +020010839 execute( TC_si_acc_rotate() );
Alexander Couzens4ad3a352020-09-10 22:29:12 +020010840 execute( TC_si_acc_ramp_rotate() );
Neels Hofmeyr5e686dc2020-06-30 01:26:53 +020010841
Harald Welte898113b2018-01-31 18:32:21 +010010842 /* RSL DCHAN Channel ACtivation / Deactivation */
Harald Welteae026692017-12-09 01:03:01 +010010843 execute( TC_chan_act_noreply() );
Harald Welte4003d112017-12-09 22:35:39 +010010844 execute( TC_chan_act_counter() );
Harald Welteae026692017-12-09 01:03:01 +010010845 execute( TC_chan_act_ack_noest() );
Philipp Maier9c60a622020-07-09 15:08:46 +020010846 execute( TC_chan_act_ack_noest_emerg() );
Philipp Maier606f07d2020-08-12 17:21:58 +020010847 execute( TC_chan_rqd_emerg_deny() );
Harald Welteae026692017-12-09 01:03:01 +010010848 execute( TC_chan_act_ack_est_ind_noreply() );
10849 execute( TC_chan_act_ack_est_ind_refused() );
Harald Welte618ef642017-12-14 14:58:20 +010010850 execute( TC_chan_act_nack() );
Harald Welte799c97b2017-12-14 17:50:30 +010010851 execute( TC_chan_exhaustion() );
Vadim Yanitskiy1ff1fdf2018-11-27 01:32:57 +070010852 execute( TC_chan_deact_silence() );
Harald Welte4003d112017-12-09 22:35:39 +010010853 execute( TC_chan_rel_rll_rel_ind() );
10854 execute( TC_chan_rel_conn_fail() );
10855 execute( TC_chan_rel_hard_clear() );
Pau Espin Pedrol841b90d2021-04-15 16:42:52 +020010856 execute( TC_chan_rel_last_eutran_plmn_hard_clear_no_csfb() );
10857 execute( TC_chan_rel_last_eutran_plmn_hard_clear_csfb() );
Harald Welte99787102019-02-04 10:41:36 +010010858 execute( TC_chan_rel_hard_clear_csfb() );
Harald Welted8c36cd2017-12-09 23:05:31 +010010859 execute( TC_chan_rel_hard_rlsd() );
Harald Welte550daf92018-06-11 19:22:13 +020010860 execute( TC_chan_rel_hard_rlsd_ms_dead() );
Harald Welte85804d42017-12-10 14:11:58 +010010861 execute( TC_chan_rel_a_reset() );
Pau Espin Pedrolc675b612020-01-09 19:55:40 +010010862 execute( TC_chan_rel_sccp_tiar_timeout() );
Neels Hofmeyr95a5edc2020-07-11 02:57:04 +020010863 execute( TC_chan_rel_rr_cause() );
Harald Welte6f521d82017-12-11 19:52:02 +010010864
Harald Weltecfe2c962017-12-15 12:09:32 +010010865 execute( TC_outbound_connect() );
Harald Welte898113b2018-01-31 18:32:21 +010010866
10867 /* Assignment related */
Harald Welte16a4adf2017-12-14 18:54:01 +010010868 execute( TC_assignment_cic_only() );
Harald Welte235ebf12017-12-15 14:18:16 +010010869 execute( TC_assignment_csd() );
10870 execute( TC_assignment_ctm() );
10871 execute( TC_assignment_sign() );
Pau Espin Pedrol07866632020-09-03 19:10:55 +020010872 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
10873 execute( TC_assignment_aoip_tla_v6() );
10874 }
Harald Welte235ebf12017-12-15 14:18:16 +010010875 execute( TC_assignment_fr_a5_0() );
10876 execute( TC_assignment_fr_a5_1() );
Neels Hofmeyrf246a922020-05-13 02:27:10 +020010877 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
Harald Welte8f67d1d2018-05-25 20:38:42 +020010878 execute( TC_assignment_fr_a5_1_codec_missing() );
10879 }
Harald Welte235ebf12017-12-15 14:18:16 +010010880 execute( TC_assignment_fr_a5_3() );
Neels Hofmeyr0d8ec532021-06-11 00:09:48 +020010881 execute( TC_assignment_fr_a5_4() );
Neels Hofmeyr0faeb7a2021-06-10 23:59:35 +020010882 execute( TC_assignment_fr_a5_4_fail() );
Neels Hofmeyr04d6e6a2021-06-11 00:10:02 +020010883 execute( TC_assignment_fr_a5_not_sup() );
Harald Welte3c86ea02018-05-10 22:28:05 +020010884 execute( TC_ciph_mode_a5_0() );
10885 execute( TC_ciph_mode_a5_1() );
Oliver Smith50b98122021-07-09 15:00:28 +020010886 execute( TC_ciph_mode_a5_2_0() );
Oliver Smith1dff88d2021-07-09 08:45:51 +020010887 execute( TC_ciph_mode_a5_2_1() );
Harald Welte3c86ea02018-05-10 22:28:05 +020010888 execute( TC_ciph_mode_a5_3() );
Neels Hofmeyr81ad27f2021-06-11 00:09:40 +020010889 execute( TC_ciph_mode_a5_4() );
Harald Welte16a4adf2017-12-14 18:54:01 +010010890
Harald Welte60aa5762018-03-21 19:33:13 +010010891 execute( TC_assignment_codec_fr() );
Neels Hofmeyr559d5d02021-04-16 16:50:49 +020010892 execute( TC_assignment_codec_fr_by_mode_modify() );
Harald Welte60aa5762018-03-21 19:33:13 +010010893 execute( TC_assignment_codec_hr() );
10894 execute( TC_assignment_codec_efr() );
10895 execute( TC_assignment_codec_amr_f() );
10896 execute( TC_assignment_codec_amr_h() );
Philipp Maier8a581d22019-03-26 18:32:48 +010010897
Neels Hofmeyrf246a922020-05-13 02:27:10 +020010898 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
Philipp Maier8a581d22019-03-26 18:32:48 +010010899 execute( TC_assignment_codec_amr_f_S1() );
10900 execute( TC_assignment_codec_amr_h_S1() );
10901 execute( TC_assignment_codec_amr_f_S124() );
10902 execute( TC_assignment_codec_amr_h_S124() );
10903 execute( TC_assignment_codec_amr_f_S0() );
10904 execute( TC_assignment_codec_amr_f_S02() );
10905 execute( TC_assignment_codec_amr_f_S024() );
10906 execute( TC_assignment_codec_amr_f_S0247() );
10907 execute( TC_assignment_codec_amr_h_S0() );
10908 execute( TC_assignment_codec_amr_h_S02() );
10909 execute( TC_assignment_codec_amr_h_S024() );
10910 execute( TC_assignment_codec_amr_h_S0247() );
10911 execute( TC_assignment_codec_amr_f_S01234567() );
10912 execute( TC_assignment_codec_amr_f_S0234567() );
10913 execute( TC_assignment_codec_amr_f_zero() );
10914 execute( TC_assignment_codec_amr_f_unsupp() );
10915 execute( TC_assignment_codec_amr_h_S7() );
Neels Hofmeyr21863562020-11-26 00:34:33 +000010916 execute( TC_assignment_codec_amr_f_start_mode_auto() );
10917 execute( TC_assignment_codec_amr_h_start_mode_auto() );
Neels Hofmeyr3eb94562020-11-26 02:40:26 +000010918 execute( TC_assignment_codec_amr_f_start_mode_4() );
10919 execute( TC_assignment_codec_amr_h_start_mode_4() );
Neels Hofmeyr454d7922020-11-26 02:24:57 +000010920 execute( TC_assignment_codec_amr_startmode_cruft() );
Philipp Maier8a581d22019-03-26 18:32:48 +010010921 }
Harald Welte60aa5762018-03-21 19:33:13 +010010922
Philipp Maierac09bfc2019-01-08 13:41:39 +010010923 execute( TC_assignment_codec_fr_exhausted_req_hr() );
10924 execute( TC_assignment_codec_fr_exhausted_req_fr() );
10925 execute( TC_assignment_codec_fr_exhausted_req_fr_hr() );
10926 execute( TC_assignment_codec_fr_exhausted_req_hr_fr() );
10927 execute( TC_assignment_codec_hr_exhausted_req_fr() );
10928 execute( TC_assignment_codec_hr_exhausted_req_hr() );
10929 execute( TC_assignment_codec_hr_exhausted_req_hr_fr() );
10930 execute( TC_assignment_codec_hr_exhausted_req_fr_hr() );
10931 execute( TC_assignment_codec_req_hr_fr() );
10932 execute( TC_assignment_codec_req_fr_hr() );
Pau Espin Pedrol14475352021-07-22 15:48:16 +020010933 execute( TC_assignment_sdcch_exhausted_req_signalling() );
10934 execute( TC_assignment_sdcch_exhausted_req_signalling_tch_forbidden() );
10935 execute( TC_assignment_sdcch_exhausted_req_voice_tch_forbidden() );
Philipp Maierac09bfc2019-01-08 13:41:39 +010010936
Pau Espin Pedrol23510fb2021-07-20 17:00:38 +020010937 execute( TC_assignment_osmux() );
Pau Espin Pedrolc6a53db2019-05-20 19:31:47 +020010938
Harald Welte898113b2018-01-31 18:32:21 +010010939 /* RLL Establish Indication on inactive DCHAN / SAPI */
Harald Welte5cd20ed2017-12-13 21:03:20 +010010940 execute( TC_rll_est_ind_inact_lchan() );
10941 execute( TC_rll_est_ind_inval_sapi1() );
10942 execute( TC_rll_est_ind_inval_sapi3() );
10943 execute( TC_rll_est_ind_inval_sacch() );
10944
Vadim Yanitskiy61f784a2020-10-01 21:12:19 +070010945 /* DLCI / RSL Link ID conversion for MO/MT messages on SAPI0/SAPI3 */
10946 execute( TC_tch_dlci_link_id_sapi() );
10947
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +070010948 /* SAPI N Reject triggered by RLL establishment failures */
10949 execute( TC_rll_rel_ind_sapi_n_reject() );
10950 execute( TC_rll_err_ind_sapi_n_reject() );
10951 execute( TC_rll_timeout_sapi_n_reject() );
Vadim Yanitskiy999ceb62020-10-04 00:04:49 +070010952 execute( TC_rll_sapi_n_reject_dlci_cc() );
Vadim Yanitskiy6ef5dfa2020-08-28 18:04:41 +070010953
Harald Welte898113b2018-01-31 18:32:21 +010010954 /* Paging related tests */
Harald Welte6f521d82017-12-11 19:52:02 +010010955 execute( TC_paging_imsi_nochan() );
10956 execute( TC_paging_tmsi_nochan() );
10957 execute( TC_paging_tmsi_any() );
10958 execute( TC_paging_tmsi_sdcch() );
10959 execute( TC_paging_tmsi_tch_f() );
10960 execute( TC_paging_tmsi_tch_hf() );
10961 execute( TC_paging_imsi_nochan_cgi() );
10962 execute( TC_paging_imsi_nochan_lac_ci() );
10963 execute( TC_paging_imsi_nochan_ci() );
10964 execute( TC_paging_imsi_nochan_lai() );
10965 execute( TC_paging_imsi_nochan_lac() );
10966 execute( TC_paging_imsi_nochan_all() );
Harald Welte751d3eb2018-01-31 15:51:06 +010010967 execute( TC_paging_imsi_nochan_plmn_lac_rnc() );
10968 execute( TC_paging_imsi_nochan_rnc() );
10969 execute( TC_paging_imsi_nochan_lac_rnc() );
10970 execute( TC_paging_imsi_nochan_lacs() );
10971 execute( TC_paging_imsi_nochan_lacs_empty() );
Stefan Sperling049a86e2018-03-20 15:51:00 +010010972 execute( TC_paging_imsi_nochan_cgi_unknown_cid() );
Harald Welte10985002017-12-12 09:29:15 +010010973 execute( TC_paging_imsi_a_reset() );
Harald Weltee65d40e2017-12-13 00:09:06 +010010974 execute( TC_paging_imsi_load() );
Philipp Maier779a7922018-02-16 11:00:37 +010010975 execute( TC_paging_counter() );
Pau Espin Pedrol3466cc52018-11-05 12:41:05 +010010976 execute( TC_paging_resp_unsol() );
Harald Welte4e9b9cc2017-12-14 18:31:02 +010010977
10978 execute( TC_rsl_drop_counter() );
Stefan Sperling830dc9d2018-02-12 21:08:28 +010010979 execute( TC_rsl_unknown_unit_id() );
10980
10981 execute( TC_oml_unknown_unit_id() );
Harald Welte898113b2018-01-31 18:32:21 +010010982
10983 execute( TC_classmark() );
Harald Welteeddf0e92020-06-21 19:42:15 +020010984 execute( TC_common_id() );
Harald Welte898113b2018-01-31 18:32:21 +010010985 execute( TC_unsol_ass_fail() );
Harald Welteea99a002018-01-31 20:46:43 +010010986 execute( TC_unsol_ass_compl() );
Harald Weltefbf9b5e2018-01-31 20:41:23 +010010987 execute( TC_unsol_ho_fail() );
Harald Weltee3bd6582018-01-31 22:51:25 +010010988 execute( TC_err_82_short_msg() );
Harald Weltee9e02e42018-01-31 23:36:25 +010010989 execute( TC_err_84_unknown_msg() );
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +010010990
Harald Welte261af4b2018-02-12 21:20:39 +010010991 execute( TC_ho_int() );
Neels Hofmeyraf88d9d2021-06-21 02:14:27 +020010992 execute( TC_ho_int_a5_0() );
10993 execute( TC_ho_int_a5_1() );
10994 execute( TC_ho_int_a5_3() );
10995 execute( TC_ho_int_a5_4() );
Neels Hofmeyr5f144212020-11-03 15:41:58 +000010996 execute( TC_ho_int_radio_link_failure() );
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +010010997
Neels Hofmeyrafe2ea52021-11-24 15:16:12 +010010998 /* TC_ho_out_of_this_bsc is run last, see comment below */
Neels Hofmeyr61ebb8b2018-10-09 18:28:06 +020010999 execute( TC_ho_out_fail_no_msc_response() );
11000 execute( TC_ho_out_fail_rr_ho_failure() );
Neels Hofmeyrd8a602c2019-07-09 19:46:01 +020011001 execute( TC_ho_out_fail_no_result_after_ho_cmd() );
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +010011002
Neels Hofmeyrbd0ef932018-03-19 14:58:46 +010011003 execute( TC_ho_into_this_bsc() );
Neels Hofmeyr8ebf19c2021-06-21 05:24:01 +020011004 execute( TC_ho_into_this_bsc_a5_0() );
11005 execute( TC_ho_into_this_bsc_a5_1() );
11006 execute( TC_ho_into_this_bsc_a5_3() );
11007 execute( TC_ho_into_this_bsc_a5_4() );
Pau Espin Pedrol07866632020-09-03 19:10:55 +020011008 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
11009 execute( TC_ho_into_this_bsc_tla_v6() );
11010 }
Pau Espin Pedrolc08d5522021-04-16 15:40:38 +020011011 execute( TC_srvcc_eutran_to_geran() );
Pau Espin Pedrol35801c32021-04-19 13:03:20 +020011012 execute( TC_srvcc_eutran_to_geran_ho_out() );
Pau Espin Pedrol9ae36d52021-06-15 17:29:43 +020011013 execute( TC_srvcc_eutran_to_geran_forbid_fast_return() );
11014 execute( TC_srvcc_eutran_to_geran_ho_out_forbid_fast_return() );
Neels Hofmeyr20bc3e22018-11-09 01:40:16 +010011015 execute( TC_ho_in_fail_msc_clears() );
11016 execute( TC_ho_in_fail_msc_clears_after_ho_detect() );
11017 execute( TC_ho_in_fail_no_detect() );
11018 execute( TC_ho_in_fail_no_detect2() );
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +010011019
Neels Hofmeyr91401012019-07-11 00:42:35 +020011020 execute( TC_ho_neighbor_config_1() );
11021 execute( TC_ho_neighbor_config_2() );
11022 execute( TC_ho_neighbor_config_3() );
11023 execute( TC_ho_neighbor_config_4() );
11024 execute( TC_ho_neighbor_config_5() );
11025 execute( TC_ho_neighbor_config_6() );
11026 execute( TC_ho_neighbor_config_7() );
11027
Neels Hofmeyrcdc2d762018-03-12 01:48:11 +010011028 execute( TC_bssap_rlsd_does_not_cause_bssmap_reset() );
Neels Hofmeyr4ff93282018-03-12 04:25:35 +010011029 execute( TC_bssmap_clear_does_not_cause_bssmap_reset() );
Neels Hofmeyrfd445c32018-03-09 15:39:31 +010011030 execute( TC_ms_rel_ind_does_not_cause_bssmap_reset() );
Harald Welte94e0c342018-04-07 11:33:23 +020011031
11032 execute( TC_dyn_pdch_ipa_act_deact() );
11033 execute( TC_dyn_pdch_ipa_act_nack() );
11034 execute( TC_dyn_pdch_osmo_act_deact() );
11035 execute( TC_dyn_pdch_osmo_act_nack() );
Pau Espin Pedrol37a4c152021-11-16 19:02:23 +010011036 execute( TC_dyn_ts_sdcch8_act_deact() );
11037 execute( TC_dyn_ts_sdcch8_all_subslots_used() );
11038 execute( TC_dyn_ts_sdcch8_tch_call_act_deact() );
11039 execute( TC_dyn_ts_sdcch8_act_nack() );
Harald Welte99f3ca02018-06-14 13:40:29 +020011040
Stefan Sperling0796a822018-10-05 13:01:39 +020011041 execute( TC_chopped_ipa_ping() );
Stefan Sperlingaa1e60f2018-10-15 16:34:07 +020011042 execute( TC_chopped_ipa_payload() );
Stefan Sperling0796a822018-10-05 13:01:39 +020011043
Pau Espin Pedrol8f773632019-11-05 11:46:53 +010011044 /* Power control related */
11045 execute( TC_assignment_verify_ms_power_params_ie() );
Vadim Yanitskiy4b233042021-06-30 00:58:43 +020011046 execute( TC_c0_power_red_mode() );
Neels Hofmeyr4f118412020-06-04 15:25:10 +020011047
11048 /* MSC pooling */
11049 /* FIXME: in SCCPlite, indicating how many MSCs should be connected does currently not work. Since
11050 * RESET->RESET-ACK is unconditionally negotiated for all configured MSCs, they always all appear as connected
11051 * to osmo-bsc. The MSC pooling tests however require disconnecting selected MSCs, and hence don't work out as
11052 * intended on SCCPlite. So for now, run these only for SCCP/M3UA. */
11053 if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
11054 execute( TC_mscpool_L3Compl_on_1_msc() );
11055 execute( TC_mscpool_L3Complete_by_imsi_round_robin() );
11056 execute( TC_mscpool_LU_by_tmsi_null_nri_0_round_robin() );
11057 execute( TC_mscpool_LU_by_tmsi_null_nri_1_round_robin() );
11058 execute( TC_mscpool_L3Complete_by_tmsi_unassigned_nri_round_robin() );
11059 execute( TC_mscpool_L3Complete_by_tmsi_valid_nri_msc_not_connected_round_robin() );
11060 execute( TC_mscpool_L3Complete_by_tmsi_valid_nri_1() );
11061 execute( TC_mscpool_L3Complete_by_tmsi_valid_nri_2() );
11062 execute( TC_mscpool_LU_by_tmsi_from_other_PLMN() );
11063 execute( TC_mscpool_paging_and_response_imsi() );
11064 execute( TC_mscpool_paging_and_response_tmsi() );
11065 execute( TC_mscpool_no_allow_attach_round_robin() );
11066 execute( TC_mscpool_no_allow_attach_valid_nri() );
11067 }
11068
Harald Welte99f3ca02018-06-14 13:40:29 +020011069 execute( TC_early_conn_fail() );
11070 execute( TC_late_conn_fail() );
Oliver Smithaf03bef2021-08-24 15:34:51 +020011071 execute( TC_stats_conn_fail() );
Harald Welte99f3ca02018-06-14 13:40:29 +020011072
Philipp Maier783681c2020-07-16 16:47:06 +020011073 /* Emergency call handling (deny / allow) */
11074 execute( TC_assignment_emerg_setup_allow() );
11075 execute( TC_assignment_emerg_setup_deny_msc() );
11076 execute( TC_assignment_emerg_setup_deny_bts() );
Philipp Maier82812002020-08-13 18:48:27 +020011077 execute( TC_emerg_premption() );
11078
Vadim Yanitskiy16bbde92020-08-28 05:30:45 +070011079 /* Frequency hopping parameters handling */
11080 execute( TC_fh_params_chan_activ() );
11081 execute( TC_fh_params_imm_ass() );
Vadim Yanitskiyaeb54a22020-09-01 06:25:25 +070011082 execute( TC_fh_params_assignment_cmd() );
Vadim Yanitskiy8f5430d2020-09-02 18:51:38 +070011083 execute( TC_fh_params_handover_cmd() );
Vadim Yanitskiyca974032020-09-01 07:20:39 +070011084 execute( TC_fh_params_si4_cbch() );
Neels Hofmeyr2b910dc2020-10-01 06:36:04 +020011085
11086 if (mp_enable_lcs_tests) {
11087 execute( TC_lcs_loc_req_for_active_ms() );
11088 execute( TC_lcs_loc_req_for_active_ms_ta_req() );
11089 execute( TC_lcs_loc_req_for_idle_ms() );
11090 execute( TC_lcs_loc_req_no_subscriber() );
11091 execute( TC_lcs_loc_req_for_active_ms_le_timeout() );
11092 execute( TC_lcs_loc_req_for_active_ms_le_timeout2() );
11093 execute( TC_lcs_loc_req_for_idle_ms_no_pag_resp() );
11094 execute( TC_cm_service_during_lcs_loc_req() );
11095 execute( TC_ho_during_lcs_loc_req() );
11096 }
Neels Hofmeyrbf037052020-10-28 22:52:02 +000011097
11098 execute( TC_no_msc() );
Neels Hofmeyr87857ec2021-04-25 16:17:47 +000011099
11100 execute( TC_refuse_chan_act_to_vamos() );
11101 execute( TC_refuse_mode_modif_to_vamos() );
Neels Hofmeyrd2d9f332021-04-28 22:23:36 +000011102
11103 execute( TC_reassignment_fr() );
Neels Hofmeyrfeda88e2021-07-19 13:51:29 +020011104
11105 execute( TC_cm_reestablishment() );
Neels Hofmeyrb07b2952021-08-07 04:23:14 +020011106
11107 execute( TC_imm_ass_post_chan_ack() );
11108 execute( TC_imm_ass_pre_chan_ack() );
Neels Hofmeyr23158742021-09-07 19:08:07 +020011109 execute( TC_imm_ass_pre_ts_ack() );
Neels Hofmeyr7a6d0602021-08-07 04:23:50 +020011110 execute( TC_imm_ass_pre_chan_ack_dyn_ts() );
Neels Hofmeyrc8b95c12021-08-07 04:24:02 +020011111 execute( TC_imm_ass_pre_ts_ack_dyn_ts() );
Neels Hofmeyr5d7d13f2021-09-07 14:44:36 +020011112
11113 execute( TC_ctrl_trx_rf_locked() );
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020011114
Neels Hofmeyrbd94fe72021-10-26 22:04:53 +020011115 execute( TC_ratectr_all_available_allocated() );
11116 execute( TC_ratectr_all_available_allocated_dyn() );
11117
Neels Hofmeyrb7581872021-11-07 14:02:49 +010011118 execute( TC_cm_serv_rej() );
11119
Neels Hofmeyr92cfa1c2021-09-28 18:29:44 +020011120 execute( TC_lost_sdcch_during_assignment() );
Neels Hofmeyrafe2ea52021-11-24 15:16:12 +010011121
11122 /* Run TC_ho_out_of_this_bsc last, because it may trigger a segfault before osmo-bsc's patch
11123 * with change-id I5a3345ab0005a73597f5c27207480912a2f5aae6 */
11124 execute( TC_ho_out_of_this_bsc() );
Harald Welte28d943e2017-11-25 15:00:50 +010011125}
11126
11127}