blob: 15948a33028c21194a2303f2f1863237eb88e1e0 [file] [log] [blame]
Harald Welte70767382018-02-21 12:16:40 +01001module BTS_Tests {
2
Harald Welte14906952019-05-27 09:19:49 +02003/* Integration Tests for OsmoBTS
Harald Welte34b5a952019-05-27 11:54:11 +02004 * (C) 2018-2019 by Harald Welte <laforge@gnumonks.org>
Harald Welte14906952019-05-27 09:19:49 +02005 * contributions by Vadim Yanitskiy and sysmocom - s.f.m.c. GmbH
6 * All rights reserved.
7 *
8 * Released under the terms of GNU General Public License, Version 2 or
9 * (at your option) any later version.
10 *
Harald Welte34b5a952019-05-27 11:54:11 +020011 * SPDX-License-Identifier: GPL-2.0-or-later
12 *
Harald Welte14906952019-05-27 09:19:49 +020013 * This test suite tests OsmoBTS by attaching to the external interfaces
14 * such as Abis RSL, PCU, VTY as well as by attaching to a MS L1 implementation
15 * using the L1CTL protocol/interface.
16 *
17 * You can run the tests with
18 * a) osmo-bts-trx + trxcon + fake_trx (without any hardware)
19 * b) any osmo-bts-* + OsmocomBB layer1 + osmocon (with real BTS hardware)
20 * c) osmo-bts-virtual + virt_phy (without any hardware)
21 *
22 * Some of the tests will only run on a subset of those three configurations
23 * due to limitations in the respective L1.
24 */
25
Daniel Willmann0fcc4d32018-10-23 20:32:19 +020026import from Misc_Helpers all;
Harald Welte70767382018-02-21 12:16:40 +010027import from General_Types all;
28import from GSM_Types all;
29import from GSM_RR_Types all;
30import from Osmocom_Types all;
31import from GSM_Types all;
Harald Welte82ccef72018-02-25 16:17:33 +010032import from GSM_SystemInformation all;
Harald Welte70767382018-02-21 12:16:40 +010033import from L1CTL_PortType all;
34import from L1CTL_Types all;
35import from LAPDm_Types all;
Harald Weltead033dc2019-05-25 17:28:16 +020036import from LAPDm_RAW_PT all;
Harald Welte70767382018-02-21 12:16:40 +010037import from Osmocom_CTRL_Adapter all;
Neels Hofmeyr6a84b232018-04-03 19:12:36 +020038import from Osmocom_CTRL_Functions all;
Harald Welte70767382018-02-21 12:16:40 +010039
40import from RSL_Types all;
Harald Welte7484fc42018-02-24 14:09:45 +010041import from IPA_Types all;
Harald Welte70767382018-02-21 12:16:40 +010042import from IPA_Emulation all;
Stefan Sperling0ec1c262018-10-15 15:12:52 +020043import from IPA_Testing all;
Harald Welte70767382018-02-21 12:16:40 +010044import from RSL_Emulation all;
45
46import from IPL4asp_Types all;
47import from TRXC_Types all;
48import from TRXC_CodecPort all;
49import from TRXC_CodecPort_CtrlFunct all;
50
Harald Welte883340c2018-02-28 18:59:29 +010051import from PCUIF_Types all;
52import from PCUIF_CodecPort all;
Harald Weltea2e0e942019-05-27 18:12:53 +020053import from UD_Types all;
Harald Welte883340c2018-02-28 18:59:29 +010054
Harald Welte7484fc42018-02-24 14:09:45 +010055import from MobileL3_CommonIE_Types all;
Harald Welte68e495b2018-02-25 00:05:57 +010056import from MobileL3_RRM_Types all;
57import from MobileL3_Types all;
58import from L3_Templates all;
Harald Welteeaa9a862019-05-26 23:01:08 +020059import from L3_Common all;
60import from MobileL3_GMM_SM_Types all;
Harald Welte7484fc42018-02-24 14:09:45 +010061
Harald Welte8da48242018-02-27 20:41:32 +010062import from Osmocom_VTY_Functions all;
63import from TELNETasp_PortType all;
Harald Welte2f2b2b72019-05-31 22:24:57 +020064import from BTS_Tests_LAPDm all;
Harald Welte8da48242018-02-27 20:41:32 +010065
Harald Welte505cf9b2018-09-15 17:47:23 +030066friend module BTS_Tests_SMSCB;
Harald Weltead033dc2019-05-25 17:28:16 +020067friend module BTS_Tests_virtphy;
Harald Welte2f2b2b72019-05-31 22:24:57 +020068friend module BTS_Tests_LAPDm;
Harald Welte505cf9b2018-09-15 17:47:23 +030069
Harald Welte70767382018-02-21 12:16:40 +010070/* The tests assume a BTS with the following timeslot configuration:
71 * TS0 : Combined CCCH + SDCCH/4
Harald Welte3d04ae62018-04-04 20:29:05 +020072 * TS1 : TCH/F
73 * TS2 : TCH/F
74 * TS3 : TCH/F_PDCH (IPA Style)
75 * TS4 : TCH/F_TCH/H_PDCH (Osmocom Style)
Harald Welte70767382018-02-21 12:16:40 +010076 * TS5 : TCH/H
77 * TS6 : SDCCH/8
78 * TS7 : PDCH
79 */
80
81modulepar {
82 charstring mp_rsl_ip := "127.0.0.2";
83 integer mp_rsl_port := 3003;
84 integer mp_trx0_arfcn := 871;
Vadim Yanitskiy44ff2142019-01-12 07:04:58 +070085 charstring mp_bts_trxc_ip := "127.0.0.1";
86 integer mp_bts_trxc_port := 5701;
Harald Welte883340c2018-02-28 18:59:29 +010087 charstring mp_pcu_socket := PCU_SOCK_DEFAULT;
Neels Hofmeyr6a84b232018-04-03 19:12:36 +020088 charstring mp_ctrl_ip := "127.0.0.1";
89 integer mp_ctrl_port := 4238;
Harald Welte07bd2d22019-05-25 11:03:30 +020090 charstring mp_bsc_ctrl_ip := "127.0.0.1";
91 integer mp_bsc_ctrl_port := 4249;
Pau Espin Pedrol121724c2018-09-28 15:58:12 +020092 integer mp_tolerance_rxqual := 1;
93 integer mp_tolerance_rxlev := 3;
94 integer mp_tolerance_timing_offset_256syms := 0;
Pau Espin Pedrol752ffd52018-06-07 13:55:45 +020095 integer mp_rxlev_exp := 57;
Pau Espin Pedrole9571aa2018-10-22 17:13:07 +020096 integer mp_ul_rxlev_exp := 10;
Pau Espin Pedroled359cb2018-09-28 16:08:24 +020097 integer mp_ms_power_level_exp := 7;
Pau Espin Pedrol121724c2018-09-28 15:58:12 +020098 integer mp_ms_actual_ta_exp := 0;
99 integer mp_timing_offset_256syms_exp := 512;
Pau Espin Pedrol315e4712018-11-01 16:27:07 +0100100 /* Time to wait for RSL conn from BTS during startup of test */
Philipp Maier12567e42019-04-17 14:10:05 +0200101 float mp_ipa_up_timeout := 15.0;
Philipp Maiere63229e2019-04-26 12:21:37 +0200102 float mp_ipa_up_delay := 0.0;
Harald Weltead033dc2019-05-25 17:28:16 +0200103 /* false for now, as only virtphy supports it, not calypso-l1 nor trxcon */
104 boolean mp_l1_supports_gprs := false;
Harald Welte70767382018-02-21 12:16:40 +0100105}
106
Harald Welte629cc6b2018-03-11 17:19:05 +0100107type record of RslChannelNr ChannelNrs;
108
Harald Welte70767382018-02-21 12:16:40 +0100109type component test_CT extends CTRL_Adapter_CT {
Harald Welte68e495b2018-02-25 00:05:57 +0100110 /* IPA Emulation component underneath RSL */
Harald Welte70767382018-02-21 12:16:40 +0100111 var IPA_Emulation_CT vc_IPA;
Harald Welte68e495b2018-02-25 00:05:57 +0100112 /* RSL Emulation component (for ConnHdlr tests) */
Harald Welte70767382018-02-21 12:16:40 +0100113 var RSL_Emulation_CT vc_RSL;
Harald Welte68e495b2018-02-25 00:05:57 +0100114 /* Direct RSL_CCHAN_PT */
Harald Welte70767382018-02-21 12:16:40 +0100115 port RSL_CCHAN_PT RSL_CCHAN;
Harald Welte68e495b2018-02-25 00:05:57 +0100116
117 /* L1CTL port (for classic tests) */
118 port L1CTL_PT L1CTL;
Harald Welte48494ca2018-02-25 16:59:50 +0100119
Vadim Yanitskiyf4e997c2019-06-04 21:40:33 +0700120 /* Optional TRXC connection to FakeTRX (BTS side) */
Vadim Yanitskiy44ff2142019-01-12 07:04:58 +0700121 port TRXC_CODEC_PT BTS_TRXC;
122 var integer g_bts_trxc_conn_id;
Harald Welte54a2a2d2018-02-26 09:14:05 +0100123
Harald Weltef50e3ae2018-09-10 10:27:56 +0200124 /* VTY connections to both BTS and BSC */
Harald Welte8da48242018-02-27 20:41:32 +0100125 port TELNETasp_PT BTSVTY;
Harald Weltef50e3ae2018-09-10 10:27:56 +0200126 port TELNETasp_PT BSCVTY;
Harald Welte8da48242018-02-27 20:41:32 +0100127
Harald Welte883340c2018-02-28 18:59:29 +0100128 /* PCU Interface of BTS */
129 port PCUIF_CODEC_PT PCU;
130 var integer g_pcu_conn_id;
131 /* Last PCU INFO IND we received */
132 var PCUIF_Message g_pcu_last_info;
133
Harald Welte48494ca2018-02-25 16:59:50 +0100134 /* SI configuration */
135 var SystemInformationConfig si_cfg := {
136 bcch_extended := false,
137 si1_present := false,
138 si2bis_present := false,
139 si2ter_present := false,
140 si2quater_present := false,
141 si7_present := false,
142 si8_present := false,
143 si9_present := false,
144 si13_present := false,
145 si13alt_present := false,
146 si15_present := false,
147 si16_present := false,
148 si17_present := false,
149 si2n_present := false,
150 si21_present := false,
151 si22_present := false
152 };
Harald Welte629cc6b2018-03-11 17:19:05 +0100153
154 /* all logical channels available on the BTS */
155 var ChannelNrs g_AllChannels;
Harald Welte0472ab42018-03-12 15:02:26 +0100156 var ChannelNrs g_AllChanTypes;
Harald Welte70767382018-02-21 12:16:40 +0100157}
158
159/* an individual call / channel */
Harald Welte2f2b2b72019-05-31 22:24:57 +0200160type component ConnHdlr extends RSL_DchanHdlr, lapdm_test_CT {
Harald Welte70767382018-02-21 12:16:40 +0100161 port L1CTL_PT L1CTL;
162
Vadim Yanitskiyf4e997c2019-06-04 21:40:33 +0700163 /* Optional TRXC connection to FakeTRX (BTS side) */
Vadim Yanitskiy44ff2142019-01-12 07:04:58 +0700164 port TRXC_CODEC_PT BTS_TRXC;
165 var integer g_bts_trxc_conn_id;
Harald Welte70767382018-02-21 12:16:40 +0100166
167 timer g_Tguard;
168 timer g_Tmeas_exp := 2.0; /* >= 103 SACCH multiframe ~ 500ms */
169
170 var ConnHdlrPars g_pars;
171 var uint8_t g_next_meas_res_nr := 0;
Harald Weltefa45e9e2018-03-10 18:59:03 +0100172 var boolean g_first_meas_res := true;
Harald Weltef26de0b2018-04-04 20:28:05 +0200173
174 /* PCU Interface of BTS */
175 port PCUIF_CODEC_PT PCU;
Harald Welte70767382018-02-21 12:16:40 +0100176}
177
178function f_init_rsl(charstring id) runs on test_CT {
179 vc_IPA := IPA_Emulation_CT.create(id & "-RSL-IPA");
180 vc_RSL := RSL_Emulation_CT.create(id & "-RSL");
181
182 map(vc_IPA:IPA_PORT, system:IPA_CODEC_PT);
183 connect(vc_IPA:IPA_RSL_PORT, vc_RSL:IPA_PT);
184 connect(self:RSL_CCHAN, vc_RSL:CCHAN_PT);
185
186 vc_IPA.start(IPA_Emulation.main_server(mp_rsl_ip, mp_rsl_port));
187 vc_RSL.start(RSL_Emulation.main(false));
188}
189
190type record ConnHdlrPars {
191 RslChannelNr chan_nr,
192 RSL_IE_ChannelMode chan_mode,
193 float t_guard,
Harald Welte0472ab42018-03-12 15:02:26 +0100194 ConnL1Pars l1_pars,
Harald Weltee613f962018-04-18 22:38:16 +0200195 TestSpecUnion spec optional,
Eric Wild61edb7e2019-06-03 12:38:31 +0200196 RSL_IE_EncryptionInfo encr optional,
197 BtsBand bts0_band optional
Harald Welte0472ab42018-03-12 15:02:26 +0100198}
199
200/* Test-specific parameters */
201type union TestSpecUnion {
202 RllTestCase rll
Harald Welte70767382018-02-21 12:16:40 +0100203}
204
Harald Welte82ccef72018-02-25 16:17:33 +0100205template (value) RachControlParameters ts_RachCtrl_default := {
Harald Welte0fd1fb02018-03-10 17:19:50 +0100206 max_retrans := RACH_MAX_RETRANS_7,
207 tx_integer := '1001'B, /* 12 slots */
Harald Welte82ccef72018-02-25 16:17:33 +0100208 cell_barr_access := false,
209 re_not_allowed := true,
Harald Welteb9585f82018-03-10 17:18:47 +0100210 acc := '0000010000000000'B
Harald Welte82ccef72018-02-25 16:17:33 +0100211};
212
Harald Weltef10153f2018-02-25 16:34:05 +0100213template (value) CellSelectionParameters ts_CellSelPar_default := {
Harald Welte0fd1fb02018-03-10 17:19:50 +0100214 cell_resel_hyst_2dB := 2,
Pau Espin Pedroled359cb2018-09-28 16:08:24 +0200215 ms_txpwr_max_cch := mp_ms_power_level_exp,
Harald Weltef10153f2018-02-25 16:34:05 +0100216 acs := '0'B,
217 neci := true,
218 rxlev_access_min := 0
219}
220
221template (value) LocationAreaIdentification ts_LAI_default := {
222 mcc_mnc := '262F42'H,
223 lac := 42
224}
225
Harald Welte7484fc42018-02-24 14:09:45 +0100226/* Default SYSTEM INFORMATION 3 */
Harald Weltef8df4cb2018-03-10 15:15:08 +0100227template (value) SystemInformation ts_SI3_default := {
228 header := ts_RrHeader(SYSTEM_INFORMATION_TYPE_3, 18),
Harald Welte7484fc42018-02-24 14:09:45 +0100229 payload := {
230 si3 := {
231 cell_id := 23,
Harald Weltef10153f2018-02-25 16:34:05 +0100232 lai := ts_LAI_default,
Harald Welte7484fc42018-02-24 14:09:45 +0100233 ctrl_chan_desc := {
234 msc_r99 := true,
235 att := true,
236 bs_ag_blks_res := 1,
237 ccch_conf := CCHAN_DESC_1CCCH_COMBINED,
Harald Welte82ccef72018-02-25 16:17:33 +0100238 si22ind := false,
Harald Welte7484fc42018-02-24 14:09:45 +0100239 cbq3 := CBQ3_IU_MODE_NOT_SUPPORTED,
240 spare := '00'B,
241 bs_pa_mfrms := 0, /* 2 multiframes */
242 t3212 := 1 /* 6 minutes */
243 },
Harald Welte82ccef72018-02-25 16:17:33 +0100244 cell_options := {
Harald Welte7484fc42018-02-24 14:09:45 +0100245 dn_ind := false,
246 pwrc := false,
247 dtx := MS_MAY_USE_UL_DTX,
Harald Welte0fd1fb02018-03-10 17:19:50 +0100248 radio_link_tout_div4 := (32/4)-1
Harald Welte7484fc42018-02-24 14:09:45 +0100249 },
Harald Weltef10153f2018-02-25 16:34:05 +0100250 cell_sel_par := ts_CellSelPar_default,
Harald Welte82ccef72018-02-25 16:17:33 +0100251 rach_control := ts_RachCtrl_default,
Harald Weltebe030482019-05-27 22:29:35 +0200252 rest_octets := '2C2B2B2B'O /* GPRS present */
Harald Welte7484fc42018-02-24 14:09:45 +0100253 }
254 }
255}
Harald Welte70767382018-02-21 12:16:40 +0100256
Harald Weltef8df4cb2018-03-10 15:15:08 +0100257template (value) SystemInformation ts_SI2_default := {
258 header := ts_RrHeader(SYSTEM_INFORMATION_TYPE_2, 22),
Harald Weltef10153f2018-02-25 16:34:05 +0100259 payload := {
260 si2 := {
261 bcch_freq_list := '00000000000000000000000000000000'O,
262 ncc_permitted := '11111111'B,
263 rach_control := ts_RachCtrl_default
264 }
265 }
266}
267
Harald Weltef8df4cb2018-03-10 15:15:08 +0100268template (value) SystemInformation ts_SI4_default := {
269 header := ts_RrHeader(SYSTEM_INFORMATION_TYPE_4, 12), /* no CBCH / restoct */
Harald Weltef10153f2018-02-25 16:34:05 +0100270 payload := {
271 si4 := {
272 lai := ts_LAI_default,
273 cell_sel_par := ts_CellSelPar_default,
274 rach_control := ts_RachCtrl_default,
275 cbch_chan_desc := omit,
276 cbch_mobile_alloc := omit,
277 rest_octets := ''O
278 }
279 }
280}
281
282function f_rsl_bcch_fill_raw(RSL_IE_SysinfoType rsl_si_type, octetstring si_enc)
283runs on test_CT {
284 log("Setting ", rsl_si_type, ": ", si_enc);
285 RSL_CCHAN.send(ts_RSL_UD(ts_RSL_BCCH_INFO(rsl_si_type, si_enc)));
286}
287
288function f_rsl_bcch_fill(RSL_IE_SysinfoType rsl_si_type, template (value) SystemInformation si_dec)
289runs on test_CT {
290 var octetstring si_enc := enc_SystemInformation(valueof(si_dec));
291 log("Setting ", rsl_si_type, ": ", si_dec);
292 f_rsl_bcch_fill_raw(rsl_si_type, si_enc);
293}
294
Harald Welte505cf9b2018-09-15 17:47:23 +0300295friend function f_init_vty(charstring id) runs on test_CT {
Harald Welte8da48242018-02-27 20:41:32 +0100296 map(self:BTSVTY, system:BTSVTY);
297 f_vty_set_prompts(BTSVTY);
298 f_vty_transceive(BTSVTY, "enable");
299}
300
Harald Welte505cf9b2018-09-15 17:47:23 +0300301friend function f_init_vty_bsc() runs on test_CT {
Harald Weltef50e3ae2018-09-10 10:27:56 +0200302 map(self:BSCVTY, system:BSCVTY);
303 f_vty_set_prompts(BSCVTY, "OsmoBSC");
304 f_vty_transceive(BSCVTY, "enable");
305}
306
Harald Welte883340c2018-02-28 18:59:29 +0100307/* PCU socket may at any time receive a new INFO.ind */
Harald Weltef26de0b2018-04-04 20:28:05 +0200308private altstep as_pcu_info_ind(PCUIF_CODEC_PT pt, integer pcu_conn_id,
309 out PCUIF_Message pcu_last_info) {
Harald Welte883340c2018-02-28 18:59:29 +0100310 var PCUIF_send_data sd;
Harald Weltef26de0b2018-04-04 20:28:05 +0200311 [] pt.receive(t_SD_PCUIF(pcu_conn_id, tr_PCUIF_INFO_IND(0, ?))) -> value sd {
312 pcu_last_info := sd.data;
Harald Welted378a252018-03-13 17:02:14 +0100313 }
Harald Weltef26de0b2018-04-04 20:28:05 +0200314 [] pt.receive(t_SD_PCUIF(pcu_conn_id, tr_PCUIF_INFO_IND(?, ?, ?))) -> value sd {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +0200315 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Invalid PCU Version/BTS Number received");
Harald Welte883340c2018-02-28 18:59:29 +0100316 }
317}
318
Harald Weltef26de0b2018-04-04 20:28:05 +0200319private function f_init_pcu(PCUIF_CODEC_PT pt, charstring id,
320 out integer pcu_conn_id, out PCUIF_Message pcu_last_info) {
Harald Welte883340c2018-02-28 18:59:29 +0100321 timer T := 2.0;
322 var PCUIF_send_data sd;
Harald Welte84271622018-03-10 17:21:03 +0100323 if (mp_pcu_socket == "") {
Harald Weltef26de0b2018-04-04 20:28:05 +0200324 pcu_conn_id := -1;
Harald Welte84271622018-03-10 17:21:03 +0100325 return;
326 }
Oliver Smithc089b412019-08-29 14:25:11 +0200327
328 f_sleep(0.5); /* workaround for OS#4179 */
329
Harald Weltef26de0b2018-04-04 20:28:05 +0200330 pcu_conn_id := f_pcuif_connect(pt, mp_pcu_socket);
Harald Welte883340c2018-02-28 18:59:29 +0100331
332 T.start;
333 alt {
Harald Weltef26de0b2018-04-04 20:28:05 +0200334 [] as_pcu_info_ind(pt, pcu_conn_id, pcu_last_info);
Harald Welte883340c2018-02-28 18:59:29 +0100335 [] T.timeout {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +0200336 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout waiting for PCU INFO_IND");
Harald Welte883340c2018-02-28 18:59:29 +0100337 }
338 }
339}
340
Vadim Yanitskiyf4e997c2019-06-04 21:40:33 +0700341private function f_init_trxc(TRXC_CODEC_PT pt, charstring id,
342 out integer trxc_conn_id) {
343 var Result res;
344
345 res := TRXC_CodecPort_CtrlFunct.f_IPL4_connect(pt, mp_bts_trxc_ip, mp_bts_trxc_port,
346 "", -1, -1, { udp := {} }, {});
347 if (not ispresent(res.connId)) {
348 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
349 "Could not connect to the control (TRXC) interface " &
350 "of FakeTRX, check your configuration");
351 }
352 trxc_conn_id := res.connId;
353}
354
Harald Welte70767382018-02-21 12:16:40 +0100355/* global init function */
Harald Welte10474062019-05-30 16:48:17 +0200356function f_init() runs on test_CT {
357 var charstring id := testcasename();
Pau Espin Pedrol315e4712018-11-01 16:27:07 +0100358 timer T := mp_ipa_up_timeout;
Harald Welte629cc6b2018-03-11 17:19:05 +0100359 g_AllChannels := {
360 /* TS 1..4: TCH/F */
361 valueof(ts_RslChanNr_Bm(1)), valueof(ts_RslChanNr_Bm(2)),
362 valueof(ts_RslChanNr_Bm(3)), valueof(ts_RslChanNr_Bm(4)),
363 /* TS 5: TCH/H */
364 valueof(ts_RslChanNr_Lm(5,0)), valueof(ts_RslChanNr_Lm(5,1)),
365 /* TS 0: SDCCH/4 */
366 valueof(ts_RslChanNr_SDCCH4(0,0)), valueof(ts_RslChanNr_SDCCH4(0,1)),
367 valueof(ts_RslChanNr_SDCCH4(0,2)), valueof(ts_RslChanNr_SDCCH4(0,3)),
368 /* TS 6: SDCCH/8 */
369 valueof(ts_RslChanNr_SDCCH8(6,0)), valueof(ts_RslChanNr_SDCCH8(6,1)),
370 valueof(ts_RslChanNr_SDCCH8(6,2)), valueof(ts_RslChanNr_SDCCH8(6,3)),
371 valueof(ts_RslChanNr_SDCCH8(6,4)), valueof(ts_RslChanNr_SDCCH8(6,5)),
372 valueof(ts_RslChanNr_SDCCH8(6,6)), valueof(ts_RslChanNr_SDCCH8(6,7))
373 };
374
Pau Espin Pedrol3dcf38f2018-10-22 14:07:54 +0200375 /* FIXME: FACCH/H is unreliable with calypso firmware, see OS#3653 */
Vadim Yanitskiy44ff2142019-01-12 07:04:58 +0700376 if (mp_bts_trxc_port != -1) {
Pau Espin Pedrol3dcf38f2018-10-22 14:07:54 +0200377 g_AllChanTypes := {
378 /* TS 1..4: TCH/F */
379 valueof(ts_RslChanNr_Bm(1)),
380 /* TS 5: TCH/H */
381 valueof(ts_RslChanNr_Lm(5,1)),
382 /* TS 0: SDCCH/4 */
383 valueof(ts_RslChanNr_SDCCH4(0,2)),
384 /* TS 6: SDCCH/8 */
385 valueof(ts_RslChanNr_SDCCH8(6,4))
386 };
387 } else {
388 g_AllChanTypes := {
389 /* TS 1..4: TCH/F */
390 valueof(ts_RslChanNr_Bm(1)),
391 /* TS 0: SDCCH/4 */
392 valueof(ts_RslChanNr_SDCCH4(0,2)),
393 /* TS 6: SDCCH/8 */
394 valueof(ts_RslChanNr_SDCCH8(6,4))
395 };
396 }
Harald Welte70767382018-02-21 12:16:40 +0100397 f_init_rsl(id);
Harald Welte83f6dbf2018-06-03 18:26:50 +0200398 T.start;
399 alt {
400 [] RSL_CCHAN.receive(ASP_IPA_Event:{up_down := ASP_IPA_EVENT_UP});
401 [] T.timeout {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +0200402 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout waiting for ASP_IPA_EVENT_UP");
Harald Welte83f6dbf2018-06-03 18:26:50 +0200403 }
404 }
Harald Welte2d142592018-02-25 13:19:44 +0100405 f_sleep(0.5); /* workaround for OS#3000 */
Harald Welte8da48242018-02-27 20:41:32 +0100406 f_init_vty(id);
Neels Hofmeyr6a84b232018-04-03 19:12:36 +0200407 f_ipa_ctrl_start(mp_ctrl_ip, mp_ctrl_port);
Harald Welte7484fc42018-02-24 14:09:45 +0100408
409 /* Send SI3 to the BTS, it is needed for various computations */
Harald Weltef10153f2018-02-25 16:34:05 +0100410 f_rsl_bcch_fill(RSL_SYSTEM_INFO_3, ts_SI3_default);
411 /* SI2 + SI4 are required for SI testing as they are mandatory defaults */
412 f_rsl_bcch_fill(RSL_SYSTEM_INFO_2, ts_SI2_default);
413 f_rsl_bcch_fill(RSL_SYSTEM_INFO_4, ts_SI4_default);
Harald Welte57fe8232018-02-26 17:52:50 +0100414
Harald Weltef26de0b2018-04-04 20:28:05 +0200415 map(self:PCU, system:PCU);
416 f_init_pcu(PCU, id, g_pcu_conn_id, g_pcu_last_info);
Harald Welte883340c2018-02-28 18:59:29 +0100417
Vadim Yanitskiy44ff2142019-01-12 07:04:58 +0700418 if (mp_bts_trxc_port != -1) {
Harald Welte84271622018-03-10 17:21:03 +0100419 var TrxcMessage ret;
Vadim Yanitskiyf4e997c2019-06-04 21:40:33 +0700420
421 /* Init TRXC interface to FakeTRX */
422 map(self:BTS_TRXC, system:BTS_TRXC);
423 f_init_trxc(BTS_TRXC, id, g_bts_trxc_conn_id);
424
Vadim Yanitskiy10d72462019-06-04 22:27:52 +0700425 /* Start with a default moderate timing offset equalling TA=2, and RSSI=-60 */
Vadim Yanitskiy44ff2142019-01-12 07:04:58 +0700426 ret := f_TRXC_transceive(BTS_TRXC, g_bts_trxc_conn_id, valueof(ts_TRXC_FAKE_TIMING(2*256)));
Vadim Yanitskiy10d72462019-06-04 22:27:52 +0700427 ret := f_TRXC_transceive(BTS_TRXC, g_bts_trxc_conn_id, valueof(ts_TRXC_FAKE_RSSI(-60)));
Vadim Yanitskiyde535e02019-07-26 16:29:27 +0700428 /* OsmoBTS may have different AB / NB threshold (see MIN_QUAL_NORM, MIN_QUAL_RACH) */
429 ret := f_TRXC_transceive(BTS_TRXC, g_bts_trxc_conn_id, valueof(ts_TRXC_FAKE_CI(60)));
Harald Welte84271622018-03-10 17:21:03 +0100430 }
Philipp Maierd95f3402019-04-18 17:50:52 +0200431
432 /* Wait some extra time to make sure the BTS emits a stable carrier.
433 * (this is only relevant when running the tests with a physical BTS.) */
434 f_sleep(mp_ipa_up_delay);
Harald Welte70767382018-02-21 12:16:40 +0100435}
436
Harald Welte68e495b2018-02-25 00:05:57 +0100437/* Attach L1CTL to master test_CT (classic tests, non-handler mode) */
438function f_init_l1ctl() runs on test_CT {
439 map(self:L1CTL, system:L1CTL);
440 f_connect_reset(L1CTL);
441}
442
Harald Welte70767382018-02-21 12:16:40 +0100443type function void_fn(charstring id) runs on ConnHdlr;
444
445/* create a new test component */
Vadim Yanitskiyf4e997c2019-06-04 21:40:33 +0700446function f_start_handler(void_fn fn, ConnHdlrPars pars,
447 boolean pcu_comp := false,
448 boolean trxc_comp := false)
Harald Welte70767382018-02-21 12:16:40 +0100449runs on test_CT return ConnHdlr {
450 var charstring id := testcasename();
451 var ConnHdlr vc_conn;
452
453 vc_conn := ConnHdlr.create(id);
454 /* connect to RSL Emulation main component */
455 connect(vc_conn:RSL, vc_RSL:CLIENT_PT);
456 connect(vc_conn:RSL_PROC, vc_RSL:RSL_PROC);
Vadim Yanitskiyf4e997c2019-06-04 21:40:33 +0700457
458 /* The ConnHdlr component may want to talk to some ports directly,
459 * so we disconnect it from the test_CT and connect it to the component.
460 * This obviously only works for one component, i.e. no concurrency. */
Harald Weltef26de0b2018-04-04 20:28:05 +0200461 if (pcu_comp) {
Harald Weltef26de0b2018-04-04 20:28:05 +0200462 unmap(self:PCU, system:PCU);
463 map(vc_conn:PCU, system:PCU);
464 }
Vadim Yanitskiyf4e997c2019-06-04 21:40:33 +0700465 if (trxc_comp) {
466 unmap(self:BTS_TRXC, system:BTS_TRXC);
467 map(vc_conn:BTS_TRXC, system:BTS_TRXC);
468 }
Harald Welte70767382018-02-21 12:16:40 +0100469
470 vc_conn.start(f_handler_init(fn, id, pars));
471 return vc_conn;
472}
473
Harald Welte7484fc42018-02-24 14:09:45 +0100474template ASP_RSL_Unitdata ts_RSL_UD(template RSL_Message rsl, IpaStreamId sid := IPAC_PROTO_RSL_TRX0) := {
475 streamId := sid,
476 rsl := rsl
477}
478
479template ASP_RSL_Unitdata tr_RSL_UD(template RSL_Message rsl,
480 template IpaStreamId sid := IPAC_PROTO_RSL_TRX0) := {
481 streamId := sid,
482 rsl := rsl
483}
484
Harald Welte70767382018-02-21 12:16:40 +0100485private altstep as_Tguard() runs on ConnHdlr {
486 [] g_Tguard.timeout {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +0200487 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Tguard timeout");
Harald Welte70767382018-02-21 12:16:40 +0100488 }
489}
490
Harald Welte990a3612019-05-27 14:02:13 +0200491friend function f_l1_tune(L1CTL_PT L1CTL, L1ctlCcchMode ccch_mode := CCCH_MODE_COMBINED) {
492 f_L1CTL_FBSB(L1CTL, { false, mp_trx0_arfcn }, ccch_mode, mp_rxlev_exp);
Harald Welte70767382018-02-21 12:16:40 +0100493}
494
Vadim Yanitskiy2f01fbd2019-06-01 01:32:48 +0700495private function f_trxc_fake_rssi(TRXC_RSSI rssi) runs on ConnHdlr {
Harald Weltef8df4cb2018-03-10 15:15:08 +0100496 var TrxcMessage ret;
Vadim Yanitskiy44ff2142019-01-12 07:04:58 +0700497 ret := f_TRXC_transceive(BTS_TRXC, g_bts_trxc_conn_id, valueof(ts_TRXC_FAKE_RSSI(rssi)));
Harald Welte70767382018-02-21 12:16:40 +0100498}
499
Vadim Yanitskiydc8db922019-06-04 21:58:15 +0700500private function f_trxc_fake_toffs256(int16_t toffs256) runs on ConnHdlr {
Harald Weltef8df4cb2018-03-10 15:15:08 +0100501 var TrxcMessage ret;
Vadim Yanitskiy44ff2142019-01-12 07:04:58 +0700502 ret := f_TRXC_transceive(BTS_TRXC, g_bts_trxc_conn_id, valueof(ts_TRXC_FAKE_TIMING(toffs256)));
Harald Welte70767382018-02-21 12:16:40 +0100503}
504
505/* first function started in ConnHdlr component */
506private function f_handler_init(void_fn fn, charstring id, ConnHdlrPars pars)
507runs on ConnHdlr {
508 g_pars := pars;
509 g_chan_nr := pars.chan_nr;
510
511 map(self:L1CTL, system:L1CTL);
512 f_connect_reset(L1CTL);
513
Harald Welted48c0c72019-06-05 10:01:15 +0200514 if (mp_bts_trxc_port != -1 and BTS_TRXC.checkstate("Mapped")) {
Vadim Yanitskiyf4e997c2019-06-04 21:40:33 +0700515 f_init_trxc(BTS_TRXC, id, g_bts_trxc_conn_id);
Harald Welte84271622018-03-10 17:21:03 +0100516 }
Harald Welte70767382018-02-21 12:16:40 +0100517
518 g_Tguard.start(pars.t_guard);
519 activate(as_Tguard());
520
521 f_rslem_register(0, pars.chan_nr);
522
523 /* call the user-supplied test case function */
524 fn.apply(id);
525}
526
Harald Welteb1726c92018-03-30 11:56:38 +0200527function f_rsl_transceive_ret(template RSL_Message tx, template RSL_Message exp_rx, charstring id,
528 boolean ignore_other := false)
529runs on ConnHdlr return RSL_Message {
530 var RSL_Message rx;
Harald Welte1eba3742018-02-25 12:48:14 +0100531 timer T := 3.0;
532 RSL.send(tx);
533 T.start;
Harald Welte70767382018-02-21 12:16:40 +0100534 alt {
Harald Welteb1726c92018-03-30 11:56:38 +0200535 [] RSL.receive(exp_rx) -> value rx {
Harald Welte1eba3742018-02-25 12:48:14 +0100536 T.stop;
537 setverdict(pass);
Harald Welte70767382018-02-21 12:16:40 +0100538 }
Harald Welte1eba3742018-02-25 12:48:14 +0100539 [] T.timeout {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +0200540 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout expecting " & id);
Harald Welte1eba3742018-02-25 12:48:14 +0100541 }
Harald Welte21240e62018-03-11 21:43:35 +0100542 [not ignore_other] as_l1_sacch();
543 [not ignore_other] as_meas_res();
544 [not ignore_other] as_l1_dcch();
545 [not ignore_other] RSL.receive {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +0200546 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Unexpected RSL message received");
Harald Welte70767382018-02-21 12:16:40 +0100547 }
Harald Welte21240e62018-03-11 21:43:35 +0100548 [ignore_other] RSL.receive { repeat; }
Harald Welte70767382018-02-21 12:16:40 +0100549 }
Harald Welteb1726c92018-03-30 11:56:38 +0200550 return rx;
551}
552
553function f_rsl_transceive(template RSL_Message tx, template RSL_Message exp_rx, charstring id,
554 boolean ignore_other := false)
555runs on ConnHdlr {
556 var RSL_Message rx := f_rsl_transceive_ret(tx, exp_rx, id, ignore_other);
Harald Welte70767382018-02-21 12:16:40 +0100557}
558
Harald Welte8b01c792019-05-19 22:51:25 +0200559function f_rsl_chan_act(RSL_IE_ChannelMode mode, boolean encr_enable := false, RSL_IE_List more_ies := {},
560 RSL_IE_ActivationType act_type := t_RSL_IE_ActType_IA) runs on ConnHdlr {
561 var RSL_Message ch_act := valueof(ts_RSL_CHAN_ACT(g_chan_nr, mode, act_type));
Harald Weltee613f962018-04-18 22:38:16 +0200562 if (encr_enable) {
563 /* append encryption related IEs, if requested */
564 var RSL_IE_EncryptionInfo encr_info;
565 encr_info := valueof(ts_RSL_IE_EncrInfo(g_pars.encr.alg_id, g_pars.encr.key));
566 ch_act.ies := ch_act.ies & { valueof(t_RSL_IE(RSL_IE_ENCR_INFO, RSL_IE_Body:{encr_info :=
567encr_info})) };
568 }
Harald Weltec8d363c2019-05-19 20:36:48 +0200569 ch_act.ies := ch_act.ies & more_ies;
Harald Weltee613f962018-04-18 22:38:16 +0200570 f_rsl_transceive(ch_act, tr_RSL_CHAN_ACT_ACK(g_chan_nr), "RSL CHAN ACT");
Harald Welte1eba3742018-02-25 12:48:14 +0100571}
572
Harald Welte70767382018-02-21 12:16:40 +0100573function f_rsl_chan_deact() runs on ConnHdlr {
Harald Welte1eba3742018-02-25 12:48:14 +0100574 f_rsl_transceive(ts_RSL_RF_CHAN_REL(g_chan_nr), tr_RSL_RF_CHAN_REL_ACK(g_chan_nr),
Harald Welte21240e62018-03-11 21:43:35 +0100575 "RF CHAN REL", true);
Harald Welte70767382018-02-21 12:16:40 +0100576}
577
Harald Welte2f2b2b72019-05-31 22:24:57 +0200578friend template ConnHdlrPars t_Pars(template RslChannelNr chan_nr,
Harald Welte70767382018-02-21 12:16:40 +0100579 template RSL_IE_ChannelMode chan_mode,
580 float t_guard := 20.0) := {
581 chan_nr := valueof(chan_nr),
582 chan_mode := valueof(chan_mode),
583 t_guard := t_guard,
584 l1_pars := {
585 dtx_enabled := false,
Harald Welte685d5982018-02-27 20:42:05 +0100586 toa256_enabled := false,
Harald Welte70767382018-02-21 12:16:40 +0100587 meas_ul := {
588 full := {
Pau Espin Pedrole9571aa2018-10-22 17:13:07 +0200589 rxlev := mp_ul_rxlev_exp,
Harald Welte70767382018-02-21 12:16:40 +0100590 rxqual := 0
591 },
592 sub := {
Pau Espin Pedrole9571aa2018-10-22 17:13:07 +0200593 rxlev := mp_ul_rxlev_exp,
Harald Welte70767382018-02-21 12:16:40 +0100594 rxqual := 0
595 }
596 },
Pau Espin Pedrol121724c2018-09-28 15:58:12 +0200597 timing_offset_256syms := mp_timing_offset_256syms_exp,
Harald Welte70767382018-02-21 12:16:40 +0100598 bs_power_level := 0,
Pau Espin Pedroled359cb2018-09-28 16:08:24 +0200599 ms_power_level := mp_ms_power_level_exp,
Pau Espin Pedrol121724c2018-09-28 15:58:12 +0200600 ms_actual_ta := mp_ms_actual_ta_exp
Harald Welte0472ab42018-03-12 15:02:26 +0100601 },
Harald Weltee613f962018-04-18 22:38:16 +0200602 spec := omit,
Eric Wild61edb7e2019-06-03 12:38:31 +0200603 encr := omit,
604 bts0_band := omit
Harald Welte70767382018-02-21 12:16:40 +0100605}
606
Harald Welte93640c62018-02-25 16:59:33 +0100607/***********************************************************************
608 * Channel Activation / Deactivation
609 ***********************************************************************/
610
Harald Welte70767382018-02-21 12:16:40 +0100611/* Stress test: Do 500 channel activations/deactivations in rapid succession */
612function f_TC_chan_act_stress(charstring id) runs on ConnHdlr {
613 for (var integer i := 0; i < 500; i := i+1) {
614 f_rsl_chan_act(g_pars.chan_mode);
615 f_rsl_chan_deact();
616 }
617 setverdict(pass);
618}
619testcase TC_chan_act_stress() runs on test_CT {
620 var ConnHdlr vc_conn;
621 var ConnHdlrPars pars := valueof(t_Pars(t_RslChanNr_Bm(1), ts_RSL_ChanMode_SIGN));
Harald Welte10474062019-05-30 16:48:17 +0200622 f_init();
Harald Welte70767382018-02-21 12:16:40 +0100623 vc_conn := f_start_handler(refers(f_TC_chan_act_stress), pars);
624 vc_conn.done;
Daniel Willmann0fcc4d32018-10-23 20:32:19 +0200625 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
Harald Welte70767382018-02-21 12:16:40 +0100626}
627
628/* Test if re-activation of an already active channel fails as expected */
629function f_TC_chan_act_react(charstring id) runs on ConnHdlr {
630 f_rsl_chan_act(g_pars.chan_mode);
631 /* attempt to activate the same lchan again -> expect reject */
632 RSL.send(ts_RSL_CHAN_ACT(g_chan_nr, g_pars.chan_mode));
633 alt {
634 [] RSL.receive(tr_RSL_CHAN_ACT_ACK(g_chan_nr)) {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +0200635 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Unexpected CHAN ACT ACK on double activation");
Harald Welte70767382018-02-21 12:16:40 +0100636 }
637 [] RSL.receive(tr_RSL_CHAN_ACT_NACK(g_chan_nr)) {
638 setverdict(pass);
639 }
640 }
641 f_rsl_chan_deact();
642}
643testcase TC_chan_act_react() runs on test_CT {
644 var ConnHdlr vc_conn;
645 var ConnHdlrPars pars := valueof(t_Pars(t_RslChanNr_Bm(1), ts_RSL_ChanMode_SIGN));
Harald Welte294b0a22018-03-10 23:26:48 +0100646 f_init();
Harald Welte70767382018-02-21 12:16:40 +0100647 vc_conn := f_start_handler(refers(f_TC_chan_act_react), pars);
648 vc_conn.done;
Daniel Willmann0fcc4d32018-10-23 20:32:19 +0200649 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
Harald Welte70767382018-02-21 12:16:40 +0100650}
651
652/* Attempt to de-activate a channel that's not active */
653function f_TC_chan_deact_not_active(charstring id) runs on ConnHdlr {
654 timer T := 3.0;
655 RSL.send(ts_RSL_RF_CHAN_REL(g_chan_nr));
656 T.start;
657 alt {
658 [] RSL.receive(tr_RSL_RF_CHAN_REL_ACK(g_chan_nr)) {
659 setverdict(pass);
660 }
661 [] T.timeout {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +0200662 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout expecting RF_CHAN_REL_ACK");
Harald Welte70767382018-02-21 12:16:40 +0100663 }
664 }
665}
666testcase TC_chan_deact_not_active() runs on test_CT {
667 var ConnHdlrPars pars := valueof(t_Pars(t_RslChanNr_Bm(1), ts_RSL_ChanMode_SIGN));
Harald Welte294b0a22018-03-10 23:26:48 +0100668 f_init();
Harald Welte70767382018-02-21 12:16:40 +0100669 var ConnHdlr vc_conn := f_start_handler(refers(f_TC_chan_deact_not_active), pars);
670 vc_conn.done;
Daniel Willmann0fcc4d32018-10-23 20:32:19 +0200671 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
Harald Welte70767382018-02-21 12:16:40 +0100672}
673
674/* attempt to activate channel with wrong RSL Channel Nr IE; expect NACK */
675function f_TC_chan_act_wrong_nr(charstring id) runs on ConnHdlr {
676 RSL.send(ts_RSL_CHAN_ACT(g_chan_nr, g_pars.chan_mode));
677 alt {
678 [] RSL.receive(tr_RSL_CHAN_ACT_ACK(g_chan_nr)) {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +0200679 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Unexpected CHAN ACT ACK");
Harald Welte70767382018-02-21 12:16:40 +0100680 }
681 [] RSL.receive(tr_RSL_CHAN_ACT_NACK(g_chan_nr)) {
682 setverdict(pass);
683 }
684 }
685}
686private type record WrongChanNrCase {
687 RslChannelNr chan_nr,
688 charstring description
689}
690private type record of WrongChanNrCase WrongChanNrCases;
691private template WrongChanNrCase t_WCN(template RslChannelNr chan_nr, charstring desc) := {
692 chan_nr := chan_nr,
693 description := desc
694}
695
696testcase TC_chan_act_wrong_nr() runs on test_CT {
697 var ConnHdlr vc_conn;
698 var ConnHdlrPars pars;
699
Harald Welte294b0a22018-03-10 23:26:48 +0100700 f_init();
Harald Welte70767382018-02-21 12:16:40 +0100701
702 var WrongChanNrCases wrong := {
703 valueof(t_WCN(t_RslChanNr_RACH(0), "RACH is not a dedicated channel")),
704 valueof(t_WCN(t_RslChanNr_RACH(1), "RACH doesn't exist on timeslot")),
705 valueof(t_WCN(t_RslChanNr_BCCH(0), "BCCH is not a dedicated channel")),
706 valueof(t_WCN(t_RslChanNr_PCH_AGCH(0), "PCH/AGCH is not a dedicated channel")),
707 valueof(t_WCN(t_RslChanNr_Bm(0), "TS0 cannot be TCH/F")),
708 valueof(t_WCN(t_RslChanNr_Lm(0, 0), "TS0 cannot be TCH/H")),
709 valueof(t_WCN(t_RslChanNr_Lm(0, 1), "TS0 cannot be TCH/H")),
710 valueof(t_WCN(t_RslChanNr_PDCH(0), "TS0 cannot be PDCH")),
711 valueof(t_WCN(t_RslChanNr_SDCCH8(0, 0), "TS0 cannot be SDCCH/8")),
712 valueof(t_WCN(t_RslChanNr_SDCCH8(0, 7), "TS0 cannot be SDCCH/8")),
713 valueof(t_WCN(t_RslChanNr_SDCCH4(7, 0), "TS7 cannot be SDCCH/4")),
714 valueof(t_WCN(t_RslChanNr_SDCCH4(7, 3), "TS7 cannot be SDCCH/4")),
715 valueof(t_WCN(t_RslChanNr_Lm(1, 0), "TS1 cannot be TCH/H"))
716 };
717
718 for (var integer i := 0; i < sizeof(wrong); i := i+1) {
719 pars := valueof(t_Pars(wrong[i].chan_nr, ts_RSL_ChanMode_SIGN));
720 vc_conn := f_start_handler(refers(f_TC_chan_act_wrong_nr), pars);
721 vc_conn.done;
722 }
Daniel Willmann0fcc4d32018-10-23 20:32:19 +0200723 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
Harald Welte70767382018-02-21 12:16:40 +0100724}
725
Harald Weltee613f962018-04-18 22:38:16 +0200726/* execute the same callback function on a variety of logical channels */
Harald Welte2f2b2b72019-05-31 22:24:57 +0200727friend function f_testmatrix_each_chan(ConnHdlrPars pars, void_fn fn) runs on test_CT {
Harald Weltee613f962018-04-18 22:38:16 +0200728 var ConnHdlr vc_conn;
Harald Welte10474062019-05-30 16:48:17 +0200729 f_init();
Harald Weltee613f962018-04-18 22:38:16 +0200730
731 /* test on each of the channels we have */
732 for (var integer i := 0; i < sizeof(g_AllChanTypes); i := i+1) {
733 pars.chan_nr := valueof(g_AllChanTypes[i]);
734
735 log(testcasename(), ": XXX Starting on ", g_AllChanTypes[i]);
736 vc_conn := f_start_handler(fn, pars);
737 vc_conn.done;
738 }
739
Daniel Willmann0fcc4d32018-10-23 20:32:19 +0200740 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
Harald Weltee613f962018-04-18 22:38:16 +0200741}
742
Harald Welte93640c62018-02-25 16:59:33 +0100743/***********************************************************************
Harald Welte629cc6b2018-03-11 17:19:05 +0100744 * SACCH handling
745 ***********************************************************************/
746
747private function f_exp_sacch(boolean exp) runs on ConnHdlr {
748 timer T_sacch := 3.0;
749 T_sacch.start;
750 alt {
751 [not exp] L1CTL.receive(tr_L1CTL_DATA_IND(g_chan_nr, tr_RslLinkID_SACCH(0))) {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +0200752 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Received SACCH when not expecting it");
Harald Welte629cc6b2018-03-11 17:19:05 +0100753 }
754 [not exp] T_sacch.timeout {
755 setverdict(pass);
756 }
757 [exp] L1CTL.receive(tr_L1CTL_DATA_IND(g_chan_nr, tr_RslLinkID_SACCH(0))) {
758 setverdict(pass);
759 }
760 [exp] T_sacch.timeout {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +0200761 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("Timeout waiting for SACCH on ", g_chan_nr));
Harald Welte629cc6b2018-03-11 17:19:05 +0100762 }
763 [] L1CTL.receive { repeat; }
764 [] RSL.receive { repeat; }
765 }
766}
767
768/* Test if DEACTIVATE SACCH actualy deactivates its transmission (TS 48.058 4.6) */
769private function f_TC_deact_sacch(charstring id) runs on ConnHdlr {
770 f_l1_tune(L1CTL);
771 RSL.clear;
772
773 /* activate the logical channel */
774 f_est_dchan();
775 L1CTL.clear;
776
777 /* check that SACCH actually are received as expected */
778 f_exp_sacch(true);
779
780 /* deactivate SACCH on the logical channel */
781 RSL.send(ts_RSL_DEACT_SACCH(g_chan_nr));
782 f_sleep(1.0);
783 L1CTL.clear;
784
785 /* check that no SACCH are received anymore */
786 f_exp_sacch(false);
787
788 /* release the channel */
789 f_rsl_chan_deact();
790 f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
791}
792testcase TC_deact_sacch() runs on test_CT {
793 var ConnHdlr vc_conn;
794 var ConnHdlrPars pars;
795 f_init();
796 for (var integer i := 0; i < sizeof(g_AllChannels); i := i+1) {
797 //for (var integer i := 0; i < 1; i := i+1) {
798 pars := valueof(t_Pars(g_AllChannels[i], ts_RSL_ChanMode_SIGN));
799 log(testcasename(), ": Starting for ", g_AllChannels[i]);
800 vc_conn := f_start_handler(refers(f_TC_deact_sacch), pars);
801 vc_conn.done;
802 }
803 /* TODO: do the above in parallel, rather than sequentially? */
Daniel Willmann0fcc4d32018-10-23 20:32:19 +0200804 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
Harald Welte629cc6b2018-03-11 17:19:05 +0100805}
806
Harald Welte55700662018-03-12 13:15:43 +0100807/* verify that given SACCH payload is present */
Harald Welteea17b912018-03-11 22:29:31 +0100808private function f_sacch_present(template octetstring l3_exp) runs on ConnHdlr {
809 var L1ctlDlMessage dl;
810 /* check that the specified SI5 value is actually sent */
811 timer T_sacch := 3.0;
812 L1CTL.clear;
813 T_sacch.start;
814 alt {
815 [] L1CTL.receive(tr_L1CTL_DATA_IND(g_chan_nr, tr_RslLinkID_SACCH(0))) -> value dl {
816 var octetstring l3 := substr(dl.payload.data_ind.payload, 4, 19);
817 if (match(l3, l3_exp)) {
818 setverdict(pass);
819 } else {
820 repeat;
821 }
822 }
823 [] L1CTL.receive { repeat; }
824 [] T_sacch.timeout {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +0200825 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("Timeout waiting for SACCH ", l3_exp));
Harald Welteea17b912018-03-11 22:29:31 +0100826 }
827 }
828}
829
Harald Welte55700662018-03-12 13:15:43 +0100830/* verify that given SACCH payload is not present */
831private function f_sacch_missing(template octetstring l3_exp) runs on ConnHdlr {
832 var L1ctlDlMessage dl;
833 /* check that the specified SI5 value is actually sent */
834 timer T_sacch := 3.0;
835 L1CTL.clear;
836 T_sacch.start;
837 alt {
838 [] L1CTL.receive(tr_L1CTL_DATA_IND(g_chan_nr, tr_RslLinkID_SACCH(0))) -> value dl {
839 var octetstring l3 := substr(dl.payload.data_ind.payload, 4, 19);
840 if (match(l3, l3_exp)) {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +0200841 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("Received unexpected SACCH ", dl));
Harald Welte55700662018-03-12 13:15:43 +0100842 } else {
843 repeat;
844 }
845 }
846 [] L1CTL.receive { repeat; }
847 [] T_sacch.timeout {
848 setverdict(pass);
849 }
850 }
851}
852
Harald Welte629cc6b2018-03-11 17:19:05 +0100853/* Test for default SACCH FILL transmitted in DL SACCH (all channel types) */
Harald Welteea17b912018-03-11 22:29:31 +0100854private function f_TC_sacch_filling(charstring id) runs on ConnHdlr {
855 /* Set a known default SACCH filling for SI5 */
856 var octetstring si5 := f_rnd_octstring(19);
857 RSL.send(ts_RSL_SACCH_FILL(RSL_SYSTEM_INFO_5, si5));
858
859 f_l1_tune(L1CTL);
860 RSL.clear;
861
862 /* activate the logical channel */
863 f_est_dchan();
864
865 /* check that the specified SI5 value is actually sent */
866 f_sacch_present(si5);
867
868 /* release the channel */
869 RSL.clear;
870 f_rsl_chan_deact();
871 f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
872}
873testcase TC_sacch_filling() runs on test_CT {
874 var ConnHdlr vc_conn;
875 var ConnHdlrPars pars;
876 f_init();
877 for (var integer i := 0; i < sizeof(g_AllChannels); i := i+1) {
878 pars := valueof(t_Pars(g_AllChannels[i], ts_RSL_ChanMode_SIGN));
879 log(testcasename(), ": Starting for ", g_AllChannels[i]);
880 vc_conn := f_start_handler(refers(f_TC_sacch_filling), pars);
881 vc_conn.done;
882 }
883 /* TODO: do the above in parallel, rather than sequentially? */
Daniel Willmann0fcc4d32018-10-23 20:32:19 +0200884 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
Harald Welteea17b912018-03-11 22:29:31 +0100885}
886
Harald Welte629cc6b2018-03-11 17:19:05 +0100887/* Test for lchan-specific SACCH INFO MODIFY (TS 48.058 4.12) */
Harald Welteea17b912018-03-11 22:29:31 +0100888private function f_TC_sacch_info_mod(charstring id) runs on ConnHdlr {
889 /* Set a known default SACCH filling for SI5 */
890 var octetstring si5 := f_rnd_octstring(19);
891 var octetstring si5_diff := f_rnd_octstring(19);
892 RSL.send(ts_RSL_SACCH_FILL(RSL_SYSTEM_INFO_5, si5));
893
894 f_l1_tune(L1CTL);
895 RSL.clear;
896
897 log("Activating channel, expecting standard SI5");
898 /* activate the logical channel */
899 f_est_dchan();
900 /* check that the specified SI5 value is actually sent */
901 f_sacch_present(si5);
902
903 /* set channel-specific different SI5 */
904 log("Setting channel specific SACCH INFO, expecting it");
905 RSL.send(ts_RSL_SACCH_INF_MOD(g_chan_nr, RSL_SYSTEM_INFO_5, si5_diff))
906 /* check that the specified lchan-specific value is now used */
907 f_sacch_present(si5_diff);
908
909 /* deactivate the channel and re-activate it, this should result in default SI5 */
910 log("De-activating and re-activating channel, expecting standard SI5");
911 f_rsl_chan_deact();
912 f_rsl_chan_act(valueof(ts_RSL_ChanMode_SIGN));
913 /* Verify that the TRX-wide default SACCH filling is present again */
914 f_sacch_present(si5);
915
916 /* release the channel */
917 RSL.clear;
918 f_rsl_chan_deact();
919 f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
920}
921testcase TC_sacch_info_mod() runs on test_CT {
922 var ConnHdlr vc_conn;
923 var ConnHdlrPars pars;
924 f_init();
925 for (var integer i := 0; i < sizeof(g_AllChannels); i := i+1) {
926 pars := valueof(t_Pars(g_AllChannels[i], ts_RSL_ChanMode_SIGN));
927 log(testcasename(), ": Starting for ", g_AllChannels[i]);
928 vc_conn := f_start_handler(refers(f_TC_sacch_info_mod), pars);
929 vc_conn.done;
930 }
931 /* TODO: do the above in parallel, rather than sequentially? */
Daniel Willmann0fcc4d32018-10-23 20:32:19 +0200932 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
Harald Welteea17b912018-03-11 22:29:31 +0100933}
934
Harald Welte075d84c2018-03-12 13:07:24 +0100935/* Test SACCH scheduling of multiple different SI message types */
936private function f_TC_sacch_multi(charstring id) runs on ConnHdlr {
937 var octetstring si5 := f_rnd_octstring(19);
938 var octetstring si5bis := f_rnd_octstring(19);
939 var octetstring si5ter := f_rnd_octstring(19);
940 var octetstring si6 := f_rnd_octstring(19);
941
942 RSL.send(ts_RSL_SACCH_FILL(RSL_SYSTEM_INFO_5, si5));
943 RSL.send(ts_RSL_SACCH_FILL(RSL_SYSTEM_INFO_5bis, si5bis));
944 RSL.send(ts_RSL_SACCH_FILL(RSL_SYSTEM_INFO_5ter, si5ter));
945 RSL.send(ts_RSL_SACCH_FILL(RSL_SYSTEM_INFO_6, si6));
946
947 f_l1_tune(L1CTL);
948 RSL.clear;
949
950 /* activate the logical channel */
951 f_est_dchan();
952 L1CTL.clear;
953
954 /* check that SACCH actually are received as expected */
955 f_sacch_present(si5);
956 f_sacch_present(si5bis);
957 f_sacch_present(si5ter);
958 f_sacch_present(si6);
959
960 /* release the channel */
961 f_rsl_chan_deact();
962 f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
963}
964testcase TC_sacch_multi() runs on test_CT {
965 var ConnHdlr vc_conn;
966 var ConnHdlrPars pars;
967 f_init();
968 for (var integer i := 0; i < sizeof(g_AllChannels); i := i+1) {
969 pars := valueof(t_Pars(g_AllChannels[i], ts_RSL_ChanMode_SIGN));
970 log(testcasename(), ": Starting for ", g_AllChannels[i]);
971 vc_conn := f_start_handler(refers(f_TC_sacch_multi), pars);
972 vc_conn.done;
973 }
974 /* TODO: do the above in parallel, rather than sequentially? */
Daniel Willmann0fcc4d32018-10-23 20:32:19 +0200975 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
Harald Welte075d84c2018-03-12 13:07:24 +0100976}
977
Harald Welte55700662018-03-12 13:15:43 +0100978/* Test if SACH information is modified as expected */
979private function f_TC_sacch_multi_chg(charstring id) runs on ConnHdlr {
980 var octetstring si5 := f_rnd_octstring(19);
981 var octetstring si6 := f_rnd_octstring(19);
982
983 /* First, configure both SI5 and SI6 to be transmitted */
984 RSL.send(ts_RSL_SACCH_FILL(RSL_SYSTEM_INFO_5, si5));
985 RSL.send(ts_RSL_SACCH_FILL(RSL_SYSTEM_INFO_6, si6));
986
987 f_l1_tune(L1CTL);
988 RSL.clear;
989
990 /* activate the logical channel */
991 f_est_dchan();
992 L1CTL.clear;
993
994 /* check that SACCH actually are received as expected */
995 f_sacch_present(si5);
996 f_sacch_present(si6);
997
998 /* disable SI6 */
999 RSL.send(ts_RSL_SACCH_FILL(RSL_SYSTEM_INFO_6, ''O));
1000
1001 /* check that SI5 is still transmitted */
1002 f_sacch_present(si5);
1003 /* check if SI6 is now gone */
1004 f_sacch_missing(si6);
1005
1006 /* release the channel */
1007 f_rsl_chan_deact();
1008 f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
1009}
1010testcase TC_sacch_multi_chg() runs on test_CT {
1011 var ConnHdlr vc_conn;
1012 var ConnHdlrPars pars;
1013 f_init();
1014 for (var integer i := 0; i < sizeof(g_AllChannels); i := i+1) {
1015 pars := valueof(t_Pars(g_AllChannels[i], ts_RSL_ChanMode_SIGN));
1016 log(testcasename(), ": Starting for ", g_AllChannels[i]);
1017 vc_conn := f_start_handler(refers(f_TC_sacch_multi_chg), pars);
1018 vc_conn.done;
1019 }
1020 /* TODO: do the above in parallel, rather than sequentially? */
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02001021 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
Harald Welte55700662018-03-12 13:15:43 +01001022}
1023
Harald Weltec8d363c2019-05-19 20:36:48 +02001024/* Test for SACCH information present in RSL CHAN ACT (overrides FILLING) */
1025private function f_TC_sacch_chan_act(charstring id) runs on ConnHdlr {
1026 var octetstring si5 := f_rnd_octstring(19);
1027 var octetstring si6 := f_rnd_octstring(19);
1028 var octetstring si5_specific := f_rnd_octstring(19);
1029 var octetstring si6_specific := f_rnd_octstring(19);
1030
1031 /* First, configure both SI5 and SI6 to be transmitted */
1032 RSL.send(ts_RSL_SACCH_FILL(RSL_SYSTEM_INFO_5, si5));
1033 RSL.send(ts_RSL_SACCH_FILL(RSL_SYSTEM_INFO_6, si6));
1034
1035 f_l1_tune(L1CTL);
1036 RSL.clear;
1037
1038 /* activate channel with different SACCH filling */
1039 var RSL_SacchInfo sacch_info := valueof(ts_RSL_SacchInfo({
1040 ts_RSL_SacchInfoElem(RSL_SYSTEM_INFO_5, si5_specific),
1041 ts_RSL_SacchInfoElem(RSL_SYSTEM_INFO_6, si6_specific)
1042 }));
1043 var RSL_IE_List addl_ies := { valueof(t_RSL_IE(RSL_IE_SACCH_INFO,
1044 RSL_IE_Body:{sacch_info := sacch_info})) };
1045 f_est_dchan(more_ies := addl_ies);
1046
1047 /* check that SACCH actually are received as expected */
1048 f_sacch_present(si5_specific);
1049 f_sacch_present(si6_specific);
1050
1051 /* release the channel */
1052 f_rsl_chan_deact();
1053 f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
1054}
1055testcase TC_sacch_chan_act() runs on test_CT {
1056 var ConnHdlr vc_conn;
1057 var ConnHdlrPars pars;
1058 f_init();
1059
1060 for (var integer i := 0; i < sizeof(g_AllChannels); i := i+1) {
1061 pars := valueof(t_Pars(g_AllChannels[i], ts_RSL_ChanMode_SIGN));
1062 log(testcasename(), ": Starting for ", g_AllChannels[i]);
1063 vc_conn := f_start_handler(refers(f_TC_sacch_chan_act), pars);
1064 vc_conn.done;
1065 }
1066 /* TODO: do the above in parallel, rather than sequentially? */
1067 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
1068}
1069
Harald Welte8b01c792019-05-19 22:51:25 +02001070/* verify that SACCH DL transmission is started only if MS power IE present
1071 * see section 4.1.3 of 3GPP TS 48.058 */
1072private function f_TC_sacch_chan_act_ho_async(charstring id) runs on ConnHdlr {
1073 var octetstring si5 := f_rnd_octstring(19);
1074
1075 f_l1_tune(L1CTL);
1076 RSL.clear;
1077
1078 /* Step 1: Activate ASYNC HO channel without MS power IE */
1079
1080 /* Activate channel on BTS side */
1081 f_rsl_chan_act(g_pars.chan_mode, act_type := t_RSL_IE_ActType_HO_ASYNC);
1082 /* don't perform immediate assignment here, as we're testing non-IA case */
1083 /* enable dedicated mode */
1084 f_L1CTL_DM_EST_REQ(L1CTL, {false, mp_trx0_arfcn }, g_pars.chan_nr, 7);
1085
1086 /* Verify that no DL SACCH is being received */
1087 f_sacch_missing(?);
1088
1089 f_rsl_chan_deact();
1090 f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
1091
1092
1093 /* Step 2: Activate ASYNC HO channel with MS power IE */
1094
1095 /* Activate channel on BTS side */
1096 var RSL_IE_List addl_ies := {
1097 valueof(t_RSL_IE(RSL_IE_MS_POWER, RSL_IE_Body:{ms_power := ts_RSL_IE_MS_Power(0)}))
1098 };
1099 f_rsl_chan_act(g_pars.chan_mode, more_ies := addl_ies, act_type := t_RSL_IE_ActType_HO_ASYNC);
1100 /* don't perform immediate assignment here, as we're testing non-IA case */
1101 /* enable dedicated mode */
1102 f_L1CTL_DM_EST_REQ(L1CTL, {false, mp_trx0_arfcn }, g_pars.chan_nr, 7);
1103
1104 /* Verify that DL SACCH is being received */
1105 f_sacch_present(si5);
1106
1107 f_rsl_chan_deact();
1108 f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
1109}
1110testcase TC_sacch_chan_act_ho_async() runs on test_CT {
1111 var ConnHdlr vc_conn;
1112 var ConnHdlrPars pars;
1113 f_init();
1114
1115 for (var integer i := 0; i < sizeof(g_AllChannels); i := i+1) {
1116 pars := valueof(t_Pars(g_AllChannels[i], ts_RSL_ChanMode_SIGN));
1117 log(testcasename(), ": Starting for ", g_AllChannels[i]);
1118 vc_conn := f_start_handler(refers(f_TC_sacch_chan_act_ho_async), pars);
1119 vc_conn.done;
1120 }
1121 /* TODO: do the above in parallel, rather than sequentially? */
1122 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
1123}
1124
1125/* verify that SACCH DL transmission is started only if TA + MS power IEs present,
1126 * see section 4.1.4 of 3GPP TS 48.058 */
1127private function f_TC_sacch_chan_act_ho_sync(charstring id) runs on ConnHdlr {
1128 var octetstring si5 := f_rnd_octstring(19);
1129 var RSL_IE_List addl_ies;
1130
1131 f_l1_tune(L1CTL);
1132 RSL.clear;
1133
1134 /* Step 1: Activate SYNC HO channel without MS power IE */
1135
1136 /* Activate channel on BTS side */
1137 f_rsl_chan_act(g_pars.chan_mode, act_type := t_RSL_IE_ActType_HO_SYNC);
1138 /* don't perform immediate assignment here, as we're testing non-IA case */
1139 /* enable dedicated mode */
1140 f_L1CTL_DM_EST_REQ(L1CTL, {false, mp_trx0_arfcn }, g_pars.chan_nr, 7);
1141
1142 /* Verify that no DL SACCH is being received */
1143 f_sacch_missing(?);
1144
1145 f_rsl_chan_deact();
1146 f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
1147
1148
1149 /* Step 2a: Activate SYNC HO channel with only MS power IE */
1150
1151 /* Activate channel on BTS side */
1152 addl_ies := {
1153 valueof(t_RSL_IE(RSL_IE_MS_POWER, RSL_IE_Body:{ms_power := ts_RSL_IE_MS_Power(0)}))
1154 };
1155 f_rsl_chan_act(g_pars.chan_mode, more_ies := addl_ies, act_type := t_RSL_IE_ActType_HO_SYNC);
1156 /* don't perform immediate assignment here, as we're testing non-IA case */
1157 /* enable dedicated mode */
1158 f_L1CTL_DM_EST_REQ(L1CTL, {false, mp_trx0_arfcn }, g_pars.chan_nr, 7);
1159
1160 /* Verify that no DL SACCH is being received */
1161 f_sacch_missing(?);
1162
1163 f_rsl_chan_deact();
1164 f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
1165
1166
1167 /* Step 2b: Activate SYNC HO channel with TA IE */
1168
1169 /* Activate channel on BTS side */
1170 addl_ies := {
1171 valueof(t_RSL_IE(RSL_IE_TIMING_ADVANCE, RSL_IE_Body:{timing_adv := 0}))
1172 };
1173 f_rsl_chan_act(g_pars.chan_mode, more_ies := addl_ies, act_type := t_RSL_IE_ActType_HO_SYNC);
1174 /* don't perform immediate assignment here, as we're testing non-IA case */
1175 /* enable dedicated mode */
1176 f_L1CTL_DM_EST_REQ(L1CTL, {false, mp_trx0_arfcn }, g_pars.chan_nr, 7);
1177
1178 /* Verify that no DL SACCH is being received */
1179 f_sacch_missing(?);
1180
1181 f_rsl_chan_deact();
1182 f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
1183
1184
1185 /* Step 3: Activate SYNC HO channel with MS power IE and TA IE */
1186
1187 /* Activate channel on BTS side */
1188 addl_ies := {
1189 valueof(t_RSL_IE(RSL_IE_TIMING_ADVANCE, RSL_IE_Body:{timing_adv := 0})),
1190 valueof(t_RSL_IE(RSL_IE_MS_POWER, RSL_IE_Body:{ms_power := ts_RSL_IE_MS_Power(0)}))
1191 };
1192 f_rsl_chan_act(g_pars.chan_mode, more_ies := addl_ies, act_type := t_RSL_IE_ActType_HO_SYNC);
1193 /* don't perform immediate assignment here, as we're testing non-IA case */
1194 /* enable dedicated mode */
1195 f_L1CTL_DM_EST_REQ(L1CTL, {false, mp_trx0_arfcn }, g_pars.chan_nr, 7);
1196
1197 /* Verify that DL SACCH is being received */
1198 f_sacch_present(si5);
1199
1200 f_rsl_chan_deact();
1201 f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
1202}
1203testcase TC_sacch_chan_act_ho_sync() runs on test_CT {
1204 var ConnHdlr vc_conn;
1205 var ConnHdlrPars pars;
1206 f_init();
1207
1208 for (var integer i := 0; i < sizeof(g_AllChannels); i := i+1) {
1209 pars := valueof(t_Pars(g_AllChannels[i], ts_RSL_ChanMode_SIGN));
1210 log(testcasename(), ": Starting for ", g_AllChannels[i]);
1211 vc_conn := f_start_handler(refers(f_TC_sacch_chan_act_ho_sync), pars);
1212 vc_conn.done;
1213 }
1214 /* TODO: do the above in parallel, rather than sequentially? */
1215 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
1216}
Harald Welte629cc6b2018-03-11 17:19:05 +01001217
1218
1219/***********************************************************************
Harald Welte93640c62018-02-25 16:59:33 +01001220 * RACH Handling
1221 ***********************************************************************/
1222
Harald Welte8c24c2b2018-02-26 08:31:31 +01001223/* like L1SAP_IS_PACKET_RACH */
1224private function ra_is_ps(OCT1 ra) return boolean {
Harald Welte56c05802018-02-28 21:39:35 +01001225 if ((ra and4b 'F0'O == '70'O) and (ra and4b '0F'O != '0F'O)) {
Harald Welte8c24c2b2018-02-26 08:31:31 +01001226 return true;
1227 }
1228 return false;
1229}
1230
1231/* generate a random RACH for circuit-switched */
1232private function f_rnd_ra_cs() return OCT1 {
1233 var OCT1 ra;
1234 do {
1235 ra := f_rnd_octstring(1);
1236 } while (ra_is_ps(ra));
1237 return ra;
1238}
1239
Harald Welte883340c2018-02-28 18:59:29 +01001240/* generate a random RACH for packet-switched */
1241private function f_rnd_ra_ps() return OCT1 {
1242 var OCT1 ra;
1243 do {
1244 ra := f_rnd_octstring(1);
1245 } while (not ra_is_ps(ra));
1246 return ra;
1247}
1248
Vadim Yanitskiy51cbc102019-04-22 06:37:30 +07001249/* generate a random 11-bit RA (packet-switched only) */
1250private function f_rnd_ra11_ps() return BIT11 {
1251 var integer ra11 := f_rnd_int(bit2int('11111111111'B));
1252 return int2bit(ra11, 11);
1253}
1254
Harald Welte8c24c2b2018-02-26 08:31:31 +01001255/* Send 1000 RACH requests and check their RA+FN on the RSL side */
1256testcase TC_rach_content() runs on test_CT {
Harald Welte10474062019-05-30 16:48:17 +02001257 f_init();
Harald Welte8c24c2b2018-02-26 08:31:31 +01001258 f_init_l1ctl();
Harald Welte68e495b2018-02-25 00:05:57 +01001259 f_l1_tune(L1CTL);
Harald Welte70767382018-02-21 12:16:40 +01001260
Harald Welte8c24c2b2018-02-26 08:31:31 +01001261 var GsmFrameNumber fn_last := 0;
Maxa199a2e2019-02-25 16:31:11 +01001262 var boolean test_failed := false;
Harald Welte8c24c2b2018-02-26 08:31:31 +01001263 for (var integer i := 0; i < 1000; i := i+1) {
1264 var OCT1 ra := f_rnd_ra_cs();
1265 var GsmFrameNumber fn := f_L1CTL_RACH(L1CTL, oct2int(ra));
1266 if (fn == fn_last) {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02001267 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Two RACH in same FN?!?");
Harald Welte8c24c2b2018-02-26 08:31:31 +01001268 }
1269 fn_last := fn;
1270
1271 timer T := 5.0;
Harald Welte56c05802018-02-28 21:39:35 +01001272 T.start;
Harald Welte8c24c2b2018-02-26 08:31:31 +01001273 alt {
Vadim Yanitskiyab448a52019-05-31 20:24:03 +07001274 [] RSL_CCHAN.receive(tr_RSL_UD(tr_RSL_CHAN_RQD(ra, fn, t_RslChanNr_RACH(0)))) {
Harald Welte8c24c2b2018-02-26 08:31:31 +01001275 T.stop;
1276 }
Vadim Yanitskiyab448a52019-05-31 20:24:03 +07001277 [] RSL_CCHAN.receive(tr_RSL_UD(tr_RSL_CHAN_RQD(?, ?, ?, ?))) {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02001278 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Unexpected CHAN RQD");
Harald Welte8c24c2b2018-02-26 08:31:31 +01001279 }
1280 [] RSL_CCHAN.receive { repeat; }
1281 [] T.timeout {
Maxa199a2e2019-02-25 16:31:11 +01001282 test_failed := true;
1283 log("[", i, "] Timeout waiting for CHAN RQD FN=", fn, " RA=", ra);
Harald Welte8c24c2b2018-02-26 08:31:31 +01001284 }
1285 }
1286 }
Maxba06feb2019-03-05 10:52:46 +01001287 if (test_failed) {
1288 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("Some out of 1000 RACH requests timed out"));
Maxa199a2e2019-02-25 16:31:11 +01001289 }
Maxba06feb2019-03-05 10:52:46 +01001290 setverdict(pass);
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02001291 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
Harald Welte70767382018-02-21 12:16:40 +01001292}
Harald Welte8c24c2b2018-02-26 08:31:31 +01001293
1294/* Send 1000 RACH Requests (flood ~ 89/s) and count if count(Abis) == count(Um) */
1295testcase TC_rach_count() runs on test_CT {
Harald Welte294b0a22018-03-10 23:26:48 +01001296 f_init();
Harald Welte8c24c2b2018-02-26 08:31:31 +01001297 f_init_l1ctl();
Harald Welte294b0a22018-03-10 23:26:48 +01001298 f_sleep(1.0);
Harald Welte8c24c2b2018-02-26 08:31:31 +01001299 f_l1_tune(L1CTL);
1300
1301 var GsmFrameNumber fn_last := 0;
1302 for (var integer i := 0; i < 1000; i := i+1) {
1303 var OCT1 ra := f_rnd_ra_cs();
1304 var GsmFrameNumber fn := f_L1CTL_RACH(L1CTL, oct2int(ra));
1305 if (fn == fn_last) {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02001306 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Two RACH in same FN?!?");
Harald Welte8c24c2b2018-02-26 08:31:31 +01001307 }
1308 fn_last := fn;
1309 }
1310 var integer rsl_chrqd := 0;
1311 timer T := 3.0;
Harald Welte56c05802018-02-28 21:39:35 +01001312 T.start;
Harald Welte8c24c2b2018-02-26 08:31:31 +01001313 alt {
1314 [] RSL_CCHAN.receive(tr_RSL_UD(tr_RSL_CHAN_RQD(?,?))) {
1315 rsl_chrqd := rsl_chrqd + 1;
Harald Weltec3a3f452018-02-26 17:37:47 +01001316 f_timer_safe_restart(T);
Harald Welte8c24c2b2018-02-26 08:31:31 +01001317 repeat;
1318 }
1319 [] RSL_CCHAN.receive { repeat; }
1320 [] T.timeout { }
1321 }
1322 if (rsl_chrqd == 1000) {
1323 setverdict(pass);
1324 } else {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02001325 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("Received only ", rsl_chrqd, " out of 1000 RACH"));
Harald Welte8c24c2b2018-02-26 08:31:31 +01001326 }
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02001327 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
Harald Welte70767382018-02-21 12:16:40 +01001328}
1329
Harald Welte3453ab42019-05-24 21:19:58 +02001330private function f_vty_load_ind_thresh(integer period := 10, integer bts_nr := 0) runs on test_CT {
1331 var charstring bts_str := "bts " & int2str(bts_nr);
1332 f_vty_config2(BSCVTY, {"network", bts_str}, "ccch load-indication-threshold " & int2str(period));
1333}
1334
1335/* empirical value: Number of RACH slots per reporting interval (1s) on combined CCCH */
1336private template integer tr_rach_slots_per_interval := (90 .. 130);
1337
1338/* Expect 0 RACH load on an idle BTS that has just started up */
1339testcase TC_rach_load_idle_thresh0() runs on test_CT {
1340 var ASP_RSL_Unitdata rx_ud;
1341
1342 f_init_vty_bsc();
1343 /* send load indications even at 0% load */
1344 f_vty_load_ind_thresh(0);
1345 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
1346 f_sleep(2.0);
1347
1348 f_init();
1349
1350 timer T := 5.0;
1351 T.start;
1352 alt {
1353 [] RSL_CCHAN.receive(tr_RSL_UD(tr_RSL_RACH_LOAD_IND(tr_rach_slots_per_interval, 0, 0))) {
1354 setverdict(pass);
1355 repeat;
1356 }
1357 [] RSL_CCHAN.receive(tr_RSL_UD(tr_RSL_RACH_LOAD_IND(?, ?, ?))) -> value rx_ud {
1358 setverdict(fail, "Unexpected RACH LOAD IND: ", rx_ud);
1359 repeat;
1360 }
1361 [] RSL_CCHAN.receive {
1362 repeat;
1363 }
1364 [] T.timeout { }
1365 }
1366
1367 f_vty_load_ind_thresh(10);
1368 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
1369}
1370
1371/* Expect no RACH load indications on an idle BTS that has just started up (default threshold 10%) */
1372testcase TC_rach_load_idle_below_thresh() runs on test_CT {
1373 var ASP_RSL_Unitdata rx_ud;
1374
1375 f_init_vty_bsc();
1376 f_init();
1377
1378 timer T := 5.0;
1379 T.start;
1380 alt {
1381 [] RSL_CCHAN.receive(tr_RSL_UD(tr_RSL_RACH_LOAD_IND(?, ?, ?))) -> value rx_ud {
1382 setverdict(fail, "Unexpected RACH LOAD IND: ", rx_ud);
1383 repeat;
1384 }
1385 [] RSL_CCHAN.receive {
1386 repeat;
1387 }
1388 [] T.timeout {
1389 setverdict(pass);
1390 }
1391 }
1392
1393 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
1394}
1395
1396/* Expect 0 RACH load on an idle BTS that has just started up */
1397testcase TC_rach_load_count() runs on test_CT {
1398 var ASP_RSL_Unitdata rx_ud;
1399 var integer load_access_count := 0;
1400
1401 f_init_vty_bsc();
1402 /* send load indications even at 0% load */
1403 f_vty_load_ind_thresh(0);
1404 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
1405 f_sleep(2.0);
1406 f_init();
1407
1408 f_init_l1ctl();
1409 f_sleep(1.0);
1410 f_l1_tune(L1CTL);
1411
1412 var GsmFrameNumber fn_last := 0;
1413 for (var integer i := 0; i < 1000; i := i+1) {
1414 var OCT1 ra := f_rnd_ra_cs();
1415 var GsmFrameNumber fn := f_L1CTL_RACH(L1CTL, oct2int(ra));
1416 if (fn == fn_last) {
1417 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Two RACH in same FN?!?");
1418 }
1419 fn_last := fn;
1420 }
1421
1422 timer T := 5.0;
1423 T.start;
1424 alt {
1425 [] RSL_CCHAN.receive(tr_RSL_UD(tr_RSL_RACH_LOAD_IND(tr_rach_slots_per_interval, ?, ?)))
1426 -> value rx_ud {
1427 var RSL_IE_Body ie;
1428 f_rsl_find_ie(rx_ud.rsl, RSL_IE_RACH_LOAD, ie);
1429 load_access_count := load_access_count + ie.rach_load.access_count;
1430 if (ie.rach_load.busy_count < ie.rach_load.access_count) {
1431 setverdict(fail, "Access count cannot be < Busy count");
1432 }
1433 repeat;
1434 }
1435 [] RSL_CCHAN.receive(tr_RSL_UD(tr_RSL_RACH_LOAD_IND(?, ?, ?))) -> value rx_ud {
1436 setverdict(fail, "Unexpected RACH LOAD IND: ", rx_ud);
1437 repeat;
1438 }
1439 [] RSL_CCHAN.receive {
1440 repeat;
1441 }
1442 [] T.timeout { }
1443 }
1444 if (load_access_count == 1000) {
1445 setverdict(pass);
1446 } else {
1447 setverdict(fail, "Load reports state ", load_access_count, " RACH, but we sent 1000");
1448 }
1449
1450 f_vty_load_ind_thresh(10);
1451 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
1452}
1453
Harald Welte54a2a2d2018-02-26 09:14:05 +01001454private function f_rach_toffs(int16_t toffs256, boolean expect_pass) runs on test_CT {
Harald Weltef8df4cb2018-03-10 15:15:08 +01001455 var TrxcMessage ret;
Harald Welte54a2a2d2018-02-26 09:14:05 +01001456 /* tell fake_trx to use a given timing offset for all bursts */
Vadim Yanitskiy44ff2142019-01-12 07:04:58 +07001457 ret := f_TRXC_transceive(BTS_TRXC, g_bts_trxc_conn_id, valueof(ts_TRXC_FAKE_TIMING(toffs256)));
Harald Welte54a2a2d2018-02-26 09:14:05 +01001458 f_sleep(0.5);
1459
1460 /* Transmit RACH request + wait for confirmation */
1461 var OCT1 ra := f_rnd_ra_cs();
1462 var GsmFrameNumber fn := f_L1CTL_RACH(L1CTL, oct2int(ra));
1463
1464 /* Check for expected result */
1465 timer T := 1.5;
1466 T.start;
1467 alt {
1468 [expect_pass] RSL_CCHAN.receive(tr_RSL_UD(tr_RSL_CHAN_RQD(ra, fn))) {
1469 setverdict(pass);
1470 }
1471 [not expect_pass] RSL_CCHAN.receive(tr_RSL_UD(tr_RSL_CHAN_RQD(ra, fn))) {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02001472 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("RACH passed but was expected to be dropped: ", toffs256));
Harald Welte54a2a2d2018-02-26 09:14:05 +01001473 }
1474 [] RSL_CCHAN.receive { repeat; }
1475 [not expect_pass] T.timeout {
1476 setverdict(pass);
1477 }
1478 [expect_pass] T.timeout {
Max6e053042019-03-14 16:34:22 +01001479 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("Timeout waiting for CHAN RQD: FN=", fn, " RA=", ra));
Harald Welte54a2a2d2018-02-26 09:14:05 +01001480 }
1481 }
1482}
1483
1484/* Test if dropping of RACH Based on NM_ATT_MAX_TA works */
1485testcase TC_rach_max_ta() runs on test_CT {
Harald Welte10474062019-05-30 16:48:17 +02001486 f_init();
Harald Welte54a2a2d2018-02-26 09:14:05 +01001487 f_init_l1ctl();
1488 f_l1_tune(L1CTL);
Harald Welte54a2a2d2018-02-26 09:14:05 +01001489 f_sleep(1.0);
1490
1491 /* default max-ta is 63 (full range of GSM timing advance */
1492
Vadim Yanitskiyc81d6e42018-03-05 22:39:01 +07001493 /* We allow early arrival up to 2 symbols */
1494 f_rach_toffs(-1*256, true);
1495 f_rach_toffs(-2*256, true);
Harald Welte54a2a2d2018-02-26 09:14:05 +01001496 f_rach_toffs(-10*256, false);
1497
1498 /* 0 / 32 / 63 bits is legal / permitted */
1499 f_rach_toffs(0, true);
1500 f_rach_toffs(32*256, true);
1501 f_rach_toffs(63*256, true);
1502
1503 /* more than 63 bits is not legal / permitted */
1504 f_rach_toffs(64*256, false);
1505 f_rach_toffs(127*256, false);
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02001506 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
Harald Welte54a2a2d2018-02-26 09:14:05 +01001507}
Harald Welte8c24c2b2018-02-26 08:31:31 +01001508
Vadim Yanitskiy7c2c10c2019-05-31 20:42:01 +07001509function f_TC_ho_rach(charstring id) runs on ConnHdlr {
1510 var GsmFrameNumber fn;
1511 var RSL_Message rm;
1512
1513 f_l1_tune(L1CTL);
1514 RSL.clear;
1515
1516 /* Generate a random Handover Reference */
1517 var integer ho_ref := oct2int(f_rnd_octstring(1));
1518
1519 /* Handover Reference IE (see 3GPP TS 48.058, 9.3.9) */
1520 var RSL_IE ho_ref_ie := valueof(t_RSL_IE(RSL_IE_HANDO_REF,
1521 RSL_IE_Body:{ handover_ref := ho_ref }));
1522
1523 /* Activate a channel on the BTS side (no encryption) */
1524 f_rsl_chan_act(g_pars.chan_mode, more_ies := { ho_ref_ie },
1525 act_type := t_RSL_IE_ActType_HO_SYNC);
1526
1527 /* Switch the MS side (e.g. trxcon) to a dedicated channel without
1528 * waiting for Immediate Assignment and sending Access Burst */
1529 f_L1CTL_DM_EST_REQ(L1CTL, { false, mp_trx0_arfcn }, g_pars.chan_nr, 7);
1530
1531 /* Send handover Access Burst */
1532 fn := f_L1CTL_RACH(L1CTL, ho_ref, chan_nr := g_pars.chan_nr);
1533
1534 /* TODO: test mismatching Handover Reference, and missing IE */
1535
1536 /* Wait for handover detection */
1537 timer T := 3.0;
1538 T.start;
1539 alt {
1540 [] RSL.receive(tr_RSL_HANDO_DET(g_pars.chan_nr)) -> value rm {
1541 log("Handover RACH has been detected: ", rm);
1542 setverdict(pass);
1543 }
1544 [] RSL.receive(tr_RSL_CHAN_RQD(?, ?, ?, ?)) -> value rm {
1545 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
1546 log2str("RSL_CHAN_RQD was not expected: ", rm));
1547 }
1548 [] RSL.receive { repeat; }
1549 [] T.timeout {
1550 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
1551 log2str("Timeout waiting for handover RACH: FN=", fn, " RA=", ho_ref));
1552 }
1553 }
1554
1555 /* Release the channel */
1556 f_rsl_chan_deact();
1557 f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
1558}
1559
1560/* Test handover RACH detection */
1561testcase TC_ho_rach() runs on test_CT {
1562 var ConnHdlrPars pars;
1563 var ConnHdlr vc_conn;
1564
1565 f_init();
1566
1567 for (var integer i := 0; i < sizeof(g_AllChannels); i := i + 1) {
1568 pars := valueof(t_Pars(g_AllChannels[i], ts_RSL_ChanMode_SIGN));
1569 log(testcasename(), ": Starting for ", g_AllChannels[i]);
1570 vc_conn := f_start_handler(refers(f_TC_ho_rach), pars);
1571 vc_conn.done;
1572 }
1573
1574 /* TODO: do the above in parallel, rather than sequentially? */
1575 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
1576}
1577
Harald Welte93640c62018-02-25 16:59:33 +01001578/***********************************************************************
1579 * Measurement Processing / Reporting
1580 ***********************************************************************/
1581
Harald Welte70767382018-02-21 12:16:40 +01001582template LapdmAddressField ts_LapdmAddr(LapdmSapi sapi, boolean c_r) := {
1583 spare := '0'B,
1584 lpd := 0,
1585 sapi := sapi,
1586 c_r := c_r,
1587 ea := true
1588}
1589
Harald Welted879bd92018-03-12 15:01:23 +01001590template LapdmFrameAB ts_LAPDm_AB(LapdmSapi sapi, boolean c_r, boolean p, octetstring pl) := {
Harald Welte70767382018-02-21 12:16:40 +01001591 addr := ts_LapdmAddr(sapi, c_r),
Harald Welted879bd92018-03-12 15:01:23 +01001592 ctrl := ts_LapdmCtrlUI(p),
Harald Welte70767382018-02-21 12:16:40 +01001593 len := 0, /* overwritten */
1594 m := false,
1595 el := 1,
1596 payload := pl
1597}
1598
1599/* handle incoming downlink SACCH and respond with uplink SACCH (meas res) */
1600altstep as_l1_sacch() runs on ConnHdlr {
1601 var L1ctlDlMessage l1_dl;
Harald Weltef8df4cb2018-03-10 15:15:08 +01001602 [] L1CTL.receive(tr_L1CTL_DATA_IND(g_chan_nr, tr_RslLinkID_SACCH(?))) -> value l1_dl {
Harald Welte70767382018-02-21 12:16:40 +01001603 log("SACCH received: ", l1_dl.payload.data_ind.payload);
Pau Espin Pedrole9571aa2018-10-22 17:13:07 +02001604 var GsmRrL3Message meas_rep := valueof(ts_MEAS_REP(true, mp_rxlev_exp, mp_rxlev_exp, 0, 0, omit));
Harald Welted879bd92018-03-12 15:01:23 +01001605 var LapdmFrameAB lb := valueof(ts_LAPDm_AB(0, false, false, enc_GsmRrL3Message(meas_rep)));
Harald Welte70767382018-02-21 12:16:40 +01001606 log("LAPDm: ", lb);
Pau Espin Pedroled359cb2018-09-28 16:08:24 +02001607
Vadim Yanitskiy0a8d6da2019-05-28 22:18:28 +07001608 var template (value) SacchL1Header l1h := ts_SacchL1Header(
1609 g_pars.l1_pars.ms_power_level, false,
1610 g_pars.l1_pars.ms_actual_ta);
1611
1612 /* TODO: we can use an extension of TTCN-3 for that, i.e. PADDING('2B'O) */
1613 var octetstring l2 := f_pad_oct(enc_LapdmFrameAB(lb), 21, '2B'O);
1614
1615 log("Sending Measurement Report: ", l1h, l2);
1616 L1CTL.send(ts_L1CTL_DATA_REQ_SACCH(g_chan_nr, ts_RslLinkID_SACCH(0), l1h, l2));
Harald Welte70767382018-02-21 12:16:40 +01001617 repeat;
1618 }
1619}
1620
1621altstep as_l1_dcch() runs on ConnHdlr {
1622 var L1ctlDlMessage l1_dl;
Harald Weltef8df4cb2018-03-10 15:15:08 +01001623 [] L1CTL.receive(tr_L1CTL_DATA_IND(g_chan_nr, tr_RslLinkID_DCCH(?))) -> value l1_dl {
Harald Welte70767382018-02-21 12:16:40 +01001624 log("DCCH received: ", l1_dl.payload.data_ind.payload);
1625 var octetstring pl := '010301'O;
Vadim Yanitskiy31e7c672018-07-27 02:23:16 +07001626 L1CTL.send(ts_L1CTL_DATA_REQ(g_chan_nr, ts_RslLinkID_DCCH(0),
1627 f_pad_oct(pl, 23, '2B'O)));
Harald Welte70767382018-02-21 12:16:40 +01001628 repeat;
1629 }
1630}
1631
1632type record MeasElem {
1633 uint6_t rxlev,
1634 uint3_t rxqual
1635}
1636
1637type record MeasElemFS {
1638 MeasElem full,
1639 MeasElem sub
1640}
1641
1642type record ConnL1Pars {
1643 boolean dtx_enabled,
Harald Welte685d5982018-02-27 20:42:05 +01001644 boolean toa256_enabled,
Harald Welte70767382018-02-21 12:16:40 +01001645 MeasElemFS meas_ul,
1646 int16_t timing_offset_256syms,
1647 uint5_t bs_power_level,
1648 uint5_t ms_power_level,
1649 uint8_t ms_actual_ta
1650}
1651
1652/* Convert tiing offset from 1/256th symbol to RSL Timing Offset */
1653private function toffs256s_to_rsl(int16_t toffs256s) return uint8_t {
1654 return 63 + (toffs256s/256);
1655}
1656
Harald Welted5684392018-03-10 18:22:04 +01001657private function f_max(integer a, integer b) return integer {
1658 if (a > b) {
1659 return a;
1660 } else {
1661 return b;
1662 }
1663}
1664
1665private function f_min(integer a, integer b) return integer {
1666 if (a < b) {
1667 return a;
1668 } else {
1669 return b;
1670 }
1671}
1672
1673/* compute negative tolerance val-tolerance, ensure >= min */
1674private function f_tolerance_neg(integer val, integer min, integer tolerance) return integer {
1675 val := val - tolerance;
1676 return f_max(val, min);
1677}
1678
1679/* compute positive tolerance val+tolerance, ensure <= max */
1680private function f_tolerance_pos(integer val, integer max, integer tolerance) return integer {
1681 val := val + tolerance;
1682 return f_min(val, max);
1683}
1684
1685/* return a template of (val-tolerance .. val+tolerance) ensuring it is within (min .. max) */
1686private function f_tolerance(integer val, integer min, integer max, integer tolerance)
1687return template integer {
1688 var template integer ret;
1689 ret := (f_tolerance_neg(val, min, tolerance) .. f_tolerance_pos(val, max, tolerance));
1690 return ret;
1691}
1692
1693
Harald Welte70767382018-02-21 12:16:40 +01001694/* build a template for matching measurement results against */
1695private function f_build_meas_res_tmpl() runs on ConnHdlr return template RSL_Message {
1696 var ConnL1Pars l1p := g_pars.l1_pars;
1697 var template RSL_IE_UplinkMeas ul_meas := {
1698 len := 3,
1699 rfu := '0'B,
1700 dtx_d := l1p.dtx_enabled,
Harald Welted5684392018-03-10 18:22:04 +01001701 rxlev_f_u := f_tolerance(l1p.meas_ul.full.rxlev, 0, 63, mp_tolerance_rxlev),
Harald Welte70767382018-02-21 12:16:40 +01001702 reserved1 := '00'B,
Harald Welted5684392018-03-10 18:22:04 +01001703 rxlev_s_u := f_tolerance(l1p.meas_ul.sub.rxlev, 0, 63, mp_tolerance_rxlev),
Harald Welte70767382018-02-21 12:16:40 +01001704 reserved2 := '00'B,
Harald Welted5684392018-03-10 18:22:04 +01001705 rxq_f_u := f_tolerance(l1p.meas_ul.full.rxqual, 0, 7, mp_tolerance_rxqual),
1706 rxq_s_u := f_tolerance(l1p.meas_ul.sub.rxqual, 0, 7, mp_tolerance_rxqual),
Harald Welte70767382018-02-21 12:16:40 +01001707 supp_meas_info := omit
1708 };
Harald Welte685d5982018-02-27 20:42:05 +01001709 if (l1p.toa256_enabled) {
Harald Welte15de8ba2018-06-29 08:51:42 +02001710 ul_meas.len := (3+8);
1711 ul_meas.supp_meas_info := {
Pau Espin Pedrol121724c2018-09-28 15:58:12 +02001712 toa256_mean := f_tolerance(l1p.timing_offset_256syms, -63*256, 192*256, mp_tolerance_timing_offset_256syms),
Harald Welte15de8ba2018-06-29 08:51:42 +02001713 toa256_min := ?,
1714 toa256_max := ?,
1715 toa256_std_dev := ?
1716 }
Harald Welte685d5982018-02-27 20:42:05 +01001717 }
Harald Welte70767382018-02-21 12:16:40 +01001718 var template RSL_IE_BS_Power bs_power := {
1719 reserved := 0,
1720 epc := false,
1721 fpc := false,
1722 power_level := l1p.bs_power_level
1723 };
1724 var template RSL_IE_L1Info l1_info := {
1725 ms_power_lvl := l1p.ms_power_level,
1726 fpc := false,
1727 reserved := 0,
Pau Espin Pedrol121724c2018-09-28 15:58:12 +02001728 actual_ta := f_tolerance(l1p.ms_actual_ta, 0, 63, mp_tolerance_timing_offset_256syms/256)
Harald Welte70767382018-02-21 12:16:40 +01001729 };
1730 var uint8_t offs := toffs256s_to_rsl(l1p.timing_offset_256syms);
Pau Espin Pedrol121724c2018-09-28 15:58:12 +02001731 var template uint8_t t_toffs := f_tolerance(offs, 0, 255, mp_tolerance_timing_offset_256syms/256);
Harald Welte70767382018-02-21 12:16:40 +01001732 return tr_RSL_MEAS_RES_OSMO(g_chan_nr, g_next_meas_res_nr, ul_meas, bs_power, l1_info,
1733 ?, t_toffs);
1734}
1735
1736/* verify we regularly receive measurement reports with incrementing numbers */
Vadim Yanitskiy41baf002018-10-04 17:44:50 +07001737altstep as_meas_res(boolean verify_meas := true) runs on ConnHdlr {
Harald Welte70767382018-02-21 12:16:40 +01001738 var RSL_Message rsl;
Vadim Yanitskiy41baf002018-10-04 17:44:50 +07001739 [not verify_meas] RSL.receive(tr_RSL_MEAS_RES(?)) { repeat; }
Harald Welte70767382018-02-21 12:16:40 +01001740 [] RSL.receive(f_build_meas_res_tmpl()) -> value rsl {
1741 /* increment counter of next to-be-expected meas rep */
1742 g_next_meas_res_nr := (g_next_meas_res_nr + 1) mod 256;
1743 /* Re-start the timer expecting the next MEAS RES */
Harald Weltec3a3f452018-02-26 17:37:47 +01001744 f_timer_safe_restart(g_Tmeas_exp);
Harald Welte70767382018-02-21 12:16:40 +01001745 repeat;
1746 }
1747 [] RSL.receive(tr_RSL_MEAS_RES(g_chan_nr, g_next_meas_res_nr)) -> value rsl {
Harald Weltefa45e9e2018-03-10 18:59:03 +01001748 /* increment counter of next to-be-expected meas rep */
1749 g_next_meas_res_nr := (g_next_meas_res_nr + 1) mod 256;
1750 if (g_first_meas_res) {
1751 g_first_meas_res := false;
1752 repeat;
1753 } else {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02001754 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("Received unspecific MEAS RES ", rsl));
Harald Weltefa45e9e2018-03-10 18:59:03 +01001755 }
Harald Welte70767382018-02-21 12:16:40 +01001756 }
1757 [] RSL.receive(tr_RSL_MEAS_RES(?)) -> value rsl {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02001758 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("Received unexpected MEAS RES ", rsl));
Harald Welte70767382018-02-21 12:16:40 +01001759 }
Pau Espin Pedrol425b62f2018-07-06 16:11:43 +02001760 [g_Tmeas_exp.running] g_Tmeas_exp.timeout {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02001761 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Didn't receive expected measurement result")
Harald Welte70767382018-02-21 12:16:40 +01001762 }
1763}
1764
Harald Weltee613f962018-04-18 22:38:16 +02001765private function f_alg_id_to_l1ctl(RSL_AlgId rsl_alg_id) return uint8_t {
1766 select (rsl_alg_id) {
1767 case (RSL_ALG_ID_A5_0) { return 0; }
1768 case (RSL_ALG_ID_A5_1) { return 1; }
1769 case (RSL_ALG_ID_A5_2) { return 2; }
1770 case (RSL_ALG_ID_A5_3) { return 3; }
1771 case (RSL_ALG_ID_A5_4) { return 4; }
1772 case (RSL_ALG_ID_A5_5) { return 5; }
1773 case (RSL_ALG_ID_A5_6) { return 6; }
1774 case (RSL_ALG_ID_A5_7) { return 7; }
1775 case else {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02001776 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Unknwon Algorithm ID");
1777 /* Make compiler happy by calling mtc.stop here. It is already
1778 * called in f_shutdown */
Daniel Willmann17ddd852018-07-05 17:33:20 +02001779 mtc.stop;
Harald Weltee613f962018-04-18 22:38:16 +02001780 }
1781 }
1782}
1783
1784private function f_alg_id_to_l3(RSL_AlgId rsl_alg_id) return BIT3 {
1785 select (rsl_alg_id) {
1786 case (RSL_ALG_ID_A5_1) { return '000'B; }
1787 case (RSL_ALG_ID_A5_2) { return '001'B; }
1788 case (RSL_ALG_ID_A5_3) { return '010'B; }
1789 case (RSL_ALG_ID_A5_4) { return '011'B; }
1790 case (RSL_ALG_ID_A5_5) { return '100'B; }
1791 case (RSL_ALG_ID_A5_6) { return '101'B; }
1792 case (RSL_ALG_ID_A5_7) { return '110'B; }
1793 case else {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02001794 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Unknwon Algorithm ID");
1795 /* Make compiler happy by calling mtc.stop here. It is already
1796 * called in f_shutdown */
Daniel Willmann17ddd852018-07-05 17:33:20 +02001797 mtc.stop;
Harald Weltee613f962018-04-18 22:38:16 +02001798 }
1799 }
1800}
1801
Pau Espin Pedrol6451b042018-10-24 20:36:16 +02001802/* Send RACH request through l1CTL and wait for ChanReq on RSL BST->BSC */
1803private function f_rach_req_wait_chan_rqd(integer ra) runs on ConnHdlr return GsmFrameNumber {
1804 var GsmFrameNumber fn;
1805 timer T := 8.0;
1806
1807 /* advertise to RSL Emulation that we expect to receive confirmation from RACH */
1808 RSL.send(ts_RSLDC_ChanRqd_anyFN(int2oct(ra,1)));
1809
1810 f_L1CTL_PARAM(L1CTL, g_pars.l1_pars.ms_actual_ta, g_pars.l1_pars.ms_power_level);
1811 /* Send the actual RACH */
1812 fn := f_L1CTL_RACH(L1CTL, ra);
1813
1814 T.start;
1815 alt {
1816 [] RSL.receive(tr_RSL_CHAN_RQD(int2oct(ra,1), fn)) { setverdict(pass, "Received CHAN-RQD from RACH REQ") }
1817 [] T.timeout {
1818 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("Timeout waiting for CHAN-RQD from RACH REQ <", ra, ", ", fn, ">"));
1819 }
1820 }
1821 T.stop
1822 return fn;
1823}
Harald Weltee613f962018-04-18 22:38:16 +02001824
Harald Welte70767382018-02-21 12:16:40 +01001825/* Establish dedicated channel: L1CTL + RSL side */
Harald Weltec8d363c2019-05-19 20:36:48 +02001826private function f_est_dchan(boolean encr_enable := false, RSL_IE_List more_ies := {}) runs on ConnHdlr {
Harald Welte70767382018-02-21 12:16:40 +01001827 var GsmFrameNumber fn;
1828 var ImmediateAssignment imm_ass;
1829 var integer ra := 23;
1830
Pau Espin Pedrol6451b042018-10-24 20:36:16 +02001831 /* Send RACH request and wait for ChanReq */
1832 fn := f_rach_req_wait_chan_rqd(ra);
Harald Welte70767382018-02-21 12:16:40 +01001833
1834 /* Activate channel on BTS side */
Harald Weltec8d363c2019-05-19 20:36:48 +02001835 f_rsl_chan_act(g_pars.chan_mode, encr_enable, more_ies);
Harald Welte70767382018-02-21 12:16:40 +01001836
1837 /* Send IMM.ASS via CCHAN */
1838 var ChannelDescription ch_desc := {
1839 chan_nr := g_pars.chan_nr,
1840 tsc := 7,
1841 h := false,
1842 arfcn := mp_trx0_arfcn,
1843 maio_hsn := omit
1844 };
1845 var MobileAllocation ma := {
1846 len := 0,
1847 ma := ''B
1848 };
1849 var GsmRrMessage rr_msg := valueof(ts_IMM_ASS(ra, fn, 0, ch_desc, ma));
1850 RSL.send(ts_RSL_IMM_ASSIGN(enc_GsmRrMessage(rr_msg)));
1851
1852 /* receive IMM.ASS on MS side */
1853 var ImmediateAssignment ia_um;
1854 ia_um := f_L1CTL_WAIT_IMM_ASS(L1CTL, ra, fn);
1855 /* enable dedicated mode */
1856 f_L1CTL_DM_EST_REQ_IA(L1CTL, ia_um);
Harald Weltee613f962018-04-18 22:38:16 +02001857 /* enable encryption, if requested */
1858 if (encr_enable) {
1859 var uint8_t alg_id := f_alg_id_to_l1ctl(g_pars.encr.alg_id);
1860 f_L1CTL_CRYPTO_REQ(L1CTL, g_pars.chan_nr, alg_id, g_pars.encr.key);
1861 }
Harald Weltefa45e9e2018-03-10 18:59:03 +01001862
1863 g_first_meas_res := true;
Harald Welte70767382018-02-21 12:16:40 +01001864}
1865
1866/* establish DChan, verify existance + contents of measurement reports */
1867function f_TC_meas_res_periodic(charstring id) runs on ConnHdlr {
Harald Welte68e495b2018-02-25 00:05:57 +01001868 f_l1_tune(L1CTL);
Harald Welte70767382018-02-21 12:16:40 +01001869 RSL.clear;
1870
Vadim Yanitskiy44ff2142019-01-12 07:04:58 +07001871 if (mp_bts_trxc_port != -1) {
Pau Espin Pedrole9571aa2018-10-22 17:13:07 +02001872 f_trxc_fake_rssi(rxlev2dbm(mp_ul_rxlev_exp));
Vadim Yanitskiydc8db922019-06-04 21:58:15 +07001873 f_trxc_fake_toffs256(g_pars.l1_pars.timing_offset_256syms);
Pau Espin Pedrol121724c2018-09-28 15:58:12 +02001874 }
Harald Welte70767382018-02-21 12:16:40 +01001875
1876 f_est_dchan();
1877
1878 /* run for a number of seconds, send SACCH + FACCH from MS side and verify
1879 * RSL measurement reports on Abis side */
1880 timer T := 8.0;
1881 T.start;
1882 alt {
1883 [] as_l1_sacch();
1884 [] as_meas_res();
1885 [] as_l1_dcch();
1886 [] L1CTL.receive { repeat; }
1887 [g_Tmeas_exp.running] T.timeout {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02001888 /* as_meas_res() would have done Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail) in case
Harald Welte70767382018-02-21 12:16:40 +01001889 * of any earlier errors, so if we reach this timeout, we're good */
1890 setverdict(pass);
1891 }
1892 [] T.timeout {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02001893 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "No MEAS RES received at all");
Harald Welte70767382018-02-21 12:16:40 +01001894 }
1895 }
1896 f_rsl_chan_deact();
Harald Welte3dc20462018-03-10 23:03:38 +01001897 f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
Harald Welte70767382018-02-21 12:16:40 +01001898}
Harald Welte0472ab42018-03-12 15:02:26 +01001899
Eric Wildae8f2622019-06-18 17:05:11 +02001900function f_check_meas_bs_power_level(integer level) runs on ConnHdlr {
1901 timer T := 8.0;
1902 T.start;
1903 var RSL_Message rsl;
1904 alt {
1905 [] as_l1_sacch();
1906 [] L1CTL.receive { repeat; }
1907 [] RSL.receive(tr_RSL_MEAS_RES(g_chan_nr, ?, ?, ?)) -> value rsl {
1908 if (rsl.ies[3].body.bs_power.power_level == level) {
1909 setverdict(pass)
1910 } else {
1911 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("Received wrong BS power level in MEAS RES ", rsl));
1912 }
1913 }
1914 [] T.timeout {
1915 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "No MEAS RES received at all");
1916 }
1917 }
1918}
1919
1920/* see if the rsl meas res contains our expeced bs power level
1921bs power set during assignment */
1922function f_TC_rsl_bs_pwr_static_ass(charstring id) runs on ConnHdlr {
1923 f_l1_tune(L1CTL);
1924 RSL.clear;
1925
1926 if (mp_bts_trxc_port != -1) {
1927 f_trxc_fake_rssi(rxlev2dbm(mp_ul_rxlev_exp));
1928 f_trxc_fake_toffs256(g_pars.l1_pars.timing_offset_256syms);
1929 }
1930
1931 var uint5_t pwr_var := 1;
1932 var template (value) RSL_IE_BS_Power bs_power := ts_RSL_IE_BS_Power(pwr_var);
1933 var template (value) RSL_IE pwr := t_RSL_IE(RSL_IE_BS_POWER, RSL_IE_Body:{bs_power := bs_power});
1934
1935 f_est_dchan(more_ies :={valueof(pwr)});
1936
1937 f_check_meas_bs_power_level(pwr_var);
1938
1939 f_rsl_chan_deact();
1940 f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
1941}
1942
1943/* see if the rsl meas res contains our expeced bs power level
1944bs power set after assignment */
1945function f_TC_rsl_bs_pwr_static_power_control(charstring id) runs on ConnHdlr {
1946 f_l1_tune(L1CTL);
1947 RSL.clear;
1948
1949 if (mp_bts_trxc_port != -1) {
1950 f_trxc_fake_rssi(rxlev2dbm(mp_ul_rxlev_exp));
1951 f_trxc_fake_toffs256(g_pars.l1_pars.timing_offset_256syms);
1952 }
1953
1954 var uint5_t pwr_var := 1;
1955 var template (value) RSL_IE_BS_Power bs_power := ts_RSL_IE_BS_Power(pwr_var);
1956
1957 f_est_dchan();
1958
1959 RSL.send(ts_RSL_BS_PWR_CTRL(g_chan_nr, bs_power));
1960
1961 f_check_meas_bs_power_level(pwr_var);
1962
1963 f_rsl_chan_deact();
1964 f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
1965}
1966
1967testcase TC_rsl_bs_pwr_static_ass() runs on test_CT {
1968 var ConnHdlr vc_conn;
1969 var ConnHdlrPars pars;
1970 f_init();
1971 for (var integer tn := 1; tn <= 4; tn := tn+1) {
1972 pars := valueof(t_Pars(t_RslChanNr_Bm(tn), ts_RSL_ChanMode_SIGN));
1973 vc_conn := f_start_handler(refers(f_TC_rsl_bs_pwr_static_ass), pars,
1974 pcu_comp := false, trxc_comp := true);
1975 vc_conn.done;
1976 }
1977 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
1978}
1979
1980testcase TC_rsl_bs_pwr_static_power_control() runs on test_CT {
1981 var ConnHdlr vc_conn;
1982 var ConnHdlrPars pars;
1983 f_init();
1984 for (var integer tn := 1; tn <= 4; tn := tn+1) {
1985 pars := valueof(t_Pars(t_RslChanNr_Bm(tn), ts_RSL_ChanMode_SIGN));
1986 vc_conn := f_start_handler(refers(f_TC_rsl_bs_pwr_static_power_control), pars,
1987 pcu_comp := false, trxc_comp := true);
1988 vc_conn.done;
1989 }
1990 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
1991}
1992
Eric Wild61edb7e2019-06-03 12:38:31 +02001993/* target level -100, first rssi -90, ms power 7, expected increase to 7+6 within 6 seconds,
1994second rssi -110, ms power 7+6, expected decrease to 7 within 6 seconds,
1995These power levels are valid for all bands and require no special handling */
1996function f_TC_rsl_ms_pwr_dyn_ass_updown(charstring id) runs on ConnHdlr {
1997 var uint5_t pwr_var := 7;
1998 var L1ctlDlMessage l1_dl;
1999
2000 f_trxc_fake_rssi(rxlev2dbm(10));
2001 f_l1_tune(L1CTL);
2002 RSL.clear;
2003
2004 var RSL_IE_List addl_ies;
2005 var template (value) RSL_IE_MS_Power_Parameters pp := (ts_RSL_IE_MS_Power_Parameters(''O));
2006
2007 addl_ies := {
2008 valueof(t_RSL_IE(RSL_IE_MS_POWER, RSL_IE_Body:{ms_power := ts_RSL_IE_MS_Power(pwr_var)})),
2009 valueof(t_RSL_IE(RSL_IE_MS_POWER_PARAM, RSL_IE_Body:{ms_power_params := pp}))
2010 };
2011
2012 /* establish with power parameters */
2013 f_est_dchan(more_ies := addl_ies);
2014
2015 /* set a high value to ensure L1 power control level increases */
2016 f_trxc_fake_rssi(rxlev2dbm(20));
2017
2018 timer T2 := 6.0;
2019 T2.start;
2020 alt {
2021 [] L1CTL.receive(tr_L1CTL_DATA_IND(g_chan_nr, tr_RslLinkID_SACCH(?))) -> value l1_dl {
2022 if( not(oct2int(l1_dl.payload.data_ind.payload[0]) > (pwr_var+6))){
2023 repeat;
2024 }
2025 T2.stop;
2026 }
2027 [] L1CTL.receive { repeat; }
2028 [] T2.timeout {
2029 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
2030 "Power Level in L1 header has not increased sufficiently");
2031 }
2032 }
2033
2034 /* set a low value to ensure L1 power control level decreases */
2035 f_trxc_fake_rssi(rxlev2dbm(0));
2036
2037 timer T4 := 6.0;
2038 T4.start;
2039 alt {
2040 [] L1CTL.receive(tr_L1CTL_DATA_IND(g_chan_nr, tr_RslLinkID_SACCH(?))) -> value l1_dl {
2041 if( not(oct2int(l1_dl.payload.data_ind.payload[0]) <= (pwr_var))){
2042 repeat;
2043 }
2044 T4.stop;
2045 setverdict(pass, "Power level in L1 decreased/increased as expected");
2046 }
2047 [] L1CTL.receive { repeat; }
2048 [] T4.timeout {
2049 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
2050 "Power Level in L1 header has not decreased sufficiently");
2051 }
2052 }
2053
2054 f_rsl_chan_deact();
2055 f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
2056
2057}
2058
2059/* check that we do not exceed the max power */
2060function f_TC_rsl_ms_pwr_dyn_max(charstring id) runs on ConnHdlr {
2061 var uint5_t pwr_var := 7;
2062 var L1ctlDlMessage l1_dl;
2063
2064 /* set a low value to ensure power increases */
2065 f_trxc_fake_rssi(rxlev2dbm(10));
2066 f_l1_tune(L1CTL);
2067 RSL.clear;
2068
2069 var RSL_IE_List addl_ies;
2070 var template (value) RSL_IE_MS_Power_Parameters pp := (ts_RSL_IE_MS_Power_Parameters(''O));
2071
2072 addl_ies := {
2073 valueof(t_RSL_IE(RSL_IE_MS_POWER, RSL_IE_Body:{ms_power := ts_RSL_IE_MS_Power(pwr_var)})),
2074 valueof(t_RSL_IE(RSL_IE_MS_POWER_PARAM, RSL_IE_Body:{ms_power_params := pp}))
2075 };
2076
2077 /* establish with power parameters */
2078 f_est_dchan(more_ies := addl_ies);
2079
2080 timer T1 := 10.0;
2081 T1.start;
2082 alt {
2083 [] L1CTL.receive(tr_L1CTL_DATA_IND(g_chan_nr, tr_RslLinkID_SACCH(?))) -> value l1_dl { repeat; }
2084 [] L1CTL.receive { repeat; }
2085 [] T1.timeout {
2086 if( oct2int(l1_dl.payload.data_ind.payload[0]) != pwr_var){
2087 setverdict(fail, "Power level in L1 header should not have changed");
2088 }
2089 }
2090 }
2091
2092 f_rsl_chan_deact();
2093 f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
2094
2095}
2096
2097/* see if we reach the band max power */
2098function f_TC_rsl_ms_pwr_dyn_up(charstring id) runs on ConnHdlr {
2099 var L1ctlDlMessage l1_dl;
2100 var uint5_t pwr_var := 15;
2101 var uint5_t pwr_max_var := f_get_max_power_from_band();
2102
2103 /* set a low value to ensure power increases */
2104 f_trxc_fake_rssi(rxlev2dbm(10));
2105 f_l1_tune(L1CTL);
2106 RSL.clear;
2107
2108 var template (value) RSL_IE_MS_Power ms_power := ts_RSL_IE_MS_Power(pwr_var);
2109 var template (value) RSL_IE pwr := t_RSL_IE(RSL_IE_MS_POWER, RSL_IE_Body:{ms_power := ms_power});
2110
2111 /* establish with fixed power level */
2112 f_est_dchan(more_ies :={valueof(pwr)});
2113
2114 /* check our initial power level */
2115 f_wait_for_l1_power_level(pwr_var);
2116
2117 /* update power param to enable power loop
2118 48.058 The maximum power to be used is indicated in the BS and MS Power elements respectively. */
2119 RSL.send(ts_RSL_MS_PWR_CTRL_with_pp(g_chan_nr, pwr_max_var));
2120
2121 /* wait, then check that our power level was reduced */
2122 timer T1 := 10.0;
2123 T1.start;
2124 alt {
2125 [] L1CTL.receive(tr_L1CTL_DATA_IND(g_chan_nr, tr_RslLinkID_SACCH(?))) -> value l1_dl { repeat; }
2126 [] L1CTL.receive { repeat; }
2127 [] T1.timeout {
2128 var int8_t rcv := oct2int(l1_dl.payload.data_ind.payload[0]);
2129 if( f_power_level_is_highest_dbm(rcv) ){
2130 setverdict(pass, "Power level in L1 header reduced as expected");
2131 } else {
2132 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
2133 log2str("Power Level in L1 header did not reach the expected value, e:",pwr_max_var," r:",rcv));
2134 }
2135 }
2136 }
2137
2138 f_rsl_chan_deact();
2139 f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
2140
2141}
2142
2143/* see if we reach the band min power */
2144function f_TC_rsl_ms_pwr_dyn_down(charstring id) runs on ConnHdlr {
2145 var L1ctlDlMessage l1_dl;
2146
2147 /* set a high value to ensure power decreases */
2148 f_trxc_fake_rssi(rxlev2dbm(50));
2149 f_l1_tune(L1CTL);
2150 RSL.clear;
2151
2152 var uint5_t pwr_var := 5;
2153 var uint5_t pwr_target_val := 15;
2154
2155 var template (value) RSL_IE_MS_Power ms_power := ts_RSL_IE_MS_Power(pwr_var);
2156 var template (value) RSL_IE pwr := t_RSL_IE(RSL_IE_MS_POWER, RSL_IE_Body:{ms_power := ms_power});
2157
2158 /* establish with fixed power level */
2159 f_est_dchan(more_ies :={valueof(pwr)});
2160
2161 /* check our initial power level */
2162 f_wait_for_l1_power_level(pwr_var);
2163
2164 /* update power param to enable power loop
2165 as per spec the supplied ms power IE should set the max allowed power...*/
2166 RSL.send(ts_RSL_MS_PWR_CTRL_with_pp(g_chan_nr, pwr_var));
2167
2168 /* wait, then check that our power level was increased */
2169 timer T1 := 10.0;
2170 T1.start;
2171 alt {
2172 [] L1CTL.receive(tr_L1CTL_DATA_IND(g_chan_nr, tr_RslLinkID_SACCH(?))) -> value l1_dl { repeat; }
2173 [] L1CTL.receive { repeat; }
2174 [] T1.timeout {
2175 if( f_power_level_is_lowest_dbm(oct2int(l1_dl.payload.data_ind.payload[0])) ){
2176 setverdict(pass, "Power level in L1 header increased to lowest power value");
2177 } else {
2178 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
2179 "Power level in L1 header NOT increased to lowest power value");
2180 }
2181 }
2182 }
2183
2184 f_rsl_chan_deact();
2185 f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
2186
2187}
2188
Eric Wild095024b2019-06-17 15:08:57 +02002189/* see if we change the power level without receiving power parameters, which should not happen
2190rsl chan act WITHOUT power parameters */
Eric Wild280ccb82019-06-17 11:11:52 +02002191function f_TC_rsl_ms_pwr_dyn_active(charstring id) runs on ConnHdlr {
2192 var L1ctlDlMessage l1_dl;
2193
2194 /* set a high value to ensure power decreases */
2195 f_trxc_fake_rssi(rxlev2dbm(50));
2196 f_l1_tune(L1CTL);
2197 RSL.clear;
2198
2199 var uint5_t pwr_var := 5;
2200
2201 var template (value) RSL_IE_MS_Power ms_power := ts_RSL_IE_MS_Power(pwr_var);
2202 var template (value) RSL_IE pwr := t_RSL_IE(RSL_IE_MS_POWER, RSL_IE_Body:{ms_power := ms_power});
2203
2204 /* establish with fixed power level */
2205 f_est_dchan(more_ies :={valueof(pwr)});
2206
2207 /* check our initial power level */
2208 f_wait_for_l1_power_level(pwr_var);
2209
2210 /* wait, then check that our power level did not change */
2211 timer T1 := 10.0;
2212 T1.start;
2213 alt {
2214 [] L1CTL.receive(tr_L1CTL_DATA_IND(g_chan_nr, tr_RslLinkID_SACCH(?))) -> value l1_dl {
2215 if ( oct2int(l1_dl.payload.data_ind.payload[0]) != pwr_var) {
2216 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
2217 "BS power control should not be active unless we receive a power parameters IE!");
2218 }
2219 repeat;
2220 }
2221 [] L1CTL.receive { repeat; }
2222 [] T1.timeout { setverdict(pass); }
2223 }
2224
2225 f_rsl_chan_deact();
2226 f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
2227
2228}
2229
Eric Wild095024b2019-06-17 15:08:57 +02002230/* see if we change the power level without receiving power parameters, which should not happen
2231ms power control WITHOUT power parameters */
2232function f_TC_rsl_ms_pwr_dyn_active2(charstring id) runs on ConnHdlr {
2233 var L1ctlDlMessage l1_dl;
2234
2235 /* set a high value to ensure power decreases */
2236 f_trxc_fake_rssi(rxlev2dbm(50));
2237 f_l1_tune(L1CTL);
2238 RSL.clear;
2239
2240 var uint5_t pwr_var := 5;
2241
2242 var template (value) RSL_IE_MS_Power ms_power := ts_RSL_IE_MS_Power(pwr_var);
2243 var template (value) RSL_IE pwr := t_RSL_IE(RSL_IE_MS_POWER, RSL_IE_Body:{ms_power := ms_power});
2244
2245 /* establish with fixed power level */
2246 f_est_dchan(more_ies :={valueof(pwr)});
2247
2248 /* check our initial power level */
2249 f_wait_for_l1_power_level(pwr_var);
2250
2251 /* pwr control without power params IE, should NOT activate MS power control*/
2252 RSL.send(ts_RSL_MS_PWR_CTRL(g_chan_nr, ms_power));
2253
2254 /* wait, then check that our power level did not change */
2255 timer T1 := 10.0;
2256 T1.start;
2257 alt {
2258 [] L1CTL.receive(tr_L1CTL_DATA_IND(g_chan_nr, tr_RslLinkID_SACCH(?))) -> value l1_dl {
2259 if ( oct2int(l1_dl.payload.data_ind.payload[0]) != pwr_var) {
2260 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
2261 "BS power control should not be active unless we receive a power parameters IE!");
2262 }
2263 repeat;
2264 }
2265 [] L1CTL.receive { repeat; }
2266 [] T1.timeout { setverdict(pass); }
2267 }
2268
2269 f_rsl_chan_deact();
2270 f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
2271
2272}
2273
Eric Wild61edb7e2019-06-03 12:38:31 +02002274function f_wait_for_l1_power_level(integer level) runs on ConnHdlr {
2275 var L1ctlDlMessage l1_dl;
2276 timer T0 := 10.0;
2277 T0.start;
2278 alt {
2279 [] L1CTL.receive(tr_L1CTL_DATA_IND(g_chan_nr, tr_RslLinkID_SACCH(?))) -> value l1_dl {
2280 if (not (l1_dl.payload.data_ind.payload[0] == int2oct(level, 1))) {
2281 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
2282 "Power level in L1 header != signaled (RSL) power level.");
2283 }
2284 }
2285 [] L1CTL.receive { repeat; }
2286 [] T0.timeout {
2287 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
2288 "Timeout waiting for initial power level");
2289 }
2290 }
2291 T0.stop;
2292}
2293
2294private function f_power_level_is_lowest_dbm(integer level) runs on ConnHdlr return boolean {
2295 var IntegerRecord min_dbm_level;
2296 var IntegerRecord max_dbm_level;
2297 var IntegerRecord x := f_power_from_band(g_pars.bts0_band, min_dbm_level, max_dbm_level);
2298
2299 for (var integer i := 0; i < sizeof(min_dbm_level); i := i+1) {
2300 if (min_dbm_level[i] == level) {
2301 return true;
2302 }
2303 }
2304 return false;
2305}
2306
2307private function f_power_level_is_highest_dbm(integer level) runs on ConnHdlr return boolean {
2308 var IntegerRecord min_dbm_level;
2309 var IntegerRecord max_dbm_level;
2310 var IntegerRecord x := f_power_from_band(g_pars.bts0_band, min_dbm_level, max_dbm_level);
2311
2312 for (var integer i := 0; i < sizeof(max_dbm_level); i := i+1) {
2313 if (max_dbm_level[i] == level) {
2314 return true;
2315 }
2316 }
2317 return false;
2318}
2319
2320private function f_get_max_power_from_band() runs on ConnHdlr return integer {
2321 var IntegerRecord min_dbm_level;
2322 var IntegerRecord max_dbm_level;
2323 var IntegerRecord x := f_power_from_band(g_pars.bts0_band, min_dbm_level, max_dbm_level);
2324 return max_dbm_level[0];
2325}
2326
2327type charstring BtsBand ("GSM450","GSM480","GSM750","GSM810","GSM850","GSM900","DCS1800","PCS1900");
2328template charstring BtsBand_allGSM:= pattern "GSM???";
2329private function f_power_from_band(in BtsBand band, out IntegerRecord min_dbm_level, out IntegerRecord max_dbm_level) return IntegerRecord {
2330 // 45.005 4.1.1
2331 var IntegerRecord gsm_power :={31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19,
2332 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3,
2333 2, 1, 0};
2334 var IntegerRecord dcs_power :={28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15,
2335 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 31, 30, 29};
2336 var IntegerRecord pcs_power :={15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 31, 30};
2337 var IntegerRecord rv;
2338
2339 select(band){
2340 case (BtsBand_allGSM){
2341 rv := gsm_power;
2342 min_dbm_level := {31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19} ;
2343 max_dbm_level := {2, 1, 0};
2344 }
2345 case("DCS1800"){
2346 rv := dcs_power;
2347 min_dbm_level := {28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15};
2348 max_dbm_level := {0, 29}; // let's cheat here, assume MS_TXPWR_MAX_CCH might be being broadcast, so maybe no 29,30,31
2349 }
2350 case("PCS1900"){
2351 rv := pcs_power;
2352 min_dbm_level := {15};
2353 max_dbm_level := {30};
2354 }
2355 }
2356
2357 return rv;
2358}
2359
2360private function f_vty_get_bts0_band() runs on test_CT return BtsBand {
2361 return f_vty_transceive_match_regex(BTSVTY, "show bts 0", "BTS 0 is of \w+ type in band (\w+),*", 0);
2362}
2363
2364testcase TC_rsl_ms_pwr_dyn_ass_updown() runs on test_CT {
2365 var ConnHdlr vc_conn;
2366 var ConnHdlrPars pars;
2367 f_init();
2368 f_vty_config(BTSVTY, "phy 0", "osmotrx ms-power-loop -100");
2369 for (var integer tn := 1; tn <= 1; tn := tn+1) {
2370 pars := valueof(t_Pars(t_RslChanNr_Bm(tn), ts_RSL_ChanMode_SIGN));
2371 pars.bts0_band := f_vty_get_bts0_band();
2372 vc_conn := f_start_handler(refers(f_TC_rsl_ms_pwr_dyn_ass_updown), pars, trxc_comp := true);
2373 vc_conn.done;
2374 }
2375 f_vty_config(BTSVTY, "phy 0", "no osmotrx ms-power-loop");
2376 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
2377}
2378
2379testcase TC_rsl_ms_pwr_dyn_up() runs on test_CT {
2380 var ConnHdlr vc_conn;
2381 var ConnHdlrPars pars;
2382 f_init();
2383 f_vty_config(BTSVTY, "phy 0", "osmotrx ms-power-loop -10");
2384 for (var integer tn := 1; tn <= 1; tn := tn+1) {
2385 pars := valueof(t_Pars(t_RslChanNr_Bm(tn), ts_RSL_ChanMode_SIGN));
2386 pars.bts0_band := f_vty_get_bts0_band();
2387 vc_conn := f_start_handler(refers(f_TC_rsl_ms_pwr_dyn_up), pars, trxc_comp := true);
2388 vc_conn.done;
2389 }
2390 f_vty_config(BTSVTY, "phy 0", "no osmotrx ms-power-loop");
2391 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
2392}
2393
2394testcase TC_rsl_ms_pwr_dyn_max() runs on test_CT {
2395 var ConnHdlr vc_conn;
2396 var ConnHdlrPars pars;
2397 f_init();
2398 f_vty_config(BTSVTY, "phy 0", "osmotrx ms-power-loop -10");
2399 for (var integer tn := 1; tn <= 1; tn := tn+1) {
2400 pars := valueof(t_Pars(t_RslChanNr_Bm(tn), ts_RSL_ChanMode_SIGN));
2401 pars.bts0_band := f_vty_get_bts0_band();
2402 vc_conn := f_start_handler(refers(f_TC_rsl_ms_pwr_dyn_max), pars, trxc_comp := true);
2403 vc_conn.done;
2404 }
2405 f_vty_config(BTSVTY, "phy 0", "no osmotrx ms-power-loop");
2406 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
2407}
2408
2409testcase TC_rsl_ms_pwr_dyn_down() runs on test_CT {
2410 var ConnHdlr vc_conn;
2411 var ConnHdlrPars pars;
2412 f_init();
2413 f_vty_config(BTSVTY, "phy 0", "osmotrx ms-power-loop -100");
2414 for (var integer tn := 1; tn <= 1; tn := tn+1) {
2415 pars := valueof(t_Pars(t_RslChanNr_Bm(tn), ts_RSL_ChanMode_SIGN));
2416 pars.bts0_band := f_vty_get_bts0_band();
2417 vc_conn := f_start_handler(refers(f_TC_rsl_ms_pwr_dyn_down), pars, trxc_comp := true);
2418 vc_conn.done;
2419 }
2420 f_vty_config(BTSVTY, "phy 0", "no osmotrx ms-power-loop");
2421 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
2422}
2423
Eric Wild280ccb82019-06-17 11:11:52 +02002424testcase TC_rsl_ms_pwr_dyn_active() runs on test_CT {
2425 var ConnHdlr vc_conn;
2426 var ConnHdlrPars pars;
2427 f_init();
2428 f_vty_config(BTSVTY, "phy 0", "osmotrx ms-power-loop -100");
2429 for (var integer tn := 1; tn <= 1; tn := tn+1) {
2430 pars := valueof(t_Pars(t_RslChanNr_Bm(tn), ts_RSL_ChanMode_SIGN));
2431 pars.bts0_band := f_vty_get_bts0_band();
2432 vc_conn := f_start_handler(refers(f_TC_rsl_ms_pwr_dyn_active), pars, trxc_comp := true);
2433 vc_conn.done;
2434 }
2435 f_vty_config(BTSVTY, "phy 0", "no osmotrx ms-power-loop");
2436 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
2437}
2438
Eric Wild095024b2019-06-17 15:08:57 +02002439testcase TC_rsl_ms_pwr_dyn_active2() runs on test_CT {
2440 var ConnHdlr vc_conn;
2441 var ConnHdlrPars pars;
2442 f_init();
2443 f_vty_config(BTSVTY, "phy 0", "osmotrx ms-power-loop -100");
2444 for (var integer tn := 1; tn <= 1; tn := tn+1) {
2445 pars := valueof(t_Pars(t_RslChanNr_Bm(tn), ts_RSL_ChanMode_SIGN));
2446 pars.bts0_band := f_vty_get_bts0_band();
2447 vc_conn := f_start_handler(refers(f_TC_rsl_ms_pwr_dyn_active2), pars, trxc_comp := true);
2448 vc_conn.done;
2449 }
2450 f_vty_config(BTSVTY, "phy 0", "no osmotrx ms-power-loop");
2451 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
2452}
2453
Harald Welte70767382018-02-21 12:16:40 +01002454testcase TC_meas_res_sign_tchf() runs on test_CT {
2455 var ConnHdlr vc_conn;
2456 var ConnHdlrPars pars;
Harald Welte10474062019-05-30 16:48:17 +02002457 f_init();
Harald Welte70767382018-02-21 12:16:40 +01002458 for (var integer tn := 1; tn <= 4; tn := tn+1) {
2459 pars := valueof(t_Pars(t_RslChanNr_Bm(tn), ts_RSL_ChanMode_SIGN));
Vadim Yanitskiyf4e997c2019-06-04 21:40:33 +07002460 vc_conn := f_start_handler(refers(f_TC_meas_res_periodic), pars,
2461 pcu_comp := false, trxc_comp := true);
Harald Welte70767382018-02-21 12:16:40 +01002462 vc_conn.done;
2463 }
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02002464 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
Harald Welte70767382018-02-21 12:16:40 +01002465}
2466testcase TC_meas_res_sign_tchh() runs on test_CT {
2467 var ConnHdlr vc_conn;
2468 var ConnHdlrPars pars;
Harald Welte10474062019-05-30 16:48:17 +02002469 f_init();
Harald Welte70767382018-02-21 12:16:40 +01002470 for (var integer ss := 0; ss <= 1; ss := ss+1) {
2471 pars := valueof(t_Pars(t_RslChanNr_Lm(5, ss), ts_RSL_ChanMode_SIGN));
Eric Wild5b9ef142019-07-11 19:28:02 +02002472 vc_conn := f_start_handler(refers(f_TC_meas_res_periodic), pars,
2473 pcu_comp := false, trxc_comp := true);
Harald Welte70767382018-02-21 12:16:40 +01002474 vc_conn.done;
2475 }
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02002476 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
Harald Welte70767382018-02-21 12:16:40 +01002477}
2478testcase TC_meas_res_sign_sdcch4() runs on test_CT {
2479 var ConnHdlr vc_conn;
2480 var ConnHdlrPars pars;
Harald Welte10474062019-05-30 16:48:17 +02002481 f_init();
Harald Welte70767382018-02-21 12:16:40 +01002482 for (var integer ss := 0; ss <= 3; ss := ss+1) {
2483 pars := valueof(t_Pars(t_RslChanNr_SDCCH4(0, ss), ts_RSL_ChanMode_SIGN));
Eric Wild5b9ef142019-07-11 19:28:02 +02002484 vc_conn := f_start_handler(refers(f_TC_meas_res_periodic), pars,
2485 pcu_comp := false, trxc_comp := true);
Harald Welte70767382018-02-21 12:16:40 +01002486 vc_conn.done;
2487 }
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02002488 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
Harald Welte70767382018-02-21 12:16:40 +01002489}
2490testcase TC_meas_res_sign_sdcch8() runs on test_CT {
2491 var ConnHdlr vc_conn;
2492 var ConnHdlrPars pars;
Harald Welte10474062019-05-30 16:48:17 +02002493 f_init();
Harald Welte70767382018-02-21 12:16:40 +01002494 for (var integer ss := 0; ss <= 7; ss := ss+1) {
2495 pars := valueof(t_Pars(t_RslChanNr_SDCCH8(6, ss), ts_RSL_ChanMode_SIGN));
Eric Wild5b9ef142019-07-11 19:28:02 +02002496 vc_conn := f_start_handler(refers(f_TC_meas_res_periodic), pars,
2497 pcu_comp := false, trxc_comp := true);
Harald Welte70767382018-02-21 12:16:40 +01002498 vc_conn.done;
2499 }
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02002500 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
Harald Welte70767382018-02-21 12:16:40 +01002501}
Harald Welte685d5982018-02-27 20:42:05 +01002502testcase TC_meas_res_sign_tchh_toa256() runs on test_CT {
2503 var ConnHdlr vc_conn;
2504 var ConnHdlrPars pars;
Harald Welte10474062019-05-30 16:48:17 +02002505 f_init();
Harald Welte685d5982018-02-27 20:42:05 +01002506 f_vty_config(BTSVTY, "bts 0", "supp-meas-info toa256");
2507 for (var integer ss := 0; ss <= 1; ss := ss+1) {
2508 pars := valueof(t_Pars(t_RslChanNr_Lm(5, ss), ts_RSL_ChanMode_SIGN));
2509 pars.l1_pars.toa256_enabled := true;
2510 vc_conn := f_start_handler(refers(f_TC_meas_res_periodic), pars);
2511 vc_conn.done;
2512 }
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02002513 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
Harald Welte685d5982018-02-27 20:42:05 +01002514}
2515
Philipp Maier4d1e9c92018-12-20 11:11:56 +01002516/* establish DChan, and send MS POWER CONTROL messages via RSL, verify that
2517 * the BTS is forwarding those values to the MS via the SACCH L1 header. */
2518function f_tc_rsl_ms_pwr_ctrl(charstring id) runs on ConnHdlr {
2519 var L1ctlDlMessage l1_dl;
2520 var RSL_IE_MS_Power ms_power;
2521 var RSL_Message rsl;
2522 var uint5_t power_level := 0;
2523
2524 f_l1_tune(L1CTL);
2525 RSL.clear;
2526
2527 f_est_dchan();
2528
2529 ms_power.reserved := 0;
2530 ms_power.fpc_epc := false;
2531
2532 /* Send the first power control command. This will disable any BTS/TRX
2533 * internal power control and switch the MS (which is not in scope of
2534 * this test) to a constant power level. We start with a power level
2535 * of 0 */
2536 ms_power.power_level := power_level;
2537 rsl := valueof(ts_RSL_MS_PWR_CTRL(g_chan_nr, ms_power));
2538 RSL.send(rsl);
2539
2540 alt {
2541
2542 /* Pick all SACCH blocks for checking */
2543 [] L1CTL.receive(tr_L1CTL_DATA_IND(g_chan_nr, tr_RslLinkID_SACCH(?))) -> value l1_dl {
2544
2545 /* The first byte of the L1 header contains the power level.
2546 * The reserved bits and the fpc bit is set to 0, so we may
2547 * compare directly. */
2548 if (not (l1_dl.payload.data_ind.payload[0] == int2oct(power_level, 1))) {
2549 setverdict(fail, "Power level in L1 header does not match the signaled (RSL) power level.");
2550 }
2551
2552 /* Signal a new power level via RSL for the next turn. */
2553 if (power_level < 31) {
2554 power_level := power_level + 1;
2555 ms_power.power_level := power_level;
2556 rsl := valueof(ts_RSL_MS_PWR_CTRL(g_chan_nr, ms_power));
2557 RSL.send(rsl);
2558 repeat;
2559 }
2560
2561 }
2562
2563 /* Ignore all other blocks */
2564 [] L1CTL.receive { repeat; }
2565
2566 }
2567
2568 f_rsl_chan_deact();
2569 f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
2570
2571 setverdict(pass);
2572}
2573
2574testcase TC_rsl_ms_pwr_ctrl() runs on test_CT {
2575 var ConnHdlr vc_conn;
2576 var ConnHdlrPars pars;
Harald Welte10474062019-05-30 16:48:17 +02002577 f_init();
Philipp Maier4d1e9c92018-12-20 11:11:56 +01002578
2579 for (var integer tn := 1; tn <= 4; tn := tn+1) {
2580 pars := valueof(t_Pars(t_RslChanNr_Bm(tn), ts_RSL_ChanMode_SIGN));
2581 vc_conn := f_start_handler(refers(f_tc_rsl_ms_pwr_ctrl), pars);
2582 vc_conn.done;
2583 }
2584 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
2585}
Harald Welte70767382018-02-21 12:16:40 +01002586
Eric Wild6833cc92019-05-23 19:34:44 +02002587/* establish DChan, verify that the BTS sets the TA in the first SACCH L1 header.
2588TA for the IMM ASS messages is still controlled by g_pars.l1_pars.ms_actual_ta! */
2589function f_tc_rsl_chan_initial_ta(charstring id) runs on ConnHdlr {
2590 var L1ctlDlMessage l1_dl;
2591 var uint5_t ta_to_test := 16;
2592
2593
2594 f_l1_tune(L1CTL);
2595 RSL.clear;
2596
2597 /* tell fake_trx to use a given timing offset for all bursts */
Vadim Yanitskiydc8db922019-06-04 21:58:15 +07002598 f_trxc_fake_toffs256(ta_to_test*256);
Eric Wild6833cc92019-05-23 19:34:44 +02002599
2600 f_est_dchan(more_ies :={valueof(t_RSL_IE(RSL_IE_TIMING_ADVANCE, RSL_IE_Body:{timing_adv := ta_to_test}))} );
2601
2602
2603 alt {
2604
2605 /* Pick all SACCH blocks for checking */
2606 [] L1CTL.receive(tr_L1CTL_DATA_IND(g_chan_nr, tr_RslLinkID_SACCH(?))) -> value l1_dl {
2607
2608 /* The second byte of the L1 header contains the TA. */
2609 if (not (l1_dl.payload.data_ind.payload[1] == int2oct(ta_to_test, 1))) {
2610 setverdict(fail, "TA in L1 header does not match the signaled (RSL) TA.");
2611 }
2612
2613 }
2614
2615 /* Ignore all other blocks */
2616 [] L1CTL.receive { repeat; }
2617
2618 }
2619
2620 f_rsl_chan_deact();
2621 f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
2622
2623 setverdict(pass);
2624}
2625
2626testcase TC_rsl_chan_initial_ta() runs on test_CT {
2627 var ConnHdlr vc_conn;
2628 var ConnHdlrPars pars;
Harald Welte10474062019-05-30 16:48:17 +02002629 f_init();
Eric Wild6833cc92019-05-23 19:34:44 +02002630 pars := valueof(t_Pars(t_RslChanNr_Bm(1), ts_RSL_ChanMode_SIGN));
Vadim Yanitskiyf4e997c2019-06-04 21:40:33 +07002631 vc_conn := f_start_handler(refers(f_tc_rsl_chan_initial_ta), pars,
2632 pcu_comp := false, trxc_comp := true);
Eric Wild6833cc92019-05-23 19:34:44 +02002633 vc_conn.done;
2634 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
2635}
2636
Eric Wilde57e1a62019-05-28 13:30:55 +02002637/* establish DChan, verify that the BTS sets MS power in the first SACCH L1 header. */
2638function f_tc_rsl_chan_initial_ms_pwr(charstring id) runs on ConnHdlr {
2639 var L1ctlDlMessage l1_dl;
2640 var uint5_t ms_power_level := 7;
2641
2642 var RSL_IE_MS_Power ms_power;
2643 ms_power.reserved := 0;
2644 ms_power.fpc_epc := false;
2645 ms_power.power_level := ms_power_level;
2646
2647 f_l1_tune(L1CTL);
2648 RSL.clear;
2649
2650 f_est_dchan(more_ies :={valueof(t_RSL_IE(RSL_IE_MS_POWER, RSL_IE_Body:{ms_power := ms_power}))} );
2651
2652 timer T := 1.0;
2653 T.start;
2654 alt {
2655 /* Pick all SACCH blocks for checking */
2656 [] L1CTL.receive(tr_L1CTL_DATA_IND(g_chan_nr, tr_RslLinkID_SACCH(?))) -> value l1_dl {
2657 /* The first byte of the L1 header contains the power level.. */
2658 if (not (l1_dl.payload.data_ind.payload[0] == int2oct(ms_power_level, 1))) {
2659 setverdict(fail, "Power Level in L1 header does not match the signaled (RSL) MS Power Level.");
2660 }
2661 }
2662 /* Ignore all other blocks */
2663 [] L1CTL.receive { repeat; }
2664 [] T.timeout {
2665 setverdict(fail, "Power Level in L1 header does not match the signaled (RSL) MS Power Level.");
2666 }
2667 }
2668
2669 f_rsl_chan_deact();
2670 f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
2671 setverdict(pass);
2672}
2673
2674testcase TC_rsl_chan_initial_ms_pwr() runs on test_CT {
2675 var ConnHdlrPars pars := valueof(t_Pars(t_RslChanNr_Bm(1), ts_RSL_ChanMode_SIGN));
2676 f_testmatrix_each_chan(pars, refers(f_tc_rsl_chan_initial_ms_pwr));
2677}
2678
Harald Welte0472ab42018-03-12 15:02:26 +01002679/* Test if a channel without valid uplink bursts generates RSL CONN FAIL IND (TS 48.058 4.10) */
Harald Welte70767382018-02-21 12:16:40 +01002680private function f_TC_conn_fail_crit(charstring id) runs on ConnHdlr {
Harald Welte68e495b2018-02-25 00:05:57 +01002681 f_l1_tune(L1CTL);
Harald Welte70767382018-02-21 12:16:40 +01002682 RSL.clear;
2683
2684 f_est_dchan();
2685 f_sleep(2.0);
Harald Weltef8df4cb2018-03-10 15:15:08 +01002686 L1CTL.send(ts_L1CTL_DM_REL_REQ(g_chan_nr));
Harald Welte70767382018-02-21 12:16:40 +01002687
2688 timer T := 40.0;
2689 T.start;
2690 alt {
2691 [] RSL.receive(tr_RSL_CONN_FAIL_IND(g_chan_nr, ?)) {
2692 setverdict(pass)
2693 }
2694 [] RSL.receive { repeat };
2695 [] T.timeout {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02002696 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "No CONN FAIL IND received");
Harald Welte70767382018-02-21 12:16:40 +01002697 }
2698 }
2699 f_rsl_chan_deact();
2700}
2701testcase TC_conn_fail_crit() runs on test_CT {
2702 var ConnHdlr vc_conn;
2703 var ConnHdlrPars pars;
Harald Welte10474062019-05-30 16:48:17 +02002704 f_init();
Harald Welte70767382018-02-21 12:16:40 +01002705 pars := valueof(t_Pars(t_RslChanNr_SDCCH8(6, 3), ts_RSL_ChanMode_SIGN));
2706 pars.t_guard := 60.0;
2707 vc_conn := f_start_handler(refers(f_TC_conn_fail_crit), pars);
2708 vc_conn.done;
2709}
2710
Harald Welte93640c62018-02-25 16:59:33 +01002711/***********************************************************************
2712 * Paging
2713 ***********************************************************************/
2714
Harald Welte68e495b2018-02-25 00:05:57 +01002715function tmsi_is_dummy(TMSIP_TMSI_V tmsi) return boolean {
2716 if (tmsi == 'FFFFFFFF'O) {
2717 return true;
2718 } else {
2719 return false;
2720 }
2721}
Harald Welte70767382018-02-21 12:16:40 +01002722
Philipp Maier82cb0b12018-08-31 14:41:39 +02002723type record allowedFn { integer frame_nr }
2724template allowedFn bs_ag_blks_res_0 := { frame_nr := (6, 12, 16, 22, 26, 32, 36, 42, 46) }
2725template allowedFn bs_ag_blks_res_1 := { frame_nr := (12, 16, 22, 26, 32, 36, 42, 46) }
2726template allowedFn bs_ag_blks_res_2 := { frame_nr := (16, 22, 26, 32, 36, 42, 46) }
2727template allowedFn bs_ag_blks_res_3 := { frame_nr := (22, 26, 32, 36, 42, 46) }
2728template allowedFn bs_ag_blks_res_4 := { frame_nr := (26, 32, 36, 42, 46) }
2729template allowedFn bs_ag_blks_res_5 := { frame_nr := (32, 36, 42, 46) }
2730template allowedFn bs_ag_blks_res_6 := { frame_nr := (36, 42, 46) }
2731template allowedFn bs_ag_blks_res_7 := { frame_nr := (42, 46) }
2732function check_pch_fn(integer frame_nr, integer bs_ag_blks_res) runs on test_CT
2733{
2734 var integer frame_nr_51;
2735 frame_nr_51 := frame_nr mod 51
2736
2737 var allowedFn fn_check;
2738 fn_check.frame_nr := frame_nr_51;
2739
2740 if (bs_ag_blks_res < 0 or bs_ag_blks_res > 7) {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02002741 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "bs_ag_blks_res out of valid range (0..7)");
Philipp Maier82cb0b12018-08-31 14:41:39 +02002742 return;
2743 }
2744
2745 if (bs_ag_blks_res == 0 and match(fn_check, bs_ag_blks_res_0)) {
2746 return;
2747 }
2748 if (bs_ag_blks_res == 1 and match(fn_check, bs_ag_blks_res_1)) {
2749 return;
2750 }
2751 if (bs_ag_blks_res == 2 and match(fn_check, bs_ag_blks_res_2)) {
2752 return;
2753 }
2754 if (bs_ag_blks_res == 3 and match(fn_check, bs_ag_blks_res_3)) {
2755 return;
2756 }
2757 if (bs_ag_blks_res == 4 and match(fn_check, bs_ag_blks_res_4)) {
2758 return;
2759 }
2760 if (bs_ag_blks_res == 5 and match(fn_check, bs_ag_blks_res_5)) {
2761 return;
2762 }
2763 if (bs_ag_blks_res == 6 and match(fn_check, bs_ag_blks_res_6)) {
2764 return;
2765 }
2766 if (bs_ag_blks_res == 7 and match(fn_check, bs_ag_blks_res_7)) {
2767 return;
2768 }
2769
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02002770 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "received paging on AGCH");
Philipp Maier82cb0b12018-08-31 14:41:39 +02002771 return;
2772}
2773
2774altstep as_l1_count_paging(inout integer num_paging_rcv_msgs, inout integer num_paging_rcv_ids, PagingTestCfg cfg)
Harald Welte68e495b2018-02-25 00:05:57 +01002775runs on test_CT {
2776 var L1ctlDlMessage dl;
Harald Weltef8df4cb2018-03-10 15:15:08 +01002777 [] L1CTL.receive(tr_L1CTL_DATA_IND(t_RslChanNr_PCH_AGCH(0), ?, c_DummyUI)) {
Harald Welte68e495b2018-02-25 00:05:57 +01002778 repeat;
2779 }
Harald Weltef8df4cb2018-03-10 15:15:08 +01002780 [] L1CTL.receive(tr_L1CTL_DATA_IND(t_RslChanNr_PCH_AGCH(0))) -> value dl {
Harald Welte68e495b2018-02-25 00:05:57 +01002781 var octetstring without_plen :=
2782 substr(dl.payload.data_ind.payload, 1, lengthof(dl.payload.data_ind.payload)-1);
2783 var PDU_ML3_NW_MS rr := dec_PDU_ML3_NW_MS(without_plen);
Philipp Maier82cb0b12018-08-31 14:41:39 +02002784
2785 check_pch_fn(dl.dl_info.frame_nr, cfg.bs_ag_blks_res);
2786
Harald Welte68e495b2018-02-25 00:05:57 +01002787 if (match(rr, tr_PAGING_REQ1)) {
2788 num_paging_rcv_msgs := num_paging_rcv_msgs + 1;
2789 num_paging_rcv_ids := num_paging_rcv_ids + 1;
2790 if (isvalue(rr.msgs.rrm.pagingReq_Type1.mobileIdentity2)) {
2791 num_paging_rcv_ids := num_paging_rcv_ids + 1;
2792 }
2793 } else if (match(rr, tr_PAGING_REQ2)) {
2794 num_paging_rcv_msgs := num_paging_rcv_msgs + 1;
2795 if (not tmsi_is_dummy(rr.msgs.rrm.pagingReq_Type2.mobileIdentity1)) {
2796 num_paging_rcv_ids := num_paging_rcv_ids + 1;
2797 }
2798 if (not tmsi_is_dummy(rr.msgs.rrm.pagingReq_Type2.mobileIdentity2)) {
2799 num_paging_rcv_ids := num_paging_rcv_ids + 1;
2800 }
2801 if (isvalue(rr.msgs.rrm.pagingReq_Type2.mobileIdentity3)) {
2802 num_paging_rcv_ids := num_paging_rcv_ids + 1;
2803 }
2804 } else if (match(rr, tr_PAGING_REQ3)) {
2805 num_paging_rcv_msgs := num_paging_rcv_msgs + 1;
2806 if (not tmsi_is_dummy(rr.msgs.rrm.pagingReq_Type3.mobileIdentity1)) {
2807 num_paging_rcv_ids := num_paging_rcv_ids + 1;
2808 }
2809 if (not tmsi_is_dummy(rr.msgs.rrm.pagingReq_Type3.mobileIdentity2)) {
2810 num_paging_rcv_ids := num_paging_rcv_ids + 1;
2811 }
2812 if (not tmsi_is_dummy(rr.msgs.rrm.pagingReq_Type3.mobileIdentity3)) {
2813 num_paging_rcv_ids := num_paging_rcv_ids + 1;
2814 }
2815 if (not tmsi_is_dummy(rr.msgs.rrm.pagingReq_Type3.mobileIdentity4)) {
2816 num_paging_rcv_ids := num_paging_rcv_ids + 1;
2817 }
2818 }
2819 repeat;
2820 }
2821}
2822
2823type record PagingTestCfg {
2824 boolean combined_ccch,
2825 integer bs_ag_blks_res,
2826 float load_factor,
2827 boolean exp_load_ind,
2828 boolean exp_overload,
2829 boolean use_tmsi
2830}
2831
2832type record PagingTestState {
2833 integer num_paging_sent,
2834 integer num_paging_rcv_msgs,
2835 integer num_paging_rcv_ids,
2836 integer num_overload
2837}
2838
2839/* receive + ignore RSL RF RES IND */
2840altstep as_rsl_res_ind() runs on test_CT {
2841 [] RSL_CCHAN.receive(tr_RSL_UD(tr_RSL_RF_RES_IND)) {
2842 repeat;
2843 }
2844}
2845
2846/* Helper function for paging related testing */
2847private function f_TC_paging(PagingTestCfg cfg) runs on test_CT return PagingTestState {
Harald Welte10474062019-05-30 16:48:17 +02002848 f_init();
Harald Welte68e495b2018-02-25 00:05:57 +01002849 f_init_l1ctl();
2850 f_l1_tune(L1CTL);
2851
2852 var PagingTestState st := {
2853 num_paging_sent := 0,
2854 num_paging_rcv_msgs := 0,
2855 num_paging_rcv_ids := 0,
2856 num_overload := 0
2857 };
2858
2859 var float max_pch_blocks_per_sec := f_pch_block_rate_est(cfg.combined_ccch, cfg.bs_ag_blks_res);
2860 var float max_pch_imsi_per_sec;
2861 if (cfg.use_tmsi) {
2862 max_pch_imsi_per_sec := max_pch_blocks_per_sec * 4.0; /* Type 3 */
2863 } else {
2864 max_pch_imsi_per_sec := max_pch_blocks_per_sec * 2.0; /* Type 1 */
2865 }
2866 var float pch_blocks_per_sec := max_pch_imsi_per_sec * cfg.load_factor;
2867 var float interval := 1.0 / pch_blocks_per_sec;
Pau Espin Pedrol9c3ff4e2018-09-26 18:30:16 +02002868 var float time_total := 20.0;
2869 var integer pkt_total := float2int(time_total * pch_blocks_per_sec);
2870 log("pch_blocks_total=", pkt_total," pch_blocks_per_sec=", pch_blocks_per_sec, " interval=", interval);
Harald Welte68e495b2018-02-25 00:05:57 +01002871
Pau Espin Pedrol9c3ff4e2018-09-26 18:30:16 +02002872 timer T_total := 300.0; /* big value (far bigger than time_total), used to count elapsed time */
2873 T_total.start;
Harald Welte68e495b2018-02-25 00:05:57 +01002874
Pau Espin Pedrol9c3ff4e2018-09-26 18:30:16 +02002875 timer T_itv := 0.0;
2876 T_itv.start;
2877 while (st.num_paging_sent < pkt_total) {
Harald Welte68e495b2018-02-25 00:05:57 +01002878 alt {
2879 /* check for presence of CCCH LOAD IND (paging load) */
2880 [cfg.exp_overload] RSL_CCHAN.receive(tr_RSL_UD(tr_RSL_PAGING_LOAD_IND(0))) {
2881 st.num_overload := st.num_overload + 1;
2882 repeat;
2883 }
2884 [not cfg.exp_overload] RSL_CCHAN.receive(tr_RSL_UD(tr_RSL_PAGING_LOAD_IND(0))) {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02002885 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Unexpected PCH Overload");
Harald Welte68e495b2018-02-25 00:05:57 +01002886 }
2887 [cfg.exp_load_ind] RSL_CCHAN.receive(tr_RSL_UD(tr_RSL_PAGING_LOAD_IND)) {
2888 log("Rx LOAD_IND");
2889 /* FIXME: analyze/verify interval + contents */
2890 repeat;
2891 }
2892 /* check if paging requests arrive on Um side */
Philipp Maier82cb0b12018-08-31 14:41:39 +02002893 [] as_l1_count_paging(st.num_paging_rcv_msgs, st.num_paging_rcv_ids, cfg);
Harald Welte68e495b2018-02-25 00:05:57 +01002894 [] L1CTL.receive { repeat; }
Pau Espin Pedrol9c3ff4e2018-09-26 18:30:16 +02002895 [] T_itv.timeout {
2896 /* Send paging cmds based on elapsed time */
2897 var integer new_sent := f_min(pkt_total, float2int(T_total.read * pch_blocks_per_sec) + 1);
2898 while (st.num_paging_sent < new_sent) {
2899 /* build mobile Identity */
2900 var MobileL3_CommonIE_Types.MobileIdentityLV mi;
2901 if (cfg.use_tmsi) {
2902 mi := valueof(ts_MI_TMSI_LV(f_rnd_octstring(4)));
2903 } else {
2904 mi := valueof(ts_MI_IMSI_LV(f_gen_imsi(st.num_paging_sent)));
2905 }
2906 var octetstring mi_enc_lv := enc_MobileIdentityLV(mi);
2907 var octetstring mi_enc := substr(mi_enc_lv, 1, lengthof(mi_enc_lv)-1);
2908
2909 /* Send RSL PAGING COMMAND */
2910 RSL_CCHAN.send(ts_RSL_UD(ts_RSL_PAGING_CMD(mi_enc, st.num_paging_sent mod 4)));
2911
2912 st.num_paging_sent := st.num_paging_sent + 1;
2913 }
2914 if (st.num_paging_sent < pkt_total) {
2915 /* Wait for interval to next PAGING COMMAND */
2916 var float time_now := T_total.read;
2917 var float next_sched := int2float(st.num_paging_sent)*interval;
2918 if (next_sched > time_now) {
2919 T_itv.start(next_sched - time_now);
2920 } else {
2921 T_itv.start(0.0);
2922 }
2923 } else {
2924 /* We are done, no need to keep counting */
2925 T_total.stop;
2926 }
2927 }
2928 [] T_total.timeout { }
Harald Welte68e495b2018-02-25 00:05:57 +01002929 [] as_rsl_res_ind();
2930 }
2931 }
2932
2933 /* wait for max 18s for paging queue to drain (size: 200, ~ 13 per s -> 15s) */
2934 timer T_wait := 18.0;
2935 T_wait.start;
2936 alt {
Philipp Maier82cb0b12018-08-31 14:41:39 +02002937 [] as_l1_count_paging(st.num_paging_rcv_msgs, st.num_paging_rcv_ids, cfg);
Harald Welte68e495b2018-02-25 00:05:57 +01002938 [] L1CTL.receive { repeat; }
2939 /* 65535 == empty paging queue, we can terminate*/
2940 [] RSL_CCHAN.receive(tr_RSL_UD(tr_RSL_PAGING_LOAD_IND(65535))) { }
2941 [] RSL_CCHAN.receive(tr_RSL_UD(tr_RSL_PAGING_LOAD_IND)) { repeat; }
2942 [] T_wait.timeout {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02002943 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Waiting for empty paging queue");
Harald Welte68e495b2018-02-25 00:05:57 +01002944 }
2945 [] as_rsl_res_ind();
2946 }
2947
2948 log("num_paging_sent=", st.num_paging_sent, " rcvd_msgs=", st.num_paging_rcv_msgs,
2949 " rcvd_ids=", st.num_paging_rcv_ids);
2950 return st;
2951}
2952
2953/* Create ~ 80% paging load (IMSI only) sustained for about 20s, verifying that
2954 * - the number of Mobile Identities on Um PCH match the number of pages on RSL
2955 * - that CCCH LOAD IND (PCH) are being generated
2956 * - that CCCH LOAD IND (PCH) [no load] is received after paging flood is over */
2957testcase TC_paging_imsi_80percent() runs on test_CT {
Philipp Maierd65d0562018-08-30 16:25:47 +02002958 var SystemInformation si3 := valueof(ts_SI3_default);
Harald Welte68e495b2018-02-25 00:05:57 +01002959 var PagingTestCfg cfg := {
2960 combined_ccch := true,
Philipp Maierd65d0562018-08-30 16:25:47 +02002961 bs_ag_blks_res := si3.payload.si3.ctrl_chan_desc.bs_ag_blks_res,
Harald Welte68e495b2018-02-25 00:05:57 +01002962 load_factor := 0.8,
2963 exp_load_ind := true,
2964 exp_overload := false,
2965 use_tmsi := false
2966 };
2967 var PagingTestState st := f_TC_paging(cfg);
2968 if (st.num_paging_sent != st.num_paging_rcv_ids) {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02002969 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("Expected ", st.num_paging_sent, " pagings but have ",
2970 st.num_paging_rcv_ids));
Harald Welte68e495b2018-02-25 00:05:57 +01002971 } else {
2972 setverdict(pass);
2973 }
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02002974 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
Harald Welte68e495b2018-02-25 00:05:57 +01002975}
2976
2977/* Create ~ 80% paging load (TMSI only) sustained for about 20s, verifying that
2978 * - the number of Mobile Identities on Um PCH match the number of pages on RSL
2979 * - that CCCH LOAD IND (PCH) are being generated
2980 * - that CCCH LOAD IND (PCH) [no load] is received after paging flood is over */
2981testcase TC_paging_tmsi_80percent() runs on test_CT {
Philipp Maierd65d0562018-08-30 16:25:47 +02002982 var SystemInformation si3 := valueof(ts_SI3_default);
Harald Welte68e495b2018-02-25 00:05:57 +01002983 var PagingTestCfg cfg := {
2984 combined_ccch := true,
Philipp Maierd65d0562018-08-30 16:25:47 +02002985 bs_ag_blks_res := si3.payload.si3.ctrl_chan_desc.bs_ag_blks_res,
Harald Welte68e495b2018-02-25 00:05:57 +01002986 load_factor := 0.8,
2987 exp_load_ind := true,
2988 exp_overload := false,
2989 use_tmsi := true
2990 };
2991 var PagingTestState st := f_TC_paging(cfg);
2992 if (st.num_paging_sent != st.num_paging_rcv_ids) {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02002993 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("Expected ", st.num_paging_sent, " pagings but have ",
2994 st.num_paging_rcv_ids));
Harald Welte68e495b2018-02-25 00:05:57 +01002995 } else {
2996 setverdict(pass);
2997 }
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02002998 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
Harald Welte68e495b2018-02-25 00:05:57 +01002999}
3000
3001/* Create ~ 200% paging load (IMSI only) sustained for about 20s, verifying that
3002 * - the number of Mobile Identities on Um PCH are ~ 82% of the number of pages on RSL
3003 * - that CCCH LOAD IND (PCH) are being generated and reach 0 at some point
3004 * - that CCCH LOAD IND (PCH) [no load] is received after paging flood is over */
3005testcase TC_paging_imsi_200percent() runs on test_CT {
Philipp Maierd65d0562018-08-30 16:25:47 +02003006 var SystemInformation si3 := valueof(ts_SI3_default);
Harald Welte68e495b2018-02-25 00:05:57 +01003007 var PagingTestCfg cfg := {
3008 combined_ccch := true,
Philipp Maierd65d0562018-08-30 16:25:47 +02003009 bs_ag_blks_res := si3.payload.si3.ctrl_chan_desc.bs_ag_blks_res,
Harald Welte68e495b2018-02-25 00:05:57 +01003010 load_factor := 2.0,
3011 exp_load_ind := true,
3012 exp_overload := true,
3013 use_tmsi := false
3014 };
3015 var PagingTestState st := f_TC_paging(cfg);
3016 /* We expect about 80-85% to pass, given that we can fill the paging buffer of 200
3017 * slots and will fully drain that buffer before returning */
Pau Espin Pedrol9c3ff4e2018-09-26 18:30:16 +02003018 var template integer tpl := (st.num_paging_sent*78/100 .. st.num_paging_sent *85/100);
Harald Welte68e495b2018-02-25 00:05:57 +01003019 if (not match(st.num_paging_rcv_ids, tpl)) {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02003020 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("Expected ", tpl, " pagings but have ", st.num_paging_rcv_ids));
Harald Welte68e495b2018-02-25 00:05:57 +01003021 } else {
3022 setverdict(pass);
3023 }
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02003024 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
Harald Welte68e495b2018-02-25 00:05:57 +01003025}
3026
3027/* Create ~ 200% paging load (TMSI only) sustained for about 20s, verifying that
3028 * - the number of Mobile Identities on Um PCH are ~ 82% of the number of pages on RSL
3029 * - that CCCH LOAD IND (PCH) are being generated and reach 0 at some point
3030 * - that CCCH LOAD IND (PCH) [no load] is received after paging flood is over */
3031testcase TC_paging_tmsi_200percent() runs on test_CT {
Philipp Maierd65d0562018-08-30 16:25:47 +02003032 var SystemInformation si3 := valueof(ts_SI3_default);
Harald Welte68e495b2018-02-25 00:05:57 +01003033 var PagingTestCfg cfg := {
3034 combined_ccch := true,
Philipp Maierd65d0562018-08-30 16:25:47 +02003035 bs_ag_blks_res := si3.payload.si3.ctrl_chan_desc.bs_ag_blks_res,
Harald Welte68e495b2018-02-25 00:05:57 +01003036 load_factor := 2.0,
3037 exp_load_ind := true,
3038 exp_overload := true,
3039 use_tmsi := true
3040 };
3041 var PagingTestState st := f_TC_paging(cfg);
3042 /* We expect about 70% to pass, given that we can fill the paging buffer of 200
3043 * slots and will fully drain that buffer before returning */
Pau Espin Pedrol9c3ff4e2018-09-26 18:30:16 +02003044 var template integer tpl := (st.num_paging_sent*64/100 .. st.num_paging_sent *72/100);
Harald Welte68e495b2018-02-25 00:05:57 +01003045 if (not match(st.num_paging_rcv_ids, tpl)) {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02003046 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("Expected ", tpl, " pagings but have ", st.num_paging_rcv_ids));
Harald Welte68e495b2018-02-25 00:05:57 +01003047 } else {
3048 setverdict(pass);
3049 }
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02003050 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
Harald Welte68e495b2018-02-25 00:05:57 +01003051}
3052
3053
Harald Welte93640c62018-02-25 16:59:33 +01003054/***********************************************************************
3055 * Immediate Assignment / AGCH
3056 ***********************************************************************/
Harald Weltee8d750e2018-06-10 21:41:35 +02003057const MobileAllocation c_MA_null := {
3058 len := 0,
3059 ma := ''B
3060}
Harald Welte93640c62018-02-25 16:59:33 +01003061
Harald Weltee8d750e2018-06-10 21:41:35 +02003062template (value) ChannelDescription ts_ChanDesc(template (value) RslChannelNr chan_nr, uint3_t tsc := 7,
3063 uint12_t arfcn := 871) := {
3064 chan_nr := chan_nr,
3065 tsc := tsc,
3066 h := false,
3067 arfcn := arfcn,
3068 maio_hsn := omit
3069}
3070
3071private function f_fmt_ia_stats(integer num_tx, integer num_rx, integer num_del) return charstring {
3072 return int2str(num_tx) & " sent, "
3073 & int2str(num_rx) & " received, "
3074 & int2str(num_del) & " deleted";
3075}
3076
3077private function f_TC_imm_ass(integer num_total, float sleep_s, float exp_pass) runs on test_CT {
3078 var L1ctlDlMessage l1_dl;
3079 timer T := 10.0;
3080 var integer num_tx := 0;
3081 var integer num_rx := 0;
3082 var integer num_del := 0;
3083 var charstring res_str;
3084 var float rx_ratio;
3085
Harald Welte10474062019-05-30 16:48:17 +02003086 f_init();
Harald Weltee8d750e2018-06-10 21:41:35 +02003087 f_init_l1ctl();
3088 f_l1_tune(L1CTL);
3089
3090 for (var integer i := 0; i < num_total; i := i+1) {
3091 var ChannelDescription ch_desc := valueof(ts_ChanDesc(valueof(t_RslChanNr_SDCCH4(0, 0))));
3092 var GsmRrMessage ia := valueof(ts_IMM_ASS(42, i, 5, ch_desc, c_MA_null));
3093 var octetstring ia_enc := enc_GsmRrMessage(ia);
Harald Welte68e495b2018-02-25 00:05:57 +01003094 RSL_CCHAN.send(ts_RSL_UD(ts_RSL_IMM_ASSIGN(ia_enc, 0)));
Harald Weltee8d750e2018-06-10 21:41:35 +02003095 num_tx := num_tx+1;
3096 f_sleep(sleep_s);
Harald Welte68e495b2018-02-25 00:05:57 +01003097 }
3098 /* FIXME: check if imm.ass arrive on Um side */
Harald Weltee8d750e2018-06-10 21:41:35 +02003099 T.start;
3100 alt {
3101 [] RSL_CCHAN.receive(tr_RSL_UD(tr_RSL_DELETE_IND(?, 0))) {
3102 num_del := num_del+1;
3103 repeat;
3104 }
3105 [] RSL_CCHAN.receive {
3106 repeat;
3107 }
3108 [] L1CTL.receive(tr_L1CTL_DATA_IND(t_RslChanNr_PCH_AGCH(0), ?)) -> value l1_dl {
3109 /* somehow dec_SystemInformation will try to decode even non-RR as SI */
3110 var GsmRrMessage rr := dec_GsmRrMessage(l1_dl.payload.data_ind.payload);
3111 if (not match(rr, tr_IMM_ASS(42, ?, 5, ?, ?))) {
3112 /* FIXME: Why are we seeing paging requests on PCH/AGCH? */
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02003113 //Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("Unexpected IMM-ASS values on AGCH: ", rr));
Harald Weltee8d750e2018-06-10 21:41:35 +02003114 } else {
3115 num_rx := num_rx+1;
3116 }
3117 repeat;
3118 }
3119 [] L1CTL.receive { repeat; }
3120 [] T.timeout { }
3121 }
3122 res_str := f_fmt_ia_stats(num_tx, num_rx, num_del);
3123 log("AGCH test: " & res_str);
3124 if (num_rx + num_del != num_tx) {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02003125 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "RX + DEL != TX ?!?: " & res_str);
Harald Weltee8d750e2018-06-10 21:41:35 +02003126 }
3127 rx_ratio := int2float(num_rx) / int2float(num_tx);
3128 if (rx_ratio < exp_pass*0.8 or rx_ratio > exp_pass*1.2) {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02003129 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "RX ratio ("&float2str(rx_ratio)&") far from expected ("&float2str(exp_pass)&") " & res_str);
Harald Weltee8d750e2018-06-10 21:41:35 +02003130 } else {
3131 setverdict(pass);
3132 }
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02003133 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
Harald Welte68e495b2018-02-25 00:05:57 +01003134}
3135
Harald Weltee8d750e2018-06-10 21:41:35 +02003136/* send a long burst of 1000 IMM.ASS with 20ms spacing (50 per s); expect 75% of them to be deleted */
3137testcase TC_imm_ass_1000_20ms() runs on test_CT {
3138 f_TC_imm_ass(1000, 0.02, 0.25);
3139}
3140
3141/* send a short burst of 200 IMM.ASS without any spacing; expect 95% of them to be deleted */
3142testcase TC_imm_ass_200_0ms() runs on test_CT {
3143 f_TC_imm_ass(200, 0.0, 0.05);
3144}
3145
3146/* send 150 IMM.ASS at rate of 13/s; expect none of them to be deleted */
3147testcase TC_imm_ass_200_76ms() runs on test_CT {
3148 f_TC_imm_ass(150, 0.076, 1.00);
3149}
3150
3151
3152
Harald Welte48494ca2018-02-25 16:59:50 +01003153/***********************************************************************
3154 * BCCH
3155 ***********************************************************************/
3156
3157/* tuple of Frame Number + decoded SI */
3158type record SystemInformationFn {
3159 GsmFrameNumber frame_number,
3160 SystemInformation si
3161}
3162
3163/* an arbitrary-length vector of decoded SI + gsmtap header */
3164type record of SystemInformationFn SystemInformationVector;
3165
3166/* an array of SI-vectors indexed by TC value */
3167type SystemInformationVector SystemInformationVectorPerTc[8];
3168
3169/* determine if a given SI vector contains given SI type at least once */
3170function f_si_vecslot_contains(SystemInformationVector arr, RrMessageType key, boolean bcch_ext := false) return boolean {
3171 for (var integer i:= 0; i< sizeof(arr); i := i + 1) {
3172 var integer fn_mod51 := arr[i].frame_number mod 51;
3173 if (not bcch_ext and fn_mod51 == 2 or
3174 bcch_ext and fn_mod51 == 6) {
3175 if (arr[i].si.header.message_type == key) {
3176 return true;
3177 }
3178 }
3179 }
3180 return false;
3181}
3182
3183/* ensure a given TC slot of the SI vector contains given SI type at least once at TC */
3184function f_ensure_si_vec_contains(SystemInformationVectorPerTc arr, integer tc, RrMessageType key, boolean ext_bcch := false) {
3185 if (not f_si_vecslot_contains(arr[tc], key, ext_bcch)) {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02003186 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("No ", key, " in TC=", tc, "!"));
Harald Welte48494ca2018-02-25 16:59:50 +01003187 }
3188}
3189
3190/* check if a given SI vector contains given SI type at least once on any TC */
3191function f_si_vec_contains(SystemInformationVectorPerTc arr, RrMessageType key) return boolean {
3192 for (var integer tc:= 0; tc < sizeof(arr); tc := tc + 1) {
3193 if (f_si_vecslot_contains(arr[tc], key) or
3194 f_si_vecslot_contains(arr[tc], key, true)) {
3195 return true;
3196 }
3197 }
3198 return false;
3199}
3200
3201/* determine if a given SI vector contains given SI type at least N of M times */
3202function f_si_vecslot_contains_n_of_m(SystemInformationVector arr, RrMessageType key, boolean bcch_ext := false, integer n := 1, integer m := 4) return boolean {
3203 var integer count := 0;
3204 if (sizeof(arr) < m) {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02003205 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Error: Insufficient SI in array");
Harald Welte48494ca2018-02-25 16:59:50 +01003206 }
3207 for (var integer i:= 0; i < m; i := i + 1) {
3208 var integer fn_mod51 := arr[i].frame_number mod 51;
3209 if (not bcch_ext and fn_mod51 == 2 or
3210 bcch_ext and fn_mod51 == 6) {
3211 if (arr[i].si.header.message_type == key) {
3212 count := count + 1;
3213 }
3214 }
3215 }
3216 if (count >= n) {
3217 return true;
3218 } else {
3219 return false;
3220 }
3221}
3222
3223/* ensure a given TC slot of the SI vector contains given SI type at least N out of M times at TC */
3224function f_ensure_si_vec_contains_n_of_m(SystemInformationVectorPerTc arr, integer tc, RrMessageType key, boolean ext_bcch := false, integer n, integer m) {
3225 if (not f_si_vecslot_contains_n_of_m(arr[tc], key, ext_bcch, n, m)) {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02003226 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("Not ", n, "/", m, " of ", key, " in TC=", tc, "!"));
Harald Welte48494ca2018-02-25 16:59:50 +01003227 }
3228}
3229
3230/* determine if a given SI vector contains given SI type at least once */
3231function f_si_vecslot_contains_only(SystemInformationVector arr, RrMessageType key, boolean bcch_ext := false) return boolean {
3232 for (var integer i:= 0; i< sizeof(arr); i := i + 1) {
3233 var integer fn_mod51 := arr[i].frame_number mod 51;
3234 if (not bcch_ext and fn_mod51 == 2 or
3235 bcch_ext and fn_mod51 == 6) {
3236 if (arr[i].si.header.message_type != key) {
3237 return false;
3238 }
3239 }
3240 }
3241 return true;
3242}
3243
3244/* ensure a given TC slot of the SI vector contains only given SI type */
3245function f_ensure_si_vec_contains_only(SystemInformationVectorPerTc arr, integer tc, RrMessageType key, boolean ext_bcch := false) {
3246 if (not f_si_vecslot_contains_only(arr[tc], key, ext_bcch)) {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02003247 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("Not all ", key, " in TC=", tc, "!"));
Harald Welte48494ca2018-02-25 16:59:50 +01003248 }
3249}
3250
3251/* SI configuration of cell, against which we validate actual SI messages */
3252type set SystemInformationConfig {
3253 boolean bcch_extended,
3254 boolean si1_present,
3255 boolean si2bis_present,
3256 boolean si2ter_present,
3257 boolean si2quater_present,
3258 boolean si7_present,
3259 boolean si8_present,
3260 boolean si9_present,
3261 boolean si13_present,
3262 boolean si13alt_present,
3263 boolean si15_present,
3264 boolean si16_present,
3265 boolean si17_present,
3266 boolean si2n_present,
3267 boolean si21_present,
3268 boolean si22_present
3269}
3270
3271/* validate the SI scheduling according to TS 45.002 version 14.1.0 Release 14, Section 6.3.1.3 */
3272function f_validate_si_scheduling(SystemInformationConfig cfg, SystemInformationVectorPerTc si_per_tc) {
3273 var integer i;
3274 for (i := 0; i < sizeof(si_per_tc); i := i + 1) {
3275 if (sizeof(si_per_tc[i]) == 0) {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02003276 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("No SI messages for TC=", i));
Harald Welte48494ca2018-02-25 16:59:50 +01003277 }
3278 }
3279 if (cfg.si1_present) {
3280 /* ii) System Information Type 1 needs to be sent if frequency hopping is in use or
3281 * when the NCH is present in a cell. If the MS finds another message on BCCH Norm
3282 * when TC = 0, it can assume that System Information Type 1 is not in use. */
3283 f_ensure_si_vec_contains(si_per_tc, 0, SYSTEM_INFORMATION_TYPE_1);
3284 /* make sure *ALL* contain SI1 */
3285 f_ensure_si_vec_contains_only(si_per_tc, 0, SYSTEM_INFORMATION_TYPE_1);
3286 }
3287 f_ensure_si_vec_contains(si_per_tc, 1, SYSTEM_INFORMATION_TYPE_2);
3288 /* iii) A SI 2 message will be sent at least every time TC = 1 */
3289 f_ensure_si_vec_contains(si_per_tc, 2, SYSTEM_INFORMATION_TYPE_3);
3290 f_ensure_si_vec_contains(si_per_tc, 6, SYSTEM_INFORMATION_TYPE_3);
3291 f_ensure_si_vec_contains(si_per_tc, 3, SYSTEM_INFORMATION_TYPE_4);
3292 f_ensure_si_vec_contains(si_per_tc, 7, SYSTEM_INFORMATION_TYPE_4);
3293
3294 /* iii) System information type 2 bis or 2 ter messages are sent if needed, as determined by the
3295 * system operator. If only one of them is needed, it is sent when TC = 5. If both are
3296 * needed, 2bis is sent when TC = 5 and 2ter is sent at least once within any of 4
3297 * consecutive occurrences of TC = 4. */
3298 if (cfg.si2bis_present and not cfg.si2ter_present) {
3299 f_ensure_si_vec_contains(si_per_tc, 5, SYSTEM_INFORMATION_TYPE_2bis);
3300 } else if (cfg.si2ter_present and not cfg.si2bis_present) {
3301 f_ensure_si_vec_contains(si_per_tc, 5, SYSTEM_INFORMATION_TYPE_2ter);
3302 } else if (cfg.si2ter_present and cfg.si2bis_present) {
3303 f_ensure_si_vec_contains(si_per_tc, 5, SYSTEM_INFORMATION_TYPE_2bis);
3304 f_ensure_si_vec_contains_n_of_m(si_per_tc, 4, SYSTEM_INFORMATION_TYPE_2ter, false, 1, 4);
3305 }
3306
3307 if (cfg.si7_present or cfg.si8_present) {
3308 /* vi) Use of System Information type 7 and 8 is not always necessary. It is necessary
3309 * if System Information type 4 does not contain all information needed for cell
3310 * selection and reselection. */
3311 if (not cfg.bcch_extended) {
3312 testcase.stop("Error: SI7/SI8 require BCCH Extd.");
3313 }
3314 if (cfg.si7_present) {
3315 f_ensure_si_vec_contains(si_per_tc, 7, SYSTEM_INFORMATION_TYPE_7, true);
3316 }
3317 if (cfg.si8_present) {
3318 f_ensure_si_vec_contains(si_per_tc, 3, SYSTEM_INFORMATION_TYPE_8, true);
3319 }
3320 }
3321
3322 if (cfg.si2quater_present) {
3323 /* iii) System information type 2 quater is sent if needed, as determined by the system
3324 * operator. If sent on BCCH Norm, it shall be sent when TC = 5 if neither of 2bis
3325 * and 2ter are used, otherwise it shall be sent at least once within any of 4
3326 * consecutive occurrences of TC = 4. If sent on BCCH Ext, it is sent at least once
3327 * within any of 4 consecutive occurrences of TC = 5. */
3328 if (not (cfg.bcch_extended)) {
3329 if (not (cfg.si2bis_present or cfg.si2ter_present)) {
3330 f_ensure_si_vec_contains(si_per_tc, 5, SYSTEM_INFORMATION_TYPE_2quater);
3331 } else {
3332 f_ensure_si_vec_contains_n_of_m(si_per_tc, 4, SYSTEM_INFORMATION_TYPE_2quater, false, 1, 4);
3333 }
3334 } else {
3335 f_ensure_si_vec_contains_n_of_m(si_per_tc, 5, SYSTEM_INFORMATION_TYPE_2quater, true, 1, 4);
3336 }
3337 }
3338 if (cfg.si9_present) {
3339 /* vi) System Information type 9 is sent in those blocks with TC = 4 which are specified
3340 * in system information type 3 as defined in 3GPP TS 44.018. */
3341 f_ensure_si_vec_contains(si_per_tc, 4, SYSTEM_INFORMATION_TYPE_9); // FIXME SI3
3342 }
3343 if (cfg.si13_present) {
3344 /* vii) System Information type 13 is only related to the GPRS service. System Information
3345 * Type 13 need only be sent if GPRS support is indicated in one or more of System
3346 * Information Type 3 or 4 or 7 or 8 messages. These messages also indicate if the
3347 * message is sent on the BCCH Norm or if the message is transmitted on the BCCH Ext.
3348 * In the case that the message is sent on the BCCH Norm, it is sent at least once
3349 * within any of 4 consecutive occurrences of TC=4. */
3350 if (not cfg.bcch_extended) {
3351 log("not-bccch-extended");
3352 f_ensure_si_vec_contains_n_of_m(si_per_tc, 4, SYSTEM_INFORMATION_TYPE_13, false, 1, 4);
3353 } else {
3354 log("bccch-extended");
3355 f_ensure_si_vec_contains(si_per_tc, 0, SYSTEM_INFORMATION_TYPE_13, true);
3356 }
3357 if (f_si_vec_contains(si_per_tc, SYSTEM_INFORMATION_TYPE_13alt)) {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02003358 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Cannot have SI13alt and SI13");
Harald Welte48494ca2018-02-25 16:59:50 +01003359 }
3360 }
3361 if (cfg.si16_present or cfg.si17_present) {
3362 /* viii) System Information type 16 and 17 are only related to the SoLSA service. They
3363 * should not be sent in a cell where network sharing is used (see rule xv). */
3364 if (cfg.si22_present) {
3365 testcase.stop("Error: Cannot have SI16/SI17 and SI22!");
3366 }
3367 if (f_si_vec_contains(si_per_tc, SYSTEM_INFORMATION_TYPE_22)) {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02003368 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Cannot have SI16/SI17 and SI22!");
Harald Welte48494ca2018-02-25 16:59:50 +01003369 }
3370 if (not cfg.bcch_extended) {
3371 testcase.stop("Error: SI16/SI17 requires BCCH Extd!");
3372 }
3373 if (cfg.si16_present) {
3374 f_ensure_si_vec_contains(si_per_tc, 6, SYSTEM_INFORMATION_TYPE_16, true);
3375 }
3376 if (cfg.si17_present) {
3377 f_ensure_si_vec_contains(si_per_tc, 2, SYSTEM_INFORMATION_TYPE_17, true);
3378 }
3379 }
3380
3381 /* ix) System Information type 18 and 20 are sent in order to transmit non-GSM
3382 * broadcast information. The frequency with which they are sent is determined by the
3383 * system operator. System Information type 9 identifies the scheduling of System
3384 * Information type 18 and 20 messages. */
3385
3386 /* x) System Information Type 19 is sent if COMPACT neighbours exist. If System
3387 * Information Type 19 is present, then its scheduling shall be indicated in System
3388 * Information Type 9. */
3389
3390 if (cfg.si15_present) {
3391 /* xi) System Information Type 15 is broadcast if dynamic ARFCN mapping is used in the
3392 * PLMN. If sent on BCCH Norm, it is sent at least once within any of 4 consecutive
3393 * occurrences of TC = 4. If sent on BCCH Ext, it is sent at least once within any of
3394 * 4 consecutive occurrences of TC = 1. */
3395 if (not cfg.bcch_extended) {
3396 f_ensure_si_vec_contains_n_of_m(si_per_tc, 4, SYSTEM_INFORMATION_TYPE_15, false, 1, 4);
3397 } else {
3398 f_ensure_si_vec_contains_n_of_m(si_per_tc, 1, SYSTEM_INFORMATION_TYPE_15, true, 1, 4);
3399 }
3400 }
3401 if (cfg.si13alt_present) {
3402 /* xii) System Information type 13 alt is only related to the GERAN Iu mode. System
3403 * Information Type 13 alt need only be sent if GERAN Iu mode support is indicated in
3404 * one or more of System Information Type 3 or 4 or 7 or 8 messages and SI 13 is not
3405 * broadcast. These messages also indicate if the message is sent on the BCCH Norm or
3406 * if the message is transmitted on the BCCH Ext. In the case that the message is sent
3407 * on the BCCH Norm, it is sent at least once within any of 4 consecutive occurrences
3408 * of TC = 4. */
3409 if (cfg.si13_present) {
3410 testcase.stop("Error: Cannot have SI13alt and SI13");
3411 }
3412 if (f_si_vec_contains(si_per_tc, SYSTEM_INFORMATION_TYPE_13)) {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02003413 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Cannot have SI13alt and SI13");
Harald Welte48494ca2018-02-25 16:59:50 +01003414 }
3415 if (not cfg.bcch_extended) {
3416 f_ensure_si_vec_contains_n_of_m(si_per_tc, 4, SYSTEM_INFORMATION_TYPE_13alt, false, 1, 4);
3417 } else {
3418 f_ensure_si_vec_contains(si_per_tc, 0, SYSTEM_INFORMATION_TYPE_13alt, true);
3419 }
3420 }
3421 if (cfg.si2n_present) {
3422 /* xiii) System Information Type 2n is optionally sent on BCCH Norm or BCCH Ext if needed,
3423 * as determined by the system operator. In the case that the message is sent on the
3424 * BCCH Norm, it is sent at least once within any of 4 consecutive occurrences of TC =
3425 * 4. If the message is sent on BCCH Ext, it is sent at least once within any of 2
3426 * consecutive occurrences of TC = 4. */
3427 if (not cfg.bcch_extended) {
3428 f_ensure_si_vec_contains_n_of_m(si_per_tc, 4, SYSTEM_INFORMATION_TYPE_2n, false, 1, 4);
3429 } else {
3430 f_ensure_si_vec_contains_n_of_m(si_per_tc, 4, SYSTEM_INFORMATION_TYPE_2n, true, 2, 4);
3431 }
3432 }
3433 if (cfg.si21_present) {
3434 /* xiv) System Information Type 21 is optionally sent on BCCH Norm or BCCH Ext, as
3435 * determined by the system operator. If Extended Access Barring is in use in the cell
3436 * then this message is sent at least once within any of 4 consecutive occurrences of
3437 * TC = 4 regardless if it is sent on BCCH Norm or BCCH Ext. If BCCH Ext is used in a
3438 * cell then this message shall only be sent on BCCH Ext. */
3439 if (not cfg.bcch_extended) {
3440 f_ensure_si_vec_contains_n_of_m(si_per_tc, 4, SYSTEM_INFORMATION_TYPE_21, false, 1, 4);
3441 } else {
3442 f_ensure_si_vec_contains_n_of_m(si_per_tc, 4, SYSTEM_INFORMATION_TYPE_21, true, 1, 4);
3443 if (f_si_vecslot_contains(si_per_tc[4], SYSTEM_INFORMATION_TYPE_21)) {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02003444 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Cannot have SI21 on BCCH Norm if BCCH Extd enabled!");
Harald Welte48494ca2018-02-25 16:59:50 +01003445 }
3446 }
3447 }
3448 if (cfg.si22_present) {
3449 /* xv) System Information Type 22 is sent if network sharing is in use in the cell. It
3450 * should not be sent in a cell where SoLSA is used (see rule viii). System
3451 * Information Type 22 instances shall be sent on BCCH Ext within any occurrence of TC
3452 * =2 and TC=6. */
3453 if (cfg.si16_present or cfg.si17_present) {
3454 testcase.stop("Error: Cannot have SI16/SI17 and SI22!");
3455 }
3456 if (f_si_vec_contains(si_per_tc, SYSTEM_INFORMATION_TYPE_16) or
3457 f_si_vec_contains(si_per_tc, SYSTEM_INFORMATION_TYPE_17)) {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02003458 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Cannot have SI16/SI17 and SI22!");
Harald Welte48494ca2018-02-25 16:59:50 +01003459 }
3460 if (not cfg.bcch_extended) {
3461 testcase.stop("Error: SI22 requires BCCH Extd!");
3462 } else {
3463 f_ensure_si_vec_contains_only(si_per_tc, 2, SYSTEM_INFORMATION_TYPE_22, true);
3464 f_ensure_si_vec_contains_only(si_per_tc, 6, SYSTEM_INFORMATION_TYPE_22, true);
3465 }
3466 }
3467}
3468
3469/* sample Systme Information for specified duration via L1CTL */
3470function f_l1_sample_si(L1CTL_PT pt, float duration := 8.0) return SystemInformationVectorPerTc {
3471 timer T := duration;
3472 var SystemInformationVectorPerTc si_per_tc;
3473 var L1ctlDlMessage l1_dl;
3474
3475 /* initialize all per-TC vectors empty */
3476 for (var integer i:= 0; i < sizeof(si_per_tc); i := i+1) {
3477 si_per_tc[i] := {};
3478 }
3479
3480 /* flush all previous L1 queued msgs */
3481 pt.clear;
3482
3483 T.start;
3484 alt {
Harald Weltef8df4cb2018-03-10 15:15:08 +01003485 [] pt.receive(tr_L1CTL_DATA_IND(t_RslChanNr_BCCH(0), ?)) -> value l1_dl {
Harald Welte48494ca2018-02-25 16:59:50 +01003486 /* somehow dec_SystemInformation will try to decode even non-RR as SI */
3487 if (not (l1_dl.payload.data_ind.payload[1] == '06'O)) {
3488 log("Ignoring non-RR SI ", l1_dl);
3489 repeat;
3490 }
3491 var SystemInformationFn sig := {
3492 frame_number := l1_dl.dl_info.frame_nr,
3493 si := dec_SystemInformation(l1_dl.payload.data_ind.payload)
3494 }
3495 var integer tc := f_gsm_compute_tc(sig.frame_number);
3496 log("SI received at TC=", tc, ": ", sig.si);
3497 /* append to the per-TC bucket */
3498 si_per_tc[tc] := si_per_tc[tc] & { sig };
3499 repeat;
3500 }
3501 [] pt.receive { repeat; }
3502 [] T.timeout { }
3503 }
3504
3505 for (var integer i:= 0; i < sizeof(si_per_tc); i := i+1) {
3506 log(testcasename(), ": TC=", i, " has #of SI=", sizeof(si_per_tc[i]));
3507 }
3508 log("si_per_tc=", si_per_tc);
3509 return si_per_tc;
3510}
3511
3512/* helper function: Set given SI via RSL + validate scheduling.
3513 * CALLER MUST MAKE SURE TO CHANGE GLOBAL si_cfg! */
3514function f_TC_si_sched() runs on test_CT {
3515 var SystemInformationVectorPerTc si_per_tc;
3516 f_init_l1ctl();
3517 f_l1_tune(L1CTL);
3518
3519 /* Sample + Validate Scheduling */
3520 si_per_tc := f_l1_sample_si(L1CTL);
3521 f_validate_si_scheduling(si_cfg, si_per_tc);
3522
3523 setverdict(pass);
3524}
3525
3526testcase TC_si_sched_default() runs on test_CT {
3527 f_init();
Harald Welte0cae4552018-03-09 22:20:26 +01003528 /* 2+3+4 are mandatory and set in f_init() */
3529 f_TC_si_sched();
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02003530 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
Harald Welte0cae4552018-03-09 22:20:26 +01003531}
3532
3533testcase TC_si_sched_1() runs on test_CT {
3534 f_init();
3535 si_cfg.si1_present := true;
3536 f_rsl_bcch_fill_raw(RSL_SYSTEM_INFO_1, '5506198fb38000000000000000000000000000e504002b'O);
Harald Welte48494ca2018-02-25 16:59:50 +01003537 f_TC_si_sched();
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02003538 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
Harald Welte48494ca2018-02-25 16:59:50 +01003539}
3540
3541testcase TC_si_sched_2bis() runs on test_CT {
3542 f_init();
3543 si_cfg.si2bis_present := true;
3544 f_rsl_bcch_fill_raw(RSL_SYSTEM_INFO_2bis, '550602bfe809b3ff00000000000000000000007900002b'O);
3545 f_TC_si_sched();
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02003546 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
Harald Welte48494ca2018-02-25 16:59:50 +01003547}
3548
3549testcase TC_si_sched_2ter() runs on test_CT {
3550 f_init();
3551 si_cfg.si2ter_present := true;
3552 f_rsl_bcch_fill_raw(RSL_SYSTEM_INFO_2ter, '010603bf66b0aa0a00000002000000000000002b2b2b2b'O);
3553 f_TC_si_sched();
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02003554 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
Harald Welte48494ca2018-02-25 16:59:50 +01003555}
3556
3557testcase TC_si_sched_2ter_2bis() runs on test_CT {
3558 f_init();
3559 si_cfg.si2bis_present := true;
3560 f_rsl_bcch_fill_raw(RSL_SYSTEM_INFO_2bis, '550602bfe809b3ff00000000000000000000007900002b'O);
3561 si_cfg.si2ter_present := true;
3562 f_rsl_bcch_fill_raw(RSL_SYSTEM_INFO_2ter, '010603bf66b0aa0a00000002000000000000002b2b2b2b'O);
3563 f_TC_si_sched();
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02003564 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
Harald Welte48494ca2018-02-25 16:59:50 +01003565}
3566
3567testcase TC_si_sched_2quater() runs on test_CT {
3568 f_init();
3569 si_cfg.si2quater_present := true;
3570 f_rsl_bcch_fill_raw(RSL_SYSTEM_INFO_2quater, '050607a8a0364aa698d72ff424feee0506d5e7fff02043'O);
3571 f_TC_si_sched();
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02003572 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
Harald Welte48494ca2018-02-25 16:59:50 +01003573}
3574
3575testcase TC_si_sched_13() runs on test_CT {
3576 f_init();
3577 si_cfg.si13_present := true;
Harald Welte5618c2a2018-04-15 16:24:46 +02003578 f_rsl_bcch_fill_raw(RSL_SYSTEM_INFO_13, '0106009000185a6fc9e08410ab2b2b2b2b2b2b2b2b2b2b'O);
Harald Welte48494ca2018-02-25 16:59:50 +01003579 f_TC_si_sched();
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02003580 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
Harald Welte48494ca2018-02-25 16:59:50 +01003581}
3582
3583testcase TC_si_sched_13_2bis_2ter_2quater() runs on test_CT {
3584 f_init();
3585 si_cfg.si2bis_present := true;
3586 f_rsl_bcch_fill_raw(RSL_SYSTEM_INFO_2bis, '550602bfe809b3ff00000000000000000000007900002b'O);
3587 si_cfg.si2ter_present := true;
3588 f_rsl_bcch_fill_raw(RSL_SYSTEM_INFO_2ter, '010603bf66b0aa0a00000002000000000000002b2b2b2b'O);
3589 si_cfg.si2quater_present := true;
3590 f_rsl_bcch_fill_raw(RSL_SYSTEM_INFO_2quater, '050607a8a0364aa698d72ff424feee0506d5e7fff02043'O);
3591 si_cfg.si13_present := true;
Harald Welte5618c2a2018-04-15 16:24:46 +02003592 f_rsl_bcch_fill_raw(RSL_SYSTEM_INFO_13, '0106009000185a6fc9e08410ab2b2b2b2b2b2b2b2b2b2b'O);
Harald Welte48494ca2018-02-25 16:59:50 +01003593 f_TC_si_sched();
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02003594 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
Harald Welte48494ca2018-02-25 16:59:50 +01003595}
3596
3597
Harald Welte68e495b2018-02-25 00:05:57 +01003598testcase TC_bcch_info() runs on test_CT {
Harald Welte10474062019-05-30 16:48:17 +02003599 f_init();
Harald Welte68e495b2018-02-25 00:05:57 +01003600 /* FIXME: enable / disable individual BCCH info */
3601 //ts_RSL_BCCH_INFO(si_type, info);
3602 /* expect no ERROR REPORT after either of them *
3603 /* negative test: ensure ERROR REPORT on unsupported types */
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02003604 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
Harald Welte68e495b2018-02-25 00:05:57 +01003605}
3606
Harald Welte93640c62018-02-25 16:59:33 +01003607/***********************************************************************
3608 * Low-Level Protocol Errors / ERROR REPORT
3609 ***********************************************************************/
3610
Harald Welte01d982c2018-02-25 01:31:40 +01003611private function f_exp_err_rep(template RSL_Cause cause) runs on test_CT {
3612 timer T := 5.0;
3613 T.start;
3614 alt {
3615 [] RSL_CCHAN.receive(tr_RSL_UD(tr_RSL_ERROR_REPORT(cause))) {
3616 setverdict(pass);
3617 }
3618 [] RSL_CCHAN.receive(tr_RSL_UD(tr_RSL_ERROR_REPORT(?))) {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02003619 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Wrong cause in RSL ERR REP");
Harald Welte01d982c2018-02-25 01:31:40 +01003620 }
3621 [] RSL_CCHAN.receive {
3622 repeat;
3623 }
3624 [] T.timeout {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02003625 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout waiting for RSL ERR REP");
Harald Welte01d982c2018-02-25 01:31:40 +01003626 }
3627 }
3628}
3629
3630/* Provoke a protocol error (message too short) and match on ERROR REPORT */
3631testcase TC_rsl_protocol_error() runs on test_CT {
Harald Welte10474062019-05-30 16:48:17 +02003632 f_init();
Harald Welte01d982c2018-02-25 01:31:40 +01003633 var RSL_Message rsl := valueof(ts_RSL_BCCH_INFO(RSL_SYSTEM_INFO_1, ''O));
3634 rsl.ies := omit;
3635 RSL_CCHAN.send(ts_RSL_UD(rsl));
3636
3637 f_exp_err_rep(RSL_ERR_PROTO);
3638}
3639
3640/* Provoke a mandatory IE error and match on ERROR REPORT */
3641testcase TC_rsl_mand_ie_error() runs on test_CT {
Harald Welte10474062019-05-30 16:48:17 +02003642 f_init();
Harald Welte01d982c2018-02-25 01:31:40 +01003643
3644 var RSL_Message rsl := valueof(ts_RSL_BCCH_INFO(RSL_SYSTEM_INFO_1, ''O));
3645 rsl.ies := { rsl.ies[0] };
3646 RSL_CCHAN.send(ts_RSL_UD(rsl));
3647
3648 f_exp_err_rep(RSL_ERR_MAND_IE_ERROR);
3649}
3650
3651/* Provoke an IE content error and match on ERROR REPORT */
3652testcase TC_rsl_ie_content_error() runs on test_CT {
Harald Welte10474062019-05-30 16:48:17 +02003653 f_init();
Harald Welte01d982c2018-02-25 01:31:40 +01003654 var RSL_Message rsl := valueof(ts_RSL_BCCH_INFO(RSL_SYSTEM_INFO_1, ''O));
3655 rsl.ies[1].body.sysinfo_type := RSL_SYSTEM_INFO_5;
3656 RSL_CCHAN.send(ts_RSL_UD(rsl));
3657
3658 f_exp_err_rep(RSL_ERR_IE_CONTENT);
3659}
3660
Harald Welteee25aae2019-05-19 14:32:37 +02003661/* attempt to activate channel with wrong RSL Message Discriminator IE */
3662function f_TC_chan_act_wrong_mdisc(charstring id) runs on ConnHdlr {
3663 var template RSL_Message rsl := ts_RSL_CHAN_ACT(g_chan_nr, g_pars.chan_mode);
3664 rsl.msg_disc := ts_RSL_MsgDisc(RSL_MDISC_RESERVED, false);
3665 RSL.send(rsl);
3666 f_rslem_unregister(0, g_chan_nr);
3667}
3668testcase TC_err_rep_wrong_mdisc() runs on test_CT {
3669 var ConnHdlr vc_conn;
3670 var ConnHdlrPars pars := valueof(t_Pars(ts_RslChanNr_SDCCH4(0,0), ts_RSL_ChanMode_SIGN));
3671
Harald Welte10474062019-05-30 16:48:17 +02003672 f_init();
Harald Welteee25aae2019-05-19 14:32:37 +02003673
3674 vc_conn := f_start_handler(refers(f_TC_chan_act_wrong_mdisc), pars);
3675 vc_conn.done;
3676 f_exp_err_rep(RSL_ERR_MSG_DISCR);
3677
3678 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
3679}
3680
3681/* Send messages with wrong message type */
3682function f_TC_wrong_msg_type_dchan(charstring id) runs on ConnHdlr {
3683 var template (value) RSL_Message rsl_tx;
3684 rsl_tx := ts_RSL_CHAN_ACT(g_chan_nr, g_pars.chan_mode);
3685 rsl_tx.msg_type := RSL_MT_NOT_CMD;
3686 RSL.send(rsl_tx);
3687 f_rslem_unregister(0, g_chan_nr);
3688}
3689function f_TC_wrong_msg_type_rll(charstring id) runs on ConnHdlr {
3690 var template (value) RSL_Message rsl_tx;
3691 /* we first have to activate the dedicated channel */
3692 f_rsl_chan_act(g_pars.chan_mode);
3693 /* ... to then send an invalid RLL message */
3694 rsl_tx := ts_RSL_UNITDATA_REQ(g_chan_nr, ts_RslLinkID_DCCH(0), '0102'O);
3695 rsl_tx.msg_type := RSL_MT_CBCH_LOAD_IND;
3696 RSL.send(rsl_tx);
3697 f_rslem_unregister(0, g_chan_nr);
3698}
3699testcase TC_err_rep_wrong_msg_type() runs on test_CT {
3700 var ConnHdlr vc_conn;
3701 var ConnHdlrPars pars := valueof(t_Pars(ts_RslChanNr_SDCCH4(0,0), ts_RSL_ChanMode_SIGN));
3702 var template (value) RSL_Message rsl_tx;
3703
Harald Welte10474062019-05-30 16:48:17 +02003704 f_init();
Harald Welteee25aae2019-05-19 14:32:37 +02003705
3706 /* Common Channel with wrong message type */
3707 RSL_CCHAN.clear;
3708 rsl_tx := valueof(ts_RSL_BCCH_INFO(RSL_SYSTEM_INFO_1, ''O));
3709 rsl_tx.msg_type := RSL_MT_LOCATION_INFO;
3710 RSL_CCHAN.send(ts_RSL_UD(rsl_tx));
3711 f_exp_err_rep(RSL_ERR_MSG_TYPE);
3712
3713 /* TRX Management */
3714 RSL_CCHAN.clear;
3715 rsl_tx := ts_RSL_SACCH_FILL(RSL_SYSTEM_INFO_5, ''O);
3716 rsl_tx.msg_type := RSL_MT_UNIT_DATA_IND;
3717 RSL_CCHAN.send(ts_RSL_UD(rsl_tx));
3718 f_exp_err_rep(RSL_ERR_MSG_TYPE);
3719
3720 /* Dedicated Channel */
3721 RSL_CCHAN.clear;
3722 vc_conn := f_start_handler(refers(f_TC_wrong_msg_type_dchan), pars);
3723 vc_conn.done;
3724 f_exp_err_rep(RSL_ERR_MSG_TYPE);
3725
3726 /* RLL */
3727 RSL_CCHAN.clear;
3728 vc_conn := f_start_handler(refers(f_TC_wrong_msg_type_rll), pars);
3729 vc_conn.done;
3730 f_exp_err_rep(RSL_ERR_MSG_TYPE);
3731}
3732
3733/* Send messages in wrong sequence (RLL to an inactive lchan) */
3734function f_TC_err_rep_wrong_sequence(charstring id) runs on ConnHdlr {
3735 RSL.send(ts_RSL_UNITDATA_REQ(g_chan_nr, ts_RslLinkID_DCCH(0), '0102'O));
3736 f_rslem_unregister(0, g_chan_nr);
3737}
3738testcase TC_err_rep_wrong_sequence() runs on test_CT {
3739 var ConnHdlr vc_conn;
3740 var ConnHdlrPars pars := valueof(t_Pars(ts_RslChanNr_SDCCH4(0,0), ts_RSL_ChanMode_SIGN));
3741
Harald Welte10474062019-05-30 16:48:17 +02003742 f_init();
Harald Welteee25aae2019-05-19 14:32:37 +02003743
3744 RSL_CCHAN.clear;
3745 vc_conn := f_start_handler(refers(f_TC_err_rep_wrong_sequence), pars);
3746 vc_conn.done;
3747 f_exp_err_rep(RSL_ERR_MSG_SEQ);
3748}
3749
Harald Welte93640c62018-02-25 16:59:33 +01003750/***********************************************************************
3751 * IPA CRCX/MDCX/DLCS media stream handling
3752 ***********************************************************************/
3753
Harald Weltea871a382018-02-25 02:03:14 +01003754/* Send IPA DLCX to inactive lchan */
3755function f_TC_ipa_dlcx_not_active(charstring id) runs on ConnHdlr {
Harald Welte1eba3742018-02-25 12:48:14 +01003756 f_rsl_transceive(ts_RSL_IPA_DLCX(g_chan_nr, 0), tr_RSL_IPA_DLCX_ACK(g_chan_nr, ?, ?),
3757 "IPA DLCX ACK");
Harald Weltea871a382018-02-25 02:03:14 +01003758}
3759testcase TC_ipa_dlcx_not_active() runs on test_CT {
3760 var ConnHdlrPars pars := valueof(t_Pars(t_RslChanNr_Bm(1), ts_RSL_ChanMode_SIGN));
Harald Welte10474062019-05-30 16:48:17 +02003761 f_init();
Harald Weltea871a382018-02-25 02:03:14 +01003762 var ConnHdlr vc_conn := f_start_handler(refers(f_TC_ipa_dlcx_not_active), pars);
3763 vc_conn.done;
3764}
Harald Welte68e495b2018-02-25 00:05:57 +01003765
Harald Weltea3f1df92018-02-25 12:49:55 +01003766/* Send IPA CRCX twice to inactive lchan */
3767function f_TC_ipa_crcx_twice_not_active(charstring id) runs on ConnHdlr {
3768 f_rsl_transceive(ts_RSL_IPA_CRCX(g_chan_nr), tr_RSL_IPA_CRCX_ACK(g_chan_nr, ?, ?, ?),
3769 "IPA CRCX ACK");
3770 f_rsl_transceive(ts_RSL_IPA_CRCX(g_chan_nr), tr_RSL_IPA_CRCX_NACK(g_chan_nr, RSL_ERR_RES_UNAVAIL),
3771 "IPA CRCX NACK");
3772}
3773testcase TC_ipa_crcx_twice_not_active() runs on test_CT {
3774 var ConnHdlrPars pars := valueof(t_Pars(t_RslChanNr_Bm(1), ts_RSL_ChanMode_SIGN));
Harald Welte10474062019-05-30 16:48:17 +02003775 f_init();
Harald Weltea3f1df92018-02-25 12:49:55 +01003776 var ConnHdlr vc_conn := f_start_handler(refers(f_TC_ipa_crcx_twice_not_active), pars);
3777 vc_conn.done;
3778}
3779
3780/* Regular sequence of CRCX/MDCX/DLCX */
3781function f_TC_ipa_crcx_mdcx_dlcx_not_active(charstring id) runs on ConnHdlr {
3782 f_rsl_transceive(ts_RSL_IPA_CRCX(g_chan_nr), tr_RSL_IPA_CRCX_ACK(g_chan_nr, ?, ?, ?),
3783 "IPA CRCX ACK");
3784 var uint32_t remote_ip := f_rnd_int(c_UINT32_MAX);
3785 var uint16_t remote_port := f_rnd_int(c_UINT16_MAX);
3786 var uint7_t rtp_pt2 := f_rnd_int(127);
3787 var uint16_t fake_conn_id := 23; /* we're too lazy to read it out from the CRCX ACK above */
3788 f_rsl_transceive(ts_RSL_IPA_MDCX(g_chan_nr, fake_conn_id, remote_ip, remote_port, rtp_pt2),
3789 tr_RSL_IPA_MDCX_ACK(g_chan_nr, ?, ?, ?, rtp_pt2),
3790 "IPA MDCX ACK");
3791 f_rsl_transceive(ts_RSL_IPA_DLCX(g_chan_nr, fake_conn_id), tr_RSL_IPA_DLCX_ACK(g_chan_nr, ?, ?),
3792 "IPA DLCX ACK");
3793}
3794testcase TC_ipa_crcx_mdcx_dlcx_not_active() runs on test_CT {
3795 var ConnHdlrPars pars := valueof(t_Pars(t_RslChanNr_Bm(1), ts_RSL_ChanMode_SIGN));
Harald Welte10474062019-05-30 16:48:17 +02003796 f_init();
Harald Weltea3f1df92018-02-25 12:49:55 +01003797 var ConnHdlr vc_conn := f_start_handler(refers(f_TC_ipa_crcx_mdcx_dlcx_not_active), pars);
3798 vc_conn.done;
3799}
3800
Harald Welte3ae11da2018-02-25 13:36:06 +01003801/* Sequence of CRCX, 2x MDCX, DLCX */
3802function f_TC_ipa_crcx_mdcx_mdcx_dlcx_not_active(charstring id) runs on ConnHdlr {
3803 f_rsl_transceive(ts_RSL_IPA_CRCX(g_chan_nr), tr_RSL_IPA_CRCX_ACK(g_chan_nr, ?, ?, ?),
3804 "IPA CRCX ACK");
3805 var uint32_t remote_ip := f_rnd_int(c_UINT32_MAX);
3806 var uint16_t remote_port := f_rnd_int(c_UINT16_MAX);
3807 var uint7_t rtp_pt2 := f_rnd_int(127);
3808 var uint16_t fake_conn_id := 23; /* we're too lazy to read it out from the CRCX ACK above */
3809 f_rsl_transceive(ts_RSL_IPA_MDCX(g_chan_nr, fake_conn_id, remote_ip, remote_port, rtp_pt2),
3810 tr_RSL_IPA_MDCX_ACK(g_chan_nr, ?, ?, ?, rtp_pt2),
3811 "IPA MDCX ACK");
3812 /* Second MDCX */
3813 remote_ip := f_rnd_int(c_UINT32_MAX);
3814 remote_port := f_rnd_int(c_UINT16_MAX);
3815 f_rsl_transceive(ts_RSL_IPA_MDCX(g_chan_nr, fake_conn_id, remote_ip, remote_port, rtp_pt2),
3816 tr_RSL_IPA_MDCX_ACK(g_chan_nr, ?, ?, ?, rtp_pt2),
3817 "IPA MDCX ACK");
3818 f_rsl_transceive(ts_RSL_IPA_DLCX(g_chan_nr, fake_conn_id), tr_RSL_IPA_DLCX_ACK(g_chan_nr, ?, ?),
3819 "IPA DLCX ACK");
3820}
3821testcase TC_ipa_crcx_mdcx_mdcx_dlcx_not_active() runs on test_CT {
3822 var ConnHdlrPars pars := valueof(t_Pars(t_RslChanNr_Bm(1), ts_RSL_ChanMode_SIGN));
Harald Welte10474062019-05-30 16:48:17 +02003823 f_init();
Harald Welte3ae11da2018-02-25 13:36:06 +01003824 var ConnHdlr vc_conn := f_start_handler(refers(f_TC_ipa_crcx_mdcx_mdcx_dlcx_not_active), pars);
3825 vc_conn.done;
3826}
3827
Harald Welte9912eb52018-02-25 13:30:15 +01003828/* IPA CRCX on SDCCH/4 and SDCCH/8 (doesn't make sense) */
3829function f_TC_ipa_crcx_sdcch_not_active(charstring id) runs on ConnHdlr {
3830 f_rsl_transceive(ts_RSL_IPA_CRCX(g_chan_nr), tr_RSL_IPA_CRCX_NACK(g_chan_nr, ?),
3831 "IPA CRCX NACK");
3832}
3833testcase TC_ipa_crcx_sdcch_not_active() runs on test_CT {
3834 var ConnHdlrPars pars;
3835 var ConnHdlr vc_conn;
Harald Welte10474062019-05-30 16:48:17 +02003836 f_init();
Harald Welte9912eb52018-02-25 13:30:15 +01003837
3838 pars := valueof(t_Pars(t_RslChanNr_SDCCH4(0,1), ts_RSL_ChanMode_SIGN));
3839 vc_conn := f_start_handler(refers(f_TC_ipa_crcx_sdcch_not_active), pars);
3840 vc_conn.done;
3841
3842 pars := valueof(t_Pars(t_RslChanNr_SDCCH8(6,5), ts_RSL_ChanMode_SIGN));
3843 vc_conn := f_start_handler(refers(f_TC_ipa_crcx_sdcch_not_active), pars);
3844 vc_conn.done;
3845}
3846
Harald Weltea3f1df92018-02-25 12:49:55 +01003847
Harald Welte883340c2018-02-28 18:59:29 +01003848/***********************************************************************
3849 * PCU Socket related tests
3850 ***********************************************************************/
3851
Harald Welte07bd2d22019-05-25 11:03:30 +02003852/* Verify no RTS before ACT_REQ; verify RTS after ACT_REQ */
Harald Weltead033dc2019-05-25 17:28:16 +02003853friend function f_TC_pcu_act_req(uint8_t bts_nr, uint8_t trx_nr, uint8_t ts_nr, boolean exp_success)
Harald Welte883340c2018-02-28 18:59:29 +01003854runs on test_CT {
3855 timer T := 3.0;
3856
3857 /* we don't expect any RTS.req before PDCH are active */
3858 T.start;
3859 alt {
3860 [] PCU.receive(t_SD_PCUIF(g_pcu_conn_id, tr_PCUIF_RTS_REQ(bts_nr))) {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02003861 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "PCU RTS.req before PDCH active?");
Harald Welte883340c2018-02-28 18:59:29 +01003862 }
3863 [] PCU.receive { repeat; }
3864 [] T.timeout { }
3865 }
3866
3867 /* Send PDCH activate request for known PDCH timeslot */
3868 PCU.send(t_SD_PCUIF(g_pcu_conn_id, ts_PCUIF_ACT_REQ(bts_nr, trx_nr, ts_nr)));
3869
3870 /* we now expect RTS.req for this timeslot (only) */
3871 T.start;
3872 alt {
3873 [exp_success] PCU.receive(t_SD_PCUIF(g_pcu_conn_id, tr_PCUIF_RTS_REQ(bts_nr, trx_nr, ts_nr))) {
3874 setverdict(pass);
3875 }
3876 [not exp_success] PCU.receive(t_SD_PCUIF(g_pcu_conn_id,
3877 tr_PCUIF_RTS_REQ(bts_nr, trx_nr, ts_nr))) {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02003878 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Unexpected RTS.req for supposedly failing activation");
Harald Welte883340c2018-02-28 18:59:29 +01003879 }
3880 [] PCU.receive(t_SD_PCUIF(g_pcu_conn_id, tr_PCUIF_RTS_REQ)) {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02003881 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "RTS.req for wrong TRX/TS");
Harald Welte883340c2018-02-28 18:59:29 +01003882 }
3883 [] PCU.receive { repeat; }
3884 [exp_success] T.timeout {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02003885 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout waiting for PCU RTS.req");
Harald Welte883340c2018-02-28 18:59:29 +01003886 }
3887 [not exp_success] T.timeout {
3888 setverdict(pass);
3889 }
3890 }
3891}
3892
Harald Welte07bd2d22019-05-25 11:03:30 +02003893/* verify no more RTS after DEACT_REQ */
Harald Weltead033dc2019-05-25 17:28:16 +02003894friend function f_TC_pcu_deact_req(uint8_t bts_nr, uint8_t trx_nr, uint8_t ts_nr)
Harald Welte883340c2018-02-28 18:59:29 +01003895runs on test_CT {
3896 timer T := 3.0;
3897
3898 /* Send PDCH activate request for known PDCH timeslot */
3899 PCU.send(t_SD_PCUIF(g_pcu_conn_id, ts_PCUIF_DEACT_REQ(bts_nr, trx_nr, ts_nr)));
3900
3901 PCU.clear;
3902 /* we now expect no RTS.req for this timeslot */
3903 T.start;
3904 alt {
3905 [] PCU.receive(t_SD_PCUIF(g_pcu_conn_id, tr_PCUIF_RTS_REQ(bts_nr, trx_nr, ts_nr))) {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02003906 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Received unexpected PCU RTS.req");
Harald Welte883340c2018-02-28 18:59:29 +01003907 }
3908 [] PCU.receive { repeat; }
3909 [] T.timeout {
3910 setverdict(pass);
3911 }
3912 }
3913}
3914
Harald Weltead033dc2019-05-25 17:28:16 +02003915friend function f_init_pcu_test() runs on test_CT {
Max2c6f5632019-03-18 17:25:17 +01003916 f_init();
3917 PCU.send(t_SD_PCUIF(g_pcu_conn_id, ts_PCUIF_TXT_IND(0, PCU_VERSION, testcasename())));
3918}
3919
Harald Welte883340c2018-02-28 18:59:29 +01003920/* PDCH activation via PCU socket; check for presence of RTS.req */
3921testcase TC_pcu_act_req() runs on test_CT {
Max2c6f5632019-03-18 17:25:17 +01003922 f_init_pcu_test();
3923
Harald Welte883340c2018-02-28 18:59:29 +01003924 f_TC_pcu_act_req(0, 0, 7, true);
3925}
3926
3927/* PDCH activation via PCU socket on non-PDCU timeslot */
3928testcase TC_pcu_act_req_wrong_ts() runs on test_CT {
Max2c6f5632019-03-18 17:25:17 +01003929 f_init_pcu_test();
3930
Harald Welte883340c2018-02-28 18:59:29 +01003931 f_TC_pcu_act_req(0, 0, 1, false);
3932}
3933
3934/* PDCH activation via PCU socket on wrong BTS */
3935testcase TC_pcu_act_req_wrong_bts() runs on test_CT {
Max2c6f5632019-03-18 17:25:17 +01003936 f_init_pcu_test();
3937
Harald Welte883340c2018-02-28 18:59:29 +01003938 f_TC_pcu_act_req(23, 0, 7, false);
3939}
3940
3941/* PDCH activation via PCU socket on wrong TRX */
3942testcase TC_pcu_act_req_wrong_trx() runs on test_CT {
Max2c6f5632019-03-18 17:25:17 +01003943 f_init_pcu_test();
3944
Harald Welte883340c2018-02-28 18:59:29 +01003945 f_TC_pcu_act_req(0, 23, 7, false);
3946}
3947
3948/* PDCH deactivation via PCU socket; check for absence of RTS.req */
3949testcase TC_pcu_deact_req() runs on test_CT {
Max2c6f5632019-03-18 17:25:17 +01003950 f_init_pcu_test();
3951
Harald Welte883340c2018-02-28 18:59:29 +01003952 /* Activate PDCH */
3953 f_TC_pcu_act_req(0, 0, 7, true);
3954 f_sleep(1.0);
3955 /* and De-Activate again */
3956 f_TC_pcu_deact_req(0, 0, 7);
3957}
3958
3959/* Attempt to deactivate a PDCH on a non-PDCH timeslot */
3960testcase TC_pcu_deact_req_wrong_ts() runs on test_CT {
Max2c6f5632019-03-18 17:25:17 +01003961 f_init_pcu_test();
3962
Harald Welte883340c2018-02-28 18:59:29 +01003963 f_TC_pcu_deact_req(0, 0, 1);
3964}
3965
3966/* Test the PCU->BTS Version and BTS->PCU SI13 handshake */
3967testcase TC_pcu_ver_si13() runs on test_CT {
3968 const octetstring si13 := '00010203040506070909'O;
3969 var PCUIF_send_data sd;
3970 timer T:= 3.0;
Max2c6f5632019-03-18 17:25:17 +01003971 f_init_pcu_test();
Harald Welte883340c2018-02-28 18:59:29 +01003972
3973 /* Set SI13 via RSL */
3974 f_rsl_bcch_fill_raw(RSL_SYSTEM_INFO_13, si13);
Max2c6f5632019-03-18 17:25:17 +01003975
Harald Welte883340c2018-02-28 18:59:29 +01003976 T.start;
3977 alt {
3978 [] PCU.receive(t_SD_PCUIF(g_pcu_conn_id, tr_PCUIF_DATA_IND(0, 0, 0, ?, PCU_IF_SAPI_BCCH))) -> value sd {
3979 if (substr(sd.data.u.data_ind.data, 0, lengthof(si13)) == si13) {
3980 setverdict(pass);
3981 } else {
3982 repeat;
3983 }
3984 }
3985 [] PCU.receive { repeat; }
3986 [] T.timeout {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02003987 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout waiting for SI13");
Harald Welte883340c2018-02-28 18:59:29 +01003988 }
3989 }
3990}
3991
3992private const octetstring c_PCU_DATA := '000102030405060708090a0b0c0d0e0f10111213141516'O;
3993
3994/* helper function to send a PCU DATA.req */
Harald Weltead033dc2019-05-25 17:28:16 +02003995friend function f_pcu_data_req(uint8_t bts_nr, uint8_t trx_nr, uint8_t ts_nr,
Harald Welte883340c2018-02-28 18:59:29 +01003996 uint8_t block_nr, uint32_t fn, PCUIF_Sapi sapi, octetstring data)
3997runs on test_CT
3998{
3999 PCU.send(t_SD_PCUIF(g_pcu_conn_id,
4000 ts_PCUIF_DATA_REQ(bts_nr, trx_nr, ts_nr, block_nr, fn, sapi, data)));
4001}
4002
4003/* helper function to wait for RTS.ind for given SAPI on given BTS/TRX/TS and then send */
Harald Weltead033dc2019-05-25 17:28:16 +02004004friend function f_pcu_wait_rts_and_data_req(uint8_t bts_nr, uint8_t trx_nr, uint8_t ts_nr,
4005 PCUIF_Sapi sapi, octetstring data)
Harald Welte883340c2018-02-28 18:59:29 +01004006runs on test_CT
4007{
4008 var PCUIF_send_data sd;
4009
4010 timer T := 3.0;
4011 T.start;
4012 alt {
4013 [] PCU.receive(t_SD_PCUIF(g_pcu_conn_id,
4014 tr_PCUIF_RTS_REQ(bts_nr, trx_nr, ts_nr, sapi))) -> value sd {
4015 f_pcu_data_req(bts_nr, trx_nr, ts_nr, sd.data.u.rts_req.block_nr,
4016 sd.data.u.rts_req.fn, sapi, data);
4017 }
4018 [] PCU.receive { repeat; }
4019 [] T.timeout {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02004020 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout waiting for RTS.ind");
Harald Welte883340c2018-02-28 18:59:29 +01004021 }
4022 }
4023}
4024
4025/* Send DATA.req on invalid BTS */
4026testcase TC_pcu_data_req_wrong_bts() runs on test_CT {
Harald Welte7162a612019-05-26 12:56:09 +02004027 var TfiUsfArr tua := f_TfiUsfArrInit();
4028 var octetstring data := '0000'O & f_rnd_octstring(21);
4029
4030 f_virtphy_common();
Max2c6f5632019-03-18 17:25:17 +01004031
Harald Welte883340c2018-02-28 18:59:29 +01004032 f_TC_pcu_act_req(0, 0, 7, true);
Harald Welte7162a612019-05-26 12:56:09 +02004033 f_TfiUsfArrSet(tua, 7, 0);
4034 f_L1CTL_TBF_CFG(L1CTL, false, tua);
4035 f_sleep(1.0);
4036
4037 f_pcu_to_l1(23, 0, 7, PCU_IF_SAPI_PDTCH, data, false, false);
Harald Welte883340c2018-02-28 18:59:29 +01004038}
4039
4040/* Send DATA.req on invalid TRX */
4041testcase TC_pcu_data_req_wrong_trx() runs on test_CT {
Harald Welte7162a612019-05-26 12:56:09 +02004042 var TfiUsfArr tua := f_TfiUsfArrInit();
4043 var octetstring data := '0000'O & f_rnd_octstring(21);
4044
4045 f_virtphy_common();
Max2c6f5632019-03-18 17:25:17 +01004046
Harald Welte883340c2018-02-28 18:59:29 +01004047 f_TC_pcu_act_req(0, 0, 7, true);
Harald Welte7162a612019-05-26 12:56:09 +02004048 f_TfiUsfArrSet(tua, 7, 0);
4049 f_L1CTL_TBF_CFG(L1CTL, false, tua);
4050 f_sleep(1.0);
4051
4052 f_pcu_to_l1(0, 100, 7, PCU_IF_SAPI_PDTCH, data, false, false);
Harald Welte883340c2018-02-28 18:59:29 +01004053}
4054
4055/* Send DATA.req on invalid timeslot */
4056testcase TC_pcu_data_req_wrong_ts() runs on test_CT {
Harald Welte7162a612019-05-26 12:56:09 +02004057 var TfiUsfArr tua := f_TfiUsfArrInit();
4058 var octetstring data := '0000'O & f_rnd_octstring(21);
4059
4060 f_virtphy_common();
Max2c6f5632019-03-18 17:25:17 +01004061
Harald Welte883340c2018-02-28 18:59:29 +01004062 f_TC_pcu_act_req(0, 0, 7, true);
Harald Welte7162a612019-05-26 12:56:09 +02004063 f_TfiUsfArrSet(tua, 7, 0);
4064 f_L1CTL_TBF_CFG(L1CTL, false, tua);
4065 f_sleep(1.0);
4066
4067 f_pcu_to_l1(0, 0, 70, PCU_IF_SAPI_PDTCH, data, false, false);
Harald Welte883340c2018-02-28 18:59:29 +01004068}
4069
4070/* Send DATA.req on timeslot that hasn't been activated */
4071testcase TC_pcu_data_req_ts_inactive() runs on test_CT {
Harald Welte7162a612019-05-26 12:56:09 +02004072 var TfiUsfArr tua := f_TfiUsfArrInit();
4073 var octetstring data := '0000'O & f_rnd_octstring(21);
Max2c6f5632019-03-18 17:25:17 +01004074
Harald Welte7162a612019-05-26 12:56:09 +02004075 f_virtphy_common();
4076
4077 f_TfiUsfArrSet(tua, 7, 0);
4078 f_L1CTL_TBF_CFG(L1CTL, false, tua);
4079 f_sleep(1.0);
4080
4081 f_pcu_to_l1(0, 0, 7, PCU_IF_SAPI_PDTCH, data, false, false);
Harald Welte883340c2018-02-28 18:59:29 +01004082}
4083
Harald Weltead033dc2019-05-25 17:28:16 +02004084private function f_pcu_to_l1(uint8_t bts_nr, uint8_t trx_nr, uint8_t ts_nr,
Harald Welte7162a612019-05-26 12:56:09 +02004085 PCUIF_Sapi sapi, octetstring data, boolean expect_data := true,
4086 boolean wait_rts := true)
4087runs on test_CT {
Harald Weltead033dc2019-05-25 17:28:16 +02004088 timer T := 5.0;
Harald Welte7162a612019-05-26 12:56:09 +02004089 var L1ctlDlMessage rx_dl;
Harald Weltead033dc2019-05-25 17:28:16 +02004090
4091 PCU.clear;
Harald Welte7162a612019-05-26 12:56:09 +02004092 if (wait_rts) {
4093 f_pcu_wait_rts_and_data_req(bts_nr, trx_nr, ts_nr, sapi, data);
4094 } else {
4095 f_pcu_data_req(bts_nr, trx_nr, ts_nr, 0, 0, sapi, data);
4096 }
Harald Weltead033dc2019-05-25 17:28:16 +02004097
4098 T.start;
4099 alt {
Harald Welte7162a612019-05-26 12:56:09 +02004100 [expect_data] L1CTL.receive(tr_L1CTL_DATA_IND(t_RslChanNr_PDCH(ts_nr), ?, data)) {
Harald Weltead033dc2019-05-25 17:28:16 +02004101 /* FIXME: why is fn of DATA_IND different to fn of RTS / DATA_REQ above? */
4102 setverdict(pass);
4103 }
Harald Welte7162a612019-05-26 12:56:09 +02004104 [not expect_data] L1CTL.receive(tr_L1CTL_DATA_IND(t_RslChanNr_PDCH(ts_nr), ?, data)) -> value rx_dl {
4105 setverdict(fail, "Received unexpected ", rx_dl);
4106 }
Harald Weltead033dc2019-05-25 17:28:16 +02004107 [] L1CTL.receive {
4108 repeat;
4109 }
Harald Welte7162a612019-05-26 12:56:09 +02004110 [expect_data] T.timeout {
Harald Weltead033dc2019-05-25 17:28:16 +02004111 setverdict(fail, "Timeout waiting for ", data);
4112 }
Harald Welte7162a612019-05-26 12:56:09 +02004113 [not expect_data] T.timeout {
4114 setverdict(pass);
4115 }
Harald Weltead033dc2019-05-25 17:28:16 +02004116 }
4117}
4118
4119private function f_disable_dynamic_ts() runs on test_CT
4120{
4121 f_init_vty_bsc();
4122 /* I'm not quite sure why we need this with osmo-bts-virtual. Somehow it deosn't seem to
4123 * support dynamic timeslots? But it uses the same scheduler as osmo-bts-trx ?!? */
4124 f_vty_config2(BSCVTY, {"network", "bts 0", "trx 0", "timeslot 3"}, "phys_chan_config TCH/F");
4125 f_vty_config2(BSCVTY, {"network", "bts 0", "trx 0", "timeslot 4"}, "phys_chan_config TCH/F");
Max2c6f5632019-03-18 17:25:17 +01004126 f_init_pcu_test();
Harald Weltead033dc2019-05-25 17:28:16 +02004127}
4128
4129private function f_virtphy_common() runs on test_CT {
4130 f_disable_dynamic_ts();
4131 f_init_l1ctl();
4132 f_l1_tune(L1CTL);
4133}
4134
4135testcase TC_pcu_data_req_pdtch() runs on test_CT {
4136 var TfiUsfArr tua := f_TfiUsfArrInit();
4137 var octetstring data := '0000'O & f_rnd_octstring(21);
4138
4139 f_virtphy_common();
Max2c6f5632019-03-18 17:25:17 +01004140
Harald Welte883340c2018-02-28 18:59:29 +01004141 f_TC_pcu_act_req(0, 0, 7, true);
Harald Weltead033dc2019-05-25 17:28:16 +02004142 f_TfiUsfArrSet(tua, 7, 0);
4143 f_L1CTL_TBF_CFG(L1CTL, false, tua);
4144 f_sleep(1.0);
4145
4146 f_pcu_to_l1(0, 0, 7, PCU_IF_SAPI_PDTCH, data); //c_PCU_DATA);
Harald Welte883340c2018-02-28 18:59:29 +01004147}
4148
4149testcase TC_pcu_data_req_ptcch() runs on test_CT {
Harald Weltead033dc2019-05-25 17:28:16 +02004150 var TfiUsfArr tua := f_TfiUsfArrInit();
4151 var octetstring data := '0000'O & f_rnd_octstring(21);
4152
4153 f_virtphy_common();
Max2c6f5632019-03-18 17:25:17 +01004154
Harald Welte883340c2018-02-28 18:59:29 +01004155 f_TC_pcu_act_req(0, 0, 7, true);
Harald Weltead033dc2019-05-25 17:28:16 +02004156 f_TfiUsfArrSet(tua, 7, 0);
4157 f_L1CTL_TBF_CFG(L1CTL, false, tua);
4158 f_sleep(1.0);
4159
4160 f_pcu_to_l1(0, 0, 7, PCU_IF_SAPI_PTCCH, data);
Harald Welte883340c2018-02-28 18:59:29 +01004161}
4162
4163/* Send AGCH from PCU; check it appears on Um side */
4164testcase TC_pcu_data_req_agch() runs on test_CT {
4165 timer T := 3.0;
Max2c6f5632019-03-18 17:25:17 +01004166 f_init_pcu_test();
Harald Welte883340c2018-02-28 18:59:29 +01004167 f_init_l1ctl();
4168 f_l1_tune(L1CTL);
4169
4170 f_TC_pcu_act_req(0, 0, 7, true);
4171 f_pcu_data_req(0, 0, 7, 0, 0, PCU_IF_SAPI_AGCH, c_PCU_DATA);
4172
4173 T.start;
4174 alt {
Harald Weltef8df4cb2018-03-10 15:15:08 +01004175 [] L1CTL.receive(tr_L1CTL_DATA_IND(t_RslChanNr_PCH_AGCH(0), ?, c_PCU_DATA)) {
Harald Welte883340c2018-02-28 18:59:29 +01004176 setverdict(pass);
4177 }
4178 [] L1CTL.receive { repeat; }
4179 [] T.timeout {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02004180 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout waiting for PCU-originated AGCH block on Um");
Harald Welte883340c2018-02-28 18:59:29 +01004181 }
4182 }
4183}
4184
Harald Welte928622b2019-05-26 13:22:59 +02004185/* Send AGCH from PCU; check it appears on Um side */
4186testcase TC_pcu_data_req_pch() runs on test_CT {
4187 timer T := 3.0;
4188 f_init_pcu_test();
4189 f_init_l1ctl();
4190 f_l1_tune(L1CTL);
4191
4192 f_TC_pcu_act_req(0, 0, 7, true);
4193 /* three characters prefix: last 3 digits of IMSI as ASCII */
4194 f_pcu_data_req(0, 0, 7, 0, 0, PCU_IF_SAPI_PCH, '313233'O & c_PCU_DATA);
4195
4196 T.start;
4197 alt {
4198 [] L1CTL.receive(tr_L1CTL_DATA_IND(t_RslChanNr_PCH_AGCH(0), ?, c_PCU_DATA)) {
4199 setverdict(pass);
4200 }
4201 [] L1CTL.receive { repeat; }
4202 [] T.timeout {
4203 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout waiting for PCU-originated PCH block on Um");
4204 }
4205 }
4206}
4207
Harald Welte883340c2018-02-28 18:59:29 +01004208/* Send IMM.ASS from PCU for PCH; check it appears on Um side */
4209testcase TC_pcu_data_req_imm_ass_pch() runs on test_CT {
4210 var octetstring imm_ass := f_rnd_octstring(23);
Max2c6f5632019-03-18 17:25:17 +01004211 f_init_pcu_test();
Harald Welte883340c2018-02-28 18:59:29 +01004212 f_init_l1ctl();
4213 f_l1_tune(L1CTL);
4214
4215 /* append 3 last imsi digits so BTS can compute pagng group */
4216 var uint32_t fn := f_PCUIF_tx_imm_ass_pch(PCU, g_pcu_conn_id, imm_ass, '123459987'H);
4217
4218 timer T := 0.5;
4219 T.start;
4220 alt {
Harald Weltef8df4cb2018-03-10 15:15:08 +01004221 [] L1CTL.receive(tr_L1CTL_DATA_IND(t_RslChanNr_PCH_AGCH(0), ?, imm_ass)) {
Harald Welte883340c2018-02-28 18:59:29 +01004222 /* TODO: verify paging group */
4223 setverdict(pass);
4224 }
4225 [] L1CTL.receive { repeat; }
4226 [] T.timeout {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02004227 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout waiting for PCU-originated AGCH block on Um");
Harald Welte883340c2018-02-28 18:59:29 +01004228 }
4229 }
4230}
4231
4232/* Send RACH from Um side, expect it to show up on PCU socket */
4233testcase TC_pcu_rach_content() runs on test_CT {
Max2c6f5632019-03-18 17:25:17 +01004234 f_init_pcu_test();
Harald Welte883340c2018-02-28 18:59:29 +01004235 f_init_l1ctl();
4236 f_l1_tune(L1CTL);
4237
4238 var GsmFrameNumber fn_last := 0;
4239 for (var integer i := 0; i < 1000; i := i+1) {
4240 var OCT1 ra := f_rnd_ra_ps();
4241 var GsmFrameNumber fn := f_L1CTL_RACH(L1CTL, oct2int(ra));
4242 if (fn == fn_last) {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02004243 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Two RACH in same FN?!?");
Harald Welte883340c2018-02-28 18:59:29 +01004244 }
4245 fn_last := fn;
4246
4247 timer T := 2.0;
4248 T.start;
4249 alt {
4250 [] PCU.receive(t_SD_PCUIF(g_pcu_conn_id, tr_PCUIF_RACH_IND(0, oct2int(ra), 0, ?, fn))) {
4251 T.stop;
4252 }
4253 [] PCU.receive(t_SD_PCUIF(g_pcu_conn_id, tr_PCUIF_RACH_IND)) {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02004254 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Unexpected RACH IND");
Harald Welte883340c2018-02-28 18:59:29 +01004255 }
4256 [] PCU.receive { repeat; }
4257 [] T.timeout {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02004258 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout waiting for RACH IND");
Harald Welte883340c2018-02-28 18:59:29 +01004259 }
4260 }
4261 }
4262 setverdict(pass);
4263}
4264
Vadim Yanitskiy51cbc102019-04-22 06:37:30 +07004265/* Send extended (11-bit, TS1 & TS2) RACH bursts from the Um side,
4266 * expect them to show up on PCU socket (with proper BURST_TYPE_*). */
4267testcase TC_pcu_ext_rach_content() runs on test_CT {
4268 var template PCUIF_Message pcu_rach_ind;
4269 var GsmFrameNumber fn_last := 0;
4270 var L1ctlRachSynchSeq synch_seq;
4271 var PCUIF_BurstType pcu_bt;
4272 var GsmFrameNumber fn;
4273 var BIT11 ra11;
4274
4275 f_init_pcu_test();
4276 f_init_l1ctl();
4277 f_l1_tune(L1CTL);
4278
4279 for (var integer i := 0; i < 1000; i := i+1) {
4280 /* We need to test both TS1 & TS2 */
4281 if (i rem 2 == 0) {
4282 synch_seq := RACH_SYNCH_SEQ_TS1;
4283 pcu_bt := BURST_TYPE_1;
4284 } else {
4285 synch_seq := RACH_SYNCH_SEQ_TS2;
4286 pcu_bt := BURST_TYPE_2;
4287 }
4288
4289 ra11 := f_rnd_ra11_ps();
4290 fn := f_L1CTL_EXT_RACH(L1CTL, bit2int(ra11), synch_seq);
4291 if (fn == fn_last) {
4292 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
4293 "Two RACH in same FN?!?");
4294 }
4295 fn_last := fn;
4296
4297 /* Compose the expected message */
4298 pcu_rach_ind := tr_PCUIF_RACH_IND(
4299 bts_nr := 0,
4300 ra := bit2int(ra11),
4301 is_11bit := 1,
4302 burst_type := pcu_bt,
4303 fn := fn);
4304
4305 timer T := 2.0;
4306 T.start;
4307 alt {
4308 [] PCU.receive(t_SD_PCUIF(g_pcu_conn_id, pcu_rach_ind)) {
4309 T.stop;
4310 }
4311 [] PCU.receive(t_SD_PCUIF(g_pcu_conn_id, tr_PCUIF_RACH_IND)) {
4312 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Unexpected RACH IND");
4313 }
4314 [] PCU.receive { repeat; }
4315 [] T.timeout {
4316 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout waiting for RACH IND");
4317 }
4318 }
4319 }
4320 setverdict(pass);
4321}
4322
Vadim Yanitskiya2c68e82019-07-03 13:07:20 +07004323private function f_TC_pcu_data_ind_lqual_cb(int16_t lqual_cb_exp, int16_t thresh)
4324runs on test_CT {
4325 var template PCUIF_send_data sdt;
4326 var PCUIF_send_data sd;
4327 var int16_t lqual_cb;
4328 timer T := 1.0;
4329
4330 /* PCUIF_DATA.ind is encapsulated into a supplementary record */
4331 sdt := t_SD_PCUIF_MSGT(g_pcu_conn_id, PCU_IF_MSG_DATA_IND);
4332
4333 /* Send a random PDTCH frame over Um */
4334 L1CTL.send(ts_L1CTL_TRAFFIC_REQ(ts_RslChanNr_PDCH(7), ts_RslLinkID_DCCH(0),
4335 '0000'O & f_rnd_octstring(21)));
4336
4337 T.start;
4338 alt {
4339 /* If expected link quality is above the threshold */
4340 [lqual_cb_exp >= thresh] PCU.receive(sdt) -> value sd {
4341 lqual_cb := sd.data.u.data_ind.lqual_cb;
4342 log("Rx PCUIF_DATA.ind (lqual_cb=", lqual_cb, ")");
4343
4344 /* Make sure the actual link quality matches the expected value */
4345 if (not match(lqual_cb, lqual_cb_exp)) {
4346 setverdict(fail, log2str("Link quality ", lqual_cb, " does not match ",
4347 "expected value ", lqual_cb_exp));
4348 } else {
4349 setverdict(pass);
4350 }
4351 }
4352 /* If expected link quality is below the threshold */
4353 [lqual_cb_exp < thresh] PCU.receive(sdt) -> value sd {
4354 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
4355 log2str("Rx unexpected PCUIF_DATA.ind: ", sd.data));
4356 }
4357 /* Ignore PCUIF_RTS.req and PCUIF_TIME.ind */
4358 [] PCU.receive { repeat; }
4359 [lqual_cb_exp < thresh] T.timeout {
4360 log("Rx nothing, as expected");
4361 setverdict(pass);
4362 }
4363 [lqual_cb_exp >= thresh] T.timeout {
4364 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
4365 "Timeout waiting for PCUIF_DATA.ind");
4366 }
4367 }
4368}
4369
4370/* Verify C/I (Carrier-to-Interference ratio) processing of PDTCH frames */
4371testcase TC_pcu_data_ind_lqual_cb() runs on test_CT {
4372 f_init_pcu_test();
4373 PCU.clear;
4374
4375 f_init_l1ctl();
4376 f_l1_tune(L1CTL);
4377
4378 /* Activate a PDCH channel on TS7 */
4379 f_TC_pcu_act_req(0, 0, 7, true);
4380
4381 /* Tune trxcon to that PDCH channel on TS7 */
4382 f_L1CTL_DM_EST_REQ(L1CTL, { false, mp_trx0_arfcn },
4383 valueof(ts_RslChanNr_PDCH(7)), 7);
4384
4385 /* C/I in centiBels, test range: -256 .. +1280, step 128 */
4386 for (var int16_t i := -256; i <= 1280; i := i + 128) {
4387 var TrxcMessage ret;
4388
4389 ret := f_TRXC_transceive(BTS_TRXC, g_bts_trxc_conn_id,
4390 valueof(ts_TRXC_FAKE_CI(i)));
4391
4392 /* FIXME: OsmoBTS may have different threshold (see MIN_QUAL_NORM) */
4393 f_TC_pcu_data_ind_lqual_cb(i, thresh := 0);
4394 }
4395}
4396
Harald Welte883340c2018-02-28 18:59:29 +01004397/* Send PAGING via RSL, expect it to shw up on PCU socket */
4398testcase TC_pcu_paging_from_rsl() runs on test_CT {
Max2c6f5632019-03-18 17:25:17 +01004399 f_init_pcu_test();
Harald Welte883340c2018-02-28 18:59:29 +01004400
4401 for (var integer i := 0; i < 100; i := i+1) {
4402 var MobileL3_CommonIE_Types.MobileIdentityLV mi;
4403 timer T := 3.0;
4404 if (i < 50) {
4405 mi := valueof(ts_MI_TMSI_LV(f_rnd_octstring(4)));
4406 } else {
4407 mi := valueof(ts_MI_IMSI_LV(f_gen_imsi(i)));
4408 }
4409 var octetstring mi_enc_lv := enc_MobileIdentityLV(mi);
4410 var octetstring mi_enc := substr(mi_enc_lv, 1, lengthof(mi_enc_lv)-1);
4411 var octetstring t_mi_lv := f_pad_oct(mi_enc_lv, 9, '00'O);
4412
4413 /* Send RSL PAGING COMMAND */
4414 RSL_CCHAN.send(ts_RSL_UD(ts_RSL_PAGING_CMD(mi_enc, i mod 4)));
4415 T.start;
4416 alt {
4417 [] PCU.receive(t_SD_PCUIF(g_pcu_conn_id, tr_PCUIF_PAG_REQ(0, t_mi_lv))) {
4418 }
4419 [] PCU.receive(t_SD_PCUIF(g_pcu_conn_id, tr_PCUIF_PAG_REQ)) {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02004420 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Unexpected PAGING REQ");
Harald Welte883340c2018-02-28 18:59:29 +01004421 }
4422 [] PCU.receive { repeat; }
4423 [] T.timeout {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02004424 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout waiting for PAGING REQ");
Harald Welte883340c2018-02-28 18:59:29 +01004425 }
4426 }
4427 }
4428 setverdict(pass);
4429}
4430
Harald Welted66c9b82019-05-25 09:03:15 +02004431/* test for periodic TIME_IND; check number of FN expired and number of TIME_IND within frames */
4432testcase TC_pcu_time_ind() runs on test_CT {
4433 var PCUIF_send_data pcu_sd;
4434 var integer num_time_ind := 0;
4435 var integer first_fn, last_fn;
4436 var float test_duration := 5.0;
4437 timer T;
4438
4439 f_init_pcu_test();
4440 f_TC_pcu_act_req(0, 0, 7, true);
4441
4442 PCU.clear;
4443 T.start(test_duration);
4444 alt {
4445 [] PCU.receive(t_SD_PCUIF(g_pcu_conn_id, tr_PCUIF_TIME_IND(0, ?))) -> value pcu_sd {
4446 num_time_ind := num_time_ind + 1;
4447 if (not isbound(first_fn)) {
4448 first_fn := pcu_sd.data.u.time_ind.fn;
4449 }
4450 last_fn := pcu_sd.data.u.time_ind.fn;
4451 repeat;
4452 }
4453 [] PCU.receive(t_SD_PCUIF(g_pcu_conn_id, tr_PCUIF_TIME_IND(?, ?))) -> value pcu_sd {
4454 setverdict(fail, "Received unexpected PCUIF_TIME_IND: ", pcu_sd.data);
4455 repeat;
4456 }
4457 [] PCU.receive {
4458 repeat;
4459 }
4460 [] T.timeout {}
4461 }
4462 var integer fn_expired := last_fn - first_fn;
4463 log(fn_expired, " fn expired with ", num_time_ind, " PCU_TIME.ind");
4464
4465 /* verify the number of frames expired matches our expectation */
4466 const float c_GSM_FN_DURATION_MS := 4.61538;
4467 var float fn_expected := test_duration * 1000.0 / c_GSM_FN_DURATION_MS;
Harald Weltec761c542019-05-28 11:59:57 +02004468 var template integer t_fn_expected := f_tolerance(float2int(fn_expected), 1, 100000, 20);
Harald Welted66c9b82019-05-25 09:03:15 +02004469 if (not match(fn_expired, t_fn_expected)) {
4470 setverdict(fail, "Number of TDMA Frames (", fn_expired, ") not matching ", t_fn_expected);
4471 }
4472
4473 /* There are three TIME.ind in every fn MOD 13 */
4474 var float time_ind_expected := int2float(fn_expired) * 3.0 / 13.0;
4475 /* Add some tolerance */
4476 var template integer t_time_ind_exp := f_tolerance(float2int(time_ind_expected), 1, 100000, 5);
4477 if (not match(num_time_ind, t_time_ind_exp)) {
4478 setverdict(fail, "Number of TIME.ind (", num_time_ind, ") not matching ", t_time_ind_exp);
4479 }
4480
4481 setverdict(pass);
4482}
4483
Harald Welte4832c862019-05-25 14:57:18 +02004484/* test for periodic RTS_REQ; check number of FN expired and number of RTS_IND per SAPI */
4485testcase TC_pcu_rts_req() runs on test_CT {
4486 var PCUIF_send_data pcu_sd;
4487 var integer first_fn, last_fn;
4488 var integer num_rts_pdtch := 0;
4489 var integer num_rts_ptcch := 0;
4490 var float test_duration := 5.0;
4491 timer T;
4492
4493 f_init_pcu_test();
4494 f_TC_pcu_act_req(0, 0, 7, true);
4495
4496 PCU.clear;
4497 T.start(test_duration);
4498 alt {
4499 [] PCU.receive(t_SD_PCUIF(g_pcu_conn_id, tr_PCUIF_RTS_REQ(0, 0, 7, PCU_IF_SAPI_PDTCH, ?, ?)))
4500 -> value pcu_sd {
4501 num_rts_pdtch := num_rts_pdtch + 1;
4502 if (not isbound(first_fn)) {
4503 first_fn := pcu_sd.data.u.rts_req.fn;
4504 }
4505 last_fn := pcu_sd.data.u.rts_req.fn;
4506 repeat;
4507 }
4508 [] PCU.receive(t_SD_PCUIF(g_pcu_conn_id, tr_PCUIF_RTS_REQ(0, 0, 7, PCU_IF_SAPI_PTCCH, ?, ?)))
4509 -> value pcu_sd {
4510 num_rts_ptcch := num_rts_ptcch + 1;
4511 if (not isbound(first_fn)) {
4512 first_fn := pcu_sd.data.u.rts_req.fn;
4513 }
4514 last_fn := pcu_sd.data.u.rts_req.fn;
4515 repeat;
4516 }
4517 [] PCU.receive(t_SD_PCUIF(g_pcu_conn_id, tr_PCUIF_RTS_REQ)) -> value pcu_sd {
4518 setverdict(fail, "Received unexpected PCUIF_RTS_REQ: ", pcu_sd.data);
4519 repeat;
4520 }
4521 [] PCU.receive {
4522 repeat;
4523 }
4524 [] T.timeout {}
4525 }
4526 var integer fn_expired := last_fn - first_fn;
4527 log(fn_expired, " fn expired with num_rts_pdtch=", num_rts_pdtch,
4528 ", num_rts_ptcch=", num_rts_ptcch);
4529
4530 /* verify the number of frames expired matches our expectation */
4531 const float c_GSM_FN_DURATION_MS := 4.61538;
4532 var float fn_expected := test_duration * 1000.0 / c_GSM_FN_DURATION_MS;
Harald Weltec761c542019-05-28 11:59:57 +02004533 var template integer t_fn_expected := f_tolerance(float2int(fn_expected), 1, 100000, 20);
Harald Welte4832c862019-05-25 14:57:18 +02004534 if (not match(fn_expired, t_fn_expected)) {
4535 setverdict(fail, "Number of TDMA Frames (", fn_expired, ") not matching ", t_fn_expected);
4536 }
4537
4538 /* PTCCH is in pos. 12 + 38 of 52-multiframe, but four slots/bursts required per block */
4539 var float ptcch_expected := int2float(fn_expired) / 52.0 * 0.5;
4540 var template integer t_ptcch_exp := f_tolerance(float2int(ptcch_expected), 1, 100000, 1);
4541 if (not match(num_rts_ptcch, t_ptcch_exp)) {
4542 setverdict(fail, "Number of RTS.ind for PTCCH (", num_rts_ptcch, ") not matching ",
4543 t_ptcch_exp);
4544 }
4545
4546 /* We have 12 PDTCH blocks every 52-multiframe */
4547 var float pdtch_expected := int2float(fn_expired) / 52.0 * 12.0;
4548 var template integer t_pdtch_exp := f_tolerance(float2int(pdtch_expected), 1, 100000, 2);
4549 if (not match(num_rts_pdtch, t_pdtch_exp)) {
4550 setverdict(fail, "Number of RTS.ind for PDTCH (", num_rts_pdtch, ") not matching ",
4551 t_pdtch_exp);
4552 }
4553
4554 setverdict(pass);
4555}
4556
Harald Welte07bd2d22019-05-25 11:03:30 +02004557/* test for generating Abis side OML ALERT from the PCU */
4558testcase TC_pcu_oml_alert() runs on test_CT {
4559 var PCUIF_send_data pcu_sd;
4560 var integer num_time_ind := 0;
4561 var integer first_fn, last_fn;
4562 var float test_duration := 5.0;
4563 timer T;
4564
4565 f_init_pcu_test();
4566 f_TC_pcu_act_req(0, 0, 7, true);
4567
4568 /* re-connect CTRL port from BTS to BSC */
4569 f_ipa_ctrl_stop();
4570 f_ipa_ctrl_start(mp_bsc_ctrl_ip, mp_bsc_ctrl_port);
4571
4572 /* Send that OML Alert */
4573 PCU.send(t_SD_PCUIF(g_pcu_conn_id, ts_PCUIF_TXT_IND(0, PCU_OML_ALERT, testcasename())));
4574
4575 /* This requires https://gerrit.osmocom.org/#/c/osmo-bsc/+/14177 to be merged */
4576 f_ctrl_exp_trap(IPA_CTRL, "bts.0.oml_failure_report", ?);
4577 setverdict(pass);
4578}
4579
Harald Welteeaa9a862019-05-26 23:01:08 +02004580template (value) PDU_ML3_MS_NW ts_RRM_GprsSuspReq(template (value) OCT4 tlli,
4581 template (value) RoutingAreaIdentificationV rai,
4582 template (value) OCT1 cause) := {
4583 discriminator := '0000'B, /* overwritten */
4584 tiOrSkip := {
4585 skipIndicator := '0000'B
4586 },
4587 msgs := {
4588 rrm := {
4589 gPRS_suspensionRequest := {
4590 messageType := '00110100'B,
4591 tLLI := tlli,
4592 routingAreaIdentification := rai,
4593 suspensionCause := cause,
4594 service_Support := omit
4595 }
4596 }
4597 }
4598}
4599
4600/* test for forwarding of RR SUSPEND from CS lchan to PCU via PCU socket */
4601private function f_TC_rr_suspend_req(charstring id) runs on ConnHdlr {
4602 var PCUIF_Message first_info;
4603 var integer pcu_conn_id := -1;
4604 var RslLinkId link_id := valueof(ts_RslLinkID_DCCH(0));
4605 var RoutingAreaIdentificationV rai := f_RAI('262'H, '42F'H, '2342'O, '55'O);
4606 var OCT4 tlli := '01020304'O;
4607 var OCT1 cause := '23'O;
4608 timer T := 5.0;
4609
4610 f_init_pcu(PCU, id, pcu_conn_id, first_info);
4611
4612 f_l1_tune(L1CTL);
4613 RSL.clear;
4614
4615 f_est_dchan();
4616 L1CTL.clear;
4617
4618 f_est_rll_mo(link_id.sapi, link_id, '23420815'O);
4619
4620 var PDU_ML3_MS_NW susp_req := valueof(ts_RRM_GprsSuspReq(tlli, rai, cause));
4621 var octetstring l3 := enc_PDU_ML3_MS_NW(susp_req);
4622 f_tx_lapdm(ts_LAPDm_I(link_id.sapi, cr_MO_CMD, true, 1, 0, l3), link_id);
4623
4624 /* ConnHdlr has terminated after sending the RR SUSP REQ over a dedicaed channel */
4625 T.start;
4626 alt {
4627 [] PCU.receive(t_SD_PCUIF(pcu_conn_id, tr_PCUIF_SUSP_REQ(0, tlli, ?, oct2int(cause)))) {
4628 setverdict(pass);
4629 }
4630 [] PCU.receive(t_SD_PCUIF(pcu_conn_id, tr_PCUIF_SUSP_REQ(?, ?, ?, ?))) {
4631 setverdict(fail, "Received unexpected PCUIF SUSPE REQ: ");
4632 }
4633 [] PCU.receive {
4634 repeat;
4635 }
4636 [] T.timeout {
4637 setverdict(fail, "Timeout waiting for SUSP REQ on PCUIF");
4638 }
4639 }
Alexander Couzensa0634832019-06-07 00:28:56 +02004640
4641 /* release the channel */
4642 f_rsl_chan_deact();
4643 f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
4644 f_rslem_unregister(0, g_chan_nr);
Harald Welteeaa9a862019-05-26 23:01:08 +02004645}
4646testcase TC_pcu_rr_suspend() runs on test_CT {
4647 var ConnHdlrPars pars;
4648 var ConnHdlr vc_conn;
4649
4650 f_init();
4651
4652 pars := valueof(t_Pars(t_RslChanNr_SDCCH4(0,3), ts_RSL_ChanMode_SIGN));
4653 vc_conn := f_start_handler(refers(f_TC_rr_suspend_req), pars, true);
4654 vc_conn.done;
4655}
Harald Welte07bd2d22019-05-25 11:03:30 +02004656
Harald Weltea2e0e942019-05-27 18:12:53 +02004657/* Ensure that PCUIF socket can accept only a single connection */
4658testcase TC_pcu_socket_connect_multi() runs on test_CT {
4659 timer T := 5.0;
4660
4661 /* this (among other things) establishes the first connection to the PCUIF socket */
4662 f_init();
4663
4664 /* try to establish a second connection, expect it to fail */
4665 PCU.send(UD_connect:{mp_pcu_socket, -1});
4666 T.start;
4667 alt {
4668 [] PCU.receive(UD_connect_result:{id := ?, result := { result_code := ERROR, err := ? }}) {
4669 setverdict(pass);
4670 }
4671 [] PCU.receive(UD_connect_result:?) {
4672 setverdict(fail, "Unexpected unix domain connect result");
4673 }
4674 [] T.timeout {
4675 setverdict(pass);
4676 }
4677 }
4678 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
4679}
4680
Harald Weltec8effb72019-05-27 18:23:04 +02004681/* Ensure that PCUIF socket can disconnect + reconnect */
4682testcase TC_pcu_socket_reconnect() runs on test_CT {
4683 /* this (among other things) establishes the first connection to the PCUIF socket */
4684 f_init();
4685
4686 f_sleep(1.0);
4687
4688 f_pcuif_close(PCU, g_pcu_conn_id);
4689 g_pcu_conn_id := -1;
4690
4691 f_sleep(1.0);
4692
4693 /* re-connect */
4694 PCU.clear;
4695 f_init_pcu(PCU, testcasename(), g_pcu_conn_id, g_pcu_last_info);
4696 setverdict(pass);
4697
4698 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
4699}
4700
Harald Weltebe030482019-05-27 22:29:35 +02004701/* Ensure that GPRS capability is not advertised before PCU socket conncet */
4702private function f_get_si3(L1CTL_PT pt) runs on test_CT return SystemInformationType3 {
4703 var L1ctlDlMessage l1_dl;
4704 var SystemInformation si;
4705 timer T := 5.0;
4706 T.start;
4707 alt {
4708 [] pt.receive(tr_L1CTL_DATA_IND(t_RslChanNr_BCCH(0), ?)) -> value l1_dl {
4709 /* somehow dec_SystemInformation will try to decode even non-RR as SI */
4710 if (not (l1_dl.payload.data_ind.payload[1] == '06'O)) {
4711 log("Ignoring non-RR SI ", l1_dl);
4712 repeat;
4713 }
4714 si := dec_SystemInformation(l1_dl.payload.data_ind.payload)
4715 if (not ischosen(si.payload.si3)) {
4716 repeat;
4717 }
4718 }
4719 [] pt.receive {
4720 repeat;
4721 }
4722 [] T.timeout {
4723 setverdict(fail, "Timeout waiting for SI3");
4724 }
4725 }
4726 return si.payload.si3;
4727}
4728
4729/* CSN.1 L/H logic: is the bit at the current position using "inverted logic" (true) or not? */
4730private function f_bitpos_is_inv(integer idx) return boolean {
4731 select (idx mod 8) {
4732 case ((2, 4, 6, 7)) { return true; } /* 1-bits of 0x2B */
4733 case else { return false; } /* 0-bits of 0x2B */
4734 }
4735}
4736/* determine if the bit at position 'idx' in 'str' is a CSN.1 'H' (true) or 'L' (false) */
4737private function f_bit_is_high(bitstring str, integer idx) return boolean {
4738 var boolean invert := f_bitpos_is_inv(idx);
4739 if (invert) {
4740 if (str[idx] == '1'B) {
4741 return false;
4742 } else {
4743 return true;
4744 }
4745 } else {
4746 if (str[idx] == '1'B) {
4747 return true;
4748 } else {
4749 return false;
4750 }
4751 }
4752}
4753/* As the TITAN RAW codec cannot expres the CSN.1 L/H concept yet, we have to do this
4754 manually. Let's hope https://www.eclipse.org/forums/index.php/t/1099087/ takes off and
4755 we can replace this piece of code soon ... */
4756private function f_si3_has_gprs_indicator(OCT4 si3_restoctets) return boolean {
4757 var bitstring bits := oct2bit(si3_restoctets);
4758 var integer idx := 0;
4759
4760 if (f_bit_is_high(bits, idx)) {
4761 /* skip Optional selection parameters */
4762 idx := idx + 16;
4763 } else {
4764 idx := idx + 1;
4765 }
4766
4767 if (f_bit_is_high(bits, idx)) {
4768 /* skip Optional power offset */
4769 idx := idx + 3;
4770 } else {
4771 idx := idx + 1;
4772 }
4773
4774 /* skip SI2ter Indicator */
4775 idx := idx + 1;
4776
4777 /* skip Early CM Sending Control */
4778 idx := idx + 1;
4779
4780 /* skip Scheduling if and where */
4781 if (f_bit_is_high(bits, idx)) {
4782 idx := idx + 4;
4783 } else {
4784 idx := idx + 1;
4785 }
4786
4787 return f_bit_is_high(bits, idx);
4788}
4789
4790testcase TC_pcu_socket_noconnect_nosi3gprs() runs on test_CT {
4791 var SystemInformationType3 si3;
4792 timer T := 5.0;
4793
4794 /* don't call f_init() as this would connect PCU socket */
4795 f_init_rsl(testcasename());
4796 T.start;
4797 alt {
4798 [] RSL_CCHAN.receive(ASP_IPA_Event:{up_down := ASP_IPA_EVENT_UP});
4799 [] T.timeout {
4800 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout waiting for ASP_IPA_EVENT_UP");
4801 }
4802 }
4803 f_rsl_bcch_fill(RSL_SYSTEM_INFO_3, ts_SI3_default);
4804
4805 f_init_l1ctl();
4806 f_l1_tune(L1CTL);
4807
4808 f_sleep(2.0);
4809 L1CTL.clear;
4810 si3 := f_get_si3(L1CTL);
4811 if (f_si3_has_gprs_indicator(si3.rest_octets)) {
4812 setverdict(fail, "SI3 indicates GPRS even before PCU socket connected");
4813 } else {
4814 setverdict(pass);
4815 }
4816 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
4817}
4818
4819/* Ensure that GPRS capability is advertised after PCU socket connect */
4820testcase TC_pcu_socket_connect_si3gprs() runs on test_CT {
4821 var SystemInformationType3 si3;
4822
4823 /* this (among other things) establishes the first connection to the PCUIF socket */
4824 f_init();
4825 f_init_l1ctl();
4826 f_l1_tune(L1CTL);
4827
4828 f_sleep(2.0);
4829 L1CTL.clear;
4830 si3 := f_get_si3(L1CTL);
4831 if (not f_si3_has_gprs_indicator(si3.rest_octets)) {
4832 setverdict(fail, "SI3 indicates no GPRS despite PCU socket connected");
4833 } else {
4834 setverdict(pass);
4835 }
4836 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
4837}
4838
4839/* Ensure that GPRS capability is no longer advertised after PCU socket disconnect */
4840testcase TC_pcu_socket_disconnect_nosi3gprs() runs on test_CT {
4841 var SystemInformationType3 si3;
4842
4843 /* this (among other things) establishes the first connection to the PCUIF socket */
4844 f_init();
4845 f_init_l1ctl();
4846 f_l1_tune(L1CTL);
4847
4848 f_pcuif_close(PCU, g_pcu_conn_id);
4849 g_pcu_conn_id := -1;
4850
4851 f_sleep(1.0);
4852
4853 /* re-connect */
4854 PCU.clear;
4855 f_init_pcu(PCU, testcasename(), g_pcu_conn_id, g_pcu_last_info);
4856
4857 f_sleep(2.0);
4858 L1CTL.clear;
4859 si3 := f_get_si3(L1CTL);
4860 if (f_si3_has_gprs_indicator(si3.rest_octets)) {
4861 setverdict(fail, "SI3 indicates GPRS after PCU socket disconnected");
4862 } else {
4863 setverdict(pass);
4864 }
4865
4866 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
4867}
4868
Oliver Smithf5239c72019-08-28 10:01:25 +02004869/* Verify that the cell_id of SI3 (TS 04.08 9.1.35) and other values are passed properly to the PCU socket (OS#3854) */
4870testcase TC_pcu_socket_verify_info_ind() runs on test_CT {
4871 var SystemInformation si3 := valueof(ts_SI3_default);
4872
4873 f_init();
4874
4875 /* Verify cell_id */
4876 var uint16_t cell_id_si3 := si3.payload.si3.cell_id;
4877 var uint16_t cell_id_pcu := g_pcu_last_info.u.info_ind.cell_id;
4878 if (cell_id_si3 != cell_id_pcu) {
4879 setverdict(fail, "Expected cell_id ", cell_id_si3, " got: ", cell_id_pcu);
4880 }
4881
4882 /* Verify LAC */
4883 var uint16_t lac_si3 := si3.payload.si3.lai.lac;
4884 var uint16_t lac_pcu := g_pcu_last_info.u.info_ind.lac;
4885 if (lac_si3 != lac_pcu) {
4886 setverdict(fail, "Expected LAC ", lac_si3, " got: ", lac_pcu);
4887 }
4888
4889 setverdict(pass);
4890}
Harald Welted66c9b82019-05-25 09:03:15 +02004891
Harald Welte3d04ae62018-04-04 20:29:05 +02004892/***********************************************************************
Harald Welte9bbbfb52018-04-05 09:33:19 +02004893 * Osmocom Style Dynamic Timeslot Support
Harald Welte3d04ae62018-04-04 20:29:05 +02004894 ***********************************************************************/
4895
4896private function f_dyn_osmo_pdch_act(integer pcu_conn_id, integer bts_nr, integer trx_nr)
4897runs on ConnHdlr {
4898 var PCUIF_send_data sd;
4899 /* Expect BTS to immediately acknowledge activation as PDCH */
4900 PCU.clear;
4901 f_rsl_chan_act(g_pars.chan_mode);
4902 /* expect INFO_IND on PCU interface listing TS as PDCH */
4903 alt {
4904 [] PCU.receive(t_SD_PCUIF(pcu_conn_id, tr_PCUIF_INFO_IND(bts_nr, ?))) -> value sd {
4905 if (substr(sd.data.u.info_ind.trx[trx_nr].pdch_mask, g_chan_nr.tn, 1) != '1'B) {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02004906 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "PCUIF_INFO_IND PDCH_MASK not '1' after PDCH ACT");
Harald Welte3d04ae62018-04-04 20:29:05 +02004907 }
4908 }
4909 [] PCU.receive { repeat; }
4910 }
4911 /* try to activate this PDCH from the PCU point of view */
4912 PCU.send(t_SD_PCUIF(pcu_conn_id, ts_PCUIF_ACT_REQ(bts_nr, trx_nr, g_chan_nr.tn)));
4913 /* FIXME: is there a response? */
4914}
4915
4916private function f_dyn_osmo_pdch_deact(integer pcu_conn_id, integer bts_nr, integer trx_nr)
4917runs on ConnHdlr {
4918 var PCUIF_send_data sd;
4919 /* Send RSL CHAN REL (deactivate) */
4920 PCU.clear;
4921 RSL.send(ts_RSL_RF_CHAN_REL(g_chan_nr));
4922 /* expect BTS to ask PCU to deactivate the channel */
4923 alt {
4924 [] PCU.receive(t_SD_PCUIF(pcu_conn_id, tr_PCUIF_INFO_IND(bts_nr, ?))) -> value sd {
4925 if (substr(sd.data.u.info_ind.trx[trx_nr].pdch_mask, g_chan_nr.tn, 1) != '0'B) {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02004926 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "PCUIF_INFO_IND PDCH_MASK not '0' after PDCH DEACT");
Harald Welte3d04ae62018-04-04 20:29:05 +02004927 }
4928 }
4929 [] PCU.receive { repeat; }
4930 }
4931 /* Emulate PCU asking BTS to deactivate PDCH */
4932 PCU.send(t_SD_PCUIF(pcu_conn_id, ts_PCUIF_DEACT_REQ(bts_nr, trx_nr, g_chan_nr.tn)));
4933 alt {
4934 [] RSL.receive(tr_RSL_RF_CHAN_REL_ACK(g_chan_nr)) {
4935 setverdict(pass);
4936 }
4937 [] RSL.receive { repeat; }
4938 }
4939}
4940
4941/* Activate Osmocom-style dynamic PDCH from BSC side */
4942function f_TC_dyn_osmo_pdch_act_deact(charstring id) runs on ConnHdlr {
4943 var PCUIF_Message first_info;
4944 var integer ts_nr := g_chan_nr.tn;
4945 var integer trx_nr := 0;
4946 var integer bts_nr := 0;
4947 var integer pcu_conn_id := -1;
4948
4949 f_init_pcu(PCU, id, pcu_conn_id, first_info);
4950
4951 f_dyn_osmo_pdch_act(pcu_conn_id, bts_nr, trx_nr);
4952 f_sleep(3.0);
4953 f_dyn_osmo_pdch_deact(pcu_conn_id, bts_nr, trx_nr);
4954 setverdict(pass);
4955}
4956testcase TC_dyn_osmo_pdch_act_deact() runs on test_CT {
4957 var ConnHdlrPars pars;
4958 var ConnHdlr vc_conn;
Harald Welte10474062019-05-30 16:48:17 +02004959 f_init();
Harald Welte3d04ae62018-04-04 20:29:05 +02004960
4961 pars := valueof(t_Pars(t_RslChanNr_PDCH(4), ts_RSL_ChanMode_SIGN));
4962 vc_conn := f_start_handler(refers(f_TC_dyn_osmo_pdch_act_deact), pars, true);
4963 vc_conn.done;
4964}
4965
4966/* send a RF CHAN REL for PDCH on an osmocom dynamci PDCH that's already inactive */
4967function f_TC_dyn_osmo_pdch_unsol_deact(charstring id) runs on ConnHdlr {
4968 var PCUIF_Message first_info;
Harald Welte3d04ae62018-04-04 20:29:05 +02004969 var integer pcu_conn_id := -1;
4970
4971 f_init_pcu(PCU, id, pcu_conn_id, first_info);
4972
Neels Hofmeyr9c50ca52018-05-08 20:37:54 +02004973 RSL.send(ts_RSL_RF_CHAN_REL(g_chan_nr));
4974 /* since the lchan is already released, we don't expect any PCU changes, just a rel ack. */
4975 RSL.receive(tr_RSL_RF_CHAN_REL_ACK(g_chan_nr));
Harald Welte3d04ae62018-04-04 20:29:05 +02004976 setverdict(pass);
4977}
4978testcase TC_dyn_osmo_pdch_unsol_deact() runs on test_CT {
4979 var ConnHdlrPars pars;
4980 var ConnHdlr vc_conn;
Harald Welte10474062019-05-30 16:48:17 +02004981 f_init();
Harald Welte3d04ae62018-04-04 20:29:05 +02004982
4983 pars := valueof(t_Pars(t_RslChanNr_PDCH(4), ts_RSL_ChanMode_SIGN));
4984 vc_conn := f_start_handler(refers(f_TC_dyn_osmo_pdch_unsol_deact), pars, true);
4985 vc_conn.done;
4986}
4987
4988/* try to RSL CHAN ACT a PDCH on an osmocom-style PDCH that's already active */
4989function f_TC_dyn_osmo_pdch_double_act(charstring id) runs on ConnHdlr {
4990 var PCUIF_Message first_info;
4991 var integer ts_nr := g_chan_nr.tn;
4992 var integer trx_nr := 0;
4993 var integer bts_nr := 0;
4994 var integer pcu_conn_id := -1;
4995
4996 f_init_pcu(PCU, id, pcu_conn_id, first_info);
4997
4998 f_dyn_osmo_pdch_act(pcu_conn_id, bts_nr, trx_nr);
Neels Hofmeyrdf936a22018-05-08 22:07:57 +02004999 /* Send a second Chan Activ and expect it to be NACKed */
5000 f_rsl_transceive(ts_RSL_CHAN_ACT(g_chan_nr, g_pars.chan_mode), tr_RSL_CHAN_ACT_NACK(g_chan_nr),
5001 "RSL CHAN ACT NACK");
Harald Welte3d04ae62018-04-04 20:29:05 +02005002 setverdict(pass);
5003}
5004testcase TC_dyn_osmo_pdch_double_act() runs on test_CT {
5005 var ConnHdlrPars pars;
5006 var ConnHdlr vc_conn;
Harald Welte10474062019-05-30 16:48:17 +02005007 f_init();
Harald Welte3d04ae62018-04-04 20:29:05 +02005008
5009 pars := valueof(t_Pars(t_RslChanNr_PDCH(4), ts_RSL_ChanMode_SIGN));
5010 vc_conn := f_start_handler(refers(f_TC_dyn_osmo_pdch_double_act), pars, true);
5011 vc_conn.done;
5012}
5013
5014/* try to RSL CHAN ACT a TCH/F on an osmocom-style PDCH */
5015function f_TC_dyn_osmo_pdch_tchf_act(charstring id) runs on ConnHdlr {
5016 var PCUIF_Message first_info;
5017 var integer ts_nr := g_chan_nr.tn;
5018 var integer trx_nr := 0;
5019 var integer bts_nr := 0;
5020 var integer pcu_conn_id := -1;
5021 var RslChannelNr chan_nr := valueof(t_RslChanNr_Bm(g_chan_nr.tn));
5022
5023 /* register for the TCH/F channel number */
5024 f_rslem_register(0, chan_nr);
5025
5026 f_init_pcu(PCU, id, pcu_conn_id, first_info);
5027
5028 f_rsl_transceive(ts_RSL_CHAN_ACT(chan_nr, g_pars.chan_mode), tr_RSL_CHAN_ACT_ACK(chan_nr),
5029 "RSL CHAN ACT");
5030 setverdict(pass);
5031}
5032testcase TC_dyn_osmo_pdch_tchf_act() runs on test_CT {
5033 var ConnHdlrPars pars;
5034 var ConnHdlr vc_conn;
Harald Welte10474062019-05-30 16:48:17 +02005035 f_init();
Harald Welte3d04ae62018-04-04 20:29:05 +02005036
5037 pars := valueof(t_Pars(t_RslChanNr_PDCH(4), ts_RSL_ChanMode_SIGN));
5038 vc_conn := f_start_handler(refers(f_TC_dyn_osmo_pdch_tchf_act), pars, true);
5039 vc_conn.done;
5040}
5041
5042/* try to RSL CHAN ACT the TCH/H on an osmocom-style PDCH */
5043function f_TC_dyn_osmo_pdch_tchh_act(charstring id) runs on ConnHdlr {
5044 var PCUIF_Message first_info;
5045 var integer ts_nr := g_chan_nr.tn;
5046 var integer trx_nr := 0;
5047 var integer bts_nr := 0;
5048 var integer pcu_conn_id := -1;
5049 var RslChannelNr chan_nr[2] := { valueof(t_RslChanNr_Lm(g_chan_nr.tn, 0)),
5050 valueof(t_RslChanNr_Lm(g_chan_nr.tn, 1)) };
5051
5052 /* register for the TCH/H channel numbers */
5053 f_rslem_register(0, chan_nr[0]);
5054 f_rslem_register(0, chan_nr[1]);
5055
5056 f_init_pcu(PCU, id, pcu_conn_id, first_info);
5057
5058 f_rsl_transceive(ts_RSL_CHAN_ACT(chan_nr[1], g_pars.chan_mode),
5059 tr_RSL_CHAN_ACT_ACK(chan_nr[1]), "RSL CHAN ACT [1]");
5060 f_rsl_transceive(ts_RSL_CHAN_ACT(chan_nr[0], g_pars.chan_mode),
5061 tr_RSL_CHAN_ACT_ACK(chan_nr[0]), "RSL CHAN ACT [0]");
5062 setverdict(pass);
5063}
5064testcase TC_dyn_osmo_pdch_tchh_act() runs on test_CT {
5065 var ConnHdlrPars pars;
5066 var ConnHdlr vc_conn;
Harald Welte10474062019-05-30 16:48:17 +02005067 f_init();
Harald Welte3d04ae62018-04-04 20:29:05 +02005068
5069 pars := valueof(t_Pars(t_RslChanNr_PDCH(4), ts_RSL_ChanMode_SIGN));
5070 vc_conn := f_start_handler(refers(f_TC_dyn_osmo_pdch_tchh_act), pars, true);
5071 vc_conn.done;
5072}
5073
Harald Welte9bbbfb52018-04-05 09:33:19 +02005074/***********************************************************************
5075 * IPA Style Dynamic Timeslot Support
5076 ***********************************************************************/
5077
5078private function f_dyn_ipa_pdch_act(integer pcu_conn_id, integer bts_nr, integer trx_nr)
5079runs on ConnHdlr {
5080 var PCUIF_send_data sd;
5081 /* Expect BTS to immediately acknowledge activation as PDCH */
5082 PCU.clear;
5083 RSL.send(ts_RSL_IPA_PDCH_ACT(g_chan_nr));
5084 /* expect INFO_IND on PCU interface listing TS as PDCH */
Pau Espin Pedrol446e07b2019-02-18 21:18:36 +01005085 timer T_wait := 2.0;
5086 T_wait.start;
Harald Welte9bbbfb52018-04-05 09:33:19 +02005087 alt {
5088 [] PCU.receive(t_SD_PCUIF(pcu_conn_id, tr_PCUIF_INFO_IND(bts_nr, ?))) -> value sd {
5089 if (substr(sd.data.u.info_ind.trx[trx_nr].pdch_mask, g_chan_nr.tn, 1) != '1'B) {
Pau Espin Pedrol446e07b2019-02-18 21:18:36 +01005090 log("PCUIF_INFO_IND PDCH_MASK not yet '1' after PDCH ACT on TS", g_chan_nr.tn,
5091 " mask:", sd.data.u.info_ind.trx[trx_nr].pdch_mask);
5092 repeat;
Harald Welte9bbbfb52018-04-05 09:33:19 +02005093 }
5094 }
5095 [] PCU.receive { repeat; }
Pau Espin Pedrol446e07b2019-02-18 21:18:36 +01005096 [] T_wait.timeout {
5097 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
5098 log2str("Timeout waiting for PCUIF_INFO_IND PDCH_MASK to be '1' on TS", g_chan_nr.tn));
5099 }
Harald Welte9bbbfb52018-04-05 09:33:19 +02005100 }
5101 /* try to activate this PDCH from the PCU point of view */
5102 PCU.send(t_SD_PCUIF(pcu_conn_id, ts_PCUIF_ACT_REQ(bts_nr, trx_nr, g_chan_nr.tn)));
5103 /* FIXME: is there a response? */
5104
5105 RSL.receive(tr_RSL_IPA_PDCH_ACT_ACK(g_chan_nr, ?));
5106}
5107
5108private function f_dyn_ipa_pdch_deact(integer pcu_conn_id, integer bts_nr, integer trx_nr)
5109runs on ConnHdlr {
5110 var PCUIF_send_data sd;
5111 /* Send RSL CHAN REL (deactivate) */
5112 RSL.send(ts_RSL_IPA_PDCH_DEACT(g_chan_nr));
5113 PCU.clear;
5114 /* expect BTS to ask PCU to deactivate the channel */
Pau Espin Pedrol446e07b2019-02-18 21:18:36 +01005115 timer T_wait := 2.0;
5116 T_wait.start;
Harald Welte9bbbfb52018-04-05 09:33:19 +02005117 alt {
5118 [] PCU.receive(t_SD_PCUIF(pcu_conn_id, tr_PCUIF_INFO_IND(bts_nr, ?))) -> value sd {
5119 if (substr(sd.data.u.info_ind.trx[trx_nr].pdch_mask, g_chan_nr.tn, 1) != '0'B) {
Pau Espin Pedrol446e07b2019-02-18 21:18:36 +01005120 log("PCUIF_INFO_IND PDCH_MASK not yet '0' after PDCH DEACT on TS", g_chan_nr.tn,
5121 " mask:", sd.data.u.info_ind.trx[trx_nr].pdch_mask);
5122 repeat;
Harald Welte9bbbfb52018-04-05 09:33:19 +02005123 }
5124 }
5125 [] PCU.receive { repeat; }
Pau Espin Pedrol446e07b2019-02-18 21:18:36 +01005126 [] T_wait.timeout {
5127 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
5128 log2str("Timeout waiting for PCUIF_INFO_IND PDCH_MASK to be '0' on TS", g_chan_nr.tn));
5129 }
Harald Welte9bbbfb52018-04-05 09:33:19 +02005130 }
5131 /* Emulate PCU asking BTS to deactivate PDCH */
5132 PCU.send(t_SD_PCUIF(pcu_conn_id, ts_PCUIF_DEACT_REQ(bts_nr, trx_nr, g_chan_nr.tn)));
5133 alt {
5134 [] RSL.receive(tr_RSL_IPA_PDCH_DEACT_ACK(g_chan_nr)) {
5135 setverdict(pass);
5136 }
5137 [] RSL.receive { repeat; }
5138 }
5139}
5140
5141/* Activate and de-activate an IPA-style dynamic TCH/F + PDCH */
5142function f_TC_dyn_ipa_pdch_act_deact(charstring id) runs on ConnHdlr {
5143 var PCUIF_Message first_info;
5144 var integer ts_nr := g_chan_nr.tn;
5145 var integer trx_nr := 0;
5146 var integer bts_nr := 0;
5147 var integer pcu_conn_id := -1;
5148
5149 f_init_pcu(PCU, id, pcu_conn_id, first_info);
5150
5151 f_dyn_ipa_pdch_act(pcu_conn_id, bts_nr, trx_nr);
5152 f_sleep(3.0);
5153 f_dyn_ipa_pdch_deact(pcu_conn_id, bts_nr, trx_nr);
5154
5155 setverdict(pass);
5156
5157}
5158testcase TC_dyn_ipa_pdch_act_deact() runs on test_CT {
5159 var ConnHdlrPars pars;
5160 var ConnHdlr vc_conn;
5161 f_init();
5162
5163 pars := valueof(t_Pars(t_RslChanNr_Bm(3), ts_RSL_ChanMode_SIGN));
5164 vc_conn := f_start_handler(refers(f_TC_dyn_ipa_pdch_act_deact), pars, true);
5165 vc_conn.done;
5166}
5167
5168/* try to RSL CHAN ACT a TCH/F on an IPA-style PDCH */
5169function f_TC_dyn_ipa_pdch_tchf_act(charstring id) runs on ConnHdlr {
5170 var PCUIF_Message first_info;
5171 var integer ts_nr := g_chan_nr.tn;
5172 var integer trx_nr := 0;
5173 var integer bts_nr := 0;
5174 var integer pcu_conn_id := -1;
5175
5176 f_init_pcu(PCU, id, pcu_conn_id, first_info);
5177
5178 f_rsl_transceive(ts_RSL_CHAN_ACT(g_chan_nr, g_pars.chan_mode), tr_RSL_CHAN_ACT_ACK(g_chan_nr),
5179 "RSL CHAN ACT");
5180 f_rsl_transceive(ts_RSL_RF_CHAN_REL(g_chan_nr), tr_RSL_RF_CHAN_REL_ACK(g_chan_nr),
5181 "RF CHAN REL", true);
5182 setverdict(pass);
5183}
5184testcase TC_dyn_ipa_pdch_tchf_act() runs on test_CT {
5185 var ConnHdlrPars pars;
5186 var ConnHdlr vc_conn;
Harald Welte10474062019-05-30 16:48:17 +02005187 f_init();
Harald Welte9bbbfb52018-04-05 09:33:19 +02005188
5189 pars := valueof(t_Pars(t_RslChanNr_Bm(3), ts_RSL_ChanMode_SIGN));
5190 vc_conn := f_start_handler(refers(f_TC_dyn_ipa_pdch_tchf_act), pars, true);
5191 vc_conn.done;
5192}
5193
5194/* Activate IPA style dyn PDCH as TCH/F and then illegally try to activate it as PDCH, too */
5195function f_TC_dyn_ipa_pdch_tchf_act_pdch_act_nack(charstring id) runs on ConnHdlr {
5196 var PCUIF_Message first_info;
5197 var integer ts_nr := g_chan_nr.tn;
5198 var integer trx_nr := 0;
5199 var integer bts_nr := 0;
5200 var integer pcu_conn_id := -1;
5201
5202 f_init_pcu(PCU, id, pcu_conn_id, first_info);
5203
5204 f_rsl_transceive(ts_RSL_CHAN_ACT(g_chan_nr, g_pars.chan_mode), tr_RSL_CHAN_ACT_ACK(g_chan_nr),
5205 "RSL CHAN ACT");
5206
5207 RSL.send(ts_RSL_IPA_PDCH_ACT(g_chan_nr));
5208 alt {
5209 [] RSL.receive(tr_RSL_IPA_PDCH_ACT_NACK(g_chan_nr, ?));
5210 [] RSL.receive(tr_RSL_IPA_PDCH_ACT_ACK(g_chan_nr, ?)) {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02005211 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Unexpected PDCH ACT ACK");
Harald Welte9bbbfb52018-04-05 09:33:19 +02005212 }
5213 [] RSL.receive { repeat; }
5214 }
5215
5216 f_rsl_transceive(ts_RSL_RF_CHAN_REL(g_chan_nr), tr_RSL_RF_CHAN_REL_ACK(g_chan_nr),
5217 "RF CHAN REL", true);
5218 setverdict(pass);
5219}
5220testcase TC_dyn_ipa_pdch_tchf_act_pdch_act_nack() runs on test_CT {
5221 var ConnHdlrPars pars;
5222 var ConnHdlr vc_conn;
Harald Welte10474062019-05-30 16:48:17 +02005223 f_init();
Harald Welte9bbbfb52018-04-05 09:33:19 +02005224
5225 pars := valueof(t_Pars(t_RslChanNr_Bm(3), ts_RSL_ChanMode_SIGN));
5226 vc_conn := f_start_handler(refers(f_TC_dyn_ipa_pdch_tchf_act_pdch_act_nack), pars, true);
5227 vc_conn.done;
5228}
5229
5230/* try to RSL CHAN ACT a TCH/F on an IPA-style PDCH that's already in PDCH mode; expect NACK */
5231function f_TC_dyn_ipa_pdch_act_tchf_act_nack(charstring id) runs on ConnHdlr {
5232 var PCUIF_Message first_info;
5233 var integer ts_nr := g_chan_nr.tn;
5234 var integer trx_nr := 0;
5235 var integer bts_nr := 0;
5236 var integer pcu_conn_id := -1;
5237
5238 /* register for the TCH/F channel number */
5239 f_rslem_register(0, g_chan_nr);
5240
5241 f_init_pcu(PCU, id, pcu_conn_id, first_info);
5242
5243 f_dyn_ipa_pdch_act(pcu_conn_id, bts_nr, trx_nr);
5244
5245 f_rsl_transceive(ts_RSL_CHAN_ACT(g_chan_nr, g_pars.chan_mode), tr_RSL_CHAN_ACT_NACK(g_chan_nr),
5246 "RSL CHAN ACT");
5247
5248 f_dyn_ipa_pdch_deact(pcu_conn_id, bts_nr, trx_nr);
5249
5250 setverdict(pass);
5251}
5252testcase TC_dyn_ipa_pdch_act_tchf_act_nack() runs on test_CT {
5253 var ConnHdlrPars pars;
5254 var ConnHdlr vc_conn;
Harald Welte10474062019-05-30 16:48:17 +02005255 f_init();
Harald Welte9bbbfb52018-04-05 09:33:19 +02005256
5257 pars := valueof(t_Pars(t_RslChanNr_Bm(3), ts_RSL_ChanMode_SIGN));
5258 vc_conn := f_start_handler(refers(f_TC_dyn_ipa_pdch_act_tchf_act_nack), pars, true);
5259 vc_conn.done;
5260}
5261
5262
Harald Welte0472ab42018-03-12 15:02:26 +01005263/***********************************************************************
5264 * LAPDm / RLL related
5265 ***********************************************************************/
5266
5267private function f_tx_lapdm(template (value) LapdmFrame l,
5268 template (value) RslLinkId link_id) runs on ConnHdlr {
5269 var octetstring l2 := enc_LapdmFrame(valueof(l));
Vadim Yanitskiy0a8d6da2019-05-28 22:18:28 +07005270 var template (value) SacchL1Header l1h;
5271
5272 /* TODO: we can use an extension of TTCN-3 for padding, i.e. PADDING('2B'O) */
Harald Welte0472ab42018-03-12 15:02:26 +01005273 if (valueof(link_id.c) == SACCH) {
Vadim Yanitskiy0a8d6da2019-05-28 22:18:28 +07005274 /* Compose dummy L1 header */
5275 l1h := ts_SacchL1Header(g_pars.l1_pars.ms_power_level, false, g_pars.l1_pars.ms_actual_ta);
5276 L1CTL.send(ts_L1CTL_DATA_REQ_SACCH(g_chan_nr, link_id, l1h, f_pad_oct(l2, 21, '2B'O)));
Pau Espin Pedrola0fb42a2018-10-10 15:56:39 +02005277 } else {
5278 /* If required, pad L2 frame with constant 0x2b filling */
Vadim Yanitskiy0a8d6da2019-05-28 22:18:28 +07005279 L1CTL.send(ts_L1CTL_DATA_REQ(g_chan_nr, link_id, f_pad_oct(l2, 23, '2B'O)));
Harald Welte0472ab42018-03-12 15:02:26 +01005280 }
Harald Welte0472ab42018-03-12 15:02:26 +01005281}
5282
5283type record RllTestCase {
5284 uint3_t sapi,
5285 RslLinkId link_id,
5286 octetstring l3,
5287 boolean exp
5288}
5289type record of RllTestCase RllTestCases;
5290template RllTestCase t_EITC(uint3_t sapi, RslLinkId id, octetstring l3, boolean exp) := {
5291 sapi := sapi,
5292 link_id := id,
5293 l3 := l3,
5294 exp := exp
5295}
5296
5297/* execute the same callback function with a set of different parameters (tcs) on a
5298 * variety of logical channels */
5299private function f_rll_testmatrix(RllTestCases tcs, void_fn fn) runs on test_CT {
5300 var ConnHdlrPars pars;
5301 var ConnHdlr vc_conn;
Harald Welte10474062019-05-30 16:48:17 +02005302 f_init();
Harald Welte0472ab42018-03-12 15:02:26 +01005303
5304 /* test on each of the channels we have */
5305 for (var integer i := 0; i < sizeof(g_AllChanTypes); i := i+1) {
5306 pars := valueof(t_Pars(g_AllChanTypes[i], ts_RSL_ChanMode_SIGN));
5307
5308 /* test each of the test cases on the current channel */
5309 for (var integer j := 0; j < sizeof(tcs); j := j+1) {
5310 pars.spec.rll := tcs[j];
5311 log(testcasename(), ": XXX Starting ", tcs[j] , " on ", g_AllChanTypes[i]);
5312 vc_conn := f_start_handler(fn, pars);
5313 vc_conn.done;
5314 }
5315 }
5316
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02005317 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
Harald Welte0472ab42018-03-12 15:02:26 +01005318}
5319
5320/* test if SABM on Um triggers EST IND (TS 48.058 3.1) */
5321private function f_TC_rll_est_ind(charstring id) runs on ConnHdlr {
5322 var RllTestCase tc := g_pars.spec.rll;
5323 timer T := 3.0;
5324
5325 f_l1_tune(L1CTL);
5326 RSL.clear;
5327
5328 /* activate the logical channel */
5329 f_est_dchan();
5330 L1CTL.clear;
5331
5332 f_tx_lapdm(ts_LAPDm_SABM(tc.sapi, cr_MO_CMD, true, tc.l3), tc.link_id);
5333 T.start;
5334 alt {
5335 [tc.l3 != ''O] RSL.receive(tr_RSL_EST_IND(g_chan_nr, tc.link_id, tc.l3)) {
5336 if (tc.exp) {
5337 setverdict(pass);
5338 } else {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02005339 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("Unexpected EST IND with L3 in ", tc));
Harald Welte0472ab42018-03-12 15:02:26 +01005340 }
5341 }
5342 [tc.l3 == ''O] RSL.receive(tr_RSL_EST_IND_NOL3(g_chan_nr, tc.link_id)) {
5343 if (tc.exp) {
5344 setverdict(pass);
5345 } else {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02005346 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("Unexpected EST IND without L3 in ", tc));
Harald Welte0472ab42018-03-12 15:02:26 +01005347 }
5348 }
Vadim Yanitskiy35677872018-10-04 17:30:21 +07005349 /* We also expect to receive the measurements */
5350 [] as_meas_res(verify_meas := false);
Harald Welte0472ab42018-03-12 15:02:26 +01005351 [tc.exp] T.timeout {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02005352 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout waiting for EST IND");
Harald Welte0472ab42018-03-12 15:02:26 +01005353 }
5354 [not tc.exp] T.timeout {
5355 setverdict(pass);
5356 }
5357 }
5358
5359 f_rsl_chan_deact();
5360 f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
5361 f_rslem_unregister(0, g_chan_nr);
5362}
5363testcase TC_rll_est_ind() runs on test_CT {
5364 var RllTestCases tcs := {
Harald Welte7aacbbf2018-05-09 16:56:41 +02005365 /* SAPI0 establishment (contention resolution) */
Harald Welte0472ab42018-03-12 15:02:26 +01005366 valueof(t_EITC(0, valueof(ts_RslLinkID_DCCH(0)), '01020304'O, true)),
Harald Welte7aacbbf2018-05-09 16:56:41 +02005367 /* normal SAPI0 establishment */
5368 valueof(t_EITC(0, valueof(ts_RslLinkID_DCCH(0)), ''O, true)),
Harald Welte0472ab42018-03-12 15:02:26 +01005369 /* SAPI 3 doesn't support contention resolution */
5370 valueof(t_EITC(3, valueof(ts_RslLinkID_DCCH(3)), '01020304'O, false)),
5371 valueof(t_EITC(3, valueof(ts_RslLinkID_SACCH(3)), '01020304'O, false)),
5372 /* normal SAPI3 establishment on main DCCH */
5373 valueof(t_EITC(3, valueof(ts_RslLinkID_DCCH(3)), ''O, true)),
5374 /* normal SAPI3 establishment on SACCH */
5375 valueof(t_EITC(3, valueof(ts_RslLinkID_SACCH(3)), ''O, true))
5376 };
5377 f_rll_testmatrix(tcs, refers(f_TC_rll_est_ind));
5378}
5379
5380/* test if RLL EST REQ trigeres SABM on Um; UA on Um triggers EST CONF (TS 48.058 3.2) */
5381private function f_TC_rll_est_req(charstring id) runs on ConnHdlr {
5382 var RllTestCase tc := g_pars.spec.rll;
5383 var L1ctlDlMessage dl;
5384 timer T := 3.0;
5385
5386 f_l1_tune(L1CTL);
5387 RSL.clear;
5388
5389 /* activate the logical channel */
5390 f_est_dchan();
5391 L1CTL.clear;
5392
5393 /* Send a RSL EST REQ for SAPI3 on main DCCH */
5394 RSL.send(ts_RSL_EST_REQ(g_chan_nr, tc.link_id));
5395 T.start;
5396 alt {
5397 [] L1CTL.receive(tr_L1CTL_DATA_IND(g_chan_nr, ?)) -> value dl {
5398 var LapdmFrame lapdm;
5399 var octetstring l2 := dl.payload.data_ind.payload;
5400 if (dl.dl_info.link_id.c == SACCH) {
5401 /* remove L1 header */
5402 l2 := substr(l2, 2, lengthof(l2)-2);
5403 }
5404 lapdm.ab := dec_LapdmFrameAB(l2);
5405 if (match(lapdm, tr_LAPDm_SABM(tc.sapi, cr_MT_CMD, true, ''O))) {
5406 setverdict(pass);
5407 } else {
5408 repeat;
5409 }
5410 }
5411 [] L1CTL.receive { repeat; }
5412 [] T.timeout {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02005413 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout waiting for SABM");
Harald Welte0472ab42018-03-12 15:02:26 +01005414 }
5415 }
5416
5417 f_rsl_chan_deact();
5418 f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
5419 f_rslem_unregister(0, g_chan_nr);
5420}
5421testcase TC_rll_est_req_DCCH_3() runs on test_CT {
5422 var RllTestCases tcs := {
5423 /* normal SAPI3 establishment on main DCCH */
5424 valueof(t_EITC(3, valueof(ts_RslLinkID_DCCH(3)), ''O, true))//,
5425 };
5426 f_rll_testmatrix(tcs, refers(f_TC_rll_est_req));
5427}
5428testcase TC_rll_est_req_ACCH_3() runs on test_CT {
5429 var RllTestCases tcs := {
5430 /* normal SAPI3 establishment on SACCH */
5431 valueof(t_EITC(3, valueof(ts_RslLinkID_SACCH(3)), ''O, true))
5432 }
5433 f_rll_testmatrix(tcs, refers(f_TC_rll_est_req));
5434}
5435
5436/* altstep to receive a LAPDm frame matching the given template */
5437private altstep as_l1_exp_lapdm(template LapdmFrame exp) runs on ConnHdlr {
5438 var L1ctlDlMessage dl;
5439 [] L1CTL.receive(tr_L1CTL_DATA_IND(g_chan_nr, ?)) -> value dl {
5440 var LapdmFrame lapdm;
5441 var octetstring l2 := dl.payload.data_ind.payload;
5442 if (dl.dl_info.link_id.c == SACCH) {
5443 /* remove L1 header */
5444 l2 := substr(l2, 2, lengthof(l2)-2);
5445 }
5446 if (ischosen(exp.ab)) {
5447 lapdm.ab := dec_LapdmFrameAB(l2);
5448 } else if (ischosen(exp.b4)) {
5449 lapdm.b4 := dec_LapdmFrameB4(l2);
5450 } else if (ischosen(exp.bbis)) {
5451 lapdm.bbis := dec_LapdmFrameBbis(l2);
5452 }
5453 log("Rx LAPDm ", lapdm);
5454 if (match(lapdm, exp)) {
5455 setverdict(pass);
5456 } else {
5457 repeat;
5458 }
5459 }
5460 [] L1CTL.receive { repeat; }
5461}
5462private function f_l1_exp_lapdm(template LapdmFrame exp, float t := 3.0) runs on ConnHdlr {
5463 timer T := t;
5464 T.start;
5465 alt {
5466 [] T.timeout {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02005467 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("Timeout waiting for LAPDm ", exp));
Harald Welte0472ab42018-03-12 15:02:26 +01005468 }
5469 [] as_l1_exp_lapdm(exp);
5470 }
5471}
5472
5473/* establish one Radio Link Layer via SABM -> UA. Use l3 for contention resolution */
5474private function f_est_rll_mo(uint3_t sapi, RslLinkId link_id, octetstring l3) runs on ConnHdlr {
5475 /* send SABM from MS -> BTS */
5476 f_tx_lapdm(ts_LAPDm_SABM(sapi, cr_MO_CMD, true, l3), link_id);
5477 /* expect RLL EST IND on Abis */
5478 alt {
5479 [l3 != ''O] RSL.receive(tr_RSL_EST_IND(g_chan_nr, link_id, l3));
5480 [l3 == ''O] RSL.receive(tr_RSL_EST_IND_NOL3(g_chan_nr, link_id));
5481 [] RSL.receive(tr_RSL_ERROR_IND(g_chan_nr, link_id, ?)) {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02005482 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Failing due to RSL_ERROR_IND");
Harald Welte0472ab42018-03-12 15:02:26 +01005483 }
5484 [] RSL.receive { repeat; }
5485 }
5486 /* expect UA from BTS -> MS */
5487 f_l1_exp_lapdm(tr_LAPDm_UA(sapi, cr_MT_RSP, true, l3));
5488}
5489
5490/* test if DISC on Um triggers RLL REL IND (TS 48.058 3.3) */
5491private function f_TC_rll_rel_ind(charstring id) runs on ConnHdlr {
5492 var RllTestCase tc := g_pars.spec.rll;
5493
5494 f_l1_tune(L1CTL);
5495 RSL.clear;
5496
5497 /* activate the logical channel */
5498 f_est_dchan();
5499 L1CTL.clear;
5500
5501 /* first establish the link-layer */
5502 f_est_rll_mo(tc.sapi, tc.link_id, tc.l3);
5503
5504 /* then send the DISC */
5505 f_tx_lapdm(ts_LAPDm_DISC(tc.sapi, cr_MO_CMD, true), tc.link_id);
5506 /* ... and expect the REL IND on the RSL side */
5507 alt {
5508 [] RSL.receive(tr_RSL_REL_IND(g_chan_nr, tc.link_id)) {
5509 setverdict(pass);
5510 }
Vadim Yanitskiy35677872018-10-04 17:30:21 +07005511 /* We also expect to receive the measurements */
5512 [] as_meas_res(verify_meas := false);
Harald Welte0472ab42018-03-12 15:02:26 +01005513 }
5514
5515 /* release the channel */
5516 f_rsl_chan_deact();
5517 f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
5518 f_rslem_unregister(0, g_chan_nr);
5519}
5520testcase TC_rll_rel_ind_DCCH_0() runs on test_CT {
5521 var RllTestCases tcs := {
5522 valueof(t_EITC(0, valueof(ts_RslLinkID_DCCH(0)), '01020304'O, true))
5523 };
5524 f_rll_testmatrix(tcs, refers(f_TC_rll_rel_ind));
5525}
5526
5527testcase TC_rll_rel_ind_ACCH_0() runs on test_CT {
5528 var RllTestCases tcs := {
5529 valueof(t_EITC(0, valueof(ts_RslLinkID_SACCH(0)), ''O, true))
5530 };
5531 f_rll_testmatrix(tcs, refers(f_TC_rll_rel_ind));
5532}
5533testcase TC_rll_rel_ind_DCCH_3() runs on test_CT {
5534 var RllTestCases tcs := {
5535 valueof(t_EITC(3, valueof(ts_RslLinkID_DCCH(3)), ''O, true))
5536 };
5537 f_rll_testmatrix(tcs, refers(f_TC_rll_rel_ind));
5538}
5539testcase TC_rll_rel_ind_ACCH_3() runs on test_CT {
5540 var RllTestCases tcs := {
5541 valueof(t_EITC(3, valueof(ts_RslLinkID_SACCH(3)), ''O, true))
5542 };
5543 f_rll_testmatrix(tcs, refers(f_TC_rll_rel_ind));
5544}
5545
5546/* test if RLL REL REQ triggers DISC on Um; UA/DM triggers RLL REL CONF (TS 48.058 3.4) */
5547private function f_TC_rll_rel_req(charstring id) runs on ConnHdlr {
5548 var RllTestCase tc := g_pars.spec.rll;
5549 f_l1_tune(L1CTL);
5550 RSL.clear;
5551
5552 /* activate the logical channel */
5553 f_est_dchan();
5554 L1CTL.clear;
5555
5556 /* first establish the link-layer */
5557 f_est_rll_mo(tc.sapi, tc.link_id, tc.l3);
5558
5559 /* then send the REL REQ via RSL */
5560 RSL.send(ts_RSL_REL_REQ(g_chan_nr, tc.link_id, RSL_REL_MODE_NORMAL));
5561 /* ... and expect the DISC on the Um side */
5562 alt {
Harald Weltebc6199f2018-05-10 19:38:18 +02005563 [] as_l1_exp_lapdm(tr_LAPDm_DISC(tc.sapi, cr_MT_CMD, true)) {
Harald Welte0472ab42018-03-12 15:02:26 +01005564 /* FIXME: send a UA in resposne to the DISC */
5565 }
5566 }
5567
5568 /* release the channel */
5569 f_rsl_chan_deact();
5570 f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
5571 f_rslem_unregister(0, g_chan_nr);
5572}
5573testcase TC_rll_rel_req() runs on test_CT {
5574 var RllTestCases tcs := {
5575 valueof(t_EITC(0, valueof(ts_RslLinkID_DCCH(0)), '01020304'O, true)),
5576 valueof(t_EITC(0, valueof(ts_RslLinkID_SACCH(0)), ''O, true)),
5577 valueof(t_EITC(3, valueof(ts_RslLinkID_DCCH(3)), ''O, true)),
5578 valueof(t_EITC(3, valueof(ts_RslLinkID_SACCH(3)), ''O, true))
5579 };
5580 f_rll_testmatrix(tcs, refers(f_TC_rll_rel_req));
5581}
5582
5583/* test if RLL DATA REQ triggers I-frames on Um (TS 48.058 3.5) */
5584testcase TC_rll_data_req() runs on test_CT {
5585}
5586
5587/* test if I-frames on Um trigger RLL DATA IND (TS 48.058 3.6) */
5588testcase TC_rll_data_ind() runs on test_CT {
5589}
5590
5591/* test if RLL UNIT DATA REQ triggers UI-frame on Um (TS 48.058 3.7) */
5592private function f_TC_rll_ud_req(charstring id) runs on ConnHdlr {
5593 var RllTestCase tc := g_pars.spec.rll;
5594
5595 f_l1_tune(L1CTL);
5596 RSL.clear;
5597
5598 f_est_dchan();
5599 L1CTL.clear;
5600
5601 /* Send UNITDATA REQ on RSL side */
5602 RSL.send(ts_RSL_UNITDATA_REQ(g_chan_nr, tc.link_id, tc.l3));
5603 /* Expect it to arrive on the other side */
5604 if (tc.link_id.c == SACCH) {
Harald Weltee613f962018-04-18 22:38:16 +02005605 f_l1_exp_lapdm(tr_LAPDm_B4_UI(tc.sapi, cr_MT_CMD, tc.l3));
Harald Welte0472ab42018-03-12 15:02:26 +01005606 } else {
Harald Weltee613f962018-04-18 22:38:16 +02005607 f_l1_exp_lapdm(tr_LAPDm_UI(tc.sapi, cr_MT_CMD, tc.l3));
Harald Welte0472ab42018-03-12 15:02:26 +01005608 }
5609
5610 /* release the channel */
5611 f_rsl_chan_deact();
5612 f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
5613 f_rslem_unregister(0, g_chan_nr);
5614}
5615testcase TC_rll_unit_data_req_DCCH() runs on test_CT {
5616 var octetstring l3 := f_rnd_octstring(15);
5617 var RllTestCases tcs := {
5618 valueof(t_EITC(0, valueof(ts_RslLinkID_DCCH(0)), l3, true)),
5619 valueof(t_EITC(3, valueof(ts_RslLinkID_DCCH(3)), l3, true))
5620 };
5621 f_rll_testmatrix(tcs, refers(f_TC_rll_ud_req));
5622}
5623testcase TC_rll_unit_data_req_ACCH() runs on test_CT {
5624 var octetstring l3 := f_rnd_octstring(19);
5625 var RllTestCases tcs := {
5626 valueof(t_EITC(0, valueof(ts_RslLinkID_SACCH(0)), l3, true)),
5627 valueof(t_EITC(3, valueof(ts_RslLinkID_SACCH(3)), l3, true))
5628 };
5629 f_rll_testmatrix(tcs, refers(f_TC_rll_ud_req));
5630}
5631
5632/* test if UI-frames on Um trigger RLL UNIT DATA IND (TS 48.058 3.8) */
5633private function f_TC_rll_ud_ind(charstring id) runs on ConnHdlr {
5634 var RllTestCase tc := g_pars.spec.rll;
5635
5636 f_l1_tune(L1CTL);
5637 RSL.clear;
5638
5639 f_est_dchan();
5640 L1CTL.clear;
5641
5642 /* Send LAPDm UI frame. There is no B4 format in uplink! */
Harald Weltee613f962018-04-18 22:38:16 +02005643 f_tx_lapdm(ts_LAPDm_UI(tc.sapi, cr_MO_CMD, tc.l3), tc.link_id);
Harald Welte0472ab42018-03-12 15:02:26 +01005644 /* Expdct RLL UNITDATA IND on RSL side */
5645 alt {
5646 [] RSL.receive(tr_RSL_UNITDATA_IND(g_chan_nr, tc.link_id, tc.l3)) {
5647 setverdict(pass);
5648 }
5649 [] RSL.receive { repeat; }
5650 }
5651
5652 /* release the channel */
5653 f_rsl_chan_deact();
5654 f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
5655 f_rslem_unregister(0, g_chan_nr);
5656}
5657testcase TC_rll_unit_data_ind_DCCH() runs on test_CT {
Stefan Sperlingc4181912018-07-25 17:03:08 +02005658 var octetstring l3 := f_rnd_octstring(20);
Harald Welte0472ab42018-03-12 15:02:26 +01005659 var RllTestCases tcs := {
5660 valueof(t_EITC(0, valueof(ts_RslLinkID_DCCH(0)), l3, true)),
5661 valueof(t_EITC(3, valueof(ts_RslLinkID_DCCH(3)), l3, true))
5662 };
5663 f_rll_testmatrix(tcs, refers(f_TC_rll_ud_ind));
5664}
5665testcase TC_rll_unit_data_ind_ACCH() runs on test_CT {
5666 var octetstring l3 := f_rnd_octstring(18);
5667 var RllTestCases tcs := {
5668 valueof(t_EITC(0, valueof(ts_RslLinkID_SACCH(0)), l3, true)),
5669 valueof(t_EITC(3, valueof(ts_RslLinkID_SACCH(3)), l3, true))
5670 };
5671 f_rll_testmatrix(tcs, refers(f_TC_rll_ud_ind));
5672}
5673
Harald Weltee613f962018-04-18 22:38:16 +02005674/***********************************************************************
5675 * Encryption Related
5676 ***********************************************************************/
5677
5678/* send UNITDATA_REQ from BTS to MS and expect it to arrive */
5679function f_unitdata_mt(RslLinkId link_id, octetstring l3) runs on ConnHdlr {
5680 RSL.send(ts_RSL_UNITDATA_REQ(g_chan_nr, link_id, l3));
5681 if (link_id.c == SACCH) {
5682 f_l1_exp_lapdm(tr_LAPDm_B4_UI(link_id.sapi, cr_MT_CMD, l3));
5683 } else {
5684 f_l1_exp_lapdm(tr_LAPDm_UI(link_id.sapi, cr_MT_CMD, l3));
5685 }
5686}
5687
Vadim Yanitskiyad131c82018-10-04 06:18:59 +07005688/* Expect (or not expect) other kinds of messages */
5689private altstep as_rsl_any_ind(boolean exp_any) runs on ConnHdlr {
5690 [exp_any] RSL.receive { repeat; }
5691 [not exp_any] RSL.receive {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02005692 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Unexpected RSL message!");
Vadim Yanitskiyad131c82018-10-04 06:18:59 +07005693 }
5694}
5695
Harald Weltee613f962018-04-18 22:38:16 +02005696/* Send UI frame from MS and expect it to arrive as RLL UNITDATA IND on Abis */
Vadim Yanitskiy8d8f91c2018-10-04 06:19:45 +07005697private function f_unitdata_mo(
Vadim Yanitskiy98e03152018-10-03 18:06:06 +07005698 RslLinkId link_id,
5699 octetstring l3,
5700 boolean exp_sacch := true, /* Should tolerate SACCH messages? */
Vadim Yanitskiyb9920502018-10-03 18:29:51 +07005701 boolean exp_any := false /* Should tolerate any other RSL messages? */
Vadim Yanitskiy98e03152018-10-03 18:06:06 +07005702) runs on ConnHdlr {
Harald Weltee613f962018-04-18 22:38:16 +02005703 timer T := 3.0;
5704 f_tx_lapdm(ts_LAPDm_UI(link_id.sapi, cr_MO_CMD, l3), link_id);
5705 T.start;
5706 /* Expect RLL UNITDATA IND on RSL side */
5707 alt {
5708 [] RSL.receive(tr_RSL_UNITDATA_IND(g_chan_nr, link_id, l3)) {
5709 setverdict(pass);
5710 }
Vadim Yanitskiye0b91a72018-10-04 15:44:40 +07005711 [exp_sacch] as_meas_res(verify_meas := false);
Vadim Yanitskiyad131c82018-10-04 06:18:59 +07005712 [] as_rsl_any_ind(exp_any);
Harald Weltee613f962018-04-18 22:38:16 +02005713 [] T.timeout {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02005714 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout waiting for UNIT_DATA_IND");
Harald Weltee613f962018-04-18 22:38:16 +02005715 }
Harald Weltee613f962018-04-18 22:38:16 +02005716 }
5717}
5718
Vadim Yanitskiy4d78a702018-10-03 03:59:34 +07005719/* Send I-frame from MS and expect it to arrive as RLL DATA IND on Abis */
5720private function f_data_mo(
5721 RslLinkId link_id,
5722 boolean p, uint3_t nr, uint3_t ns,
5723 octetstring l3,
5724 boolean exp_sacch := true, /* Should tolerate SACCH messages? */
Vadim Yanitskiyb9920502018-10-03 18:29:51 +07005725 boolean exp_any := false /* Should tolerate any other RSL messages? */
Vadim Yanitskiy4d78a702018-10-03 03:59:34 +07005726) runs on ConnHdlr {
5727 timer T := 3.0;
5728 f_tx_lapdm(ts_LAPDm_I(link_id.sapi, cr_MO_CMD, p, nr, ns, l3), link_id);
5729 T.start;
5730 /* Expect RLL DATA IND on RSL side */
5731 alt {
5732 [] RSL.receive(tr_RSL_DATA_IND(g_chan_nr, link_id, l3)) {
5733 setverdict(pass);
5734 }
Vadim Yanitskiye0b91a72018-10-04 15:44:40 +07005735 [exp_sacch] as_meas_res(verify_meas := false);
Vadim Yanitskiy4d78a702018-10-03 03:59:34 +07005736 [] as_rsl_any_ind(exp_any);
5737 [] T.timeout {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02005738 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout waiting for DATA_IND");
Vadim Yanitskiy4d78a702018-10-03 03:59:34 +07005739 }
5740 }
5741}
5742
Harald Weltee613f962018-04-18 22:38:16 +02005743/* Test channel activation with A5/n right from the beginning (like in assignment + hand-over) */
5744function f_TC_chan_act_encr(charstring id) runs on ConnHdlr {
5745 f_l1_tune(L1CTL);
5746 f_est_dchan(true);
5747
5748 /* now we actually need to transmit some data both ways to check if the encryption works */
5749 var L1ctlDlMessage dl;
5750
Stefan Sperling603d98e2018-07-25 16:47:28 +02005751 var octetstring l3 := f_rnd_octstring(20);
Harald Weltee613f962018-04-18 22:38:16 +02005752 var RslLinkId link_id := valueof(ts_RslLinkID_DCCH(0));
5753
5754 /* send UNITDATA_REQ from BTS to MS and expect it to arrive */
5755 f_unitdata_mt(link_id, l3);
5756
5757 /* Send UI frame from MS and expect it to arrive as RLL UNITDATA IND on Abis */
5758 f_unitdata_mo(link_id, l3);
5759
5760 /* release the channel */
5761 f_rsl_chan_deact();
5762 f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
5763 f_rslem_unregister(0, g_chan_nr);
5764}
5765testcase TC_chan_act_a51() runs on test_CT {
5766 var ConnHdlrPars pars := valueof(t_Pars(t_RslChanNr_Bm(1), ts_RSL_ChanMode_SIGN));
5767 pars.encr := valueof(ts_RSL_IE_EncrInfo(RSL_ALG_ID_A5_1, f_rnd_octstring(8)));
5768 f_testmatrix_each_chan(pars, refers(f_TC_chan_act_encr));
5769}
5770testcase TC_chan_act_a52() runs on test_CT {
5771 var ConnHdlrPars pars := valueof(t_Pars(t_RslChanNr_Bm(1), ts_RSL_ChanMode_SIGN));
5772 pars.encr := valueof(ts_RSL_IE_EncrInfo(RSL_ALG_ID_A5_2, f_rnd_octstring(8)));
5773 f_testmatrix_each_chan(pars, refers(f_TC_chan_act_encr));
5774}
5775testcase TC_chan_act_a53() runs on test_CT {
5776 var ConnHdlrPars pars := valueof(t_Pars(t_RslChanNr_Bm(1), ts_RSL_ChanMode_SIGN));
5777 pars.encr := valueof(ts_RSL_IE_EncrInfo(RSL_ALG_ID_A5_3, f_rnd_octstring(8)));
5778 f_testmatrix_each_chan(pars, refers(f_TC_chan_act_encr));
5779}
5780
Eric Wildf1827a72019-05-28 17:37:35 +02005781/* Test channel activation with A5/n right from the beginning and RSL MODE MODIFY
5782 which should break the en/decryption on purpose by supplying a new key that is unknown to the MS*/
5783function f_TC_rsl_modify_encr(charstring id) runs on ConnHdlr {
5784 f_l1_tune(L1CTL);
5785 f_est_dchan(true);
5786
5787 /* now we actually need to transmit some data both ways to check if the encryption works */
5788 var L1ctlDlMessage dl;
5789
5790 var octetstring l3 := f_rnd_octstring(20);
5791 var RslLinkId link_id := valueof(ts_RslLinkID_DCCH(0));
5792
5793 /* send UNITDATA_REQ from BTS to MS and expect it to arrive */
5794 f_unitdata_mt(link_id, l3);
5795
5796 /* Send UI frame from MS and expect it to arrive as RLL UNITDATA IND on Abis */
5797 f_unitdata_mo(link_id, l3);
5798
5799 var RSL_Message rsl;
5800 rsl := valueof(ts_RSL_MODE_MODIFY_REQ(g_chan_nr, valueof(ts_RSL_ChanMode_SIGN(false))));
5801
5802 /* modify key to break proper encryption */
5803 g_pars.encr.key := f_rnd_octstring(8);
5804 var RSL_IE ei := valueof(t_RSL_IE(RSL_IE_ENCR_INFO, RSL_IE_Body:{encr_info := g_pars.encr}));
5805 rsl.ies := rsl.ies & { ei };
5806 RSL.send(rsl);
5807
5808 timer T0 := 1.0;
5809 T0.start;
5810 /* Expect RSL MODIFY ACK */
5811 alt {
5812 [] RSL.receive(tr_RSL_MODE_MODIFY_ACK(g_chan_nr)) {}
5813 [] RSL.receive(tr_RSL_MODE_MODIFY_NACK(g_chan_nr, ?)) {
5814 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,"MODE MODIFY NACK");
5815 }
5816 [] T0.timeout {
5817 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout waiting for MODE MODIFY (N)ACK");
5818 }
5819 }
5820
5821 var octetstring l3msg := f_rnd_octstring(15);
5822 timer T1 := 3.0;
5823 /* Send UI frame from MS, do not expect it to arrive as RLL UNITDATA IND on Abis
5824 due to broken encryption */
5825 f_tx_lapdm(ts_LAPDm_UI(link_id.sapi, cr_MO_CMD, l3msg), link_id);
5826 T1.start;
5827 alt {
5828 [] RSL.receive(tr_RSL_UNITDATA_IND(g_chan_nr, link_id, l3msg)) {
5829 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "BTS shouldn't be able to decrypt after key change")
5830 }
5831 [] T1.timeout {
5832 setverdict(pass);
5833 }
5834 }
5835
5836 /* release the channel */
5837 f_rsl_chan_deact();
5838 f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
5839 f_rslem_unregister(0, g_chan_nr);
5840}
5841testcase TC_rsl_modify_encr() runs on test_CT {
5842 var ConnHdlrPars pars := valueof(t_Pars(t_RslChanNr_Bm(1), ts_RSL_ChanMode_SIGN));
5843 pars.encr := valueof(ts_RSL_IE_EncrInfo(RSL_ALG_ID_A5_1, f_rnd_octstring(8)));
5844 f_testmatrix_each_chan(pars, refers(f_TC_rsl_modify_encr));
5845}
Harald Weltee613f962018-04-18 22:38:16 +02005846
5847/* Test unencrypted channel activation followed by explicit ENCR CMD later */
5848function f_TC_encr_cmd(charstring id) runs on ConnHdlr {
5849 /* L3 payload doesn't matter, as it is passed transparently */
5850 var BIT3 l3_alg_id := f_alg_id_to_l3(g_pars.encr.alg_id);
5851 var octetstring l3 := enc_PDU_ML3_NW_MS(valueof(ts_RRM_CiphModeCmd(l3_alg_id)));
5852 var RslLinkId link_id := valueof(ts_RslLinkID_DCCH(0));
5853
5854 f_l1_tune(L1CTL);
5855
5856 /* first establish a dedicated channel in the clear */
5857 f_est_dchan(false);
5858
5859 /* Establish ABM */
5860 f_est_rll_mo(link_id.sapi, link_id, '23420815'O);
5861
5862 /* then send the RSL ENCR CMD with an actual RR CIPH MOD CMD inside */
5863 RSL.send(ts_RSL_ENCR_CMD(g_chan_nr, link_id, g_pars.encr.alg_id, g_pars.encr.key, l3));
5864 /* expect the L3 to arrive still unencrypted on the MS side */
5865 f_l1_exp_lapdm(tr_LAPDm_I(link_id.sapi, cr_MT_CMD, ?, ?, ?, l3));
5866
5867 /* configure L1 to apply ciphering */
5868 var uint8_t alg_id := f_alg_id_to_l1ctl(g_pars.encr.alg_id);
5869 f_L1CTL_CRYPTO_REQ(L1CTL, g_pars.chan_nr, alg_id, g_pars.encr.key);
5870
Vadim Yanitskiy4d78a702018-10-03 03:59:34 +07005871 /* send first ciphered I-frame in response and expect it on RSL */
5872 f_data_mo(link_id, true, 1, 0, '0a0b0c0d'O, exp_sacch := true);
Harald Weltee613f962018-04-18 22:38:16 +02005873
5874 /* now the BTS code should have detected the first properly encrypted uplink I-frame,
5875 * and hence enable encryption also on the downlink */
5876
5877 /* expect bi-directional communication work in encrypted mode */
5878 f_unitdata_mo(link_id, f_rnd_octstring(15));
5879 f_unitdata_mt(link_id, f_rnd_octstring(15));
5880
5881 /* release the channel */
5882 f_rsl_chan_deact();
5883 f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
5884 f_rslem_unregister(0, g_chan_nr);
5885}
5886testcase TC_encr_cmd_a51() runs on test_CT {
5887 var ConnHdlrPars pars := valueof(t_Pars(t_RslChanNr_Bm(1), ts_RSL_ChanMode_SIGN));
5888 pars.encr := valueof(ts_RSL_IE_EncrInfo(RSL_ALG_ID_A5_1, f_rnd_octstring(8)));
5889 f_testmatrix_each_chan(pars, refers(f_TC_encr_cmd));
5890}
5891testcase TC_encr_cmd_a52() runs on test_CT {
5892 var ConnHdlrPars pars := valueof(t_Pars(t_RslChanNr_Bm(1), ts_RSL_ChanMode_SIGN));
5893 pars.encr := valueof(ts_RSL_IE_EncrInfo(RSL_ALG_ID_A5_2, f_rnd_octstring(8)));
5894 f_testmatrix_each_chan(pars, refers(f_TC_encr_cmd));
5895}
5896testcase TC_encr_cmd_a53() runs on test_CT {
5897 var ConnHdlrPars pars := valueof(t_Pars(t_RslChanNr_Bm(1), ts_RSL_ChanMode_SIGN));
5898 pars.encr := valueof(ts_RSL_IE_EncrInfo(RSL_ALG_ID_A5_3, f_rnd_octstring(8)));
5899 f_testmatrix_each_chan(pars, refers(f_TC_encr_cmd));
5900}
5901
5902private function f_assert_lapdm(octetstring enc, template LapdmFrame exp_match, charstring name := "") {
5903 var LapdmFrame lf;
5904 var octetstring reenc;
5905
5906 /* decode the LAPDm frame */
5907 if (ischosen(exp_match.ab)) {
5908 lf.ab := dec_LapdmFrameAB(enc);
5909 } else {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02005910 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "unsupported frame type");
Harald Weltee613f962018-04-18 22:38:16 +02005911 }
5912
5913 /* check if decoder result matches expectation */
5914 if (not match(lf, exp_match)) {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02005915 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str(name, ": decoded LAPDm doesn't match"));
Harald Weltee613f962018-04-18 22:38:16 +02005916 } else {
5917 log(name, ": matched");
5918 setverdict(pass);
5919 }
5920
5921 /* test if re-encoded frame equals original input */
5922 reenc := enc_LapdmFrame(lf);
5923 if (enc != reenc) {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02005924 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str(name, ": re-encoded LAPDm frame doesn't match"));
Harald Weltee613f962018-04-18 22:38:16 +02005925 } else {
5926 setverdict(pass);
5927 }
5928}
5929
5930testcase TC_lapdm_selftest() runs on test_CT {
5931 f_assert_lapdm('030301'O, tr_LAPDm_UI(0, true, ''O), "ui_s0_empty");
5932 f_assert_lapdm('0F0301'O, tr_LAPDm_UI(3, true, ''O), "ui_s3_empty");
5933 f_assert_lapdm('013F01'O, tr_LAPDm_SABM(0, false, true, ''O), "sabm_s0_empty");
5934 f_assert_lapdm('013F1123420815'O, tr_LAPDm_SABM(0, false, true, '23420815'O), "sabm_s0_l3");
5935 f_assert_lapdm('03E101'O, tr_LAPDm_RR(0, true, false, 7), "rr_s0_7");
5936 f_assert_lapdm('03000d063505'O, tr_LAPDm_I(0, true, false, 0, 0, '063505'O), "I/0/0");
5937 f_assert_lapdm('03e00d063505'O, tr_LAPDm_I(0, true, false, 7, 0, '063505'O), "I/7/0");
5938}
5939
Stefan Sperling4880be42018-08-07 18:12:59 +02005940/***********************************************************************
5941 * DTX Related (see GSM 05.08, section 8.3)
5942 ***********************************************************************/
5943
5944/* XXX These functions must be kept in sync with g_AllChannels defined on test_CT. */
5945function f_g_chan_is_tchf() runs on ConnHdlr return boolean {
5946 return (g_chan_nr == valueof(ts_RslChanNr_Bm(1)) or
5947 g_chan_nr == valueof(ts_RslChanNr_Bm(2)) or
5948 g_chan_nr == valueof(ts_RslChanNr_Bm(3)) or
5949 g_chan_nr == valueof(ts_RslChanNr_Bm(4)));
5950}
5951function f_g_chan_is_tchh() runs on ConnHdlr return boolean {
5952 return (g_chan_nr == valueof(ts_RslChanNr_Lm(5,0)) or
5953 g_chan_nr == valueof(ts_RslChanNr_Lm(5,1)));
5954}
5955function f_g_chan_is_sdcch4() runs on ConnHdlr return boolean {
5956 return (g_chan_nr == valueof(ts_RslChanNr_SDCCH4(0,0)) or
5957 g_chan_nr == valueof(ts_RslChanNr_SDCCH4(0,1)) or
5958 g_chan_nr == valueof(ts_RslChanNr_SDCCH4(0,2)) or
5959 g_chan_nr == valueof(ts_RslChanNr_SDCCH4(0,3)));
5960}
5961function f_g_chan_is_sdcch8() runs on ConnHdlr return boolean {
5962 return (g_chan_nr == valueof(ts_RslChanNr_SDCCH8(6,0)) or
5963 g_chan_nr == valueof(ts_RslChanNr_SDCCH8(6,1)) or
5964 g_chan_nr == valueof(ts_RslChanNr_SDCCH8(6,2)) or
5965 g_chan_nr == valueof(ts_RslChanNr_SDCCH8(6,3)) or
5966 g_chan_nr == valueof(ts_RslChanNr_SDCCH8(6,4)) or
5967 g_chan_nr == valueof(ts_RslChanNr_SDCCH8(6,5)) or
5968 g_chan_nr == valueof(ts_RslChanNr_SDCCH8(6,6)) or
5969 g_chan_nr == valueof(ts_RslChanNr_SDCCH8(6,7)));
5970}
5971
5972function f_test_l2_fill_frames(boolean dtxd) runs on ConnHdlr {
5973 var L1ctlDlMessage dl;
5974 var octetstring l2_fill_frame := '0303012B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B'O;
5975 var octetstring l2_fill_frame_sacch := substr(l2_fill_frame, 0, lengthof(l2_fill_frame) - 2);
5976 var GsmFrameNumber first_fn;
5977 var boolean is_first_frame := true;
Stefan Sperling91d4c9d2018-08-09 20:03:08 +02005978 var integer nfill_frames_sacch := 0;
5979 var integer nfill_frames_nonsacch := 0;
5980 var integer expected_fill_frames := 10000; /* initial value causes test failure if not overridden */
Stefan Sperling4880be42018-08-07 18:12:59 +02005981 /* Frames numbers (mod 104) for which a fill frame is expected on TCHF if DTX is enabled. */
5982 var Integers required_tdma_frames_dtx_tchf := { 52, 53, 54, 55, 56, 57, 58, 59 };
Stefan Sperling91d4c9d2018-08-09 20:03:08 +02005983 const integer frame_dtx_tchf_mod := 104;
5984 /* Frame numbers (mod 104) for which a fill frame is expected at the L1SAP level,
5985 * which operates in terms of blocks rather than frames. */
5986 var Integers required_tdma_blocks_dtx_tchf := { 52, 56 };
5987 const integer block_dtx_tchf_mod := 26;
Stefan Sperling4880be42018-08-07 18:12:59 +02005988 timer T := 5.0;
5989
5990 f_l1_tune(L1CTL);
5991 RSL.clear;
5992 L1CTL.clear;
5993
5994 /* activate TCHF signalling channel */
5995 f_est_dchan(false);
5996
5997 T.start;
5998 alt {
5999 [] L1CTL.receive(tr_L1CTL_DATA_IND(g_chan_nr, ?)) -> value dl {
6000 var GsmFrameNumber fn := dl.dl_info.frame_nr;
6001 var octetstring l2 := dl.payload.data_ind.payload;
6002
6003 if (is_first_frame) {
6004 is_first_frame := false;
6005 first_fn := dl.dl_info.frame_nr;
6006 }
6007
6008 if (dl.dl_info.link_id.c == SACCH) {
6009 l2 := substr(l2, 2, lengthof(l2) - 2); /* remove L1 header */
6010 if (not match(l2_fill_frame_sacch, l2)) {
6011 repeat;
6012 }
6013 } else if (not match(l2_fill_frame, l2)) {
6014 repeat;
6015 }
6016
6017 if (dtxd) {
6018 if (not f_g_chan_is_tchf()) {
6019 T.stop;
6020 f_rsl_chan_deact();
6021 f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02006022 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Received fill frame on non-TCH/F channel; DTX is only allowed on TCH/F!");
Stefan Sperling4880be42018-08-07 18:12:59 +02006023 }
Stefan Sperling91d4c9d2018-08-09 20:03:08 +02006024 if (fn > first_fn + frame_dtx_tchf_mod) {
Stefan Sperling4880be42018-08-07 18:12:59 +02006025 T.stop;
6026 f_rsl_chan_deact();
6027 f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
Stefan Sperling91d4c9d2018-08-09 20:03:08 +02006028
6029 /* With DTX enabled we can expect at least 3 fill frames for every 104 frames.
6030 * 2 SACCH, 1 TCH/F */
6031 expected_fill_frames := 3;
6032
6033 if (nfill_frames_sacch + nfill_frames_nonsacch < expected_fill_frames) {
6034 log("received only ", nfill_frames_sacch, "+", nfill_frames_nonsacch,
6035 " (SACCH+other) out of ", expected_fill_frames, " expected fill frames");
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02006036 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Not enough fill frames received");
Stefan Sperling4880be42018-08-07 18:12:59 +02006037 } else {
6038 setverdict(pass);
6039 }
Stefan Sperling91d4c9d2018-08-09 20:03:08 +02006040 } else {
6041 if (dl.dl_info.link_id.c == SACCH) {
6042 nfill_frames_sacch := nfill_frames_sacch + 1;
Stefan Sperling4880be42018-08-07 18:12:59 +02006043 repeat;
6044 }
Stefan Sperling91d4c9d2018-08-09 20:03:08 +02006045 /* On DTX TCH/F channels, fill frames occur only for specific frame numbers mod 104.
6046 * Furthermore, the L1SAP layer gives us frame numbers for the start of a block so
6047 * we should only see the subset of frames numbers which correspond to a block boundary.
6048 * TCH/F blocks are defined to start at 0,4,8,13,17,21 (modulo 26) */
6049 for (var integer i := 0; i < lengthof(required_tdma_blocks_dtx_tchf); i := i + 1) {
6050 if (fn mod frame_dtx_tchf_mod == required_tdma_blocks_dtx_tchf[i]) {
6051 nfill_frames_nonsacch := nfill_frames_nonsacch + 1;
6052 repeat;
6053 }
6054 }
6055 log("Received DTX TCH fill frame with bad frame number: ", fn,
6056 " (mod ", frame_dtx_tchf_mod, ": ", fn mod frame_dtx_tchf_mod, ")",
6057 " (mod ", block_dtx_tchf_mod, ": ", fn mod block_dtx_tchf_mod, ")");
6058 f_rsl_chan_deact();
6059 f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02006060 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Unexpected L2 fill frame received on Um");
Stefan Sperling4880be42018-08-07 18:12:59 +02006061 }
Stefan Sperling4880be42018-08-07 18:12:59 +02006062 } else {
Stefan Sperling91d4c9d2018-08-09 20:03:08 +02006063 if (dl.dl_info.link_id.c == SACCH) {
6064 nfill_frames_sacch := nfill_frames_sacch + 1;
6065 } else {
6066 nfill_frames_nonsacch := nfill_frames_nonsacch + 1;
6067 }
6068 if (fn > first_fn + frame_dtx_tchf_mod) {
Stefan Sperling4880be42018-08-07 18:12:59 +02006069 T.stop;
6070 if (f_g_chan_is_tchf()) {
6071 /* Without DTX we can expect 25 fill frames for every 104 frames.
6072 * (24 FACCH + 1 SACCH filling) */
6073 expected_fill_frames := 25;
6074 } else if (f_g_chan_is_tchh()) {
6075 /* We can expect 2 fill frames for every 104 frames. */
6076 expected_fill_frames := 2;
6077 } else if (f_g_chan_is_sdcch4() or f_g_chan_is_sdcch8()) {
6078 /* We can expect 5 fill frames for every 104 frames. */
6079 expected_fill_frames := 5;
6080 } else {
6081 f_rsl_chan_deact();
6082 f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02006083 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Unknown channel type");
Stefan Sperling4880be42018-08-07 18:12:59 +02006084 }
6085
6086 f_rsl_chan_deact();
6087 f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
Stefan Sperling91d4c9d2018-08-09 20:03:08 +02006088
6089 if (nfill_frames_sacch + nfill_frames_nonsacch >= expected_fill_frames) {
Stefan Sperling4880be42018-08-07 18:12:59 +02006090 setverdict(pass);
6091 } else {
Stefan Sperling91d4c9d2018-08-09 20:03:08 +02006092 log("received only ", nfill_frames_sacch, "+", nfill_frames_nonsacch,
6093 " (SACCH+other) out of ", expected_fill_frames, " expected fill frames");
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02006094 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Not enough fill frames received");
Stefan Sperling4880be42018-08-07 18:12:59 +02006095 }
6096 } else {
6097 repeat;
6098 }
6099 }
6100 }
6101 [] L1CTL.receive { repeat; }
6102 [] T.timeout {
6103 f_rsl_chan_deact();
6104 f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02006105 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout waiting for L2 fill frames on Um");
Stefan Sperling4880be42018-08-07 18:12:59 +02006106 }
6107 }
6108}
6109
6110function f_TC_tch_sign_l2_fill_frame(charstring id) runs on ConnHdlr {
6111 f_test_l2_fill_frames(false);
6112}
6113
6114function f_TC_tch_sign_l2_fill_frame_dtxd(charstring id) runs on ConnHdlr {
6115 f_test_l2_fill_frames(true);
6116}
6117
6118function f_tch_sign_l2_fill_frame(boolean dtxd) runs on test_CT {
6119 var ConnHdlr vc_conn;
6120 var ConnHdlrPars pars;
6121 pars.t_guard := 60.0;
Harald Welte10474062019-05-30 16:48:17 +02006122 f_init();
Stefan Sperling4880be42018-08-07 18:12:59 +02006123 for (var integer i := 0; i < sizeof(g_AllChannels); i := i + 1) {
6124 pars := valueof(t_Pars(g_AllChannels[i], ts_RSL_ChanMode_SIGN(dtxd)));
6125 if (dtxd) {
6126 if (i >= 4) { /* DTX is only allowed on TCH/F */
6127 break;
6128 }
6129 vc_conn := f_start_handler(refers(f_TC_tch_sign_l2_fill_frame_dtxd), pars);
6130 } else {
6131 vc_conn := f_start_handler(refers(f_TC_tch_sign_l2_fill_frame), pars);
6132 }
6133 vc_conn.done;
6134 }
6135}
6136
6137/* Verify that L2 fill frames are sent on TCH in signaling mode if
6138 * there is nothing to transmit while DTX is disabled on downlink. */
6139testcase TC_tch_sign_l2_fill_frame() runs on test_CT {
6140 f_tch_sign_l2_fill_frame(false);
6141}
6142
6143/* Verify that particular L2 fill frames are sent on TCH in signaling mode if
6144 * there is nothing to transmit while DTX is enabled on downlink. */
6145testcase TC_tch_sign_l2_fill_frame_dtxd() runs on test_CT {
6146 f_tch_sign_l2_fill_frame(true);
6147}
Harald Welte0472ab42018-03-12 15:02:26 +01006148
Stefan Sperling0ec1c262018-10-15 15:12:52 +02006149testcase TC_chopped_ipa_ping() runs on test_CT {
6150 IPA_Testing.f_run_TC_chopped_ipa_ping(mp_rsl_ip, mp_rsl_port, LISTEN_FOR_CLIENT);
6151}
6152
Stefan Sperlingaa1e60f2018-10-15 16:34:07 +02006153testcase TC_chopped_ipa_payload() runs on test_CT {
6154 IPA_Testing.f_run_TC_chopped_ipa_payload(mp_rsl_ip, mp_rsl_port, LISTEN_FOR_CLIENT);
6155}
6156
Harald Welte0472ab42018-03-12 15:02:26 +01006157/* test generation of RLL ERR IND based on Um errors (TS 48.058 3.9) */
6158/* protocol error as per 44.006 */
6159/* link layer failure (repetition of I-frame N200 times without ACK */
6160/* repetition of SABM or DISC N200 times without ACK */
6161/* receptiom of SABM in multi-frame established state */
6162
6163
Harald Welte68e495b2018-02-25 00:05:57 +01006164/* TODO Areas:
6165
6166* channel activation
6167** with BS_Power / MS_Power, bypassing power control loop
6168** on primary vs. secondary TRX
Harald Welte68e495b2018-02-25 00:05:57 +01006169** with timing advance from initial activation on
6170* mode modify
6171** encryption
6172** multirate
6173* check DEACTIVATE SACCH
Harald Welte68e495b2018-02-25 00:05:57 +01006174** unsupported algorithm
6175* handover detection
Harald Welte68e495b2018-02-25 00:05:57 +01006176* BS Power Control
6177* Physical Context
Harald Welte68e495b2018-02-25 00:05:57 +01006178* RF resource ind
Harald Welte68e495b2018-02-25 00:05:57 +01006179* error handling
Harald Welte68e495b2018-02-25 00:05:57 +01006180** IE duplicated?
Harald Welte883340c2018-02-28 18:59:29 +01006181* PCU interface
Harald Welte883340c2018-02-28 18:59:29 +01006182** DATA_IND from BTS->PCU
6183** verification of PCU-originated DATA_REQ arrival on Um/MS side
Harald Welte68e495b2018-02-25 00:05:57 +01006184
6185*/
Harald Welte70767382018-02-21 12:16:40 +01006186
6187control {
6188 execute( TC_chan_act_stress() );
6189 execute( TC_chan_act_react() );
6190 execute( TC_chan_deact_not_active() );
6191 execute( TC_chan_act_wrong_nr() );
Harald Welte629cc6b2018-03-11 17:19:05 +01006192 execute( TC_deact_sacch() );
Harald Welteea17b912018-03-11 22:29:31 +01006193 execute( TC_sacch_filling() );
6194 execute( TC_sacch_info_mod() );
Harald Welte075d84c2018-03-12 13:07:24 +01006195 execute( TC_sacch_multi() );
Harald Welte55700662018-03-12 13:15:43 +01006196 execute( TC_sacch_multi_chg() );
Harald Weltec8d363c2019-05-19 20:36:48 +02006197 execute( TC_sacch_chan_act() );
Harald Welte8b01c792019-05-19 22:51:25 +02006198 execute( TC_sacch_chan_act_ho_async() );
6199 execute( TC_sacch_chan_act_ho_sync() );
Harald Welte8c24c2b2018-02-26 08:31:31 +01006200 execute( TC_rach_content() );
6201 execute( TC_rach_count() );
Harald Welte54a2a2d2018-02-26 09:14:05 +01006202 execute( TC_rach_max_ta() );
Vadim Yanitskiy7c2c10c2019-05-31 20:42:01 +07006203 execute( TC_ho_rach() );
Harald Welte3453ab42019-05-24 21:19:58 +02006204 execute( TC_rach_load_idle_thresh0() );
6205 execute( TC_rach_load_idle_below_thresh() );
6206 execute( TC_rach_load_count() );
Harald Welte70767382018-02-21 12:16:40 +01006207 execute( TC_meas_res_sign_tchf() );
6208 execute( TC_meas_res_sign_tchh() );
6209 execute( TC_meas_res_sign_sdcch4() );
6210 execute( TC_meas_res_sign_sdcch8() );
Harald Welte685d5982018-02-27 20:42:05 +01006211 execute( TC_meas_res_sign_tchh_toa256() );
Eric Wildae8f2622019-06-18 17:05:11 +02006212 execute( TC_rsl_bs_pwr_static_ass() );
6213 execute( TC_rsl_bs_pwr_static_power_control() );
Philipp Maier4d1e9c92018-12-20 11:11:56 +01006214 execute( TC_rsl_ms_pwr_ctrl() );
Eric Wild280ccb82019-06-17 11:11:52 +02006215 execute( TC_rsl_ms_pwr_dyn_active() );
Eric Wild095024b2019-06-17 15:08:57 +02006216 execute( TC_rsl_ms_pwr_dyn_active2() );
Eric Wild61edb7e2019-06-03 12:38:31 +02006217 execute( TC_rsl_ms_pwr_dyn_up() );
6218 execute( TC_rsl_ms_pwr_dyn_down() );
6219 execute( TC_rsl_ms_pwr_dyn_ass_updown() );
6220 execute( TC_rsl_ms_pwr_dyn_max() );
Eric Wilde57e1a62019-05-28 13:30:55 +02006221 execute( TC_rsl_chan_initial_ms_pwr() );
Eric Wild6833cc92019-05-23 19:34:44 +02006222 execute( TC_rsl_chan_initial_ta() );
Eric Wildf1827a72019-05-28 17:37:35 +02006223 execute( TC_rsl_modify_encr() );
Harald Welte70767382018-02-21 12:16:40 +01006224 execute( TC_conn_fail_crit() );
Harald Welte68e495b2018-02-25 00:05:57 +01006225 execute( TC_paging_imsi_80percent() );
6226 execute( TC_paging_tmsi_80percent() );
6227 execute( TC_paging_imsi_200percent() );
6228 execute( TC_paging_tmsi_200percent() );
Harald Welte01d982c2018-02-25 01:31:40 +01006229 execute( TC_rsl_protocol_error() );
6230 execute( TC_rsl_mand_ie_error() );
6231 execute( TC_rsl_ie_content_error() );
Harald Welte48494ca2018-02-25 16:59:50 +01006232 execute( TC_si_sched_default() );
Harald Welte0cae4552018-03-09 22:20:26 +01006233 execute( TC_si_sched_1() );
Harald Welte48494ca2018-02-25 16:59:50 +01006234 execute( TC_si_sched_2bis() );
6235 execute( TC_si_sched_2ter() );
6236 execute( TC_si_sched_2ter_2bis() );
6237 execute( TC_si_sched_2quater() );
6238 execute( TC_si_sched_13() );
6239 execute( TC_si_sched_13_2bis_2ter_2quater() );
Harald Weltea871a382018-02-25 02:03:14 +01006240 execute( TC_ipa_dlcx_not_active() );
Harald Weltea3f1df92018-02-25 12:49:55 +01006241 execute( TC_ipa_crcx_twice_not_active() );
6242 execute( TC_ipa_crcx_mdcx_dlcx_not_active() );
Harald Welte3ae11da2018-02-25 13:36:06 +01006243 execute( TC_ipa_crcx_mdcx_mdcx_dlcx_not_active() );
Harald Welte9912eb52018-02-25 13:30:15 +01006244 execute( TC_ipa_crcx_sdcch_not_active() );
Harald Welte883340c2018-02-28 18:59:29 +01006245
Pau Espin Pedrola14a8af2018-11-20 13:12:22 +01006246 if (mp_pcu_socket != "") {
6247 execute( TC_pcu_act_req() );
6248 execute( TC_pcu_act_req_wrong_ts() );
6249 execute( TC_pcu_act_req_wrong_bts() );
6250 execute( TC_pcu_act_req_wrong_trx() );
6251 execute( TC_pcu_deact_req() );
6252 execute( TC_pcu_deact_req_wrong_ts() );
6253 execute( TC_pcu_ver_si13() );
Harald Weltead033dc2019-05-25 17:28:16 +02006254 if (mp_l1_supports_gprs) {
6255 execute( TC_pcu_data_req_pdtch() );
6256 execute( TC_pcu_data_req_ptcch() );
Harald Welte7162a612019-05-26 12:56:09 +02006257 execute( TC_pcu_data_req_wrong_bts() );
6258 execute( TC_pcu_data_req_wrong_trx() );
6259 execute( TC_pcu_data_req_wrong_ts() );
6260 execute( TC_pcu_data_req_ts_inactive() );
Harald Weltead033dc2019-05-25 17:28:16 +02006261 }
Pau Espin Pedrola14a8af2018-11-20 13:12:22 +01006262 execute( TC_pcu_data_req_agch() );
Harald Welte928622b2019-05-26 13:22:59 +02006263 execute( TC_pcu_data_req_pch() );
Pau Espin Pedrola14a8af2018-11-20 13:12:22 +01006264 execute( TC_pcu_data_req_imm_ass_pch() );
6265 execute( TC_pcu_rach_content() );
Vadim Yanitskiy51cbc102019-04-22 06:37:30 +07006266 execute( TC_pcu_ext_rach_content() );
Vadim Yanitskiya2c68e82019-07-03 13:07:20 +07006267 execute( TC_pcu_data_ind_lqual_cb() );
Pau Espin Pedrola14a8af2018-11-20 13:12:22 +01006268 execute( TC_pcu_paging_from_rsl() );
Harald Welted66c9b82019-05-25 09:03:15 +02006269 execute( TC_pcu_time_ind() );
Harald Welte4832c862019-05-25 14:57:18 +02006270 execute( TC_pcu_rts_req() );
Harald Welte07bd2d22019-05-25 11:03:30 +02006271 execute( TC_pcu_oml_alert() );
Harald Welteeaa9a862019-05-26 23:01:08 +02006272 execute( TC_pcu_rr_suspend() );
Harald Weltea2e0e942019-05-27 18:12:53 +02006273 execute( TC_pcu_socket_connect_multi() );
Harald Weltec8effb72019-05-27 18:23:04 +02006274 execute( TC_pcu_socket_reconnect() );
Harald Weltebe030482019-05-27 22:29:35 +02006275 execute( TC_pcu_socket_noconnect_nosi3gprs() );
6276 execute( TC_pcu_socket_connect_si3gprs() );
6277 execute( TC_pcu_socket_disconnect_nosi3gprs() );
Oliver Smithf5239c72019-08-28 10:01:25 +02006278 execute( TC_pcu_socket_verify_info_ind() );
Pau Espin Pedrola14a8af2018-11-20 13:12:22 +01006279 } else {
6280 log("PCU socket path not available, skipping PCU tests");
6281 }
Harald Welte3d04ae62018-04-04 20:29:05 +02006282
6283 execute( TC_dyn_osmo_pdch_act_deact() );
6284 execute( TC_dyn_osmo_pdch_unsol_deact() );
6285 execute( TC_dyn_osmo_pdch_double_act() );
6286 execute( TC_dyn_osmo_pdch_tchf_act() );
6287 execute( TC_dyn_osmo_pdch_tchh_act() );
Harald Welte9bbbfb52018-04-05 09:33:19 +02006288 execute( TC_dyn_ipa_pdch_act_deact() );
6289 execute( TC_dyn_ipa_pdch_tchf_act() );
6290 execute( TC_dyn_ipa_pdch_tchf_act_pdch_act_nack() );
6291 execute( TC_dyn_ipa_pdch_act_tchf_act_nack() );
Harald Welte0472ab42018-03-12 15:02:26 +01006292
6293 execute( TC_rll_est_ind() );
6294 execute( TC_rll_est_req_DCCH_3() );
6295 execute( TC_rll_est_req_ACCH_3() );
6296 execute( TC_rll_rel_ind_DCCH_0() );
6297 execute( TC_rll_rel_ind_DCCH_3() );
6298 execute( TC_rll_rel_ind_ACCH_0() );
6299 execute( TC_rll_rel_ind_ACCH_3() );
6300 execute( TC_rll_rel_req() );
6301 execute( TC_rll_unit_data_req_DCCH() );
6302 execute( TC_rll_unit_data_req_ACCH() );
6303 execute( TC_rll_unit_data_ind_DCCH() );
6304 execute( TC_rll_unit_data_ind_ACCH() );
Harald Weltee613f962018-04-18 22:38:16 +02006305
6306 execute( TC_chan_act_a51() );
6307 execute( TC_chan_act_a52() );
6308 execute( TC_chan_act_a53() );
6309 execute( TC_encr_cmd_a51() );
6310 execute( TC_encr_cmd_a52() );
6311 execute( TC_encr_cmd_a53() );
6312
Harald Welteee25aae2019-05-19 14:32:37 +02006313 execute( TC_err_rep_wrong_mdisc() );
6314 execute( TC_err_rep_wrong_msg_type() );
6315 execute( TC_err_rep_wrong_sequence() );
6316
Harald Weltee613f962018-04-18 22:38:16 +02006317 execute( TC_lapdm_selftest() );
Stefan Sperling4880be42018-08-07 18:12:59 +02006318
6319 execute( TC_tch_sign_l2_fill_frame() );
6320 execute( TC_tch_sign_l2_fill_frame_dtxd() );
Stefan Sperling0ec1c262018-10-15 15:12:52 +02006321
6322 execute( TC_chopped_ipa_ping() );
Stefan Sperlingaa1e60f2018-10-15 16:34:07 +02006323 execute( TC_chopped_ipa_payload() );
Harald Welte70767382018-02-21 12:16:40 +01006324}
6325
6326
6327}