blob: 5b073efd588af79843f16f4972ab149601001d08 [file] [log] [blame]
Harald Welte70767382018-02-21 12:16:40 +01001module BTS_Tests {
2
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02003import from Misc_Helpers all;
Harald Welte70767382018-02-21 12:16:40 +01004import from General_Types all;
5import from GSM_Types all;
6import from GSM_RR_Types all;
7import from Osmocom_Types all;
8import from GSM_Types all;
Harald Welte82ccef72018-02-25 16:17:33 +01009import from GSM_SystemInformation all;
Harald Welte70767382018-02-21 12:16:40 +010010import from L1CTL_PortType all;
11import from L1CTL_Types all;
12import from LAPDm_Types all;
13import from Osmocom_CTRL_Adapter all;
Neels Hofmeyr6a84b232018-04-03 19:12:36 +020014import from Osmocom_CTRL_Functions all;
Harald Welte70767382018-02-21 12:16:40 +010015
16import from RSL_Types all;
Harald Welte7484fc42018-02-24 14:09:45 +010017import from IPA_Types all;
Harald Welte70767382018-02-21 12:16:40 +010018import from IPA_Emulation all;
Stefan Sperling0ec1c262018-10-15 15:12:52 +020019import from IPA_Testing all;
Harald Welte70767382018-02-21 12:16:40 +010020import from RSL_Emulation all;
21
22import from IPL4asp_Types all;
23import from TRXC_Types all;
24import from TRXC_CodecPort all;
25import from TRXC_CodecPort_CtrlFunct all;
26
Harald Welte883340c2018-02-28 18:59:29 +010027import from PCUIF_Types all;
28import from PCUIF_CodecPort all;
29
Harald Welte7484fc42018-02-24 14:09:45 +010030import from MobileL3_CommonIE_Types all;
Harald Welte68e495b2018-02-25 00:05:57 +010031import from MobileL3_RRM_Types all;
32import from MobileL3_Types all;
33import from L3_Templates all;
Harald Welte7484fc42018-02-24 14:09:45 +010034
Harald Welte8da48242018-02-27 20:41:32 +010035import from Osmocom_VTY_Functions all;
36import from TELNETasp_PortType all;
37
Harald Welte70767382018-02-21 12:16:40 +010038/* The tests assume a BTS with the following timeslot configuration:
39 * TS0 : Combined CCCH + SDCCH/4
Harald Welte3d04ae62018-04-04 20:29:05 +020040 * TS1 : TCH/F
41 * TS2 : TCH/F
42 * TS3 : TCH/F_PDCH (IPA Style)
43 * TS4 : TCH/F_TCH/H_PDCH (Osmocom Style)
Harald Welte70767382018-02-21 12:16:40 +010044 * TS5 : TCH/H
45 * TS6 : SDCCH/8
46 * TS7 : PDCH
47 */
48
49modulepar {
50 charstring mp_rsl_ip := "127.0.0.2";
51 integer mp_rsl_port := 3003;
52 integer mp_trx0_arfcn := 871;
Harald Weltea4d8f352018-03-01 15:47:20 +010053 charstring mp_bb_trxc_ip := "127.0.0.1";
Harald Welteef3e1c92018-02-28 23:40:14 +010054 integer mp_bb_trxc_port := 6701;
Harald Welte883340c2018-02-28 18:59:29 +010055 charstring mp_pcu_socket := PCU_SOCK_DEFAULT;
Neels Hofmeyr6a84b232018-04-03 19:12:36 +020056 charstring mp_ctrl_ip := "127.0.0.1";
57 integer mp_ctrl_port := 4238;
Pau Espin Pedrol121724c2018-09-28 15:58:12 +020058 integer mp_tolerance_rxqual := 1;
59 integer mp_tolerance_rxlev := 3;
60 integer mp_tolerance_timing_offset_256syms := 0;
Pau Espin Pedrol752ffd52018-06-07 13:55:45 +020061 integer mp_rxlev_exp := 57;
Pau Espin Pedrole9571aa2018-10-22 17:13:07 +020062 integer mp_ul_rxlev_exp := 10;
Pau Espin Pedroled359cb2018-09-28 16:08:24 +020063 integer mp_ms_power_level_exp := 7;
Pau Espin Pedrol121724c2018-09-28 15:58:12 +020064 integer mp_ms_actual_ta_exp := 0;
65 integer mp_timing_offset_256syms_exp := 512;
Harald Welte70767382018-02-21 12:16:40 +010066}
67
Harald Welte629cc6b2018-03-11 17:19:05 +010068type record of RslChannelNr ChannelNrs;
69
Harald Welte70767382018-02-21 12:16:40 +010070type component test_CT extends CTRL_Adapter_CT {
Harald Welte68e495b2018-02-25 00:05:57 +010071 /* IPA Emulation component underneath RSL */
Harald Welte70767382018-02-21 12:16:40 +010072 var IPA_Emulation_CT vc_IPA;
Harald Welte68e495b2018-02-25 00:05:57 +010073 /* RSL Emulation component (for ConnHdlr tests) */
Harald Welte70767382018-02-21 12:16:40 +010074 var RSL_Emulation_CT vc_RSL;
Harald Welte68e495b2018-02-25 00:05:57 +010075 /* Direct RSL_CCHAN_PT */
Harald Welte70767382018-02-21 12:16:40 +010076 port RSL_CCHAN_PT RSL_CCHAN;
Harald Welte68e495b2018-02-25 00:05:57 +010077
78 /* L1CTL port (for classic tests) */
79 port L1CTL_PT L1CTL;
Harald Welte48494ca2018-02-25 16:59:50 +010080
Harald Welte54a2a2d2018-02-26 09:14:05 +010081 /* TRXC port (for classic tests) */
82 port TRXC_CODEC_PT BB_TRXC;
83 var integer g_bb_trxc_conn_id;
84
Harald Weltef50e3ae2018-09-10 10:27:56 +020085 /* VTY connections to both BTS and BSC */
Harald Welte8da48242018-02-27 20:41:32 +010086 port TELNETasp_PT BTSVTY;
Harald Weltef50e3ae2018-09-10 10:27:56 +020087 port TELNETasp_PT BSCVTY;
Harald Welte8da48242018-02-27 20:41:32 +010088
Harald Welte883340c2018-02-28 18:59:29 +010089 /* PCU Interface of BTS */
90 port PCUIF_CODEC_PT PCU;
91 var integer g_pcu_conn_id;
92 /* Last PCU INFO IND we received */
93 var PCUIF_Message g_pcu_last_info;
94
Harald Welte48494ca2018-02-25 16:59:50 +010095 /* SI configuration */
96 var SystemInformationConfig si_cfg := {
97 bcch_extended := false,
98 si1_present := false,
99 si2bis_present := false,
100 si2ter_present := false,
101 si2quater_present := false,
102 si7_present := false,
103 si8_present := false,
104 si9_present := false,
105 si13_present := false,
106 si13alt_present := false,
107 si15_present := false,
108 si16_present := false,
109 si17_present := false,
110 si2n_present := false,
111 si21_present := false,
112 si22_present := false
113 };
Harald Welte629cc6b2018-03-11 17:19:05 +0100114
115 /* all logical channels available on the BTS */
116 var ChannelNrs g_AllChannels;
Harald Welte0472ab42018-03-12 15:02:26 +0100117 var ChannelNrs g_AllChanTypes;
Harald Welte70767382018-02-21 12:16:40 +0100118}
119
120/* an individual call / channel */
121type component ConnHdlr extends RSL_DchanHdlr {
122 port L1CTL_PT L1CTL;
123
124 port TRXC_CODEC_PT BB_TRXC;
125 var integer g_bb_trxc_conn_id;
126
127 timer g_Tguard;
128 timer g_Tmeas_exp := 2.0; /* >= 103 SACCH multiframe ~ 500ms */
129
130 var ConnHdlrPars g_pars;
131 var uint8_t g_next_meas_res_nr := 0;
Harald Weltefa45e9e2018-03-10 18:59:03 +0100132 var boolean g_first_meas_res := true;
Harald Weltef26de0b2018-04-04 20:28:05 +0200133
134 /* PCU Interface of BTS */
135 port PCUIF_CODEC_PT PCU;
Harald Welte70767382018-02-21 12:16:40 +0100136}
137
138function f_init_rsl(charstring id) runs on test_CT {
139 vc_IPA := IPA_Emulation_CT.create(id & "-RSL-IPA");
140 vc_RSL := RSL_Emulation_CT.create(id & "-RSL");
141
142 map(vc_IPA:IPA_PORT, system:IPA_CODEC_PT);
143 connect(vc_IPA:IPA_RSL_PORT, vc_RSL:IPA_PT);
144 connect(self:RSL_CCHAN, vc_RSL:CCHAN_PT);
145
146 vc_IPA.start(IPA_Emulation.main_server(mp_rsl_ip, mp_rsl_port));
147 vc_RSL.start(RSL_Emulation.main(false));
148}
149
150type record ConnHdlrPars {
151 RslChannelNr chan_nr,
152 RSL_IE_ChannelMode chan_mode,
153 float t_guard,
Harald Welte0472ab42018-03-12 15:02:26 +0100154 ConnL1Pars l1_pars,
Harald Weltee613f962018-04-18 22:38:16 +0200155 TestSpecUnion spec optional,
156 RSL_IE_EncryptionInfo encr optional
Harald Welte0472ab42018-03-12 15:02:26 +0100157}
158
159/* Test-specific parameters */
160type union TestSpecUnion {
161 RllTestCase rll
Harald Welte70767382018-02-21 12:16:40 +0100162}
163
Harald Welte82ccef72018-02-25 16:17:33 +0100164template (value) RachControlParameters ts_RachCtrl_default := {
Harald Welte0fd1fb02018-03-10 17:19:50 +0100165 max_retrans := RACH_MAX_RETRANS_7,
166 tx_integer := '1001'B, /* 12 slots */
Harald Welte82ccef72018-02-25 16:17:33 +0100167 cell_barr_access := false,
168 re_not_allowed := true,
Harald Welteb9585f82018-03-10 17:18:47 +0100169 acc := '0000010000000000'B
Harald Welte82ccef72018-02-25 16:17:33 +0100170};
171
Harald Weltef10153f2018-02-25 16:34:05 +0100172template (value) CellSelectionParameters ts_CellSelPar_default := {
Harald Welte0fd1fb02018-03-10 17:19:50 +0100173 cell_resel_hyst_2dB := 2,
Pau Espin Pedroled359cb2018-09-28 16:08:24 +0200174 ms_txpwr_max_cch := mp_ms_power_level_exp,
Harald Weltef10153f2018-02-25 16:34:05 +0100175 acs := '0'B,
176 neci := true,
177 rxlev_access_min := 0
178}
179
180template (value) LocationAreaIdentification ts_LAI_default := {
181 mcc_mnc := '262F42'H,
182 lac := 42
183}
184
Harald Welte7484fc42018-02-24 14:09:45 +0100185/* Default SYSTEM INFORMATION 3 */
Harald Weltef8df4cb2018-03-10 15:15:08 +0100186template (value) SystemInformation ts_SI3_default := {
187 header := ts_RrHeader(SYSTEM_INFORMATION_TYPE_3, 18),
Harald Welte7484fc42018-02-24 14:09:45 +0100188 payload := {
189 si3 := {
190 cell_id := 23,
Harald Weltef10153f2018-02-25 16:34:05 +0100191 lai := ts_LAI_default,
Harald Welte7484fc42018-02-24 14:09:45 +0100192 ctrl_chan_desc := {
193 msc_r99 := true,
194 att := true,
195 bs_ag_blks_res := 1,
196 ccch_conf := CCHAN_DESC_1CCCH_COMBINED,
Harald Welte82ccef72018-02-25 16:17:33 +0100197 si22ind := false,
Harald Welte7484fc42018-02-24 14:09:45 +0100198 cbq3 := CBQ3_IU_MODE_NOT_SUPPORTED,
199 spare := '00'B,
200 bs_pa_mfrms := 0, /* 2 multiframes */
201 t3212 := 1 /* 6 minutes */
202 },
Harald Welte82ccef72018-02-25 16:17:33 +0100203 cell_options := {
Harald Welte7484fc42018-02-24 14:09:45 +0100204 dn_ind := false,
205 pwrc := false,
206 dtx := MS_MAY_USE_UL_DTX,
Harald Welte0fd1fb02018-03-10 17:19:50 +0100207 radio_link_tout_div4 := (32/4)-1
Harald Welte7484fc42018-02-24 14:09:45 +0100208 },
Harald Weltef10153f2018-02-25 16:34:05 +0100209 cell_sel_par := ts_CellSelPar_default,
Harald Welte82ccef72018-02-25 16:17:33 +0100210 rach_control := ts_RachCtrl_default,
Harald Welte3778acc2018-03-09 19:32:31 +0100211 rest_octets := '2B2B2B2B'O
Harald Welte7484fc42018-02-24 14:09:45 +0100212 }
213 }
214}
Harald Welte70767382018-02-21 12:16:40 +0100215
Harald Weltef8df4cb2018-03-10 15:15:08 +0100216template (value) SystemInformation ts_SI2_default := {
217 header := ts_RrHeader(SYSTEM_INFORMATION_TYPE_2, 22),
Harald Weltef10153f2018-02-25 16:34:05 +0100218 payload := {
219 si2 := {
220 bcch_freq_list := '00000000000000000000000000000000'O,
221 ncc_permitted := '11111111'B,
222 rach_control := ts_RachCtrl_default
223 }
224 }
225}
226
Harald Weltef8df4cb2018-03-10 15:15:08 +0100227template (value) SystemInformation ts_SI4_default := {
228 header := ts_RrHeader(SYSTEM_INFORMATION_TYPE_4, 12), /* no CBCH / restoct */
Harald Weltef10153f2018-02-25 16:34:05 +0100229 payload := {
230 si4 := {
231 lai := ts_LAI_default,
232 cell_sel_par := ts_CellSelPar_default,
233 rach_control := ts_RachCtrl_default,
234 cbch_chan_desc := omit,
235 cbch_mobile_alloc := omit,
236 rest_octets := ''O
237 }
238 }
239}
240
241function f_rsl_bcch_fill_raw(RSL_IE_SysinfoType rsl_si_type, octetstring si_enc)
242runs on test_CT {
243 log("Setting ", rsl_si_type, ": ", si_enc);
244 RSL_CCHAN.send(ts_RSL_UD(ts_RSL_BCCH_INFO(rsl_si_type, si_enc)));
245}
246
247function f_rsl_bcch_fill(RSL_IE_SysinfoType rsl_si_type, template (value) SystemInformation si_dec)
248runs on test_CT {
249 var octetstring si_enc := enc_SystemInformation(valueof(si_dec));
250 log("Setting ", rsl_si_type, ": ", si_dec);
251 f_rsl_bcch_fill_raw(rsl_si_type, si_enc);
252}
253
Harald Welte8da48242018-02-27 20:41:32 +0100254private function f_init_vty(charstring id) runs on test_CT {
255 map(self:BTSVTY, system:BTSVTY);
256 f_vty_set_prompts(BTSVTY);
257 f_vty_transceive(BTSVTY, "enable");
258}
259
Harald Weltef50e3ae2018-09-10 10:27:56 +0200260private function f_init_vty_bsc() runs on test_CT {
261 map(self:BSCVTY, system:BSCVTY);
262 f_vty_set_prompts(BSCVTY, "OsmoBSC");
263 f_vty_transceive(BSCVTY, "enable");
264}
265
Harald Welte883340c2018-02-28 18:59:29 +0100266/* PCU socket may at any time receive a new INFO.ind */
Harald Weltef26de0b2018-04-04 20:28:05 +0200267private altstep as_pcu_info_ind(PCUIF_CODEC_PT pt, integer pcu_conn_id,
268 out PCUIF_Message pcu_last_info) {
Harald Welte883340c2018-02-28 18:59:29 +0100269 var PCUIF_send_data sd;
Harald Weltef26de0b2018-04-04 20:28:05 +0200270 [] pt.receive(t_SD_PCUIF(pcu_conn_id, tr_PCUIF_INFO_IND(0, ?))) -> value sd {
271 pcu_last_info := sd.data;
Harald Welted378a252018-03-13 17:02:14 +0100272 }
Harald Weltef26de0b2018-04-04 20:28:05 +0200273 [] pt.receive(t_SD_PCUIF(pcu_conn_id, tr_PCUIF_INFO_IND(?, ?, ?))) -> value sd {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +0200274 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Invalid PCU Version/BTS Number received");
Harald Welte883340c2018-02-28 18:59:29 +0100275 }
276}
277
Harald Weltef26de0b2018-04-04 20:28:05 +0200278private function f_init_pcu(PCUIF_CODEC_PT pt, charstring id,
279 out integer pcu_conn_id, out PCUIF_Message pcu_last_info) {
Harald Welte883340c2018-02-28 18:59:29 +0100280 timer T := 2.0;
281 var PCUIF_send_data sd;
Harald Welte84271622018-03-10 17:21:03 +0100282 if (mp_pcu_socket == "") {
Harald Weltef26de0b2018-04-04 20:28:05 +0200283 pcu_conn_id := -1;
Harald Welte84271622018-03-10 17:21:03 +0100284 return;
285 }
Harald Weltef26de0b2018-04-04 20:28:05 +0200286 pcu_conn_id := f_pcuif_connect(pt, mp_pcu_socket);
Harald Welte883340c2018-02-28 18:59:29 +0100287
288 T.start;
289 alt {
Harald Weltef26de0b2018-04-04 20:28:05 +0200290 [] as_pcu_info_ind(pt, pcu_conn_id, pcu_last_info);
Harald Welte883340c2018-02-28 18:59:29 +0100291 [] T.timeout {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +0200292 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout waiting for PCU INFO_IND");
Harald Welte883340c2018-02-28 18:59:29 +0100293 }
294 }
295}
296
Harald Welte70767382018-02-21 12:16:40 +0100297/* global init function */
Harald Welte68e495b2018-02-25 00:05:57 +0100298function f_init(charstring id := "BTS-Test") runs on test_CT {
Harald Welte83f6dbf2018-06-03 18:26:50 +0200299 timer T := 10.0;
Harald Welte629cc6b2018-03-11 17:19:05 +0100300 g_AllChannels := {
301 /* TS 1..4: TCH/F */
302 valueof(ts_RslChanNr_Bm(1)), valueof(ts_RslChanNr_Bm(2)),
303 valueof(ts_RslChanNr_Bm(3)), valueof(ts_RslChanNr_Bm(4)),
304 /* TS 5: TCH/H */
305 valueof(ts_RslChanNr_Lm(5,0)), valueof(ts_RslChanNr_Lm(5,1)),
306 /* TS 0: SDCCH/4 */
307 valueof(ts_RslChanNr_SDCCH4(0,0)), valueof(ts_RslChanNr_SDCCH4(0,1)),
308 valueof(ts_RslChanNr_SDCCH4(0,2)), valueof(ts_RslChanNr_SDCCH4(0,3)),
309 /* TS 6: SDCCH/8 */
310 valueof(ts_RslChanNr_SDCCH8(6,0)), valueof(ts_RslChanNr_SDCCH8(6,1)),
311 valueof(ts_RslChanNr_SDCCH8(6,2)), valueof(ts_RslChanNr_SDCCH8(6,3)),
312 valueof(ts_RslChanNr_SDCCH8(6,4)), valueof(ts_RslChanNr_SDCCH8(6,5)),
313 valueof(ts_RslChanNr_SDCCH8(6,6)), valueof(ts_RslChanNr_SDCCH8(6,7))
314 };
315
Pau Espin Pedrol3dcf38f2018-10-22 14:07:54 +0200316 /* FIXME: FACCH/H is unreliable with calypso firmware, see OS#3653 */
317 if (mp_bb_trxc_port != -1) {
318 g_AllChanTypes := {
319 /* TS 1..4: TCH/F */
320 valueof(ts_RslChanNr_Bm(1)),
321 /* TS 5: TCH/H */
322 valueof(ts_RslChanNr_Lm(5,1)),
323 /* TS 0: SDCCH/4 */
324 valueof(ts_RslChanNr_SDCCH4(0,2)),
325 /* TS 6: SDCCH/8 */
326 valueof(ts_RslChanNr_SDCCH8(6,4))
327 };
328 } else {
329 g_AllChanTypes := {
330 /* TS 1..4: TCH/F */
331 valueof(ts_RslChanNr_Bm(1)),
332 /* TS 0: SDCCH/4 */
333 valueof(ts_RslChanNr_SDCCH4(0,2)),
334 /* TS 6: SDCCH/8 */
335 valueof(ts_RslChanNr_SDCCH8(6,4))
336 };
337 }
Harald Welte70767382018-02-21 12:16:40 +0100338 f_init_rsl(id);
Harald Welte83f6dbf2018-06-03 18:26:50 +0200339 T.start;
340 alt {
341 [] RSL_CCHAN.receive(ASP_IPA_Event:{up_down := ASP_IPA_EVENT_UP});
342 [] T.timeout {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +0200343 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout waiting for ASP_IPA_EVENT_UP");
Harald Welte83f6dbf2018-06-03 18:26:50 +0200344 }
345 }
Harald Welte2d142592018-02-25 13:19:44 +0100346 f_sleep(0.5); /* workaround for OS#3000 */
Harald Welte8da48242018-02-27 20:41:32 +0100347 f_init_vty(id);
Neels Hofmeyr6a84b232018-04-03 19:12:36 +0200348 f_ipa_ctrl_start(mp_ctrl_ip, mp_ctrl_port);
Harald Welte7484fc42018-02-24 14:09:45 +0100349
350 /* Send SI3 to the BTS, it is needed for various computations */
Harald Weltef10153f2018-02-25 16:34:05 +0100351 f_rsl_bcch_fill(RSL_SYSTEM_INFO_3, ts_SI3_default);
352 /* SI2 + SI4 are required for SI testing as they are mandatory defaults */
353 f_rsl_bcch_fill(RSL_SYSTEM_INFO_2, ts_SI2_default);
354 f_rsl_bcch_fill(RSL_SYSTEM_INFO_4, ts_SI4_default);
Harald Welte57fe8232018-02-26 17:52:50 +0100355
Harald Weltef26de0b2018-04-04 20:28:05 +0200356 map(self:PCU, system:PCU);
357 f_init_pcu(PCU, id, g_pcu_conn_id, g_pcu_last_info);
Harald Welte883340c2018-02-28 18:59:29 +0100358
Harald Welte84271622018-03-10 17:21:03 +0100359 if (mp_bb_trxc_port != -1) {
360 var TrxcMessage ret;
361 /* start with a default moderate timing offset equalling TA=2 */
362 f_main_trxc_connect();
363 ret := f_TRXC_transceive(BB_TRXC, g_bb_trxc_conn_id, valueof(ts_TRXC_FAKE_TIMING(2*256)));
364 }
Harald Welte70767382018-02-21 12:16:40 +0100365}
366
Harald Welte68e495b2018-02-25 00:05:57 +0100367/* Attach L1CTL to master test_CT (classic tests, non-handler mode) */
368function f_init_l1ctl() runs on test_CT {
369 map(self:L1CTL, system:L1CTL);
370 f_connect_reset(L1CTL);
371}
372
Harald Welte70767382018-02-21 12:16:40 +0100373type function void_fn(charstring id) runs on ConnHdlr;
374
375/* create a new test component */
Harald Weltef26de0b2018-04-04 20:28:05 +0200376function f_start_handler(void_fn fn, ConnHdlrPars pars, boolean pcu_comp := false)
Harald Welte70767382018-02-21 12:16:40 +0100377runs on test_CT return ConnHdlr {
378 var charstring id := testcasename();
379 var ConnHdlr vc_conn;
380
381 vc_conn := ConnHdlr.create(id);
382 /* connect to RSL Emulation main component */
383 connect(vc_conn:RSL, vc_RSL:CLIENT_PT);
384 connect(vc_conn:RSL_PROC, vc_RSL:RSL_PROC);
Harald Weltef26de0b2018-04-04 20:28:05 +0200385 if (pcu_comp) {
386 /* the ConnHdlr component wants to talk directly to the PCU, so disconnect
387 * it from the test_CT and connect it to the component. This obviously only
388 * works for one component, i.e. no concurrency */
389 unmap(self:PCU, system:PCU);
390 map(vc_conn:PCU, system:PCU);
391 }
Harald Welte70767382018-02-21 12:16:40 +0100392
393 vc_conn.start(f_handler_init(fn, id, pars));
394 return vc_conn;
395}
396
Harald Welte7484fc42018-02-24 14:09:45 +0100397template ASP_RSL_Unitdata ts_RSL_UD(template RSL_Message rsl, IpaStreamId sid := IPAC_PROTO_RSL_TRX0) := {
398 streamId := sid,
399 rsl := rsl
400}
401
402template ASP_RSL_Unitdata tr_RSL_UD(template RSL_Message rsl,
403 template IpaStreamId sid := IPAC_PROTO_RSL_TRX0) := {
404 streamId := sid,
405 rsl := rsl
406}
407
Harald Welte70767382018-02-21 12:16:40 +0100408private altstep as_Tguard() runs on ConnHdlr {
409 [] g_Tguard.timeout {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +0200410 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Tguard timeout");
Harald Welte70767382018-02-21 12:16:40 +0100411 }
412}
413
Harald Welte68e495b2018-02-25 00:05:57 +0100414private function f_l1_tune(L1CTL_PT L1CTL) {
Pau Espin Pedrol752ffd52018-06-07 13:55:45 +0200415 f_L1CTL_FBSB(L1CTL, { false, mp_trx0_arfcn }, CCCH_MODE_COMBINED, mp_rxlev_exp);
Harald Welte70767382018-02-21 12:16:40 +0100416}
417
418private function f_trxc_connect() runs on ConnHdlr {
419 map(self:BB_TRXC, system:BB_TRXC);
420 var Result res;
Harald Weltea4d8f352018-03-01 15:47:20 +0100421 res := TRXC_CodecPort_CtrlFunct.f_IPL4_connect(BB_TRXC, mp_bb_trxc_ip, mp_bb_trxc_port,
422 "", -1, -1, {udp:={}}, {});
Harald Welte9220f632018-05-23 20:27:02 +0200423 if (not ispresent(res.connId)) {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +0200424 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Could not connect to trx-control interface of trxcon, check your configuration");
Harald Welte9220f632018-05-23 20:27:02 +0200425 }
Harald Welte70767382018-02-21 12:16:40 +0100426 g_bb_trxc_conn_id := res.connId;
427}
428
429private function f_trxc_fake_rssi(uint8_t rssi) runs on ConnHdlr {
Harald Weltef8df4cb2018-03-10 15:15:08 +0100430 var TrxcMessage ret;
431 ret := f_TRXC_transceive(BB_TRXC, g_bb_trxc_conn_id, valueof(ts_TRXC_FAKE_RSSI(rssi)));
Harald Welte70767382018-02-21 12:16:40 +0100432}
433
434private function f_trx_fake_toffs256(int16_t toffs256) runs on ConnHdlr {
Harald Weltef8df4cb2018-03-10 15:15:08 +0100435 var TrxcMessage ret;
436 ret := f_TRXC_transceive(BB_TRXC, g_bb_trxc_conn_id, valueof(ts_TRXC_FAKE_TIMING(toffs256)));
Harald Welte70767382018-02-21 12:16:40 +0100437}
438
439/* first function started in ConnHdlr component */
440private function f_handler_init(void_fn fn, charstring id, ConnHdlrPars pars)
441runs on ConnHdlr {
442 g_pars := pars;
443 g_chan_nr := pars.chan_nr;
444
445 map(self:L1CTL, system:L1CTL);
446 f_connect_reset(L1CTL);
447
Harald Welte84271622018-03-10 17:21:03 +0100448 if (mp_bb_trxc_port != -1) {
449 f_trxc_connect();
450 }
Harald Welte70767382018-02-21 12:16:40 +0100451
452 g_Tguard.start(pars.t_guard);
453 activate(as_Tguard());
454
455 f_rslem_register(0, pars.chan_nr);
456
457 /* call the user-supplied test case function */
458 fn.apply(id);
459}
460
Harald Welteb1726c92018-03-30 11:56:38 +0200461function f_rsl_transceive_ret(template RSL_Message tx, template RSL_Message exp_rx, charstring id,
462 boolean ignore_other := false)
463runs on ConnHdlr return RSL_Message {
464 var RSL_Message rx;
Harald Welte1eba3742018-02-25 12:48:14 +0100465 timer T := 3.0;
466 RSL.send(tx);
467 T.start;
Harald Welte70767382018-02-21 12:16:40 +0100468 alt {
Harald Welteb1726c92018-03-30 11:56:38 +0200469 [] RSL.receive(exp_rx) -> value rx {
Harald Welte1eba3742018-02-25 12:48:14 +0100470 T.stop;
471 setverdict(pass);
Harald Welte70767382018-02-21 12:16:40 +0100472 }
Harald Welte1eba3742018-02-25 12:48:14 +0100473 [] T.timeout {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +0200474 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout expecting " & id);
Harald Welte1eba3742018-02-25 12:48:14 +0100475 }
Harald Welte21240e62018-03-11 21:43:35 +0100476 [not ignore_other] as_l1_sacch();
477 [not ignore_other] as_meas_res();
478 [not ignore_other] as_l1_dcch();
479 [not ignore_other] RSL.receive {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +0200480 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Unexpected RSL message received");
Harald Welte70767382018-02-21 12:16:40 +0100481 }
Harald Welte21240e62018-03-11 21:43:35 +0100482 [ignore_other] RSL.receive { repeat; }
Harald Welte70767382018-02-21 12:16:40 +0100483 }
Harald Welteb1726c92018-03-30 11:56:38 +0200484 return rx;
485}
486
487function f_rsl_transceive(template RSL_Message tx, template RSL_Message exp_rx, charstring id,
488 boolean ignore_other := false)
489runs on ConnHdlr {
490 var RSL_Message rx := f_rsl_transceive_ret(tx, exp_rx, id, ignore_other);
Harald Welte70767382018-02-21 12:16:40 +0100491}
492
Harald Weltee613f962018-04-18 22:38:16 +0200493function f_rsl_chan_act(RSL_IE_ChannelMode mode, boolean encr_enable := false)
494runs on ConnHdlr {
495 var RSL_Message ch_act := valueof(ts_RSL_CHAN_ACT(g_chan_nr, mode));
496 if (encr_enable) {
497 /* append encryption related IEs, if requested */
498 var RSL_IE_EncryptionInfo encr_info;
499 encr_info := valueof(ts_RSL_IE_EncrInfo(g_pars.encr.alg_id, g_pars.encr.key));
500 ch_act.ies := ch_act.ies & { valueof(t_RSL_IE(RSL_IE_ENCR_INFO, RSL_IE_Body:{encr_info :=
501encr_info})) };
502 }
503 f_rsl_transceive(ch_act, tr_RSL_CHAN_ACT_ACK(g_chan_nr), "RSL CHAN ACT");
Harald Welte1eba3742018-02-25 12:48:14 +0100504}
505
Harald Welte70767382018-02-21 12:16:40 +0100506function f_rsl_chan_deact() runs on ConnHdlr {
Harald Welte1eba3742018-02-25 12:48:14 +0100507 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 +0100508 "RF CHAN REL", true);
Harald Welte70767382018-02-21 12:16:40 +0100509}
510
Harald Welte70767382018-02-21 12:16:40 +0100511private template ConnHdlrPars t_Pars(template RslChannelNr chan_nr,
512 template RSL_IE_ChannelMode chan_mode,
513 float t_guard := 20.0) := {
514 chan_nr := valueof(chan_nr),
515 chan_mode := valueof(chan_mode),
516 t_guard := t_guard,
517 l1_pars := {
518 dtx_enabled := false,
Harald Welte685d5982018-02-27 20:42:05 +0100519 toa256_enabled := false,
Harald Welte70767382018-02-21 12:16:40 +0100520 meas_ul := {
521 full := {
Pau Espin Pedrole9571aa2018-10-22 17:13:07 +0200522 rxlev := mp_ul_rxlev_exp,
Harald Welte70767382018-02-21 12:16:40 +0100523 rxqual := 0
524 },
525 sub := {
Pau Espin Pedrole9571aa2018-10-22 17:13:07 +0200526 rxlev := mp_ul_rxlev_exp,
Harald Welte70767382018-02-21 12:16:40 +0100527 rxqual := 0
528 }
529 },
Pau Espin Pedrol121724c2018-09-28 15:58:12 +0200530 timing_offset_256syms := mp_timing_offset_256syms_exp,
Harald Welte70767382018-02-21 12:16:40 +0100531 bs_power_level := 0,
Pau Espin Pedroled359cb2018-09-28 16:08:24 +0200532 ms_power_level := mp_ms_power_level_exp,
Pau Espin Pedrol121724c2018-09-28 15:58:12 +0200533 ms_actual_ta := mp_ms_actual_ta_exp
Harald Welte0472ab42018-03-12 15:02:26 +0100534 },
Harald Weltee613f962018-04-18 22:38:16 +0200535 spec := omit,
536 encr := omit
Harald Welte70767382018-02-21 12:16:40 +0100537}
538
Harald Welte93640c62018-02-25 16:59:33 +0100539/***********************************************************************
540 * Channel Activation / Deactivation
541 ***********************************************************************/
542
Harald Welte70767382018-02-21 12:16:40 +0100543/* Stress test: Do 500 channel activations/deactivations in rapid succession */
544function f_TC_chan_act_stress(charstring id) runs on ConnHdlr {
545 for (var integer i := 0; i < 500; i := i+1) {
546 f_rsl_chan_act(g_pars.chan_mode);
547 f_rsl_chan_deact();
548 }
549 setverdict(pass);
550}
551testcase TC_chan_act_stress() runs on test_CT {
552 var ConnHdlr vc_conn;
553 var ConnHdlrPars pars := valueof(t_Pars(t_RslChanNr_Bm(1), ts_RSL_ChanMode_SIGN));
554 f_init(testcasename());
555 vc_conn := f_start_handler(refers(f_TC_chan_act_stress), pars);
556 vc_conn.done;
Daniel Willmann0fcc4d32018-10-23 20:32:19 +0200557 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
Harald Welte70767382018-02-21 12:16:40 +0100558}
559
560/* Test if re-activation of an already active channel fails as expected */
561function f_TC_chan_act_react(charstring id) runs on ConnHdlr {
562 f_rsl_chan_act(g_pars.chan_mode);
563 /* attempt to activate the same lchan again -> expect reject */
564 RSL.send(ts_RSL_CHAN_ACT(g_chan_nr, g_pars.chan_mode));
565 alt {
566 [] RSL.receive(tr_RSL_CHAN_ACT_ACK(g_chan_nr)) {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +0200567 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Unexpected CHAN ACT ACK on double activation");
Harald Welte70767382018-02-21 12:16:40 +0100568 }
569 [] RSL.receive(tr_RSL_CHAN_ACT_NACK(g_chan_nr)) {
570 setverdict(pass);
571 }
572 }
573 f_rsl_chan_deact();
574}
575testcase TC_chan_act_react() runs on test_CT {
576 var ConnHdlr vc_conn;
577 var ConnHdlrPars pars := valueof(t_Pars(t_RslChanNr_Bm(1), ts_RSL_ChanMode_SIGN));
Harald Welte294b0a22018-03-10 23:26:48 +0100578 f_init();
Harald Welte70767382018-02-21 12:16:40 +0100579 vc_conn := f_start_handler(refers(f_TC_chan_act_react), pars);
580 vc_conn.done;
Daniel Willmann0fcc4d32018-10-23 20:32:19 +0200581 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
Harald Welte70767382018-02-21 12:16:40 +0100582}
583
584/* Attempt to de-activate a channel that's not active */
585function f_TC_chan_deact_not_active(charstring id) runs on ConnHdlr {
586 timer T := 3.0;
587 RSL.send(ts_RSL_RF_CHAN_REL(g_chan_nr));
588 T.start;
589 alt {
590 [] RSL.receive(tr_RSL_RF_CHAN_REL_ACK(g_chan_nr)) {
591 setverdict(pass);
592 }
593 [] T.timeout {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +0200594 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout expecting RF_CHAN_REL_ACK");
Harald Welte70767382018-02-21 12:16:40 +0100595 }
596 }
597}
598testcase TC_chan_deact_not_active() runs on test_CT {
599 var ConnHdlrPars pars := valueof(t_Pars(t_RslChanNr_Bm(1), ts_RSL_ChanMode_SIGN));
Harald Welte294b0a22018-03-10 23:26:48 +0100600 f_init();
Harald Welte70767382018-02-21 12:16:40 +0100601 var ConnHdlr vc_conn := f_start_handler(refers(f_TC_chan_deact_not_active), pars);
602 vc_conn.done;
Daniel Willmann0fcc4d32018-10-23 20:32:19 +0200603 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
Harald Welte70767382018-02-21 12:16:40 +0100604}
605
606/* attempt to activate channel with wrong RSL Channel Nr IE; expect NACK */
607function f_TC_chan_act_wrong_nr(charstring id) runs on ConnHdlr {
608 RSL.send(ts_RSL_CHAN_ACT(g_chan_nr, g_pars.chan_mode));
609 alt {
610 [] RSL.receive(tr_RSL_CHAN_ACT_ACK(g_chan_nr)) {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +0200611 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Unexpected CHAN ACT ACK");
Harald Welte70767382018-02-21 12:16:40 +0100612 }
613 [] RSL.receive(tr_RSL_CHAN_ACT_NACK(g_chan_nr)) {
614 setverdict(pass);
615 }
616 }
617}
618private type record WrongChanNrCase {
619 RslChannelNr chan_nr,
620 charstring description
621}
622private type record of WrongChanNrCase WrongChanNrCases;
623private template WrongChanNrCase t_WCN(template RslChannelNr chan_nr, charstring desc) := {
624 chan_nr := chan_nr,
625 description := desc
626}
627
628testcase TC_chan_act_wrong_nr() runs on test_CT {
629 var ConnHdlr vc_conn;
630 var ConnHdlrPars pars;
631
Harald Welte294b0a22018-03-10 23:26:48 +0100632 f_init();
Harald Welte70767382018-02-21 12:16:40 +0100633
634 var WrongChanNrCases wrong := {
635 valueof(t_WCN(t_RslChanNr_RACH(0), "RACH is not a dedicated channel")),
636 valueof(t_WCN(t_RslChanNr_RACH(1), "RACH doesn't exist on timeslot")),
637 valueof(t_WCN(t_RslChanNr_BCCH(0), "BCCH is not a dedicated channel")),
638 valueof(t_WCN(t_RslChanNr_PCH_AGCH(0), "PCH/AGCH is not a dedicated channel")),
639 valueof(t_WCN(t_RslChanNr_Bm(0), "TS0 cannot be TCH/F")),
640 valueof(t_WCN(t_RslChanNr_Lm(0, 0), "TS0 cannot be TCH/H")),
641 valueof(t_WCN(t_RslChanNr_Lm(0, 1), "TS0 cannot be TCH/H")),
642 valueof(t_WCN(t_RslChanNr_PDCH(0), "TS0 cannot be PDCH")),
643 valueof(t_WCN(t_RslChanNr_SDCCH8(0, 0), "TS0 cannot be SDCCH/8")),
644 valueof(t_WCN(t_RslChanNr_SDCCH8(0, 7), "TS0 cannot be SDCCH/8")),
645 valueof(t_WCN(t_RslChanNr_SDCCH4(7, 0), "TS7 cannot be SDCCH/4")),
646 valueof(t_WCN(t_RslChanNr_SDCCH4(7, 3), "TS7 cannot be SDCCH/4")),
647 valueof(t_WCN(t_RslChanNr_Lm(1, 0), "TS1 cannot be TCH/H"))
648 };
649
650 for (var integer i := 0; i < sizeof(wrong); i := i+1) {
651 pars := valueof(t_Pars(wrong[i].chan_nr, ts_RSL_ChanMode_SIGN));
652 vc_conn := f_start_handler(refers(f_TC_chan_act_wrong_nr), pars);
653 vc_conn.done;
654 }
Daniel Willmann0fcc4d32018-10-23 20:32:19 +0200655 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
Harald Welte70767382018-02-21 12:16:40 +0100656}
657
Harald Weltee613f962018-04-18 22:38:16 +0200658/* execute the same callback function on a variety of logical channels */
659private function f_testmatrix_each_chan(ConnHdlrPars pars, void_fn fn) runs on test_CT {
660 var ConnHdlr vc_conn;
661 f_init(testcasename());
662
663 /* test on each of the channels we have */
664 for (var integer i := 0; i < sizeof(g_AllChanTypes); i := i+1) {
665 pars.chan_nr := valueof(g_AllChanTypes[i]);
666
667 log(testcasename(), ": XXX Starting on ", g_AllChanTypes[i]);
668 vc_conn := f_start_handler(fn, pars);
669 vc_conn.done;
670 }
671
Daniel Willmann0fcc4d32018-10-23 20:32:19 +0200672 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
Harald Weltee613f962018-04-18 22:38:16 +0200673}
674
Harald Welte93640c62018-02-25 16:59:33 +0100675/***********************************************************************
Harald Welte629cc6b2018-03-11 17:19:05 +0100676 * SACCH handling
677 ***********************************************************************/
678
679private function f_exp_sacch(boolean exp) runs on ConnHdlr {
680 timer T_sacch := 3.0;
681 T_sacch.start;
682 alt {
683 [not exp] L1CTL.receive(tr_L1CTL_DATA_IND(g_chan_nr, tr_RslLinkID_SACCH(0))) {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +0200684 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Received SACCH when not expecting it");
Harald Welte629cc6b2018-03-11 17:19:05 +0100685 }
686 [not exp] T_sacch.timeout {
687 setverdict(pass);
688 }
689 [exp] L1CTL.receive(tr_L1CTL_DATA_IND(g_chan_nr, tr_RslLinkID_SACCH(0))) {
690 setverdict(pass);
691 }
692 [exp] T_sacch.timeout {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +0200693 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("Timeout waiting for SACCH on ", g_chan_nr));
Harald Welte629cc6b2018-03-11 17:19:05 +0100694 }
695 [] L1CTL.receive { repeat; }
696 [] RSL.receive { repeat; }
697 }
698}
699
700/* Test if DEACTIVATE SACCH actualy deactivates its transmission (TS 48.058 4.6) */
701private function f_TC_deact_sacch(charstring id) runs on ConnHdlr {
702 f_l1_tune(L1CTL);
703 RSL.clear;
704
705 /* activate the logical channel */
706 f_est_dchan();
707 L1CTL.clear;
708
709 /* check that SACCH actually are received as expected */
710 f_exp_sacch(true);
711
712 /* deactivate SACCH on the logical channel */
713 RSL.send(ts_RSL_DEACT_SACCH(g_chan_nr));
714 f_sleep(1.0);
715 L1CTL.clear;
716
717 /* check that no SACCH are received anymore */
718 f_exp_sacch(false);
719
720 /* release the channel */
721 f_rsl_chan_deact();
722 f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
723}
724testcase TC_deact_sacch() runs on test_CT {
725 var ConnHdlr vc_conn;
726 var ConnHdlrPars pars;
727 f_init();
728 for (var integer i := 0; i < sizeof(g_AllChannels); i := i+1) {
729 //for (var integer i := 0; i < 1; i := i+1) {
730 pars := valueof(t_Pars(g_AllChannels[i], ts_RSL_ChanMode_SIGN));
731 log(testcasename(), ": Starting for ", g_AllChannels[i]);
732 vc_conn := f_start_handler(refers(f_TC_deact_sacch), pars);
733 vc_conn.done;
734 }
735 /* TODO: do the above in parallel, rather than sequentially? */
Daniel Willmann0fcc4d32018-10-23 20:32:19 +0200736 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
Harald Welte629cc6b2018-03-11 17:19:05 +0100737}
738
Harald Welte55700662018-03-12 13:15:43 +0100739/* verify that given SACCH payload is present */
Harald Welteea17b912018-03-11 22:29:31 +0100740private function f_sacch_present(template octetstring l3_exp) runs on ConnHdlr {
741 var L1ctlDlMessage dl;
742 /* check that the specified SI5 value is actually sent */
743 timer T_sacch := 3.0;
744 L1CTL.clear;
745 T_sacch.start;
746 alt {
747 [] L1CTL.receive(tr_L1CTL_DATA_IND(g_chan_nr, tr_RslLinkID_SACCH(0))) -> value dl {
748 var octetstring l3 := substr(dl.payload.data_ind.payload, 4, 19);
749 if (match(l3, l3_exp)) {
750 setverdict(pass);
751 } else {
752 repeat;
753 }
754 }
755 [] L1CTL.receive { repeat; }
756 [] T_sacch.timeout {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +0200757 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("Timeout waiting for SACCH ", l3_exp));
Harald Welteea17b912018-03-11 22:29:31 +0100758 }
759 }
760}
761
Harald Welte55700662018-03-12 13:15:43 +0100762/* verify that given SACCH payload is not present */
763private function f_sacch_missing(template octetstring l3_exp) runs on ConnHdlr {
764 var L1ctlDlMessage dl;
765 /* check that the specified SI5 value is actually sent */
766 timer T_sacch := 3.0;
767 L1CTL.clear;
768 T_sacch.start;
769 alt {
770 [] L1CTL.receive(tr_L1CTL_DATA_IND(g_chan_nr, tr_RslLinkID_SACCH(0))) -> value dl {
771 var octetstring l3 := substr(dl.payload.data_ind.payload, 4, 19);
772 if (match(l3, l3_exp)) {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +0200773 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("Received unexpected SACCH ", dl));
Harald Welte55700662018-03-12 13:15:43 +0100774 } else {
775 repeat;
776 }
777 }
778 [] L1CTL.receive { repeat; }
779 [] T_sacch.timeout {
780 setverdict(pass);
781 }
782 }
783}
784
Harald Welte629cc6b2018-03-11 17:19:05 +0100785/* Test for default SACCH FILL transmitted in DL SACCH (all channel types) */
Harald Welteea17b912018-03-11 22:29:31 +0100786private function f_TC_sacch_filling(charstring id) runs on ConnHdlr {
787 /* Set a known default SACCH filling for SI5 */
788 var octetstring si5 := f_rnd_octstring(19);
789 RSL.send(ts_RSL_SACCH_FILL(RSL_SYSTEM_INFO_5, si5));
790
791 f_l1_tune(L1CTL);
792 RSL.clear;
793
794 /* activate the logical channel */
795 f_est_dchan();
796
797 /* check that the specified SI5 value is actually sent */
798 f_sacch_present(si5);
799
800 /* release the channel */
801 RSL.clear;
802 f_rsl_chan_deact();
803 f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
804}
805testcase TC_sacch_filling() runs on test_CT {
806 var ConnHdlr vc_conn;
807 var ConnHdlrPars pars;
808 f_init();
809 for (var integer i := 0; i < sizeof(g_AllChannels); i := i+1) {
810 pars := valueof(t_Pars(g_AllChannels[i], ts_RSL_ChanMode_SIGN));
811 log(testcasename(), ": Starting for ", g_AllChannels[i]);
812 vc_conn := f_start_handler(refers(f_TC_sacch_filling), pars);
813 vc_conn.done;
814 }
815 /* TODO: do the above in parallel, rather than sequentially? */
Daniel Willmann0fcc4d32018-10-23 20:32:19 +0200816 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
Harald Welteea17b912018-03-11 22:29:31 +0100817}
818
Harald Welte629cc6b2018-03-11 17:19:05 +0100819/* Test for lchan-specific SACCH INFO MODIFY (TS 48.058 4.12) */
Harald Welteea17b912018-03-11 22:29:31 +0100820private function f_TC_sacch_info_mod(charstring id) runs on ConnHdlr {
821 /* Set a known default SACCH filling for SI5 */
822 var octetstring si5 := f_rnd_octstring(19);
823 var octetstring si5_diff := f_rnd_octstring(19);
824 RSL.send(ts_RSL_SACCH_FILL(RSL_SYSTEM_INFO_5, si5));
825
826 f_l1_tune(L1CTL);
827 RSL.clear;
828
829 log("Activating channel, expecting standard SI5");
830 /* activate the logical channel */
831 f_est_dchan();
832 /* check that the specified SI5 value is actually sent */
833 f_sacch_present(si5);
834
835 /* set channel-specific different SI5 */
836 log("Setting channel specific SACCH INFO, expecting it");
837 RSL.send(ts_RSL_SACCH_INF_MOD(g_chan_nr, RSL_SYSTEM_INFO_5, si5_diff))
838 /* check that the specified lchan-specific value is now used */
839 f_sacch_present(si5_diff);
840
841 /* deactivate the channel and re-activate it, this should result in default SI5 */
842 log("De-activating and re-activating channel, expecting standard SI5");
843 f_rsl_chan_deact();
844 f_rsl_chan_act(valueof(ts_RSL_ChanMode_SIGN));
845 /* Verify that the TRX-wide default SACCH filling is present again */
846 f_sacch_present(si5);
847
848 /* release the channel */
849 RSL.clear;
850 f_rsl_chan_deact();
851 f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
852}
853testcase TC_sacch_info_mod() runs on test_CT {
854 var ConnHdlr vc_conn;
855 var ConnHdlrPars pars;
856 f_init();
857 for (var integer i := 0; i < sizeof(g_AllChannels); i := i+1) {
858 pars := valueof(t_Pars(g_AllChannels[i], ts_RSL_ChanMode_SIGN));
859 log(testcasename(), ": Starting for ", g_AllChannels[i]);
860 vc_conn := f_start_handler(refers(f_TC_sacch_info_mod), pars);
861 vc_conn.done;
862 }
863 /* TODO: do the above in parallel, rather than sequentially? */
Daniel Willmann0fcc4d32018-10-23 20:32:19 +0200864 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
Harald Welteea17b912018-03-11 22:29:31 +0100865}
866
Harald Welte075d84c2018-03-12 13:07:24 +0100867/* Test SACCH scheduling of multiple different SI message types */
868private function f_TC_sacch_multi(charstring id) runs on ConnHdlr {
869 var octetstring si5 := f_rnd_octstring(19);
870 var octetstring si5bis := f_rnd_octstring(19);
871 var octetstring si5ter := f_rnd_octstring(19);
872 var octetstring si6 := f_rnd_octstring(19);
873
874 RSL.send(ts_RSL_SACCH_FILL(RSL_SYSTEM_INFO_5, si5));
875 RSL.send(ts_RSL_SACCH_FILL(RSL_SYSTEM_INFO_5bis, si5bis));
876 RSL.send(ts_RSL_SACCH_FILL(RSL_SYSTEM_INFO_5ter, si5ter));
877 RSL.send(ts_RSL_SACCH_FILL(RSL_SYSTEM_INFO_6, si6));
878
879 f_l1_tune(L1CTL);
880 RSL.clear;
881
882 /* activate the logical channel */
883 f_est_dchan();
884 L1CTL.clear;
885
886 /* check that SACCH actually are received as expected */
887 f_sacch_present(si5);
888 f_sacch_present(si5bis);
889 f_sacch_present(si5ter);
890 f_sacch_present(si6);
891
892 /* release the channel */
893 f_rsl_chan_deact();
894 f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
895}
896testcase TC_sacch_multi() runs on test_CT {
897 var ConnHdlr vc_conn;
898 var ConnHdlrPars pars;
899 f_init();
900 for (var integer i := 0; i < sizeof(g_AllChannels); i := i+1) {
901 pars := valueof(t_Pars(g_AllChannels[i], ts_RSL_ChanMode_SIGN));
902 log(testcasename(), ": Starting for ", g_AllChannels[i]);
903 vc_conn := f_start_handler(refers(f_TC_sacch_multi), pars);
904 vc_conn.done;
905 }
906 /* TODO: do the above in parallel, rather than sequentially? */
Daniel Willmann0fcc4d32018-10-23 20:32:19 +0200907 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
Harald Welte075d84c2018-03-12 13:07:24 +0100908}
909
Harald Welte55700662018-03-12 13:15:43 +0100910/* Test if SACH information is modified as expected */
911private function f_TC_sacch_multi_chg(charstring id) runs on ConnHdlr {
912 var octetstring si5 := f_rnd_octstring(19);
913 var octetstring si6 := f_rnd_octstring(19);
914
915 /* First, configure both SI5 and SI6 to be transmitted */
916 RSL.send(ts_RSL_SACCH_FILL(RSL_SYSTEM_INFO_5, si5));
917 RSL.send(ts_RSL_SACCH_FILL(RSL_SYSTEM_INFO_6, si6));
918
919 f_l1_tune(L1CTL);
920 RSL.clear;
921
922 /* activate the logical channel */
923 f_est_dchan();
924 L1CTL.clear;
925
926 /* check that SACCH actually are received as expected */
927 f_sacch_present(si5);
928 f_sacch_present(si6);
929
930 /* disable SI6 */
931 RSL.send(ts_RSL_SACCH_FILL(RSL_SYSTEM_INFO_6, ''O));
932
933 /* check that SI5 is still transmitted */
934 f_sacch_present(si5);
935 /* check if SI6 is now gone */
936 f_sacch_missing(si6);
937
938 /* release the channel */
939 f_rsl_chan_deact();
940 f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
941}
942testcase TC_sacch_multi_chg() runs on test_CT {
943 var ConnHdlr vc_conn;
944 var ConnHdlrPars pars;
945 f_init();
946 for (var integer i := 0; i < sizeof(g_AllChannels); i := i+1) {
947 pars := valueof(t_Pars(g_AllChannels[i], ts_RSL_ChanMode_SIGN));
948 log(testcasename(), ": Starting for ", g_AllChannels[i]);
949 vc_conn := f_start_handler(refers(f_TC_sacch_multi_chg), pars);
950 vc_conn.done;
951 }
952 /* TODO: do the above in parallel, rather than sequentially? */
Daniel Willmann0fcc4d32018-10-23 20:32:19 +0200953 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
Harald Welte55700662018-03-12 13:15:43 +0100954}
955
Harald Welte075d84c2018-03-12 13:07:24 +0100956/* TODO: Test for SACCH information present in RSL CHAN ACT (overrides FILLING) */
957/* TODO: Test for SACCH transmission rules in the context of special CHAN ACT (HO) */
Harald Welte629cc6b2018-03-11 17:19:05 +0100958
959
960/***********************************************************************
Harald Welte93640c62018-02-25 16:59:33 +0100961 * RACH Handling
962 ***********************************************************************/
963
Harald Welte8c24c2b2018-02-26 08:31:31 +0100964/* like L1SAP_IS_PACKET_RACH */
965private function ra_is_ps(OCT1 ra) return boolean {
Harald Welte56c05802018-02-28 21:39:35 +0100966 if ((ra and4b 'F0'O == '70'O) and (ra and4b '0F'O != '0F'O)) {
Harald Welte8c24c2b2018-02-26 08:31:31 +0100967 return true;
968 }
969 return false;
970}
971
972/* generate a random RACH for circuit-switched */
973private function f_rnd_ra_cs() return OCT1 {
974 var OCT1 ra;
975 do {
976 ra := f_rnd_octstring(1);
977 } while (ra_is_ps(ra));
978 return ra;
979}
980
Harald Welte883340c2018-02-28 18:59:29 +0100981/* generate a random RACH for packet-switched */
982private function f_rnd_ra_ps() return OCT1 {
983 var OCT1 ra;
984 do {
985 ra := f_rnd_octstring(1);
986 } while (not ra_is_ps(ra));
987 return ra;
988}
989
Harald Welte8c24c2b2018-02-26 08:31:31 +0100990/* Send 1000 RACH requests and check their RA+FN on the RSL side */
991testcase TC_rach_content() runs on test_CT {
992 f_init(testcasename());
993 f_init_l1ctl();
Harald Welte68e495b2018-02-25 00:05:57 +0100994 f_l1_tune(L1CTL);
Harald Welte70767382018-02-21 12:16:40 +0100995
Harald Welte8c24c2b2018-02-26 08:31:31 +0100996 var GsmFrameNumber fn_last := 0;
997 for (var integer i := 0; i < 1000; i := i+1) {
998 var OCT1 ra := f_rnd_ra_cs();
999 var GsmFrameNumber fn := f_L1CTL_RACH(L1CTL, oct2int(ra));
1000 if (fn == fn_last) {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02001001 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Two RACH in same FN?!?");
Harald Welte8c24c2b2018-02-26 08:31:31 +01001002 }
1003 fn_last := fn;
1004
1005 timer T := 5.0;
Harald Welte56c05802018-02-28 21:39:35 +01001006 T.start;
Harald Welte8c24c2b2018-02-26 08:31:31 +01001007 alt {
1008 [] RSL_CCHAN.receive(tr_RSL_UD(tr_RSL_CHAN_RQD(ra, fn, ?))) {
1009 T.stop;
1010 }
1011 [] RSL_CCHAN.receive(tr_RSL_UD(tr_RSL_CHAN_RQD(?, ?, ?))) {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02001012 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Unexpected CHAN RQD");
Harald Welte8c24c2b2018-02-26 08:31:31 +01001013 }
1014 [] RSL_CCHAN.receive { repeat; }
1015 [] T.timeout {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02001016 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout waiting for CHAN RQD");
Harald Welte8c24c2b2018-02-26 08:31:31 +01001017 }
1018 }
1019 }
1020 setverdict(pass);
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02001021 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
Harald Welte70767382018-02-21 12:16:40 +01001022}
Harald Welte8c24c2b2018-02-26 08:31:31 +01001023
1024/* Send 1000 RACH Requests (flood ~ 89/s) and count if count(Abis) == count(Um) */
1025testcase TC_rach_count() runs on test_CT {
Harald Welte294b0a22018-03-10 23:26:48 +01001026 f_init();
Harald Welte8c24c2b2018-02-26 08:31:31 +01001027 f_init_l1ctl();
Harald Welte294b0a22018-03-10 23:26:48 +01001028 f_sleep(1.0);
Harald Welte8c24c2b2018-02-26 08:31:31 +01001029 f_l1_tune(L1CTL);
1030
1031 var GsmFrameNumber fn_last := 0;
1032 for (var integer i := 0; i < 1000; i := i+1) {
1033 var OCT1 ra := f_rnd_ra_cs();
1034 var GsmFrameNumber fn := f_L1CTL_RACH(L1CTL, oct2int(ra));
1035 if (fn == fn_last) {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02001036 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Two RACH in same FN?!?");
Harald Welte8c24c2b2018-02-26 08:31:31 +01001037 }
1038 fn_last := fn;
1039 }
1040 var integer rsl_chrqd := 0;
1041 timer T := 3.0;
Harald Welte56c05802018-02-28 21:39:35 +01001042 T.start;
Harald Welte8c24c2b2018-02-26 08:31:31 +01001043 alt {
1044 [] RSL_CCHAN.receive(tr_RSL_UD(tr_RSL_CHAN_RQD(?,?))) {
1045 rsl_chrqd := rsl_chrqd + 1;
Harald Weltec3a3f452018-02-26 17:37:47 +01001046 f_timer_safe_restart(T);
Harald Welte8c24c2b2018-02-26 08:31:31 +01001047 repeat;
1048 }
1049 [] RSL_CCHAN.receive { repeat; }
1050 [] T.timeout { }
1051 }
1052 if (rsl_chrqd == 1000) {
1053 setverdict(pass);
1054 } else {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02001055 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("Received only ", rsl_chrqd, " out of 1000 RACH"));
Harald Welte8c24c2b2018-02-26 08:31:31 +01001056 }
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02001057 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
Harald Welte70767382018-02-21 12:16:40 +01001058}
1059
Harald Welte54a2a2d2018-02-26 09:14:05 +01001060private function f_main_trxc_connect() runs on test_CT {
1061 map(self:BB_TRXC, system:BB_TRXC);
1062 var Result res;
Harald Welted3a88a62018-03-01 16:04:52 +01001063 res := TRXC_CodecPort_CtrlFunct.f_IPL4_connect(BB_TRXC, mp_bb_trxc_ip, mp_bb_trxc_port,
1064 "", -1, -1, {udp:={}}, {});
Harald Welte9220f632018-05-23 20:27:02 +02001065 if (not ispresent(res.connId)) {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02001066 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Could not connect to trx-control interface of trxcon, check your configuration");
Harald Welte9220f632018-05-23 20:27:02 +02001067 }
Harald Welte54a2a2d2018-02-26 09:14:05 +01001068 g_bb_trxc_conn_id := res.connId;
1069}
1070
1071private function f_rach_toffs(int16_t toffs256, boolean expect_pass) runs on test_CT {
Harald Weltef8df4cb2018-03-10 15:15:08 +01001072 var TrxcMessage ret;
Harald Welte54a2a2d2018-02-26 09:14:05 +01001073 /* tell fake_trx to use a given timing offset for all bursts */
Harald Weltef8df4cb2018-03-10 15:15:08 +01001074 ret := f_TRXC_transceive(BB_TRXC, g_bb_trxc_conn_id, valueof(ts_TRXC_FAKE_TIMING(toffs256)));
Harald Welte54a2a2d2018-02-26 09:14:05 +01001075 f_sleep(0.5);
1076
1077 /* Transmit RACH request + wait for confirmation */
1078 var OCT1 ra := f_rnd_ra_cs();
1079 var GsmFrameNumber fn := f_L1CTL_RACH(L1CTL, oct2int(ra));
1080
1081 /* Check for expected result */
1082 timer T := 1.5;
1083 T.start;
1084 alt {
1085 [expect_pass] RSL_CCHAN.receive(tr_RSL_UD(tr_RSL_CHAN_RQD(ra, fn))) {
1086 setverdict(pass);
1087 }
1088 [not expect_pass] RSL_CCHAN.receive(tr_RSL_UD(tr_RSL_CHAN_RQD(ra, fn))) {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02001089 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("RACH passed but was expected to be dropped: ", toffs256));
Harald Welte54a2a2d2018-02-26 09:14:05 +01001090 }
1091 [] RSL_CCHAN.receive { repeat; }
1092 [not expect_pass] T.timeout {
1093 setverdict(pass);
1094 }
1095 [expect_pass] T.timeout {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02001096 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout waiting for CHAN RQD");
Harald Welte54a2a2d2018-02-26 09:14:05 +01001097 }
1098 }
1099}
1100
1101/* Test if dropping of RACH Based on NM_ATT_MAX_TA works */
1102testcase TC_rach_max_ta() runs on test_CT {
1103 f_init(testcasename());
1104 f_init_l1ctl();
1105 f_l1_tune(L1CTL);
Harald Welte54a2a2d2018-02-26 09:14:05 +01001106 f_sleep(1.0);
1107
1108 /* default max-ta is 63 (full range of GSM timing advance */
1109
Vadim Yanitskiyc81d6e42018-03-05 22:39:01 +07001110 /* We allow early arrival up to 2 symbols */
1111 f_rach_toffs(-1*256, true);
1112 f_rach_toffs(-2*256, true);
Harald Welte54a2a2d2018-02-26 09:14:05 +01001113 f_rach_toffs(-10*256, false);
1114
1115 /* 0 / 32 / 63 bits is legal / permitted */
1116 f_rach_toffs(0, true);
1117 f_rach_toffs(32*256, true);
1118 f_rach_toffs(63*256, true);
1119
1120 /* more than 63 bits is not legal / permitted */
1121 f_rach_toffs(64*256, false);
1122 f_rach_toffs(127*256, false);
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02001123 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
Harald Welte54a2a2d2018-02-26 09:14:05 +01001124}
Harald Welte8c24c2b2018-02-26 08:31:31 +01001125
Harald Welte93640c62018-02-25 16:59:33 +01001126/***********************************************************************
1127 * Measurement Processing / Reporting
1128 ***********************************************************************/
1129
Harald Welte70767382018-02-21 12:16:40 +01001130template LapdmAddressField ts_LapdmAddr(LapdmSapi sapi, boolean c_r) := {
1131 spare := '0'B,
1132 lpd := 0,
1133 sapi := sapi,
1134 c_r := c_r,
1135 ea := true
1136}
1137
Harald Welted879bd92018-03-12 15:01:23 +01001138template LapdmFrameAB ts_LAPDm_AB(LapdmSapi sapi, boolean c_r, boolean p, octetstring pl) := {
Harald Welte70767382018-02-21 12:16:40 +01001139 addr := ts_LapdmAddr(sapi, c_r),
Harald Welted879bd92018-03-12 15:01:23 +01001140 ctrl := ts_LapdmCtrlUI(p),
Harald Welte70767382018-02-21 12:16:40 +01001141 len := 0, /* overwritten */
1142 m := false,
1143 el := 1,
1144 payload := pl
1145}
1146
1147/* handle incoming downlink SACCH and respond with uplink SACCH (meas res) */
1148altstep as_l1_sacch() runs on ConnHdlr {
1149 var L1ctlDlMessage l1_dl;
Harald Weltef8df4cb2018-03-10 15:15:08 +01001150 [] L1CTL.receive(tr_L1CTL_DATA_IND(g_chan_nr, tr_RslLinkID_SACCH(?))) -> value l1_dl {
Harald Welte70767382018-02-21 12:16:40 +01001151 log("SACCH received: ", l1_dl.payload.data_ind.payload);
Pau Espin Pedrole9571aa2018-10-22 17:13:07 +02001152 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 +01001153 var LapdmFrameAB lb := valueof(ts_LAPDm_AB(0, false, false, enc_GsmRrL3Message(meas_rep)));
Harald Welte70767382018-02-21 12:16:40 +01001154 log("LAPDm: ", lb);
Pau Espin Pedroled359cb2018-09-28 16:08:24 +02001155
1156 var L1ctlDataReq data_req := {
1157 l1header := valueof(ts_SacchL1Header(g_pars.l1_pars.ms_power_level, false, g_pars.l1_pars.ms_actual_ta)),
1158 l2_payload := f_pad_oct(enc_LapdmFrameAB(lb), 21, '2B'O)
1159 }
1160 log("Sending Measurement Report: ", data_req);
1161 L1CTL.send(ts_L1CTL_DATA_REQ_SACCH(g_chan_nr, ts_RslLinkID_SACCH(0), data_req));
Harald Welte70767382018-02-21 12:16:40 +01001162 repeat;
1163 }
1164}
1165
1166altstep as_l1_dcch() runs on ConnHdlr {
1167 var L1ctlDlMessage l1_dl;
Harald Weltef8df4cb2018-03-10 15:15:08 +01001168 [] L1CTL.receive(tr_L1CTL_DATA_IND(g_chan_nr, tr_RslLinkID_DCCH(?))) -> value l1_dl {
Harald Welte70767382018-02-21 12:16:40 +01001169 log("DCCH received: ", l1_dl.payload.data_ind.payload);
1170 var octetstring pl := '010301'O;
Vadim Yanitskiy31e7c672018-07-27 02:23:16 +07001171 L1CTL.send(ts_L1CTL_DATA_REQ(g_chan_nr, ts_RslLinkID_DCCH(0),
1172 f_pad_oct(pl, 23, '2B'O)));
Harald Welte70767382018-02-21 12:16:40 +01001173 repeat;
1174 }
1175}
1176
1177type record MeasElem {
1178 uint6_t rxlev,
1179 uint3_t rxqual
1180}
1181
1182type record MeasElemFS {
1183 MeasElem full,
1184 MeasElem sub
1185}
1186
1187type record ConnL1Pars {
1188 boolean dtx_enabled,
Harald Welte685d5982018-02-27 20:42:05 +01001189 boolean toa256_enabled,
Harald Welte70767382018-02-21 12:16:40 +01001190 MeasElemFS meas_ul,
1191 int16_t timing_offset_256syms,
1192 uint5_t bs_power_level,
1193 uint5_t ms_power_level,
1194 uint8_t ms_actual_ta
1195}
1196
1197/* Convert tiing offset from 1/256th symbol to RSL Timing Offset */
1198private function toffs256s_to_rsl(int16_t toffs256s) return uint8_t {
1199 return 63 + (toffs256s/256);
1200}
1201
Harald Welted5684392018-03-10 18:22:04 +01001202private function f_max(integer a, integer b) return integer {
1203 if (a > b) {
1204 return a;
1205 } else {
1206 return b;
1207 }
1208}
1209
1210private function f_min(integer a, integer b) return integer {
1211 if (a < b) {
1212 return a;
1213 } else {
1214 return b;
1215 }
1216}
1217
1218/* compute negative tolerance val-tolerance, ensure >= min */
1219private function f_tolerance_neg(integer val, integer min, integer tolerance) return integer {
1220 val := val - tolerance;
1221 return f_max(val, min);
1222}
1223
1224/* compute positive tolerance val+tolerance, ensure <= max */
1225private function f_tolerance_pos(integer val, integer max, integer tolerance) return integer {
1226 val := val + tolerance;
1227 return f_min(val, max);
1228}
1229
1230/* return a template of (val-tolerance .. val+tolerance) ensuring it is within (min .. max) */
1231private function f_tolerance(integer val, integer min, integer max, integer tolerance)
1232return template integer {
1233 var template integer ret;
1234 ret := (f_tolerance_neg(val, min, tolerance) .. f_tolerance_pos(val, max, tolerance));
1235 return ret;
1236}
1237
1238
Harald Welte70767382018-02-21 12:16:40 +01001239/* build a template for matching measurement results against */
1240private function f_build_meas_res_tmpl() runs on ConnHdlr return template RSL_Message {
1241 var ConnL1Pars l1p := g_pars.l1_pars;
1242 var template RSL_IE_UplinkMeas ul_meas := {
1243 len := 3,
1244 rfu := '0'B,
1245 dtx_d := l1p.dtx_enabled,
Harald Welted5684392018-03-10 18:22:04 +01001246 rxlev_f_u := f_tolerance(l1p.meas_ul.full.rxlev, 0, 63, mp_tolerance_rxlev),
Harald Welte70767382018-02-21 12:16:40 +01001247 reserved1 := '00'B,
Harald Welted5684392018-03-10 18:22:04 +01001248 rxlev_s_u := f_tolerance(l1p.meas_ul.sub.rxlev, 0, 63, mp_tolerance_rxlev),
Harald Welte70767382018-02-21 12:16:40 +01001249 reserved2 := '00'B,
Harald Welted5684392018-03-10 18:22:04 +01001250 rxq_f_u := f_tolerance(l1p.meas_ul.full.rxqual, 0, 7, mp_tolerance_rxqual),
1251 rxq_s_u := f_tolerance(l1p.meas_ul.sub.rxqual, 0, 7, mp_tolerance_rxqual),
Harald Welte70767382018-02-21 12:16:40 +01001252 supp_meas_info := omit
1253 };
Harald Welte685d5982018-02-27 20:42:05 +01001254 if (l1p.toa256_enabled) {
Harald Welte15de8ba2018-06-29 08:51:42 +02001255 ul_meas.len := (3+8);
1256 ul_meas.supp_meas_info := {
Pau Espin Pedrol121724c2018-09-28 15:58:12 +02001257 toa256_mean := f_tolerance(l1p.timing_offset_256syms, -63*256, 192*256, mp_tolerance_timing_offset_256syms),
Harald Welte15de8ba2018-06-29 08:51:42 +02001258 toa256_min := ?,
1259 toa256_max := ?,
1260 toa256_std_dev := ?
1261 }
Harald Welte685d5982018-02-27 20:42:05 +01001262 }
Harald Welte70767382018-02-21 12:16:40 +01001263 var template RSL_IE_BS_Power bs_power := {
1264 reserved := 0,
1265 epc := false,
1266 fpc := false,
1267 power_level := l1p.bs_power_level
1268 };
1269 var template RSL_IE_L1Info l1_info := {
1270 ms_power_lvl := l1p.ms_power_level,
1271 fpc := false,
1272 reserved := 0,
Pau Espin Pedrol121724c2018-09-28 15:58:12 +02001273 actual_ta := f_tolerance(l1p.ms_actual_ta, 0, 63, mp_tolerance_timing_offset_256syms/256)
Harald Welte70767382018-02-21 12:16:40 +01001274 };
1275 var uint8_t offs := toffs256s_to_rsl(l1p.timing_offset_256syms);
Pau Espin Pedrol121724c2018-09-28 15:58:12 +02001276 var template uint8_t t_toffs := f_tolerance(offs, 0, 255, mp_tolerance_timing_offset_256syms/256);
Harald Welte70767382018-02-21 12:16:40 +01001277 return tr_RSL_MEAS_RES_OSMO(g_chan_nr, g_next_meas_res_nr, ul_meas, bs_power, l1_info,
1278 ?, t_toffs);
1279}
1280
1281/* verify we regularly receive measurement reports with incrementing numbers */
Vadim Yanitskiy41baf002018-10-04 17:44:50 +07001282altstep as_meas_res(boolean verify_meas := true) runs on ConnHdlr {
Harald Welte70767382018-02-21 12:16:40 +01001283 var RSL_Message rsl;
Vadim Yanitskiy41baf002018-10-04 17:44:50 +07001284 [not verify_meas] RSL.receive(tr_RSL_MEAS_RES(?)) { repeat; }
Harald Welte70767382018-02-21 12:16:40 +01001285 [] RSL.receive(f_build_meas_res_tmpl()) -> value rsl {
1286 /* increment counter of next to-be-expected meas rep */
1287 g_next_meas_res_nr := (g_next_meas_res_nr + 1) mod 256;
1288 /* Re-start the timer expecting the next MEAS RES */
Harald Weltec3a3f452018-02-26 17:37:47 +01001289 f_timer_safe_restart(g_Tmeas_exp);
Harald Welte70767382018-02-21 12:16:40 +01001290 repeat;
1291 }
1292 [] RSL.receive(tr_RSL_MEAS_RES(g_chan_nr, g_next_meas_res_nr)) -> value rsl {
Harald Weltefa45e9e2018-03-10 18:59:03 +01001293 /* increment counter of next to-be-expected meas rep */
1294 g_next_meas_res_nr := (g_next_meas_res_nr + 1) mod 256;
1295 if (g_first_meas_res) {
1296 g_first_meas_res := false;
1297 repeat;
1298 } else {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02001299 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("Received unspecific MEAS RES ", rsl));
Harald Weltefa45e9e2018-03-10 18:59:03 +01001300 }
Harald Welte70767382018-02-21 12:16:40 +01001301 }
1302 [] RSL.receive(tr_RSL_MEAS_RES(?)) -> value rsl {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02001303 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("Received unexpected MEAS RES ", rsl));
Harald Welte70767382018-02-21 12:16:40 +01001304 }
Pau Espin Pedrol425b62f2018-07-06 16:11:43 +02001305 [g_Tmeas_exp.running] g_Tmeas_exp.timeout {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02001306 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Didn't receive expected measurement result")
Harald Welte70767382018-02-21 12:16:40 +01001307 }
1308}
1309
Harald Weltee613f962018-04-18 22:38:16 +02001310private function f_alg_id_to_l1ctl(RSL_AlgId rsl_alg_id) return uint8_t {
1311 select (rsl_alg_id) {
1312 case (RSL_ALG_ID_A5_0) { return 0; }
1313 case (RSL_ALG_ID_A5_1) { return 1; }
1314 case (RSL_ALG_ID_A5_2) { return 2; }
1315 case (RSL_ALG_ID_A5_3) { return 3; }
1316 case (RSL_ALG_ID_A5_4) { return 4; }
1317 case (RSL_ALG_ID_A5_5) { return 5; }
1318 case (RSL_ALG_ID_A5_6) { return 6; }
1319 case (RSL_ALG_ID_A5_7) { return 7; }
1320 case else {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02001321 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Unknwon Algorithm ID");
1322 /* Make compiler happy by calling mtc.stop here. It is already
1323 * called in f_shutdown */
Daniel Willmann17ddd852018-07-05 17:33:20 +02001324 mtc.stop;
Harald Weltee613f962018-04-18 22:38:16 +02001325 }
1326 }
1327}
1328
1329private function f_alg_id_to_l3(RSL_AlgId rsl_alg_id) return BIT3 {
1330 select (rsl_alg_id) {
1331 case (RSL_ALG_ID_A5_1) { return '000'B; }
1332 case (RSL_ALG_ID_A5_2) { return '001'B; }
1333 case (RSL_ALG_ID_A5_3) { return '010'B; }
1334 case (RSL_ALG_ID_A5_4) { return '011'B; }
1335 case (RSL_ALG_ID_A5_5) { return '100'B; }
1336 case (RSL_ALG_ID_A5_6) { return '101'B; }
1337 case (RSL_ALG_ID_A5_7) { return '110'B; }
1338 case else {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02001339 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Unknwon Algorithm ID");
1340 /* Make compiler happy by calling mtc.stop here. It is already
1341 * called in f_shutdown */
Daniel Willmann17ddd852018-07-05 17:33:20 +02001342 mtc.stop;
Harald Weltee613f962018-04-18 22:38:16 +02001343 }
1344 }
1345}
1346
1347
Harald Welte70767382018-02-21 12:16:40 +01001348/* Establish dedicated channel: L1CTL + RSL side */
Harald Weltee613f962018-04-18 22:38:16 +02001349private function f_est_dchan(boolean encr_enable := false) runs on ConnHdlr {
Harald Welte70767382018-02-21 12:16:40 +01001350 var GsmFrameNumber fn;
1351 var ImmediateAssignment imm_ass;
1352 var integer ra := 23;
1353
Pau Espin Pedrol99a7aca2018-09-28 16:10:32 +02001354 f_L1CTL_PARAM(L1CTL, g_pars.l1_pars.ms_actual_ta, g_pars.l1_pars.ms_power_level);
Harald Welte70767382018-02-21 12:16:40 +01001355 fn := f_L1CTL_RACH(L1CTL, ra);
1356 /* This arrives on CCHAN, so we cannot test for receiving CHAN RQDhere */
1357 //RSL.receive(tr_RSL_CHAN_RQD(int2oct(23,1)));
1358
1359 /* Activate channel on BTS side */
Harald Weltee613f962018-04-18 22:38:16 +02001360 f_rsl_chan_act(g_pars.chan_mode, encr_enable);
Harald Welte70767382018-02-21 12:16:40 +01001361
1362 /* Send IMM.ASS via CCHAN */
1363 var ChannelDescription ch_desc := {
1364 chan_nr := g_pars.chan_nr,
1365 tsc := 7,
1366 h := false,
1367 arfcn := mp_trx0_arfcn,
1368 maio_hsn := omit
1369 };
1370 var MobileAllocation ma := {
1371 len := 0,
1372 ma := ''B
1373 };
1374 var GsmRrMessage rr_msg := valueof(ts_IMM_ASS(ra, fn, 0, ch_desc, ma));
1375 RSL.send(ts_RSL_IMM_ASSIGN(enc_GsmRrMessage(rr_msg)));
1376
1377 /* receive IMM.ASS on MS side */
1378 var ImmediateAssignment ia_um;
1379 ia_um := f_L1CTL_WAIT_IMM_ASS(L1CTL, ra, fn);
1380 /* enable dedicated mode */
1381 f_L1CTL_DM_EST_REQ_IA(L1CTL, ia_um);
Harald Weltee613f962018-04-18 22:38:16 +02001382 /* enable encryption, if requested */
1383 if (encr_enable) {
1384 var uint8_t alg_id := f_alg_id_to_l1ctl(g_pars.encr.alg_id);
1385 f_L1CTL_CRYPTO_REQ(L1CTL, g_pars.chan_nr, alg_id, g_pars.encr.key);
1386 }
Harald Weltefa45e9e2018-03-10 18:59:03 +01001387
1388 g_first_meas_res := true;
Harald Welte70767382018-02-21 12:16:40 +01001389}
1390
1391/* establish DChan, verify existance + contents of measurement reports */
1392function f_TC_meas_res_periodic(charstring id) runs on ConnHdlr {
Harald Welte68e495b2018-02-25 00:05:57 +01001393 f_l1_tune(L1CTL);
Harald Welte70767382018-02-21 12:16:40 +01001394 RSL.clear;
1395
Pau Espin Pedrol121724c2018-09-28 15:58:12 +02001396 if (mp_bb_trxc_port != -1) {
Pau Espin Pedrole9571aa2018-10-22 17:13:07 +02001397 f_trxc_fake_rssi(rxlev2dbm(mp_ul_rxlev_exp));
Pau Espin Pedrol121724c2018-09-28 15:58:12 +02001398 f_trx_fake_toffs256(g_pars.l1_pars.timing_offset_256syms);
1399 }
Harald Welte70767382018-02-21 12:16:40 +01001400
1401 f_est_dchan();
1402
1403 /* run for a number of seconds, send SACCH + FACCH from MS side and verify
1404 * RSL measurement reports on Abis side */
1405 timer T := 8.0;
1406 T.start;
1407 alt {
1408 [] as_l1_sacch();
1409 [] as_meas_res();
1410 [] as_l1_dcch();
1411 [] L1CTL.receive { repeat; }
1412 [g_Tmeas_exp.running] T.timeout {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02001413 /* as_meas_res() would have done Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail) in case
Harald Welte70767382018-02-21 12:16:40 +01001414 * of any earlier errors, so if we reach this timeout, we're good */
1415 setverdict(pass);
1416 }
1417 [] T.timeout {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02001418 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "No MEAS RES received at all");
Harald Welte70767382018-02-21 12:16:40 +01001419 }
1420 }
1421 f_rsl_chan_deact();
Harald Welte3dc20462018-03-10 23:03:38 +01001422 f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
Harald Welte70767382018-02-21 12:16:40 +01001423}
Harald Welte0472ab42018-03-12 15:02:26 +01001424
Harald Welte70767382018-02-21 12:16:40 +01001425testcase TC_meas_res_sign_tchf() runs on test_CT {
1426 var ConnHdlr vc_conn;
1427 var ConnHdlrPars pars;
1428 f_init(testcasename());
1429 for (var integer tn := 1; tn <= 4; tn := tn+1) {
1430 pars := valueof(t_Pars(t_RslChanNr_Bm(tn), ts_RSL_ChanMode_SIGN));
1431 vc_conn := f_start_handler(refers(f_TC_meas_res_periodic), pars);
1432 vc_conn.done;
1433 }
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02001434 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
Harald Welte70767382018-02-21 12:16:40 +01001435}
1436testcase TC_meas_res_sign_tchh() runs on test_CT {
1437 var ConnHdlr vc_conn;
1438 var ConnHdlrPars pars;
1439 f_init(testcasename());
1440 for (var integer ss := 0; ss <= 1; ss := ss+1) {
1441 pars := valueof(t_Pars(t_RslChanNr_Lm(5, ss), ts_RSL_ChanMode_SIGN));
1442 vc_conn := f_start_handler(refers(f_TC_meas_res_periodic), pars);
1443 vc_conn.done;
1444 }
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02001445 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
Harald Welte70767382018-02-21 12:16:40 +01001446}
1447testcase TC_meas_res_sign_sdcch4() runs on test_CT {
1448 var ConnHdlr vc_conn;
1449 var ConnHdlrPars pars;
1450 f_init(testcasename());
1451 for (var integer ss := 0; ss <= 3; ss := ss+1) {
1452 pars := valueof(t_Pars(t_RslChanNr_SDCCH4(0, ss), ts_RSL_ChanMode_SIGN));
1453 vc_conn := f_start_handler(refers(f_TC_meas_res_periodic), pars);
1454 vc_conn.done;
1455 }
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02001456 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
Harald Welte70767382018-02-21 12:16:40 +01001457}
1458testcase TC_meas_res_sign_sdcch8() runs on test_CT {
1459 var ConnHdlr vc_conn;
1460 var ConnHdlrPars pars;
1461 f_init(testcasename());
1462 for (var integer ss := 0; ss <= 7; ss := ss+1) {
1463 pars := valueof(t_Pars(t_RslChanNr_SDCCH8(6, ss), ts_RSL_ChanMode_SIGN));
1464 vc_conn := f_start_handler(refers(f_TC_meas_res_periodic), pars);
1465 vc_conn.done;
1466 }
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02001467 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
Harald Welte70767382018-02-21 12:16:40 +01001468}
Harald Welte685d5982018-02-27 20:42:05 +01001469testcase TC_meas_res_sign_tchh_toa256() runs on test_CT {
1470 var ConnHdlr vc_conn;
1471 var ConnHdlrPars pars;
1472 f_init(testcasename());
1473 f_vty_config(BTSVTY, "bts 0", "supp-meas-info toa256");
1474 for (var integer ss := 0; ss <= 1; ss := ss+1) {
1475 pars := valueof(t_Pars(t_RslChanNr_Lm(5, ss), ts_RSL_ChanMode_SIGN));
1476 pars.l1_pars.toa256_enabled := true;
1477 vc_conn := f_start_handler(refers(f_TC_meas_res_periodic), pars);
1478 vc_conn.done;
1479 }
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02001480 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
Harald Welte685d5982018-02-27 20:42:05 +01001481}
1482
Harald Welte70767382018-02-21 12:16:40 +01001483
Harald Welte0472ab42018-03-12 15:02:26 +01001484/* 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 +01001485private function f_TC_conn_fail_crit(charstring id) runs on ConnHdlr {
Harald Welte68e495b2018-02-25 00:05:57 +01001486 f_l1_tune(L1CTL);
Harald Welte70767382018-02-21 12:16:40 +01001487 RSL.clear;
1488
1489 f_est_dchan();
1490 f_sleep(2.0);
Harald Weltef8df4cb2018-03-10 15:15:08 +01001491 L1CTL.send(ts_L1CTL_DM_REL_REQ(g_chan_nr));
Harald Welte70767382018-02-21 12:16:40 +01001492
1493 timer T := 40.0;
1494 T.start;
1495 alt {
1496 [] RSL.receive(tr_RSL_CONN_FAIL_IND(g_chan_nr, ?)) {
1497 setverdict(pass)
1498 }
1499 [] RSL.receive { repeat };
1500 [] T.timeout {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02001501 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "No CONN FAIL IND received");
Harald Welte70767382018-02-21 12:16:40 +01001502 }
1503 }
1504 f_rsl_chan_deact();
1505}
1506testcase TC_conn_fail_crit() runs on test_CT {
1507 var ConnHdlr vc_conn;
1508 var ConnHdlrPars pars;
1509 f_init(testcasename());
1510 pars := valueof(t_Pars(t_RslChanNr_SDCCH8(6, 3), ts_RSL_ChanMode_SIGN));
1511 pars.t_guard := 60.0;
1512 vc_conn := f_start_handler(refers(f_TC_conn_fail_crit), pars);
1513 vc_conn.done;
1514}
1515
Harald Welte93640c62018-02-25 16:59:33 +01001516/***********************************************************************
1517 * Paging
1518 ***********************************************************************/
1519
Harald Welte68e495b2018-02-25 00:05:57 +01001520function tmsi_is_dummy(TMSIP_TMSI_V tmsi) return boolean {
1521 if (tmsi == 'FFFFFFFF'O) {
1522 return true;
1523 } else {
1524 return false;
1525 }
1526}
Harald Welte70767382018-02-21 12:16:40 +01001527
Philipp Maier82cb0b12018-08-31 14:41:39 +02001528type record allowedFn { integer frame_nr }
1529template allowedFn bs_ag_blks_res_0 := { frame_nr := (6, 12, 16, 22, 26, 32, 36, 42, 46) }
1530template allowedFn bs_ag_blks_res_1 := { frame_nr := (12, 16, 22, 26, 32, 36, 42, 46) }
1531template allowedFn bs_ag_blks_res_2 := { frame_nr := (16, 22, 26, 32, 36, 42, 46) }
1532template allowedFn bs_ag_blks_res_3 := { frame_nr := (22, 26, 32, 36, 42, 46) }
1533template allowedFn bs_ag_blks_res_4 := { frame_nr := (26, 32, 36, 42, 46) }
1534template allowedFn bs_ag_blks_res_5 := { frame_nr := (32, 36, 42, 46) }
1535template allowedFn bs_ag_blks_res_6 := { frame_nr := (36, 42, 46) }
1536template allowedFn bs_ag_blks_res_7 := { frame_nr := (42, 46) }
1537function check_pch_fn(integer frame_nr, integer bs_ag_blks_res) runs on test_CT
1538{
1539 var integer frame_nr_51;
1540 frame_nr_51 := frame_nr mod 51
1541
1542 var allowedFn fn_check;
1543 fn_check.frame_nr := frame_nr_51;
1544
1545 if (bs_ag_blks_res < 0 or bs_ag_blks_res > 7) {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02001546 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "bs_ag_blks_res out of valid range (0..7)");
Philipp Maier82cb0b12018-08-31 14:41:39 +02001547 return;
1548 }
1549
1550 if (bs_ag_blks_res == 0 and match(fn_check, bs_ag_blks_res_0)) {
1551 return;
1552 }
1553 if (bs_ag_blks_res == 1 and match(fn_check, bs_ag_blks_res_1)) {
1554 return;
1555 }
1556 if (bs_ag_blks_res == 2 and match(fn_check, bs_ag_blks_res_2)) {
1557 return;
1558 }
1559 if (bs_ag_blks_res == 3 and match(fn_check, bs_ag_blks_res_3)) {
1560 return;
1561 }
1562 if (bs_ag_blks_res == 4 and match(fn_check, bs_ag_blks_res_4)) {
1563 return;
1564 }
1565 if (bs_ag_blks_res == 5 and match(fn_check, bs_ag_blks_res_5)) {
1566 return;
1567 }
1568 if (bs_ag_blks_res == 6 and match(fn_check, bs_ag_blks_res_6)) {
1569 return;
1570 }
1571 if (bs_ag_blks_res == 7 and match(fn_check, bs_ag_blks_res_7)) {
1572 return;
1573 }
1574
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02001575 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "received paging on AGCH");
Philipp Maier82cb0b12018-08-31 14:41:39 +02001576 return;
1577}
1578
1579altstep 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 +01001580runs on test_CT {
1581 var L1ctlDlMessage dl;
Harald Weltef8df4cb2018-03-10 15:15:08 +01001582 [] L1CTL.receive(tr_L1CTL_DATA_IND(t_RslChanNr_PCH_AGCH(0), ?, c_DummyUI)) {
Harald Welte68e495b2018-02-25 00:05:57 +01001583 repeat;
1584 }
Harald Weltef8df4cb2018-03-10 15:15:08 +01001585 [] L1CTL.receive(tr_L1CTL_DATA_IND(t_RslChanNr_PCH_AGCH(0))) -> value dl {
Harald Welte68e495b2018-02-25 00:05:57 +01001586 var octetstring without_plen :=
1587 substr(dl.payload.data_ind.payload, 1, lengthof(dl.payload.data_ind.payload)-1);
1588 var PDU_ML3_NW_MS rr := dec_PDU_ML3_NW_MS(without_plen);
Philipp Maier82cb0b12018-08-31 14:41:39 +02001589
1590 check_pch_fn(dl.dl_info.frame_nr, cfg.bs_ag_blks_res);
1591
Harald Welte68e495b2018-02-25 00:05:57 +01001592 if (match(rr, tr_PAGING_REQ1)) {
1593 num_paging_rcv_msgs := num_paging_rcv_msgs + 1;
1594 num_paging_rcv_ids := num_paging_rcv_ids + 1;
1595 if (isvalue(rr.msgs.rrm.pagingReq_Type1.mobileIdentity2)) {
1596 num_paging_rcv_ids := num_paging_rcv_ids + 1;
1597 }
1598 } else if (match(rr, tr_PAGING_REQ2)) {
1599 num_paging_rcv_msgs := num_paging_rcv_msgs + 1;
1600 if (not tmsi_is_dummy(rr.msgs.rrm.pagingReq_Type2.mobileIdentity1)) {
1601 num_paging_rcv_ids := num_paging_rcv_ids + 1;
1602 }
1603 if (not tmsi_is_dummy(rr.msgs.rrm.pagingReq_Type2.mobileIdentity2)) {
1604 num_paging_rcv_ids := num_paging_rcv_ids + 1;
1605 }
1606 if (isvalue(rr.msgs.rrm.pagingReq_Type2.mobileIdentity3)) {
1607 num_paging_rcv_ids := num_paging_rcv_ids + 1;
1608 }
1609 } else if (match(rr, tr_PAGING_REQ3)) {
1610 num_paging_rcv_msgs := num_paging_rcv_msgs + 1;
1611 if (not tmsi_is_dummy(rr.msgs.rrm.pagingReq_Type3.mobileIdentity1)) {
1612 num_paging_rcv_ids := num_paging_rcv_ids + 1;
1613 }
1614 if (not tmsi_is_dummy(rr.msgs.rrm.pagingReq_Type3.mobileIdentity2)) {
1615 num_paging_rcv_ids := num_paging_rcv_ids + 1;
1616 }
1617 if (not tmsi_is_dummy(rr.msgs.rrm.pagingReq_Type3.mobileIdentity3)) {
1618 num_paging_rcv_ids := num_paging_rcv_ids + 1;
1619 }
1620 if (not tmsi_is_dummy(rr.msgs.rrm.pagingReq_Type3.mobileIdentity4)) {
1621 num_paging_rcv_ids := num_paging_rcv_ids + 1;
1622 }
1623 }
1624 repeat;
1625 }
1626}
1627
1628type record PagingTestCfg {
1629 boolean combined_ccch,
1630 integer bs_ag_blks_res,
1631 float load_factor,
1632 boolean exp_load_ind,
1633 boolean exp_overload,
1634 boolean use_tmsi
1635}
1636
1637type record PagingTestState {
1638 integer num_paging_sent,
1639 integer num_paging_rcv_msgs,
1640 integer num_paging_rcv_ids,
1641 integer num_overload
1642}
1643
1644/* receive + ignore RSL RF RES IND */
1645altstep as_rsl_res_ind() runs on test_CT {
1646 [] RSL_CCHAN.receive(tr_RSL_UD(tr_RSL_RF_RES_IND)) {
1647 repeat;
1648 }
1649}
1650
1651/* Helper function for paging related testing */
1652private function f_TC_paging(PagingTestCfg cfg) runs on test_CT return PagingTestState {
1653 f_init(testcasename());
1654 f_init_l1ctl();
1655 f_l1_tune(L1CTL);
1656
1657 var PagingTestState st := {
1658 num_paging_sent := 0,
1659 num_paging_rcv_msgs := 0,
1660 num_paging_rcv_ids := 0,
1661 num_overload := 0
1662 };
1663
1664 var float max_pch_blocks_per_sec := f_pch_block_rate_est(cfg.combined_ccch, cfg.bs_ag_blks_res);
1665 var float max_pch_imsi_per_sec;
1666 if (cfg.use_tmsi) {
1667 max_pch_imsi_per_sec := max_pch_blocks_per_sec * 4.0; /* Type 3 */
1668 } else {
1669 max_pch_imsi_per_sec := max_pch_blocks_per_sec * 2.0; /* Type 1 */
1670 }
1671 var float pch_blocks_per_sec := max_pch_imsi_per_sec * cfg.load_factor;
1672 var float interval := 1.0 / pch_blocks_per_sec;
Pau Espin Pedrol9c3ff4e2018-09-26 18:30:16 +02001673 var float time_total := 20.0;
1674 var integer pkt_total := float2int(time_total * pch_blocks_per_sec);
1675 log("pch_blocks_total=", pkt_total," pch_blocks_per_sec=", pch_blocks_per_sec, " interval=", interval);
Harald Welte68e495b2018-02-25 00:05:57 +01001676
Pau Espin Pedrol9c3ff4e2018-09-26 18:30:16 +02001677 timer T_total := 300.0; /* big value (far bigger than time_total), used to count elapsed time */
1678 T_total.start;
Harald Welte68e495b2018-02-25 00:05:57 +01001679
Pau Espin Pedrol9c3ff4e2018-09-26 18:30:16 +02001680 timer T_itv := 0.0;
1681 T_itv.start;
1682 while (st.num_paging_sent < pkt_total) {
Harald Welte68e495b2018-02-25 00:05:57 +01001683 alt {
1684 /* check for presence of CCCH LOAD IND (paging load) */
1685 [cfg.exp_overload] RSL_CCHAN.receive(tr_RSL_UD(tr_RSL_PAGING_LOAD_IND(0))) {
1686 st.num_overload := st.num_overload + 1;
1687 repeat;
1688 }
1689 [not cfg.exp_overload] RSL_CCHAN.receive(tr_RSL_UD(tr_RSL_PAGING_LOAD_IND(0))) {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02001690 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Unexpected PCH Overload");
Harald Welte68e495b2018-02-25 00:05:57 +01001691 }
1692 [cfg.exp_load_ind] RSL_CCHAN.receive(tr_RSL_UD(tr_RSL_PAGING_LOAD_IND)) {
1693 log("Rx LOAD_IND");
1694 /* FIXME: analyze/verify interval + contents */
1695 repeat;
1696 }
1697 /* check if paging requests arrive on Um side */
Philipp Maier82cb0b12018-08-31 14:41:39 +02001698 [] as_l1_count_paging(st.num_paging_rcv_msgs, st.num_paging_rcv_ids, cfg);
Harald Welte68e495b2018-02-25 00:05:57 +01001699 [] L1CTL.receive { repeat; }
Pau Espin Pedrol9c3ff4e2018-09-26 18:30:16 +02001700 [] T_itv.timeout {
1701 /* Send paging cmds based on elapsed time */
1702 var integer new_sent := f_min(pkt_total, float2int(T_total.read * pch_blocks_per_sec) + 1);
1703 while (st.num_paging_sent < new_sent) {
1704 /* build mobile Identity */
1705 var MobileL3_CommonIE_Types.MobileIdentityLV mi;
1706 if (cfg.use_tmsi) {
1707 mi := valueof(ts_MI_TMSI_LV(f_rnd_octstring(4)));
1708 } else {
1709 mi := valueof(ts_MI_IMSI_LV(f_gen_imsi(st.num_paging_sent)));
1710 }
1711 var octetstring mi_enc_lv := enc_MobileIdentityLV(mi);
1712 var octetstring mi_enc := substr(mi_enc_lv, 1, lengthof(mi_enc_lv)-1);
1713
1714 /* Send RSL PAGING COMMAND */
1715 RSL_CCHAN.send(ts_RSL_UD(ts_RSL_PAGING_CMD(mi_enc, st.num_paging_sent mod 4)));
1716
1717 st.num_paging_sent := st.num_paging_sent + 1;
1718 }
1719 if (st.num_paging_sent < pkt_total) {
1720 /* Wait for interval to next PAGING COMMAND */
1721 var float time_now := T_total.read;
1722 var float next_sched := int2float(st.num_paging_sent)*interval;
1723 if (next_sched > time_now) {
1724 T_itv.start(next_sched - time_now);
1725 } else {
1726 T_itv.start(0.0);
1727 }
1728 } else {
1729 /* We are done, no need to keep counting */
1730 T_total.stop;
1731 }
1732 }
1733 [] T_total.timeout { }
Harald Welte68e495b2018-02-25 00:05:57 +01001734 [] as_rsl_res_ind();
1735 }
1736 }
1737
1738 /* wait for max 18s for paging queue to drain (size: 200, ~ 13 per s -> 15s) */
1739 timer T_wait := 18.0;
1740 T_wait.start;
1741 alt {
Philipp Maier82cb0b12018-08-31 14:41:39 +02001742 [] as_l1_count_paging(st.num_paging_rcv_msgs, st.num_paging_rcv_ids, cfg);
Harald Welte68e495b2018-02-25 00:05:57 +01001743 [] L1CTL.receive { repeat; }
1744 /* 65535 == empty paging queue, we can terminate*/
1745 [] RSL_CCHAN.receive(tr_RSL_UD(tr_RSL_PAGING_LOAD_IND(65535))) { }
1746 [] RSL_CCHAN.receive(tr_RSL_UD(tr_RSL_PAGING_LOAD_IND)) { repeat; }
1747 [] T_wait.timeout {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02001748 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Waiting for empty paging queue");
Harald Welte68e495b2018-02-25 00:05:57 +01001749 }
1750 [] as_rsl_res_ind();
1751 }
1752
1753 log("num_paging_sent=", st.num_paging_sent, " rcvd_msgs=", st.num_paging_rcv_msgs,
1754 " rcvd_ids=", st.num_paging_rcv_ids);
1755 return st;
1756}
1757
1758/* Create ~ 80% paging load (IMSI only) sustained for about 20s, verifying that
1759 * - the number of Mobile Identities on Um PCH match the number of pages on RSL
1760 * - that CCCH LOAD IND (PCH) are being generated
1761 * - that CCCH LOAD IND (PCH) [no load] is received after paging flood is over */
1762testcase TC_paging_imsi_80percent() runs on test_CT {
Philipp Maierd65d0562018-08-30 16:25:47 +02001763 var SystemInformation si3 := valueof(ts_SI3_default);
Harald Welte68e495b2018-02-25 00:05:57 +01001764 var PagingTestCfg cfg := {
1765 combined_ccch := true,
Philipp Maierd65d0562018-08-30 16:25:47 +02001766 bs_ag_blks_res := si3.payload.si3.ctrl_chan_desc.bs_ag_blks_res,
Harald Welte68e495b2018-02-25 00:05:57 +01001767 load_factor := 0.8,
1768 exp_load_ind := true,
1769 exp_overload := false,
1770 use_tmsi := false
1771 };
1772 var PagingTestState st := f_TC_paging(cfg);
1773 if (st.num_paging_sent != st.num_paging_rcv_ids) {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02001774 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("Expected ", st.num_paging_sent, " pagings but have ",
1775 st.num_paging_rcv_ids));
Harald Welte68e495b2018-02-25 00:05:57 +01001776 } else {
1777 setverdict(pass);
1778 }
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02001779 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
Harald Welte68e495b2018-02-25 00:05:57 +01001780}
1781
1782/* Create ~ 80% paging load (TMSI only) sustained for about 20s, verifying that
1783 * - the number of Mobile Identities on Um PCH match the number of pages on RSL
1784 * - that CCCH LOAD IND (PCH) are being generated
1785 * - that CCCH LOAD IND (PCH) [no load] is received after paging flood is over */
1786testcase TC_paging_tmsi_80percent() runs on test_CT {
Philipp Maierd65d0562018-08-30 16:25:47 +02001787 var SystemInformation si3 := valueof(ts_SI3_default);
Harald Welte68e495b2018-02-25 00:05:57 +01001788 var PagingTestCfg cfg := {
1789 combined_ccch := true,
Philipp Maierd65d0562018-08-30 16:25:47 +02001790 bs_ag_blks_res := si3.payload.si3.ctrl_chan_desc.bs_ag_blks_res,
Harald Welte68e495b2018-02-25 00:05:57 +01001791 load_factor := 0.8,
1792 exp_load_ind := true,
1793 exp_overload := false,
1794 use_tmsi := true
1795 };
1796 var PagingTestState st := f_TC_paging(cfg);
1797 if (st.num_paging_sent != st.num_paging_rcv_ids) {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02001798 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("Expected ", st.num_paging_sent, " pagings but have ",
1799 st.num_paging_rcv_ids));
Harald Welte68e495b2018-02-25 00:05:57 +01001800 } else {
1801 setverdict(pass);
1802 }
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02001803 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
Harald Welte68e495b2018-02-25 00:05:57 +01001804}
1805
1806/* Create ~ 200% paging load (IMSI only) sustained for about 20s, verifying that
1807 * - the number of Mobile Identities on Um PCH are ~ 82% of the number of pages on RSL
1808 * - that CCCH LOAD IND (PCH) are being generated and reach 0 at some point
1809 * - that CCCH LOAD IND (PCH) [no load] is received after paging flood is over */
1810testcase TC_paging_imsi_200percent() runs on test_CT {
Philipp Maierd65d0562018-08-30 16:25:47 +02001811 var SystemInformation si3 := valueof(ts_SI3_default);
Harald Welte68e495b2018-02-25 00:05:57 +01001812 var PagingTestCfg cfg := {
1813 combined_ccch := true,
Philipp Maierd65d0562018-08-30 16:25:47 +02001814 bs_ag_blks_res := si3.payload.si3.ctrl_chan_desc.bs_ag_blks_res,
Harald Welte68e495b2018-02-25 00:05:57 +01001815 load_factor := 2.0,
1816 exp_load_ind := true,
1817 exp_overload := true,
1818 use_tmsi := false
1819 };
1820 var PagingTestState st := f_TC_paging(cfg);
1821 /* We expect about 80-85% to pass, given that we can fill the paging buffer of 200
1822 * slots and will fully drain that buffer before returning */
Pau Espin Pedrol9c3ff4e2018-09-26 18:30:16 +02001823 var template integer tpl := (st.num_paging_sent*78/100 .. st.num_paging_sent *85/100);
Harald Welte68e495b2018-02-25 00:05:57 +01001824 if (not match(st.num_paging_rcv_ids, tpl)) {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02001825 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 +01001826 } else {
1827 setverdict(pass);
1828 }
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02001829 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
Harald Welte68e495b2018-02-25 00:05:57 +01001830}
1831
1832/* Create ~ 200% paging load (TMSI only) sustained for about 20s, verifying that
1833 * - the number of Mobile Identities on Um PCH are ~ 82% of the number of pages on RSL
1834 * - that CCCH LOAD IND (PCH) are being generated and reach 0 at some point
1835 * - that CCCH LOAD IND (PCH) [no load] is received after paging flood is over */
1836testcase TC_paging_tmsi_200percent() runs on test_CT {
Philipp Maierd65d0562018-08-30 16:25:47 +02001837 var SystemInformation si3 := valueof(ts_SI3_default);
Harald Welte68e495b2018-02-25 00:05:57 +01001838 var PagingTestCfg cfg := {
1839 combined_ccch := true,
Philipp Maierd65d0562018-08-30 16:25:47 +02001840 bs_ag_blks_res := si3.payload.si3.ctrl_chan_desc.bs_ag_blks_res,
Harald Welte68e495b2018-02-25 00:05:57 +01001841 load_factor := 2.0,
1842 exp_load_ind := true,
1843 exp_overload := true,
1844 use_tmsi := true
1845 };
1846 var PagingTestState st := f_TC_paging(cfg);
1847 /* We expect about 70% to pass, given that we can fill the paging buffer of 200
1848 * slots and will fully drain that buffer before returning */
Pau Espin Pedrol9c3ff4e2018-09-26 18:30:16 +02001849 var template integer tpl := (st.num_paging_sent*64/100 .. st.num_paging_sent *72/100);
Harald Welte68e495b2018-02-25 00:05:57 +01001850 if (not match(st.num_paging_rcv_ids, tpl)) {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02001851 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 +01001852 } else {
1853 setverdict(pass);
1854 }
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02001855 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
Harald Welte68e495b2018-02-25 00:05:57 +01001856}
1857
1858
Harald Welte93640c62018-02-25 16:59:33 +01001859/***********************************************************************
1860 * Immediate Assignment / AGCH
1861 ***********************************************************************/
Harald Weltee8d750e2018-06-10 21:41:35 +02001862const MobileAllocation c_MA_null := {
1863 len := 0,
1864 ma := ''B
1865}
Harald Welte93640c62018-02-25 16:59:33 +01001866
Harald Weltee8d750e2018-06-10 21:41:35 +02001867template (value) ChannelDescription ts_ChanDesc(template (value) RslChannelNr chan_nr, uint3_t tsc := 7,
1868 uint12_t arfcn := 871) := {
1869 chan_nr := chan_nr,
1870 tsc := tsc,
1871 h := false,
1872 arfcn := arfcn,
1873 maio_hsn := omit
1874}
1875
1876private function f_fmt_ia_stats(integer num_tx, integer num_rx, integer num_del) return charstring {
1877 return int2str(num_tx) & " sent, "
1878 & int2str(num_rx) & " received, "
1879 & int2str(num_del) & " deleted";
1880}
1881
1882private function f_TC_imm_ass(integer num_total, float sleep_s, float exp_pass) runs on test_CT {
1883 var L1ctlDlMessage l1_dl;
1884 timer T := 10.0;
1885 var integer num_tx := 0;
1886 var integer num_rx := 0;
1887 var integer num_del := 0;
1888 var charstring res_str;
1889 var float rx_ratio;
1890
Harald Welte68e495b2018-02-25 00:05:57 +01001891 f_init(testcasename());
Harald Weltee8d750e2018-06-10 21:41:35 +02001892 f_init_l1ctl();
1893 f_l1_tune(L1CTL);
1894
1895 for (var integer i := 0; i < num_total; i := i+1) {
1896 var ChannelDescription ch_desc := valueof(ts_ChanDesc(valueof(t_RslChanNr_SDCCH4(0, 0))));
1897 var GsmRrMessage ia := valueof(ts_IMM_ASS(42, i, 5, ch_desc, c_MA_null));
1898 var octetstring ia_enc := enc_GsmRrMessage(ia);
Harald Welte68e495b2018-02-25 00:05:57 +01001899 RSL_CCHAN.send(ts_RSL_UD(ts_RSL_IMM_ASSIGN(ia_enc, 0)));
Harald Weltee8d750e2018-06-10 21:41:35 +02001900 num_tx := num_tx+1;
1901 f_sleep(sleep_s);
Harald Welte68e495b2018-02-25 00:05:57 +01001902 }
1903 /* FIXME: check if imm.ass arrive on Um side */
Harald Weltee8d750e2018-06-10 21:41:35 +02001904 T.start;
1905 alt {
1906 [] RSL_CCHAN.receive(tr_RSL_UD(tr_RSL_DELETE_IND(?, 0))) {
1907 num_del := num_del+1;
1908 repeat;
1909 }
1910 [] RSL_CCHAN.receive {
1911 repeat;
1912 }
1913 [] L1CTL.receive(tr_L1CTL_DATA_IND(t_RslChanNr_PCH_AGCH(0), ?)) -> value l1_dl {
1914 /* somehow dec_SystemInformation will try to decode even non-RR as SI */
1915 var GsmRrMessage rr := dec_GsmRrMessage(l1_dl.payload.data_ind.payload);
1916 if (not match(rr, tr_IMM_ASS(42, ?, 5, ?, ?))) {
1917 /* FIXME: Why are we seeing paging requests on PCH/AGCH? */
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02001918 //Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("Unexpected IMM-ASS values on AGCH: ", rr));
Harald Weltee8d750e2018-06-10 21:41:35 +02001919 } else {
1920 num_rx := num_rx+1;
1921 }
1922 repeat;
1923 }
1924 [] L1CTL.receive { repeat; }
1925 [] T.timeout { }
1926 }
1927 res_str := f_fmt_ia_stats(num_tx, num_rx, num_del);
1928 log("AGCH test: " & res_str);
1929 if (num_rx + num_del != num_tx) {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02001930 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "RX + DEL != TX ?!?: " & res_str);
Harald Weltee8d750e2018-06-10 21:41:35 +02001931 }
1932 rx_ratio := int2float(num_rx) / int2float(num_tx);
1933 if (rx_ratio < exp_pass*0.8 or rx_ratio > exp_pass*1.2) {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02001934 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 +02001935 } else {
1936 setverdict(pass);
1937 }
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02001938 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
Harald Welte68e495b2018-02-25 00:05:57 +01001939}
1940
Harald Weltee8d750e2018-06-10 21:41:35 +02001941/* send a long burst of 1000 IMM.ASS with 20ms spacing (50 per s); expect 75% of them to be deleted */
1942testcase TC_imm_ass_1000_20ms() runs on test_CT {
1943 f_TC_imm_ass(1000, 0.02, 0.25);
1944}
1945
1946/* send a short burst of 200 IMM.ASS without any spacing; expect 95% of them to be deleted */
1947testcase TC_imm_ass_200_0ms() runs on test_CT {
1948 f_TC_imm_ass(200, 0.0, 0.05);
1949}
1950
1951/* send 150 IMM.ASS at rate of 13/s; expect none of them to be deleted */
1952testcase TC_imm_ass_200_76ms() runs on test_CT {
1953 f_TC_imm_ass(150, 0.076, 1.00);
1954}
1955
1956
1957
Harald Welte48494ca2018-02-25 16:59:50 +01001958/***********************************************************************
1959 * BCCH
1960 ***********************************************************************/
1961
1962/* tuple of Frame Number + decoded SI */
1963type record SystemInformationFn {
1964 GsmFrameNumber frame_number,
1965 SystemInformation si
1966}
1967
1968/* an arbitrary-length vector of decoded SI + gsmtap header */
1969type record of SystemInformationFn SystemInformationVector;
1970
1971/* an array of SI-vectors indexed by TC value */
1972type SystemInformationVector SystemInformationVectorPerTc[8];
1973
1974/* determine if a given SI vector contains given SI type at least once */
1975function f_si_vecslot_contains(SystemInformationVector arr, RrMessageType key, boolean bcch_ext := false) return boolean {
1976 for (var integer i:= 0; i< sizeof(arr); i := i + 1) {
1977 var integer fn_mod51 := arr[i].frame_number mod 51;
1978 if (not bcch_ext and fn_mod51 == 2 or
1979 bcch_ext and fn_mod51 == 6) {
1980 if (arr[i].si.header.message_type == key) {
1981 return true;
1982 }
1983 }
1984 }
1985 return false;
1986}
1987
1988/* ensure a given TC slot of the SI vector contains given SI type at least once at TC */
1989function f_ensure_si_vec_contains(SystemInformationVectorPerTc arr, integer tc, RrMessageType key, boolean ext_bcch := false) {
1990 if (not f_si_vecslot_contains(arr[tc], key, ext_bcch)) {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02001991 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("No ", key, " in TC=", tc, "!"));
Harald Welte48494ca2018-02-25 16:59:50 +01001992 }
1993}
1994
1995/* check if a given SI vector contains given SI type at least once on any TC */
1996function f_si_vec_contains(SystemInformationVectorPerTc arr, RrMessageType key) return boolean {
1997 for (var integer tc:= 0; tc < sizeof(arr); tc := tc + 1) {
1998 if (f_si_vecslot_contains(arr[tc], key) or
1999 f_si_vecslot_contains(arr[tc], key, true)) {
2000 return true;
2001 }
2002 }
2003 return false;
2004}
2005
2006/* determine if a given SI vector contains given SI type at least N of M times */
2007function f_si_vecslot_contains_n_of_m(SystemInformationVector arr, RrMessageType key, boolean bcch_ext := false, integer n := 1, integer m := 4) return boolean {
2008 var integer count := 0;
2009 if (sizeof(arr) < m) {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02002010 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Error: Insufficient SI in array");
Harald Welte48494ca2018-02-25 16:59:50 +01002011 }
2012 for (var integer i:= 0; i < m; i := i + 1) {
2013 var integer fn_mod51 := arr[i].frame_number mod 51;
2014 if (not bcch_ext and fn_mod51 == 2 or
2015 bcch_ext and fn_mod51 == 6) {
2016 if (arr[i].si.header.message_type == key) {
2017 count := count + 1;
2018 }
2019 }
2020 }
2021 if (count >= n) {
2022 return true;
2023 } else {
2024 return false;
2025 }
2026}
2027
2028/* ensure a given TC slot of the SI vector contains given SI type at least N out of M times at TC */
2029function f_ensure_si_vec_contains_n_of_m(SystemInformationVectorPerTc arr, integer tc, RrMessageType key, boolean ext_bcch := false, integer n, integer m) {
2030 if (not f_si_vecslot_contains_n_of_m(arr[tc], key, ext_bcch, n, m)) {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02002031 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("Not ", n, "/", m, " of ", key, " in TC=", tc, "!"));
Harald Welte48494ca2018-02-25 16:59:50 +01002032 }
2033}
2034
2035/* determine if a given SI vector contains given SI type at least once */
2036function f_si_vecslot_contains_only(SystemInformationVector arr, RrMessageType key, boolean bcch_ext := false) return boolean {
2037 for (var integer i:= 0; i< sizeof(arr); i := i + 1) {
2038 var integer fn_mod51 := arr[i].frame_number mod 51;
2039 if (not bcch_ext and fn_mod51 == 2 or
2040 bcch_ext and fn_mod51 == 6) {
2041 if (arr[i].si.header.message_type != key) {
2042 return false;
2043 }
2044 }
2045 }
2046 return true;
2047}
2048
2049/* ensure a given TC slot of the SI vector contains only given SI type */
2050function f_ensure_si_vec_contains_only(SystemInformationVectorPerTc arr, integer tc, RrMessageType key, boolean ext_bcch := false) {
2051 if (not f_si_vecslot_contains_only(arr[tc], key, ext_bcch)) {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02002052 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("Not all ", key, " in TC=", tc, "!"));
Harald Welte48494ca2018-02-25 16:59:50 +01002053 }
2054}
2055
2056/* SI configuration of cell, against which we validate actual SI messages */
2057type set SystemInformationConfig {
2058 boolean bcch_extended,
2059 boolean si1_present,
2060 boolean si2bis_present,
2061 boolean si2ter_present,
2062 boolean si2quater_present,
2063 boolean si7_present,
2064 boolean si8_present,
2065 boolean si9_present,
2066 boolean si13_present,
2067 boolean si13alt_present,
2068 boolean si15_present,
2069 boolean si16_present,
2070 boolean si17_present,
2071 boolean si2n_present,
2072 boolean si21_present,
2073 boolean si22_present
2074}
2075
2076/* validate the SI scheduling according to TS 45.002 version 14.1.0 Release 14, Section 6.3.1.3 */
2077function f_validate_si_scheduling(SystemInformationConfig cfg, SystemInformationVectorPerTc si_per_tc) {
2078 var integer i;
2079 for (i := 0; i < sizeof(si_per_tc); i := i + 1) {
2080 if (sizeof(si_per_tc[i]) == 0) {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02002081 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("No SI messages for TC=", i));
Harald Welte48494ca2018-02-25 16:59:50 +01002082 }
2083 }
2084 if (cfg.si1_present) {
2085 /* ii) System Information Type 1 needs to be sent if frequency hopping is in use or
2086 * when the NCH is present in a cell. If the MS finds another message on BCCH Norm
2087 * when TC = 0, it can assume that System Information Type 1 is not in use. */
2088 f_ensure_si_vec_contains(si_per_tc, 0, SYSTEM_INFORMATION_TYPE_1);
2089 /* make sure *ALL* contain SI1 */
2090 f_ensure_si_vec_contains_only(si_per_tc, 0, SYSTEM_INFORMATION_TYPE_1);
2091 }
2092 f_ensure_si_vec_contains(si_per_tc, 1, SYSTEM_INFORMATION_TYPE_2);
2093 /* iii) A SI 2 message will be sent at least every time TC = 1 */
2094 f_ensure_si_vec_contains(si_per_tc, 2, SYSTEM_INFORMATION_TYPE_3);
2095 f_ensure_si_vec_contains(si_per_tc, 6, SYSTEM_INFORMATION_TYPE_3);
2096 f_ensure_si_vec_contains(si_per_tc, 3, SYSTEM_INFORMATION_TYPE_4);
2097 f_ensure_si_vec_contains(si_per_tc, 7, SYSTEM_INFORMATION_TYPE_4);
2098
2099 /* iii) System information type 2 bis or 2 ter messages are sent if needed, as determined by the
2100 * system operator. If only one of them is needed, it is sent when TC = 5. If both are
2101 * needed, 2bis is sent when TC = 5 and 2ter is sent at least once within any of 4
2102 * consecutive occurrences of TC = 4. */
2103 if (cfg.si2bis_present and not cfg.si2ter_present) {
2104 f_ensure_si_vec_contains(si_per_tc, 5, SYSTEM_INFORMATION_TYPE_2bis);
2105 } else if (cfg.si2ter_present and not cfg.si2bis_present) {
2106 f_ensure_si_vec_contains(si_per_tc, 5, SYSTEM_INFORMATION_TYPE_2ter);
2107 } else if (cfg.si2ter_present and cfg.si2bis_present) {
2108 f_ensure_si_vec_contains(si_per_tc, 5, SYSTEM_INFORMATION_TYPE_2bis);
2109 f_ensure_si_vec_contains_n_of_m(si_per_tc, 4, SYSTEM_INFORMATION_TYPE_2ter, false, 1, 4);
2110 }
2111
2112 if (cfg.si7_present or cfg.si8_present) {
2113 /* vi) Use of System Information type 7 and 8 is not always necessary. It is necessary
2114 * if System Information type 4 does not contain all information needed for cell
2115 * selection and reselection. */
2116 if (not cfg.bcch_extended) {
2117 testcase.stop("Error: SI7/SI8 require BCCH Extd.");
2118 }
2119 if (cfg.si7_present) {
2120 f_ensure_si_vec_contains(si_per_tc, 7, SYSTEM_INFORMATION_TYPE_7, true);
2121 }
2122 if (cfg.si8_present) {
2123 f_ensure_si_vec_contains(si_per_tc, 3, SYSTEM_INFORMATION_TYPE_8, true);
2124 }
2125 }
2126
2127 if (cfg.si2quater_present) {
2128 /* iii) System information type 2 quater is sent if needed, as determined by the system
2129 * operator. If sent on BCCH Norm, it shall be sent when TC = 5 if neither of 2bis
2130 * and 2ter are used, otherwise it shall be sent at least once within any of 4
2131 * consecutive occurrences of TC = 4. If sent on BCCH Ext, it is sent at least once
2132 * within any of 4 consecutive occurrences of TC = 5. */
2133 if (not (cfg.bcch_extended)) {
2134 if (not (cfg.si2bis_present or cfg.si2ter_present)) {
2135 f_ensure_si_vec_contains(si_per_tc, 5, SYSTEM_INFORMATION_TYPE_2quater);
2136 } else {
2137 f_ensure_si_vec_contains_n_of_m(si_per_tc, 4, SYSTEM_INFORMATION_TYPE_2quater, false, 1, 4);
2138 }
2139 } else {
2140 f_ensure_si_vec_contains_n_of_m(si_per_tc, 5, SYSTEM_INFORMATION_TYPE_2quater, true, 1, 4);
2141 }
2142 }
2143 if (cfg.si9_present) {
2144 /* vi) System Information type 9 is sent in those blocks with TC = 4 which are specified
2145 * in system information type 3 as defined in 3GPP TS 44.018. */
2146 f_ensure_si_vec_contains(si_per_tc, 4, SYSTEM_INFORMATION_TYPE_9); // FIXME SI3
2147 }
2148 if (cfg.si13_present) {
2149 /* vii) System Information type 13 is only related to the GPRS service. System Information
2150 * Type 13 need only be sent if GPRS support is indicated in one or more of System
2151 * Information Type 3 or 4 or 7 or 8 messages. These messages also indicate if the
2152 * message is sent on the BCCH Norm or if the message is transmitted on the BCCH Ext.
2153 * In the case that the message is sent on the BCCH Norm, it is sent at least once
2154 * within any of 4 consecutive occurrences of TC=4. */
2155 if (not cfg.bcch_extended) {
2156 log("not-bccch-extended");
2157 f_ensure_si_vec_contains_n_of_m(si_per_tc, 4, SYSTEM_INFORMATION_TYPE_13, false, 1, 4);
2158 } else {
2159 log("bccch-extended");
2160 f_ensure_si_vec_contains(si_per_tc, 0, SYSTEM_INFORMATION_TYPE_13, true);
2161 }
2162 if (f_si_vec_contains(si_per_tc, SYSTEM_INFORMATION_TYPE_13alt)) {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02002163 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Cannot have SI13alt and SI13");
Harald Welte48494ca2018-02-25 16:59:50 +01002164 }
2165 }
2166 if (cfg.si16_present or cfg.si17_present) {
2167 /* viii) System Information type 16 and 17 are only related to the SoLSA service. They
2168 * should not be sent in a cell where network sharing is used (see rule xv). */
2169 if (cfg.si22_present) {
2170 testcase.stop("Error: Cannot have SI16/SI17 and SI22!");
2171 }
2172 if (f_si_vec_contains(si_per_tc, SYSTEM_INFORMATION_TYPE_22)) {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02002173 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Cannot have SI16/SI17 and SI22!");
Harald Welte48494ca2018-02-25 16:59:50 +01002174 }
2175 if (not cfg.bcch_extended) {
2176 testcase.stop("Error: SI16/SI17 requires BCCH Extd!");
2177 }
2178 if (cfg.si16_present) {
2179 f_ensure_si_vec_contains(si_per_tc, 6, SYSTEM_INFORMATION_TYPE_16, true);
2180 }
2181 if (cfg.si17_present) {
2182 f_ensure_si_vec_contains(si_per_tc, 2, SYSTEM_INFORMATION_TYPE_17, true);
2183 }
2184 }
2185
2186 /* ix) System Information type 18 and 20 are sent in order to transmit non-GSM
2187 * broadcast information. The frequency with which they are sent is determined by the
2188 * system operator. System Information type 9 identifies the scheduling of System
2189 * Information type 18 and 20 messages. */
2190
2191 /* x) System Information Type 19 is sent if COMPACT neighbours exist. If System
2192 * Information Type 19 is present, then its scheduling shall be indicated in System
2193 * Information Type 9. */
2194
2195 if (cfg.si15_present) {
2196 /* xi) System Information Type 15 is broadcast if dynamic ARFCN mapping is used in the
2197 * PLMN. If sent on BCCH Norm, it is sent at least once within any of 4 consecutive
2198 * occurrences of TC = 4. If sent on BCCH Ext, it is sent at least once within any of
2199 * 4 consecutive occurrences of TC = 1. */
2200 if (not cfg.bcch_extended) {
2201 f_ensure_si_vec_contains_n_of_m(si_per_tc, 4, SYSTEM_INFORMATION_TYPE_15, false, 1, 4);
2202 } else {
2203 f_ensure_si_vec_contains_n_of_m(si_per_tc, 1, SYSTEM_INFORMATION_TYPE_15, true, 1, 4);
2204 }
2205 }
2206 if (cfg.si13alt_present) {
2207 /* xii) System Information type 13 alt is only related to the GERAN Iu mode. System
2208 * Information Type 13 alt need only be sent if GERAN Iu mode support is indicated in
2209 * one or more of System Information Type 3 or 4 or 7 or 8 messages and SI 13 is not
2210 * broadcast. These messages also indicate if the message is sent on the BCCH Norm or
2211 * if the message is transmitted on the BCCH Ext. In the case that the message is sent
2212 * on the BCCH Norm, it is sent at least once within any of 4 consecutive occurrences
2213 * of TC = 4. */
2214 if (cfg.si13_present) {
2215 testcase.stop("Error: Cannot have SI13alt and SI13");
2216 }
2217 if (f_si_vec_contains(si_per_tc, SYSTEM_INFORMATION_TYPE_13)) {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02002218 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Cannot have SI13alt and SI13");
Harald Welte48494ca2018-02-25 16:59:50 +01002219 }
2220 if (not cfg.bcch_extended) {
2221 f_ensure_si_vec_contains_n_of_m(si_per_tc, 4, SYSTEM_INFORMATION_TYPE_13alt, false, 1, 4);
2222 } else {
2223 f_ensure_si_vec_contains(si_per_tc, 0, SYSTEM_INFORMATION_TYPE_13alt, true);
2224 }
2225 }
2226 if (cfg.si2n_present) {
2227 /* xiii) System Information Type 2n is optionally sent on BCCH Norm or BCCH Ext if needed,
2228 * as determined by the system operator. In the case that the message is sent on the
2229 * BCCH Norm, it is sent at least once within any of 4 consecutive occurrences of TC =
2230 * 4. If the message is sent on BCCH Ext, it is sent at least once within any of 2
2231 * consecutive occurrences of TC = 4. */
2232 if (not cfg.bcch_extended) {
2233 f_ensure_si_vec_contains_n_of_m(si_per_tc, 4, SYSTEM_INFORMATION_TYPE_2n, false, 1, 4);
2234 } else {
2235 f_ensure_si_vec_contains_n_of_m(si_per_tc, 4, SYSTEM_INFORMATION_TYPE_2n, true, 2, 4);
2236 }
2237 }
2238 if (cfg.si21_present) {
2239 /* xiv) System Information Type 21 is optionally sent on BCCH Norm or BCCH Ext, as
2240 * determined by the system operator. If Extended Access Barring is in use in the cell
2241 * then this message is sent at least once within any of 4 consecutive occurrences of
2242 * TC = 4 regardless if it is sent on BCCH Norm or BCCH Ext. If BCCH Ext is used in a
2243 * cell then this message shall only be sent on BCCH Ext. */
2244 if (not cfg.bcch_extended) {
2245 f_ensure_si_vec_contains_n_of_m(si_per_tc, 4, SYSTEM_INFORMATION_TYPE_21, false, 1, 4);
2246 } else {
2247 f_ensure_si_vec_contains_n_of_m(si_per_tc, 4, SYSTEM_INFORMATION_TYPE_21, true, 1, 4);
2248 if (f_si_vecslot_contains(si_per_tc[4], SYSTEM_INFORMATION_TYPE_21)) {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02002249 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Cannot have SI21 on BCCH Norm if BCCH Extd enabled!");
Harald Welte48494ca2018-02-25 16:59:50 +01002250 }
2251 }
2252 }
2253 if (cfg.si22_present) {
2254 /* xv) System Information Type 22 is sent if network sharing is in use in the cell. It
2255 * should not be sent in a cell where SoLSA is used (see rule viii). System
2256 * Information Type 22 instances shall be sent on BCCH Ext within any occurrence of TC
2257 * =2 and TC=6. */
2258 if (cfg.si16_present or cfg.si17_present) {
2259 testcase.stop("Error: Cannot have SI16/SI17 and SI22!");
2260 }
2261 if (f_si_vec_contains(si_per_tc, SYSTEM_INFORMATION_TYPE_16) or
2262 f_si_vec_contains(si_per_tc, SYSTEM_INFORMATION_TYPE_17)) {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02002263 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Cannot have SI16/SI17 and SI22!");
Harald Welte48494ca2018-02-25 16:59:50 +01002264 }
2265 if (not cfg.bcch_extended) {
2266 testcase.stop("Error: SI22 requires BCCH Extd!");
2267 } else {
2268 f_ensure_si_vec_contains_only(si_per_tc, 2, SYSTEM_INFORMATION_TYPE_22, true);
2269 f_ensure_si_vec_contains_only(si_per_tc, 6, SYSTEM_INFORMATION_TYPE_22, true);
2270 }
2271 }
2272}
2273
2274/* sample Systme Information for specified duration via L1CTL */
2275function f_l1_sample_si(L1CTL_PT pt, float duration := 8.0) return SystemInformationVectorPerTc {
2276 timer T := duration;
2277 var SystemInformationVectorPerTc si_per_tc;
2278 var L1ctlDlMessage l1_dl;
2279
2280 /* initialize all per-TC vectors empty */
2281 for (var integer i:= 0; i < sizeof(si_per_tc); i := i+1) {
2282 si_per_tc[i] := {};
2283 }
2284
2285 /* flush all previous L1 queued msgs */
2286 pt.clear;
2287
2288 T.start;
2289 alt {
Harald Weltef8df4cb2018-03-10 15:15:08 +01002290 [] pt.receive(tr_L1CTL_DATA_IND(t_RslChanNr_BCCH(0), ?)) -> value l1_dl {
Harald Welte48494ca2018-02-25 16:59:50 +01002291 /* somehow dec_SystemInformation will try to decode even non-RR as SI */
2292 if (not (l1_dl.payload.data_ind.payload[1] == '06'O)) {
2293 log("Ignoring non-RR SI ", l1_dl);
2294 repeat;
2295 }
2296 var SystemInformationFn sig := {
2297 frame_number := l1_dl.dl_info.frame_nr,
2298 si := dec_SystemInformation(l1_dl.payload.data_ind.payload)
2299 }
2300 var integer tc := f_gsm_compute_tc(sig.frame_number);
2301 log("SI received at TC=", tc, ": ", sig.si);
2302 /* append to the per-TC bucket */
2303 si_per_tc[tc] := si_per_tc[tc] & { sig };
2304 repeat;
2305 }
2306 [] pt.receive { repeat; }
2307 [] T.timeout { }
2308 }
2309
2310 for (var integer i:= 0; i < sizeof(si_per_tc); i := i+1) {
2311 log(testcasename(), ": TC=", i, " has #of SI=", sizeof(si_per_tc[i]));
2312 }
2313 log("si_per_tc=", si_per_tc);
2314 return si_per_tc;
2315}
2316
2317/* helper function: Set given SI via RSL + validate scheduling.
2318 * CALLER MUST MAKE SURE TO CHANGE GLOBAL si_cfg! */
2319function f_TC_si_sched() runs on test_CT {
2320 var SystemInformationVectorPerTc si_per_tc;
2321 f_init_l1ctl();
2322 f_l1_tune(L1CTL);
2323
2324 /* Sample + Validate Scheduling */
2325 si_per_tc := f_l1_sample_si(L1CTL);
2326 f_validate_si_scheduling(si_cfg, si_per_tc);
2327
2328 setverdict(pass);
2329}
2330
2331testcase TC_si_sched_default() runs on test_CT {
2332 f_init();
Harald Welte0cae4552018-03-09 22:20:26 +01002333 /* 2+3+4 are mandatory and set in f_init() */
2334 f_TC_si_sched();
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02002335 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
Harald Welte0cae4552018-03-09 22:20:26 +01002336}
2337
2338testcase TC_si_sched_1() runs on test_CT {
2339 f_init();
2340 si_cfg.si1_present := true;
2341 f_rsl_bcch_fill_raw(RSL_SYSTEM_INFO_1, '5506198fb38000000000000000000000000000e504002b'O);
Harald Welte48494ca2018-02-25 16:59:50 +01002342 f_TC_si_sched();
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02002343 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
Harald Welte48494ca2018-02-25 16:59:50 +01002344}
2345
2346testcase TC_si_sched_2bis() runs on test_CT {
2347 f_init();
2348 si_cfg.si2bis_present := true;
2349 f_rsl_bcch_fill_raw(RSL_SYSTEM_INFO_2bis, '550602bfe809b3ff00000000000000000000007900002b'O);
2350 f_TC_si_sched();
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02002351 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
Harald Welte48494ca2018-02-25 16:59:50 +01002352}
2353
2354testcase TC_si_sched_2ter() runs on test_CT {
2355 f_init();
2356 si_cfg.si2ter_present := true;
2357 f_rsl_bcch_fill_raw(RSL_SYSTEM_INFO_2ter, '010603bf66b0aa0a00000002000000000000002b2b2b2b'O);
2358 f_TC_si_sched();
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02002359 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
Harald Welte48494ca2018-02-25 16:59:50 +01002360}
2361
2362testcase TC_si_sched_2ter_2bis() runs on test_CT {
2363 f_init();
2364 si_cfg.si2bis_present := true;
2365 f_rsl_bcch_fill_raw(RSL_SYSTEM_INFO_2bis, '550602bfe809b3ff00000000000000000000007900002b'O);
2366 si_cfg.si2ter_present := true;
2367 f_rsl_bcch_fill_raw(RSL_SYSTEM_INFO_2ter, '010603bf66b0aa0a00000002000000000000002b2b2b2b'O);
2368 f_TC_si_sched();
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02002369 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
Harald Welte48494ca2018-02-25 16:59:50 +01002370}
2371
2372testcase TC_si_sched_2quater() runs on test_CT {
2373 f_init();
2374 si_cfg.si2quater_present := true;
2375 f_rsl_bcch_fill_raw(RSL_SYSTEM_INFO_2quater, '050607a8a0364aa698d72ff424feee0506d5e7fff02043'O);
2376 f_TC_si_sched();
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02002377 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
Harald Welte48494ca2018-02-25 16:59:50 +01002378}
2379
2380testcase TC_si_sched_13() runs on test_CT {
2381 f_init();
2382 si_cfg.si13_present := true;
Harald Welte5618c2a2018-04-15 16:24:46 +02002383 f_rsl_bcch_fill_raw(RSL_SYSTEM_INFO_13, '0106009000185a6fc9e08410ab2b2b2b2b2b2b2b2b2b2b'O);
Harald Welte48494ca2018-02-25 16:59:50 +01002384 f_TC_si_sched();
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02002385 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
Harald Welte48494ca2018-02-25 16:59:50 +01002386}
2387
2388testcase TC_si_sched_13_2bis_2ter_2quater() runs on test_CT {
2389 f_init();
2390 si_cfg.si2bis_present := true;
2391 f_rsl_bcch_fill_raw(RSL_SYSTEM_INFO_2bis, '550602bfe809b3ff00000000000000000000007900002b'O);
2392 si_cfg.si2ter_present := true;
2393 f_rsl_bcch_fill_raw(RSL_SYSTEM_INFO_2ter, '010603bf66b0aa0a00000002000000000000002b2b2b2b'O);
2394 si_cfg.si2quater_present := true;
2395 f_rsl_bcch_fill_raw(RSL_SYSTEM_INFO_2quater, '050607a8a0364aa698d72ff424feee0506d5e7fff02043'O);
2396 si_cfg.si13_present := true;
Harald Welte5618c2a2018-04-15 16:24:46 +02002397 f_rsl_bcch_fill_raw(RSL_SYSTEM_INFO_13, '0106009000185a6fc9e08410ab2b2b2b2b2b2b2b2b2b2b'O);
Harald Welte48494ca2018-02-25 16:59:50 +01002398 f_TC_si_sched();
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02002399 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
Harald Welte48494ca2018-02-25 16:59:50 +01002400}
2401
2402
Harald Welte68e495b2018-02-25 00:05:57 +01002403testcase TC_bcch_info() runs on test_CT {
2404 f_init(testcasename());
2405 /* FIXME: enable / disable individual BCCH info */
2406 //ts_RSL_BCCH_INFO(si_type, info);
2407 /* expect no ERROR REPORT after either of them *
2408 /* negative test: ensure ERROR REPORT on unsupported types */
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02002409 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
Harald Welte68e495b2018-02-25 00:05:57 +01002410}
2411
Harald Welte93640c62018-02-25 16:59:33 +01002412/***********************************************************************
2413 * Low-Level Protocol Errors / ERROR REPORT
2414 ***********************************************************************/
2415
Harald Welte01d982c2018-02-25 01:31:40 +01002416private function f_exp_err_rep(template RSL_Cause cause) runs on test_CT {
2417 timer T := 5.0;
2418 T.start;
2419 alt {
2420 [] RSL_CCHAN.receive(tr_RSL_UD(tr_RSL_ERROR_REPORT(cause))) {
2421 setverdict(pass);
2422 }
2423 [] RSL_CCHAN.receive(tr_RSL_UD(tr_RSL_ERROR_REPORT(?))) {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02002424 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Wrong cause in RSL ERR REP");
Harald Welte01d982c2018-02-25 01:31:40 +01002425 }
2426 [] RSL_CCHAN.receive {
2427 repeat;
2428 }
2429 [] T.timeout {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02002430 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout waiting for RSL ERR REP");
Harald Welte01d982c2018-02-25 01:31:40 +01002431 }
2432 }
2433}
2434
2435/* Provoke a protocol error (message too short) and match on ERROR REPORT */
2436testcase TC_rsl_protocol_error() runs on test_CT {
2437 f_init(testcasename());
2438 var RSL_Message rsl := valueof(ts_RSL_BCCH_INFO(RSL_SYSTEM_INFO_1, ''O));
2439 rsl.ies := omit;
2440 RSL_CCHAN.send(ts_RSL_UD(rsl));
2441
2442 f_exp_err_rep(RSL_ERR_PROTO);
2443}
2444
2445/* Provoke a mandatory IE error and match on ERROR REPORT */
2446testcase TC_rsl_mand_ie_error() runs on test_CT {
2447 f_init(testcasename());
2448
2449 var RSL_Message rsl := valueof(ts_RSL_BCCH_INFO(RSL_SYSTEM_INFO_1, ''O));
2450 rsl.ies := { rsl.ies[0] };
2451 RSL_CCHAN.send(ts_RSL_UD(rsl));
2452
2453 f_exp_err_rep(RSL_ERR_MAND_IE_ERROR);
2454}
2455
2456/* Provoke an IE content error and match on ERROR REPORT */
2457testcase TC_rsl_ie_content_error() runs on test_CT {
2458 f_init(testcasename());
2459 var RSL_Message rsl := valueof(ts_RSL_BCCH_INFO(RSL_SYSTEM_INFO_1, ''O));
2460 rsl.ies[1].body.sysinfo_type := RSL_SYSTEM_INFO_5;
2461 RSL_CCHAN.send(ts_RSL_UD(rsl));
2462
2463 f_exp_err_rep(RSL_ERR_IE_CONTENT);
2464}
2465
Harald Welte93640c62018-02-25 16:59:33 +01002466/***********************************************************************
2467 * IPA CRCX/MDCX/DLCS media stream handling
2468 ***********************************************************************/
2469
Harald Weltea871a382018-02-25 02:03:14 +01002470/* Send IPA DLCX to inactive lchan */
2471function f_TC_ipa_dlcx_not_active(charstring id) runs on ConnHdlr {
Harald Welte1eba3742018-02-25 12:48:14 +01002472 f_rsl_transceive(ts_RSL_IPA_DLCX(g_chan_nr, 0), tr_RSL_IPA_DLCX_ACK(g_chan_nr, ?, ?),
2473 "IPA DLCX ACK");
Harald Weltea871a382018-02-25 02:03:14 +01002474}
2475testcase TC_ipa_dlcx_not_active() runs on test_CT {
2476 var ConnHdlrPars pars := valueof(t_Pars(t_RslChanNr_Bm(1), ts_RSL_ChanMode_SIGN));
2477 f_init(testcasename());
2478 var ConnHdlr vc_conn := f_start_handler(refers(f_TC_ipa_dlcx_not_active), pars);
2479 vc_conn.done;
2480}
Harald Welte68e495b2018-02-25 00:05:57 +01002481
Harald Weltea3f1df92018-02-25 12:49:55 +01002482/* Send IPA CRCX twice to inactive lchan */
2483function f_TC_ipa_crcx_twice_not_active(charstring id) runs on ConnHdlr {
2484 f_rsl_transceive(ts_RSL_IPA_CRCX(g_chan_nr), tr_RSL_IPA_CRCX_ACK(g_chan_nr, ?, ?, ?),
2485 "IPA CRCX ACK");
2486 f_rsl_transceive(ts_RSL_IPA_CRCX(g_chan_nr), tr_RSL_IPA_CRCX_NACK(g_chan_nr, RSL_ERR_RES_UNAVAIL),
2487 "IPA CRCX NACK");
2488}
2489testcase TC_ipa_crcx_twice_not_active() runs on test_CT {
2490 var ConnHdlrPars pars := valueof(t_Pars(t_RslChanNr_Bm(1), ts_RSL_ChanMode_SIGN));
2491 f_init(testcasename());
2492 var ConnHdlr vc_conn := f_start_handler(refers(f_TC_ipa_crcx_twice_not_active), pars);
2493 vc_conn.done;
2494}
2495
2496/* Regular sequence of CRCX/MDCX/DLCX */
2497function f_TC_ipa_crcx_mdcx_dlcx_not_active(charstring id) runs on ConnHdlr {
2498 f_rsl_transceive(ts_RSL_IPA_CRCX(g_chan_nr), tr_RSL_IPA_CRCX_ACK(g_chan_nr, ?, ?, ?),
2499 "IPA CRCX ACK");
2500 var uint32_t remote_ip := f_rnd_int(c_UINT32_MAX);
2501 var uint16_t remote_port := f_rnd_int(c_UINT16_MAX);
2502 var uint7_t rtp_pt2 := f_rnd_int(127);
2503 var uint16_t fake_conn_id := 23; /* we're too lazy to read it out from the CRCX ACK above */
2504 f_rsl_transceive(ts_RSL_IPA_MDCX(g_chan_nr, fake_conn_id, remote_ip, remote_port, rtp_pt2),
2505 tr_RSL_IPA_MDCX_ACK(g_chan_nr, ?, ?, ?, rtp_pt2),
2506 "IPA MDCX ACK");
2507 f_rsl_transceive(ts_RSL_IPA_DLCX(g_chan_nr, fake_conn_id), tr_RSL_IPA_DLCX_ACK(g_chan_nr, ?, ?),
2508 "IPA DLCX ACK");
2509}
2510testcase TC_ipa_crcx_mdcx_dlcx_not_active() runs on test_CT {
2511 var ConnHdlrPars pars := valueof(t_Pars(t_RslChanNr_Bm(1), ts_RSL_ChanMode_SIGN));
2512 f_init(testcasename());
2513 var ConnHdlr vc_conn := f_start_handler(refers(f_TC_ipa_crcx_mdcx_dlcx_not_active), pars);
2514 vc_conn.done;
2515}
2516
Harald Welte3ae11da2018-02-25 13:36:06 +01002517/* Sequence of CRCX, 2x MDCX, DLCX */
2518function f_TC_ipa_crcx_mdcx_mdcx_dlcx_not_active(charstring id) runs on ConnHdlr {
2519 f_rsl_transceive(ts_RSL_IPA_CRCX(g_chan_nr), tr_RSL_IPA_CRCX_ACK(g_chan_nr, ?, ?, ?),
2520 "IPA CRCX ACK");
2521 var uint32_t remote_ip := f_rnd_int(c_UINT32_MAX);
2522 var uint16_t remote_port := f_rnd_int(c_UINT16_MAX);
2523 var uint7_t rtp_pt2 := f_rnd_int(127);
2524 var uint16_t fake_conn_id := 23; /* we're too lazy to read it out from the CRCX ACK above */
2525 f_rsl_transceive(ts_RSL_IPA_MDCX(g_chan_nr, fake_conn_id, remote_ip, remote_port, rtp_pt2),
2526 tr_RSL_IPA_MDCX_ACK(g_chan_nr, ?, ?, ?, rtp_pt2),
2527 "IPA MDCX ACK");
2528 /* Second MDCX */
2529 remote_ip := f_rnd_int(c_UINT32_MAX);
2530 remote_port := f_rnd_int(c_UINT16_MAX);
2531 f_rsl_transceive(ts_RSL_IPA_MDCX(g_chan_nr, fake_conn_id, remote_ip, remote_port, rtp_pt2),
2532 tr_RSL_IPA_MDCX_ACK(g_chan_nr, ?, ?, ?, rtp_pt2),
2533 "IPA MDCX ACK");
2534 f_rsl_transceive(ts_RSL_IPA_DLCX(g_chan_nr, fake_conn_id), tr_RSL_IPA_DLCX_ACK(g_chan_nr, ?, ?),
2535 "IPA DLCX ACK");
2536}
2537testcase TC_ipa_crcx_mdcx_mdcx_dlcx_not_active() runs on test_CT {
2538 var ConnHdlrPars pars := valueof(t_Pars(t_RslChanNr_Bm(1), ts_RSL_ChanMode_SIGN));
2539 f_init(testcasename());
2540 var ConnHdlr vc_conn := f_start_handler(refers(f_TC_ipa_crcx_mdcx_mdcx_dlcx_not_active), pars);
2541 vc_conn.done;
2542}
2543
Harald Welte9912eb52018-02-25 13:30:15 +01002544/* IPA CRCX on SDCCH/4 and SDCCH/8 (doesn't make sense) */
2545function f_TC_ipa_crcx_sdcch_not_active(charstring id) runs on ConnHdlr {
2546 f_rsl_transceive(ts_RSL_IPA_CRCX(g_chan_nr), tr_RSL_IPA_CRCX_NACK(g_chan_nr, ?),
2547 "IPA CRCX NACK");
2548}
2549testcase TC_ipa_crcx_sdcch_not_active() runs on test_CT {
2550 var ConnHdlrPars pars;
2551 var ConnHdlr vc_conn;
2552 f_init(testcasename());
2553
2554 pars := valueof(t_Pars(t_RslChanNr_SDCCH4(0,1), ts_RSL_ChanMode_SIGN));
2555 vc_conn := f_start_handler(refers(f_TC_ipa_crcx_sdcch_not_active), pars);
2556 vc_conn.done;
2557
2558 pars := valueof(t_Pars(t_RslChanNr_SDCCH8(6,5), ts_RSL_ChanMode_SIGN));
2559 vc_conn := f_start_handler(refers(f_TC_ipa_crcx_sdcch_not_active), pars);
2560 vc_conn.done;
2561}
2562
Harald Weltea3f1df92018-02-25 12:49:55 +01002563
Harald Welte883340c2018-02-28 18:59:29 +01002564/***********************************************************************
2565 * PCU Socket related tests
2566 ***********************************************************************/
2567
2568private function f_TC_pcu_act_req(uint8_t bts_nr, uint8_t trx_nr, uint8_t ts_nr, boolean exp_success)
2569runs on test_CT {
2570 timer T := 3.0;
2571
2572 /* we don't expect any RTS.req before PDCH are active */
2573 T.start;
2574 alt {
2575 [] PCU.receive(t_SD_PCUIF(g_pcu_conn_id, tr_PCUIF_RTS_REQ(bts_nr))) {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02002576 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "PCU RTS.req before PDCH active?");
Harald Welte883340c2018-02-28 18:59:29 +01002577 }
2578 [] PCU.receive { repeat; }
2579 [] T.timeout { }
2580 }
2581
2582 /* Send PDCH activate request for known PDCH timeslot */
2583 PCU.send(t_SD_PCUIF(g_pcu_conn_id, ts_PCUIF_ACT_REQ(bts_nr, trx_nr, ts_nr)));
2584
2585 /* we now expect RTS.req for this timeslot (only) */
2586 T.start;
2587 alt {
2588 [exp_success] PCU.receive(t_SD_PCUIF(g_pcu_conn_id, tr_PCUIF_RTS_REQ(bts_nr, trx_nr, ts_nr))) {
2589 setverdict(pass);
2590 }
2591 [not exp_success] PCU.receive(t_SD_PCUIF(g_pcu_conn_id,
2592 tr_PCUIF_RTS_REQ(bts_nr, trx_nr, ts_nr))) {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02002593 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Unexpected RTS.req for supposedly failing activation");
Harald Welte883340c2018-02-28 18:59:29 +01002594 }
2595 [] PCU.receive(t_SD_PCUIF(g_pcu_conn_id, tr_PCUIF_RTS_REQ)) {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02002596 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "RTS.req for wrong TRX/TS");
Harald Welte883340c2018-02-28 18:59:29 +01002597 }
2598 [] PCU.receive { repeat; }
2599 [exp_success] T.timeout {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02002600 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout waiting for PCU RTS.req");
Harald Welte883340c2018-02-28 18:59:29 +01002601 }
2602 [not exp_success] T.timeout {
2603 setverdict(pass);
2604 }
2605 }
2606}
2607
2608private function f_TC_pcu_deact_req(uint8_t bts_nr, uint8_t trx_nr, uint8_t ts_nr)
2609runs on test_CT {
2610 timer T := 3.0;
2611
2612 /* Send PDCH activate request for known PDCH timeslot */
2613 PCU.send(t_SD_PCUIF(g_pcu_conn_id, ts_PCUIF_DEACT_REQ(bts_nr, trx_nr, ts_nr)));
2614
2615 PCU.clear;
2616 /* we now expect no RTS.req for this timeslot */
2617 T.start;
2618 alt {
2619 [] 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 +02002620 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Received unexpected PCU RTS.req");
Harald Welte883340c2018-02-28 18:59:29 +01002621 }
2622 [] PCU.receive { repeat; }
2623 [] T.timeout {
2624 setverdict(pass);
2625 }
2626 }
2627}
2628
2629/* PDCH activation via PCU socket; check for presence of RTS.req */
2630testcase TC_pcu_act_req() runs on test_CT {
2631 f_init();
2632 f_TC_pcu_act_req(0, 0, 7, true);
2633}
2634
2635/* PDCH activation via PCU socket on non-PDCU timeslot */
2636testcase TC_pcu_act_req_wrong_ts() runs on test_CT {
2637 f_init();
2638 f_TC_pcu_act_req(0, 0, 1, false);
2639}
2640
2641/* PDCH activation via PCU socket on wrong BTS */
2642testcase TC_pcu_act_req_wrong_bts() runs on test_CT {
2643 f_init();
2644 f_TC_pcu_act_req(23, 0, 7, false);
2645}
2646
2647/* PDCH activation via PCU socket on wrong TRX */
2648testcase TC_pcu_act_req_wrong_trx() runs on test_CT {
2649 f_init();
2650 f_TC_pcu_act_req(0, 23, 7, false);
2651}
2652
2653/* PDCH deactivation via PCU socket; check for absence of RTS.req */
2654testcase TC_pcu_deact_req() runs on test_CT {
2655 f_init();
2656 /* Activate PDCH */
2657 f_TC_pcu_act_req(0, 0, 7, true);
2658 f_sleep(1.0);
2659 /* and De-Activate again */
2660 f_TC_pcu_deact_req(0, 0, 7);
2661}
2662
2663/* Attempt to deactivate a PDCH on a non-PDCH timeslot */
2664testcase TC_pcu_deact_req_wrong_ts() runs on test_CT {
2665 f_init();
2666 f_TC_pcu_deact_req(0, 0, 1);
2667}
2668
2669/* Test the PCU->BTS Version and BTS->PCU SI13 handshake */
2670testcase TC_pcu_ver_si13() runs on test_CT {
2671 const octetstring si13 := '00010203040506070909'O;
2672 var PCUIF_send_data sd;
2673 timer T:= 3.0;
2674 f_init();
2675
2676 /* Set SI13 via RSL */
2677 f_rsl_bcch_fill_raw(RSL_SYSTEM_INFO_13, si13);
2678 PCU.send(t_SD_PCUIF(g_pcu_conn_id, ts_PCUIF_TXT_IND(0, PCU_VERSION, "BTS_Test v23")));
2679 T.start;
2680 alt {
2681 [] PCU.receive(t_SD_PCUIF(g_pcu_conn_id, tr_PCUIF_DATA_IND(0, 0, 0, ?, PCU_IF_SAPI_BCCH))) -> value sd {
2682 if (substr(sd.data.u.data_ind.data, 0, lengthof(si13)) == si13) {
2683 setverdict(pass);
2684 } else {
2685 repeat;
2686 }
2687 }
2688 [] PCU.receive { repeat; }
2689 [] T.timeout {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02002690 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout waiting for SI13");
Harald Welte883340c2018-02-28 18:59:29 +01002691 }
2692 }
2693}
2694
2695private const octetstring c_PCU_DATA := '000102030405060708090a0b0c0d0e0f10111213141516'O;
2696
2697/* helper function to send a PCU DATA.req */
2698private function f_pcu_data_req(uint8_t bts_nr, uint8_t trx_nr, uint8_t ts_nr,
2699 uint8_t block_nr, uint32_t fn, PCUIF_Sapi sapi, octetstring data)
2700runs on test_CT
2701{
2702 PCU.send(t_SD_PCUIF(g_pcu_conn_id,
2703 ts_PCUIF_DATA_REQ(bts_nr, trx_nr, ts_nr, block_nr, fn, sapi, data)));
2704}
2705
2706/* helper function to wait for RTS.ind for given SAPI on given BTS/TRX/TS and then send */
2707private function f_pcu_wait_rts_and_data_req(uint8_t bts_nr, uint8_t trx_nr, uint8_t ts_nr,
2708 PCUIF_Sapi sapi, octetstring data)
2709runs on test_CT
2710{
2711 var PCUIF_send_data sd;
2712
2713 timer T := 3.0;
2714 T.start;
2715 alt {
2716 [] PCU.receive(t_SD_PCUIF(g_pcu_conn_id,
2717 tr_PCUIF_RTS_REQ(bts_nr, trx_nr, ts_nr, sapi))) -> value sd {
2718 f_pcu_data_req(bts_nr, trx_nr, ts_nr, sd.data.u.rts_req.block_nr,
2719 sd.data.u.rts_req.fn, sapi, data);
2720 }
2721 [] PCU.receive { repeat; }
2722 [] T.timeout {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02002723 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout waiting for RTS.ind");
Harald Welte883340c2018-02-28 18:59:29 +01002724 }
2725 }
2726}
2727
2728/* Send DATA.req on invalid BTS */
2729testcase TC_pcu_data_req_wrong_bts() runs on test_CT {
2730 f_init();
2731 f_TC_pcu_act_req(0, 0, 7, true);
2732 f_pcu_data_req(23, 0, 7, 0, 0, PCU_IF_SAPI_PDTCH, c_PCU_DATA);
2733 /* FIXME: how to check this wasn't actually sent and didn't crash BTS? */
2734 f_sleep(10.0);
2735}
2736
2737/* Send DATA.req on invalid TRX */
2738testcase TC_pcu_data_req_wrong_trx() runs on test_CT {
2739 f_init();
2740 f_TC_pcu_act_req(0, 0, 7, true);
2741 f_pcu_data_req(0, 100, 7, 0, 0, PCU_IF_SAPI_PDTCH, c_PCU_DATA);
2742 /* FIXME: how to check this wasn't actually sent and didn't crash BTS? */
2743 f_sleep(10.0);
2744}
2745
2746/* Send DATA.req on invalid timeslot */
2747testcase TC_pcu_data_req_wrong_ts() runs on test_CT {
2748 f_init();
2749 f_TC_pcu_act_req(0, 0, 7, true);
2750 f_pcu_data_req(0, 0, 70, 0, 0, PCU_IF_SAPI_PDTCH, c_PCU_DATA);
2751 /* FIXME: how to check this wasn't actually sent and didn't crash BTS? */
2752 f_sleep(10.0);
2753}
2754
2755/* Send DATA.req on timeslot that hasn't been activated */
2756testcase TC_pcu_data_req_ts_inactive() runs on test_CT {
2757 f_init();
2758 f_pcu_data_req(0, 0, 7, 0, 0, PCU_IF_SAPI_PDTCH, c_PCU_DATA);
2759 /* FIXME: how to check this wasn't actually sent and didn't crash BTS? */
2760 f_sleep(2.0);
2761}
2762
2763testcase TC_pcu_data_req_pdtch() runs on test_CT {
2764 f_init();
2765 f_TC_pcu_act_req(0, 0, 7, true);
2766 f_pcu_wait_rts_and_data_req(0, 0, 7, PCU_IF_SAPI_PDTCH, c_PCU_DATA);
2767 /* FIXME: how to check this was actually sent */
2768 f_sleep(2.0);
2769}
2770
2771testcase TC_pcu_data_req_ptcch() runs on test_CT {
2772 f_init();
2773 f_TC_pcu_act_req(0, 0, 7, true);
2774 f_pcu_wait_rts_and_data_req(0, 0, 7, PCU_IF_SAPI_PTCCH, c_PCU_DATA);
2775 /* FIXME: how to check this was actually sent */
2776 f_sleep(2.0);
2777}
2778
2779/* Send AGCH from PCU; check it appears on Um side */
2780testcase TC_pcu_data_req_agch() runs on test_CT {
2781 timer T := 3.0;
2782 f_init();
2783 f_init_l1ctl();
2784 f_l1_tune(L1CTL);
2785
2786 f_TC_pcu_act_req(0, 0, 7, true);
2787 f_pcu_data_req(0, 0, 7, 0, 0, PCU_IF_SAPI_AGCH, c_PCU_DATA);
2788
2789 T.start;
2790 alt {
Harald Weltef8df4cb2018-03-10 15:15:08 +01002791 [] L1CTL.receive(tr_L1CTL_DATA_IND(t_RslChanNr_PCH_AGCH(0), ?, c_PCU_DATA)) {
Harald Welte883340c2018-02-28 18:59:29 +01002792 setverdict(pass);
2793 }
2794 [] L1CTL.receive { repeat; }
2795 [] T.timeout {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02002796 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout waiting for PCU-originated AGCH block on Um");
Harald Welte883340c2018-02-28 18:59:29 +01002797 }
2798 }
2799}
2800
2801/* Send IMM.ASS from PCU for PCH; check it appears on Um side */
2802testcase TC_pcu_data_req_imm_ass_pch() runs on test_CT {
2803 var octetstring imm_ass := f_rnd_octstring(23);
2804 f_init();
2805 f_init_l1ctl();
2806 f_l1_tune(L1CTL);
2807
2808 /* append 3 last imsi digits so BTS can compute pagng group */
2809 var uint32_t fn := f_PCUIF_tx_imm_ass_pch(PCU, g_pcu_conn_id, imm_ass, '123459987'H);
2810
2811 timer T := 0.5;
2812 T.start;
2813 alt {
Harald Weltef8df4cb2018-03-10 15:15:08 +01002814 [] L1CTL.receive(tr_L1CTL_DATA_IND(t_RslChanNr_PCH_AGCH(0), ?, imm_ass)) {
Harald Welte883340c2018-02-28 18:59:29 +01002815 /* TODO: verify paging group */
2816 setverdict(pass);
2817 }
2818 [] L1CTL.receive { repeat; }
2819 [] T.timeout {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02002820 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout waiting for PCU-originated AGCH block on Um");
Harald Welte883340c2018-02-28 18:59:29 +01002821 }
2822 }
2823}
2824
2825/* Send RACH from Um side, expect it to show up on PCU socket */
2826testcase TC_pcu_rach_content() runs on test_CT {
2827 f_init();
2828 f_init_l1ctl();
2829 f_l1_tune(L1CTL);
2830
2831 var GsmFrameNumber fn_last := 0;
2832 for (var integer i := 0; i < 1000; i := i+1) {
2833 var OCT1 ra := f_rnd_ra_ps();
2834 var GsmFrameNumber fn := f_L1CTL_RACH(L1CTL, oct2int(ra));
2835 if (fn == fn_last) {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02002836 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Two RACH in same FN?!?");
Harald Welte883340c2018-02-28 18:59:29 +01002837 }
2838 fn_last := fn;
2839
2840 timer T := 2.0;
2841 T.start;
2842 alt {
2843 [] PCU.receive(t_SD_PCUIF(g_pcu_conn_id, tr_PCUIF_RACH_IND(0, oct2int(ra), 0, ?, fn))) {
2844 T.stop;
2845 }
2846 [] PCU.receive(t_SD_PCUIF(g_pcu_conn_id, tr_PCUIF_RACH_IND)) {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02002847 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Unexpected RACH IND");
Harald Welte883340c2018-02-28 18:59:29 +01002848 }
2849 [] PCU.receive { repeat; }
2850 [] T.timeout {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02002851 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout waiting for RACH IND");
Harald Welte883340c2018-02-28 18:59:29 +01002852 }
2853 }
2854 }
2855 setverdict(pass);
2856}
2857
2858private function f_pad_oct(octetstring str, integer len, OCT1 pad) return octetstring {
2859 var integer strlen := lengthof(str);
2860 for (var integer i := 0; i < len-strlen; i := i+1) {
2861 str := str & pad;
2862 }
2863 return str;
2864}
2865
2866/* Send PAGING via RSL, expect it to shw up on PCU socket */
2867testcase TC_pcu_paging_from_rsl() runs on test_CT {
2868 f_init();
2869
2870 for (var integer i := 0; i < 100; i := i+1) {
2871 var MobileL3_CommonIE_Types.MobileIdentityLV mi;
2872 timer T := 3.0;
2873 if (i < 50) {
2874 mi := valueof(ts_MI_TMSI_LV(f_rnd_octstring(4)));
2875 } else {
2876 mi := valueof(ts_MI_IMSI_LV(f_gen_imsi(i)));
2877 }
2878 var octetstring mi_enc_lv := enc_MobileIdentityLV(mi);
2879 var octetstring mi_enc := substr(mi_enc_lv, 1, lengthof(mi_enc_lv)-1);
2880 var octetstring t_mi_lv := f_pad_oct(mi_enc_lv, 9, '00'O);
2881
2882 /* Send RSL PAGING COMMAND */
2883 RSL_CCHAN.send(ts_RSL_UD(ts_RSL_PAGING_CMD(mi_enc, i mod 4)));
2884 T.start;
2885 alt {
2886 [] PCU.receive(t_SD_PCUIF(g_pcu_conn_id, tr_PCUIF_PAG_REQ(0, t_mi_lv))) {
2887 }
2888 [] PCU.receive(t_SD_PCUIF(g_pcu_conn_id, tr_PCUIF_PAG_REQ)) {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02002889 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Unexpected PAGING REQ");
Harald Welte883340c2018-02-28 18:59:29 +01002890 }
2891 [] PCU.receive { repeat; }
2892 [] T.timeout {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02002893 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout waiting for PAGING REQ");
Harald Welte883340c2018-02-28 18:59:29 +01002894 }
2895 }
2896 }
2897 setverdict(pass);
2898}
2899
Harald Welte3d04ae62018-04-04 20:29:05 +02002900/***********************************************************************
Harald Welte9bbbfb52018-04-05 09:33:19 +02002901 * Osmocom Style Dynamic Timeslot Support
Harald Welte3d04ae62018-04-04 20:29:05 +02002902 ***********************************************************************/
2903
2904private function f_dyn_osmo_pdch_act(integer pcu_conn_id, integer bts_nr, integer trx_nr)
2905runs on ConnHdlr {
2906 var PCUIF_send_data sd;
2907 /* Expect BTS to immediately acknowledge activation as PDCH */
2908 PCU.clear;
2909 f_rsl_chan_act(g_pars.chan_mode);
2910 /* expect INFO_IND on PCU interface listing TS as PDCH */
2911 alt {
2912 [] PCU.receive(t_SD_PCUIF(pcu_conn_id, tr_PCUIF_INFO_IND(bts_nr, ?))) -> value sd {
2913 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 +02002914 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "PCUIF_INFO_IND PDCH_MASK not '1' after PDCH ACT");
Harald Welte3d04ae62018-04-04 20:29:05 +02002915 }
2916 }
2917 [] PCU.receive { repeat; }
2918 }
2919 /* try to activate this PDCH from the PCU point of view */
2920 PCU.send(t_SD_PCUIF(pcu_conn_id, ts_PCUIF_ACT_REQ(bts_nr, trx_nr, g_chan_nr.tn)));
2921 /* FIXME: is there a response? */
2922}
2923
2924private function f_dyn_osmo_pdch_deact(integer pcu_conn_id, integer bts_nr, integer trx_nr)
2925runs on ConnHdlr {
2926 var PCUIF_send_data sd;
2927 /* Send RSL CHAN REL (deactivate) */
2928 PCU.clear;
2929 RSL.send(ts_RSL_RF_CHAN_REL(g_chan_nr));
2930 /* expect BTS to ask PCU to deactivate the channel */
2931 alt {
2932 [] PCU.receive(t_SD_PCUIF(pcu_conn_id, tr_PCUIF_INFO_IND(bts_nr, ?))) -> value sd {
2933 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 +02002934 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "PCUIF_INFO_IND PDCH_MASK not '0' after PDCH DEACT");
Harald Welte3d04ae62018-04-04 20:29:05 +02002935 }
2936 }
2937 [] PCU.receive { repeat; }
2938 }
2939 /* Emulate PCU asking BTS to deactivate PDCH */
2940 PCU.send(t_SD_PCUIF(pcu_conn_id, ts_PCUIF_DEACT_REQ(bts_nr, trx_nr, g_chan_nr.tn)));
2941 alt {
2942 [] RSL.receive(tr_RSL_RF_CHAN_REL_ACK(g_chan_nr)) {
2943 setverdict(pass);
2944 }
2945 [] RSL.receive { repeat; }
2946 }
2947}
2948
2949/* Activate Osmocom-style dynamic PDCH from BSC side */
2950function f_TC_dyn_osmo_pdch_act_deact(charstring id) runs on ConnHdlr {
2951 var PCUIF_Message first_info;
2952 var integer ts_nr := g_chan_nr.tn;
2953 var integer trx_nr := 0;
2954 var integer bts_nr := 0;
2955 var integer pcu_conn_id := -1;
2956
2957 f_init_pcu(PCU, id, pcu_conn_id, first_info);
2958
2959 f_dyn_osmo_pdch_act(pcu_conn_id, bts_nr, trx_nr);
2960 f_sleep(3.0);
2961 f_dyn_osmo_pdch_deact(pcu_conn_id, bts_nr, trx_nr);
2962 setverdict(pass);
2963}
2964testcase TC_dyn_osmo_pdch_act_deact() runs on test_CT {
2965 var ConnHdlrPars pars;
2966 var ConnHdlr vc_conn;
2967 f_init(testcasename());
2968
2969 pars := valueof(t_Pars(t_RslChanNr_PDCH(4), ts_RSL_ChanMode_SIGN));
2970 vc_conn := f_start_handler(refers(f_TC_dyn_osmo_pdch_act_deact), pars, true);
2971 vc_conn.done;
2972}
2973
2974/* send a RF CHAN REL for PDCH on an osmocom dynamci PDCH that's already inactive */
2975function f_TC_dyn_osmo_pdch_unsol_deact(charstring id) runs on ConnHdlr {
2976 var PCUIF_Message first_info;
Harald Welte3d04ae62018-04-04 20:29:05 +02002977 var integer pcu_conn_id := -1;
2978
2979 f_init_pcu(PCU, id, pcu_conn_id, first_info);
2980
Neels Hofmeyr9c50ca52018-05-08 20:37:54 +02002981 RSL.send(ts_RSL_RF_CHAN_REL(g_chan_nr));
2982 /* since the lchan is already released, we don't expect any PCU changes, just a rel ack. */
2983 RSL.receive(tr_RSL_RF_CHAN_REL_ACK(g_chan_nr));
Harald Welte3d04ae62018-04-04 20:29:05 +02002984 setverdict(pass);
2985}
2986testcase TC_dyn_osmo_pdch_unsol_deact() runs on test_CT {
2987 var ConnHdlrPars pars;
2988 var ConnHdlr vc_conn;
2989 f_init(testcasename());
2990
2991 pars := valueof(t_Pars(t_RslChanNr_PDCH(4), ts_RSL_ChanMode_SIGN));
2992 vc_conn := f_start_handler(refers(f_TC_dyn_osmo_pdch_unsol_deact), pars, true);
2993 vc_conn.done;
2994}
2995
2996/* try to RSL CHAN ACT a PDCH on an osmocom-style PDCH that's already active */
2997function f_TC_dyn_osmo_pdch_double_act(charstring id) runs on ConnHdlr {
2998 var PCUIF_Message first_info;
2999 var integer ts_nr := g_chan_nr.tn;
3000 var integer trx_nr := 0;
3001 var integer bts_nr := 0;
3002 var integer pcu_conn_id := -1;
3003
3004 f_init_pcu(PCU, id, pcu_conn_id, first_info);
3005
3006 f_dyn_osmo_pdch_act(pcu_conn_id, bts_nr, trx_nr);
Neels Hofmeyrdf936a22018-05-08 22:07:57 +02003007 /* Send a second Chan Activ and expect it to be NACKed */
3008 f_rsl_transceive(ts_RSL_CHAN_ACT(g_chan_nr, g_pars.chan_mode), tr_RSL_CHAN_ACT_NACK(g_chan_nr),
3009 "RSL CHAN ACT NACK");
Harald Welte3d04ae62018-04-04 20:29:05 +02003010 setverdict(pass);
3011}
3012testcase TC_dyn_osmo_pdch_double_act() runs on test_CT {
3013 var ConnHdlrPars pars;
3014 var ConnHdlr vc_conn;
3015 f_init(testcasename());
3016
3017 pars := valueof(t_Pars(t_RslChanNr_PDCH(4), ts_RSL_ChanMode_SIGN));
3018 vc_conn := f_start_handler(refers(f_TC_dyn_osmo_pdch_double_act), pars, true);
3019 vc_conn.done;
3020}
3021
3022/* try to RSL CHAN ACT a TCH/F on an osmocom-style PDCH */
3023function f_TC_dyn_osmo_pdch_tchf_act(charstring id) runs on ConnHdlr {
3024 var PCUIF_Message first_info;
3025 var integer ts_nr := g_chan_nr.tn;
3026 var integer trx_nr := 0;
3027 var integer bts_nr := 0;
3028 var integer pcu_conn_id := -1;
3029 var RslChannelNr chan_nr := valueof(t_RslChanNr_Bm(g_chan_nr.tn));
3030
3031 /* register for the TCH/F channel number */
3032 f_rslem_register(0, chan_nr);
3033
3034 f_init_pcu(PCU, id, pcu_conn_id, first_info);
3035
3036 f_rsl_transceive(ts_RSL_CHAN_ACT(chan_nr, g_pars.chan_mode), tr_RSL_CHAN_ACT_ACK(chan_nr),
3037 "RSL CHAN ACT");
3038 setverdict(pass);
3039}
3040testcase TC_dyn_osmo_pdch_tchf_act() runs on test_CT {
3041 var ConnHdlrPars pars;
3042 var ConnHdlr vc_conn;
3043 f_init(testcasename());
3044
3045 pars := valueof(t_Pars(t_RslChanNr_PDCH(4), ts_RSL_ChanMode_SIGN));
3046 vc_conn := f_start_handler(refers(f_TC_dyn_osmo_pdch_tchf_act), pars, true);
3047 vc_conn.done;
3048}
3049
3050/* try to RSL CHAN ACT the TCH/H on an osmocom-style PDCH */
3051function f_TC_dyn_osmo_pdch_tchh_act(charstring id) runs on ConnHdlr {
3052 var PCUIF_Message first_info;
3053 var integer ts_nr := g_chan_nr.tn;
3054 var integer trx_nr := 0;
3055 var integer bts_nr := 0;
3056 var integer pcu_conn_id := -1;
3057 var RslChannelNr chan_nr[2] := { valueof(t_RslChanNr_Lm(g_chan_nr.tn, 0)),
3058 valueof(t_RslChanNr_Lm(g_chan_nr.tn, 1)) };
3059
3060 /* register for the TCH/H channel numbers */
3061 f_rslem_register(0, chan_nr[0]);
3062 f_rslem_register(0, chan_nr[1]);
3063
3064 f_init_pcu(PCU, id, pcu_conn_id, first_info);
3065
3066 f_rsl_transceive(ts_RSL_CHAN_ACT(chan_nr[1], g_pars.chan_mode),
3067 tr_RSL_CHAN_ACT_ACK(chan_nr[1]), "RSL CHAN ACT [1]");
3068 f_rsl_transceive(ts_RSL_CHAN_ACT(chan_nr[0], g_pars.chan_mode),
3069 tr_RSL_CHAN_ACT_ACK(chan_nr[0]), "RSL CHAN ACT [0]");
3070 setverdict(pass);
3071}
3072testcase TC_dyn_osmo_pdch_tchh_act() runs on test_CT {
3073 var ConnHdlrPars pars;
3074 var ConnHdlr vc_conn;
3075 f_init(testcasename());
3076
3077 pars := valueof(t_Pars(t_RslChanNr_PDCH(4), ts_RSL_ChanMode_SIGN));
3078 vc_conn := f_start_handler(refers(f_TC_dyn_osmo_pdch_tchh_act), pars, true);
3079 vc_conn.done;
3080}
3081
Harald Welte9bbbfb52018-04-05 09:33:19 +02003082/***********************************************************************
3083 * IPA Style Dynamic Timeslot Support
3084 ***********************************************************************/
3085
3086private function f_dyn_ipa_pdch_act(integer pcu_conn_id, integer bts_nr, integer trx_nr)
3087runs on ConnHdlr {
3088 var PCUIF_send_data sd;
3089 /* Expect BTS to immediately acknowledge activation as PDCH */
3090 PCU.clear;
3091 RSL.send(ts_RSL_IPA_PDCH_ACT(g_chan_nr));
3092 /* expect INFO_IND on PCU interface listing TS as PDCH */
3093 alt {
3094 [] PCU.receive(t_SD_PCUIF(pcu_conn_id, tr_PCUIF_INFO_IND(bts_nr, ?))) -> value sd {
3095 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 +02003096 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "PCUIF_INFO_IND PDCH_MASK not '1' after PDCH ACT");
Harald Welte9bbbfb52018-04-05 09:33:19 +02003097 }
3098 }
3099 [] PCU.receive { repeat; }
3100 }
3101 /* try to activate this PDCH from the PCU point of view */
3102 PCU.send(t_SD_PCUIF(pcu_conn_id, ts_PCUIF_ACT_REQ(bts_nr, trx_nr, g_chan_nr.tn)));
3103 /* FIXME: is there a response? */
3104
3105 RSL.receive(tr_RSL_IPA_PDCH_ACT_ACK(g_chan_nr, ?));
3106}
3107
3108private function f_dyn_ipa_pdch_deact(integer pcu_conn_id, integer bts_nr, integer trx_nr)
3109runs on ConnHdlr {
3110 var PCUIF_send_data sd;
3111 /* Send RSL CHAN REL (deactivate) */
3112 RSL.send(ts_RSL_IPA_PDCH_DEACT(g_chan_nr));
3113 PCU.clear;
3114 /* expect BTS to ask PCU to deactivate the channel */
3115 alt {
3116 [] PCU.receive(t_SD_PCUIF(pcu_conn_id, tr_PCUIF_INFO_IND(bts_nr, ?))) -> value sd {
3117 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 +02003118 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "PCUIF_INFO_IND PDCH_MASK not '0' after PDCH DEACT");
Harald Welte9bbbfb52018-04-05 09:33:19 +02003119 }
3120 }
3121 [] PCU.receive { repeat; }
3122 }
3123 /* Emulate PCU asking BTS to deactivate PDCH */
3124 PCU.send(t_SD_PCUIF(pcu_conn_id, ts_PCUIF_DEACT_REQ(bts_nr, trx_nr, g_chan_nr.tn)));
3125 alt {
3126 [] RSL.receive(tr_RSL_IPA_PDCH_DEACT_ACK(g_chan_nr)) {
3127 setverdict(pass);
3128 }
3129 [] RSL.receive { repeat; }
3130 }
3131}
3132
3133/* Activate and de-activate an IPA-style dynamic TCH/F + PDCH */
3134function f_TC_dyn_ipa_pdch_act_deact(charstring id) runs on ConnHdlr {
3135 var PCUIF_Message first_info;
3136 var integer ts_nr := g_chan_nr.tn;
3137 var integer trx_nr := 0;
3138 var integer bts_nr := 0;
3139 var integer pcu_conn_id := -1;
3140
3141 f_init_pcu(PCU, id, pcu_conn_id, first_info);
3142
3143 f_dyn_ipa_pdch_act(pcu_conn_id, bts_nr, trx_nr);
3144 f_sleep(3.0);
3145 f_dyn_ipa_pdch_deact(pcu_conn_id, bts_nr, trx_nr);
3146
3147 setverdict(pass);
3148
3149}
3150testcase TC_dyn_ipa_pdch_act_deact() runs on test_CT {
3151 var ConnHdlrPars pars;
3152 var ConnHdlr vc_conn;
3153 f_init();
3154
3155 pars := valueof(t_Pars(t_RslChanNr_Bm(3), ts_RSL_ChanMode_SIGN));
3156 vc_conn := f_start_handler(refers(f_TC_dyn_ipa_pdch_act_deact), pars, true);
3157 vc_conn.done;
3158}
3159
3160/* try to RSL CHAN ACT a TCH/F on an IPA-style PDCH */
3161function f_TC_dyn_ipa_pdch_tchf_act(charstring id) runs on ConnHdlr {
3162 var PCUIF_Message first_info;
3163 var integer ts_nr := g_chan_nr.tn;
3164 var integer trx_nr := 0;
3165 var integer bts_nr := 0;
3166 var integer pcu_conn_id := -1;
3167
3168 f_init_pcu(PCU, id, pcu_conn_id, first_info);
3169
3170 f_rsl_transceive(ts_RSL_CHAN_ACT(g_chan_nr, g_pars.chan_mode), tr_RSL_CHAN_ACT_ACK(g_chan_nr),
3171 "RSL CHAN ACT");
3172 f_rsl_transceive(ts_RSL_RF_CHAN_REL(g_chan_nr), tr_RSL_RF_CHAN_REL_ACK(g_chan_nr),
3173 "RF CHAN REL", true);
3174 setverdict(pass);
3175}
3176testcase TC_dyn_ipa_pdch_tchf_act() runs on test_CT {
3177 var ConnHdlrPars pars;
3178 var ConnHdlr vc_conn;
3179 f_init(testcasename());
3180
3181 pars := valueof(t_Pars(t_RslChanNr_Bm(3), ts_RSL_ChanMode_SIGN));
3182 vc_conn := f_start_handler(refers(f_TC_dyn_ipa_pdch_tchf_act), pars, true);
3183 vc_conn.done;
3184}
3185
3186/* Activate IPA style dyn PDCH as TCH/F and then illegally try to activate it as PDCH, too */
3187function f_TC_dyn_ipa_pdch_tchf_act_pdch_act_nack(charstring id) runs on ConnHdlr {
3188 var PCUIF_Message first_info;
3189 var integer ts_nr := g_chan_nr.tn;
3190 var integer trx_nr := 0;
3191 var integer bts_nr := 0;
3192 var integer pcu_conn_id := -1;
3193
3194 f_init_pcu(PCU, id, pcu_conn_id, first_info);
3195
3196 f_rsl_transceive(ts_RSL_CHAN_ACT(g_chan_nr, g_pars.chan_mode), tr_RSL_CHAN_ACT_ACK(g_chan_nr),
3197 "RSL CHAN ACT");
3198
3199 RSL.send(ts_RSL_IPA_PDCH_ACT(g_chan_nr));
3200 alt {
3201 [] RSL.receive(tr_RSL_IPA_PDCH_ACT_NACK(g_chan_nr, ?));
3202 [] RSL.receive(tr_RSL_IPA_PDCH_ACT_ACK(g_chan_nr, ?)) {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02003203 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Unexpected PDCH ACT ACK");
Harald Welte9bbbfb52018-04-05 09:33:19 +02003204 }
3205 [] RSL.receive { repeat; }
3206 }
3207
3208 f_rsl_transceive(ts_RSL_RF_CHAN_REL(g_chan_nr), tr_RSL_RF_CHAN_REL_ACK(g_chan_nr),
3209 "RF CHAN REL", true);
3210 setverdict(pass);
3211}
3212testcase TC_dyn_ipa_pdch_tchf_act_pdch_act_nack() runs on test_CT {
3213 var ConnHdlrPars pars;
3214 var ConnHdlr vc_conn;
3215 f_init(testcasename());
3216
3217 pars := valueof(t_Pars(t_RslChanNr_Bm(3), ts_RSL_ChanMode_SIGN));
3218 vc_conn := f_start_handler(refers(f_TC_dyn_ipa_pdch_tchf_act_pdch_act_nack), pars, true);
3219 vc_conn.done;
3220}
3221
3222/* try to RSL CHAN ACT a TCH/F on an IPA-style PDCH that's already in PDCH mode; expect NACK */
3223function f_TC_dyn_ipa_pdch_act_tchf_act_nack(charstring id) runs on ConnHdlr {
3224 var PCUIF_Message first_info;
3225 var integer ts_nr := g_chan_nr.tn;
3226 var integer trx_nr := 0;
3227 var integer bts_nr := 0;
3228 var integer pcu_conn_id := -1;
3229
3230 /* register for the TCH/F channel number */
3231 f_rslem_register(0, g_chan_nr);
3232
3233 f_init_pcu(PCU, id, pcu_conn_id, first_info);
3234
3235 f_dyn_ipa_pdch_act(pcu_conn_id, bts_nr, trx_nr);
3236
3237 f_rsl_transceive(ts_RSL_CHAN_ACT(g_chan_nr, g_pars.chan_mode), tr_RSL_CHAN_ACT_NACK(g_chan_nr),
3238 "RSL CHAN ACT");
3239
3240 f_dyn_ipa_pdch_deact(pcu_conn_id, bts_nr, trx_nr);
3241
3242 setverdict(pass);
3243}
3244testcase TC_dyn_ipa_pdch_act_tchf_act_nack() runs on test_CT {
3245 var ConnHdlrPars pars;
3246 var ConnHdlr vc_conn;
3247 f_init(testcasename());
3248
3249 pars := valueof(t_Pars(t_RslChanNr_Bm(3), ts_RSL_ChanMode_SIGN));
3250 vc_conn := f_start_handler(refers(f_TC_dyn_ipa_pdch_act_tchf_act_nack), pars, true);
3251 vc_conn.done;
3252}
3253
3254
Harald Welte0472ab42018-03-12 15:02:26 +01003255/***********************************************************************
3256 * LAPDm / RLL related
3257 ***********************************************************************/
3258
3259private function f_tx_lapdm(template (value) LapdmFrame l,
3260 template (value) RslLinkId link_id) runs on ConnHdlr {
3261 var octetstring l2 := enc_LapdmFrame(valueof(l));
3262 if (valueof(link_id.c) == SACCH) {
3263 /* prepend dummy L1 header */
Pau Espin Pedrola0fb42a2018-10-10 15:56:39 +02003264 var L1ctlDataReq l1hl2 := {
3265 l1header := valueof(ts_SacchL1Header(g_pars.l1_pars.ms_power_level, false, g_pars.l1_pars.ms_actual_ta)),
3266 l2_payload := f_pad_oct(l2, 21, '2B'O)
3267 }
3268 L1CTL.send(ts_L1CTL_DATA_REQ_SACCH(g_chan_nr, link_id, l1hl2));
3269 } else {
3270 /* If required, pad L2 frame with constant 0x2b filling */
3271 l2 := f_pad_oct(l2, 23, '2B'O);
3272
3273 log("encoding ", l, " to ", l2);
3274 L1CTL.send(ts_L1CTL_DATA_REQ(g_chan_nr, link_id, l2));
Harald Welte0472ab42018-03-12 15:02:26 +01003275 }
Harald Welte0472ab42018-03-12 15:02:26 +01003276}
3277
3278type record RllTestCase {
3279 uint3_t sapi,
3280 RslLinkId link_id,
3281 octetstring l3,
3282 boolean exp
3283}
3284type record of RllTestCase RllTestCases;
3285template RllTestCase t_EITC(uint3_t sapi, RslLinkId id, octetstring l3, boolean exp) := {
3286 sapi := sapi,
3287 link_id := id,
3288 l3 := l3,
3289 exp := exp
3290}
3291
3292/* execute the same callback function with a set of different parameters (tcs) on a
3293 * variety of logical channels */
3294private function f_rll_testmatrix(RllTestCases tcs, void_fn fn) runs on test_CT {
3295 var ConnHdlrPars pars;
3296 var ConnHdlr vc_conn;
3297 f_init(testcasename());
3298
3299 /* test on each of the channels we have */
3300 for (var integer i := 0; i < sizeof(g_AllChanTypes); i := i+1) {
3301 pars := valueof(t_Pars(g_AllChanTypes[i], ts_RSL_ChanMode_SIGN));
3302
3303 /* test each of the test cases on the current channel */
3304 for (var integer j := 0; j < sizeof(tcs); j := j+1) {
3305 pars.spec.rll := tcs[j];
3306 log(testcasename(), ": XXX Starting ", tcs[j] , " on ", g_AllChanTypes[i]);
3307 vc_conn := f_start_handler(fn, pars);
3308 vc_conn.done;
3309 }
3310 }
3311
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02003312 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
Harald Welte0472ab42018-03-12 15:02:26 +01003313}
3314
3315/* test if SABM on Um triggers EST IND (TS 48.058 3.1) */
3316private function f_TC_rll_est_ind(charstring id) runs on ConnHdlr {
3317 var RllTestCase tc := g_pars.spec.rll;
3318 timer T := 3.0;
3319
3320 f_l1_tune(L1CTL);
3321 RSL.clear;
3322
3323 /* activate the logical channel */
3324 f_est_dchan();
3325 L1CTL.clear;
3326
3327 f_tx_lapdm(ts_LAPDm_SABM(tc.sapi, cr_MO_CMD, true, tc.l3), tc.link_id);
3328 T.start;
3329 alt {
3330 [tc.l3 != ''O] RSL.receive(tr_RSL_EST_IND(g_chan_nr, tc.link_id, tc.l3)) {
3331 if (tc.exp) {
3332 setverdict(pass);
3333 } else {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02003334 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("Unexpected EST IND with L3 in ", tc));
Harald Welte0472ab42018-03-12 15:02:26 +01003335 }
3336 }
3337 [tc.l3 == ''O] RSL.receive(tr_RSL_EST_IND_NOL3(g_chan_nr, tc.link_id)) {
3338 if (tc.exp) {
3339 setverdict(pass);
3340 } else {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02003341 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("Unexpected EST IND without L3 in ", tc));
Harald Welte0472ab42018-03-12 15:02:26 +01003342 }
3343 }
Vadim Yanitskiy35677872018-10-04 17:30:21 +07003344 /* We also expect to receive the measurements */
3345 [] as_meas_res(verify_meas := false);
Harald Welte0472ab42018-03-12 15:02:26 +01003346 [tc.exp] T.timeout {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02003347 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout waiting for EST IND");
Harald Welte0472ab42018-03-12 15:02:26 +01003348 }
3349 [not tc.exp] T.timeout {
3350 setverdict(pass);
3351 }
3352 }
3353
3354 f_rsl_chan_deact();
3355 f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
3356 f_rslem_unregister(0, g_chan_nr);
3357}
3358testcase TC_rll_est_ind() runs on test_CT {
3359 var RllTestCases tcs := {
Harald Welte7aacbbf2018-05-09 16:56:41 +02003360 /* SAPI0 establishment (contention resolution) */
Harald Welte0472ab42018-03-12 15:02:26 +01003361 valueof(t_EITC(0, valueof(ts_RslLinkID_DCCH(0)), '01020304'O, true)),
Harald Welte7aacbbf2018-05-09 16:56:41 +02003362 /* normal SAPI0 establishment */
3363 valueof(t_EITC(0, valueof(ts_RslLinkID_DCCH(0)), ''O, true)),
Harald Welte0472ab42018-03-12 15:02:26 +01003364 /* SAPI 3 doesn't support contention resolution */
3365 valueof(t_EITC(3, valueof(ts_RslLinkID_DCCH(3)), '01020304'O, false)),
3366 valueof(t_EITC(3, valueof(ts_RslLinkID_SACCH(3)), '01020304'O, false)),
3367 /* normal SAPI3 establishment on main DCCH */
3368 valueof(t_EITC(3, valueof(ts_RslLinkID_DCCH(3)), ''O, true)),
3369 /* normal SAPI3 establishment on SACCH */
3370 valueof(t_EITC(3, valueof(ts_RslLinkID_SACCH(3)), ''O, true))
3371 };
3372 f_rll_testmatrix(tcs, refers(f_TC_rll_est_ind));
3373}
3374
3375/* test if RLL EST REQ trigeres SABM on Um; UA on Um triggers EST CONF (TS 48.058 3.2) */
3376private function f_TC_rll_est_req(charstring id) runs on ConnHdlr {
3377 var RllTestCase tc := g_pars.spec.rll;
3378 var L1ctlDlMessage dl;
3379 timer T := 3.0;
3380
3381 f_l1_tune(L1CTL);
3382 RSL.clear;
3383
3384 /* activate the logical channel */
3385 f_est_dchan();
3386 L1CTL.clear;
3387
3388 /* Send a RSL EST REQ for SAPI3 on main DCCH */
3389 RSL.send(ts_RSL_EST_REQ(g_chan_nr, tc.link_id));
3390 T.start;
3391 alt {
3392 [] L1CTL.receive(tr_L1CTL_DATA_IND(g_chan_nr, ?)) -> value dl {
3393 var LapdmFrame lapdm;
3394 var octetstring l2 := dl.payload.data_ind.payload;
3395 if (dl.dl_info.link_id.c == SACCH) {
3396 /* remove L1 header */
3397 l2 := substr(l2, 2, lengthof(l2)-2);
3398 }
3399 lapdm.ab := dec_LapdmFrameAB(l2);
3400 if (match(lapdm, tr_LAPDm_SABM(tc.sapi, cr_MT_CMD, true, ''O))) {
3401 setverdict(pass);
3402 } else {
3403 repeat;
3404 }
3405 }
3406 [] L1CTL.receive { repeat; }
3407 [] T.timeout {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02003408 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout waiting for SABM");
Harald Welte0472ab42018-03-12 15:02:26 +01003409 }
3410 }
3411
3412 f_rsl_chan_deact();
3413 f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
3414 f_rslem_unregister(0, g_chan_nr);
3415}
3416testcase TC_rll_est_req_DCCH_3() runs on test_CT {
3417 var RllTestCases tcs := {
3418 /* normal SAPI3 establishment on main DCCH */
3419 valueof(t_EITC(3, valueof(ts_RslLinkID_DCCH(3)), ''O, true))//,
3420 };
3421 f_rll_testmatrix(tcs, refers(f_TC_rll_est_req));
3422}
3423testcase TC_rll_est_req_ACCH_3() runs on test_CT {
3424 var RllTestCases tcs := {
3425 /* normal SAPI3 establishment on SACCH */
3426 valueof(t_EITC(3, valueof(ts_RslLinkID_SACCH(3)), ''O, true))
3427 }
3428 f_rll_testmatrix(tcs, refers(f_TC_rll_est_req));
3429}
3430
3431/* altstep to receive a LAPDm frame matching the given template */
3432private altstep as_l1_exp_lapdm(template LapdmFrame exp) runs on ConnHdlr {
3433 var L1ctlDlMessage dl;
3434 [] L1CTL.receive(tr_L1CTL_DATA_IND(g_chan_nr, ?)) -> value dl {
3435 var LapdmFrame lapdm;
3436 var octetstring l2 := dl.payload.data_ind.payload;
3437 if (dl.dl_info.link_id.c == SACCH) {
3438 /* remove L1 header */
3439 l2 := substr(l2, 2, lengthof(l2)-2);
3440 }
3441 if (ischosen(exp.ab)) {
3442 lapdm.ab := dec_LapdmFrameAB(l2);
3443 } else if (ischosen(exp.b4)) {
3444 lapdm.b4 := dec_LapdmFrameB4(l2);
3445 } else if (ischosen(exp.bbis)) {
3446 lapdm.bbis := dec_LapdmFrameBbis(l2);
3447 }
3448 log("Rx LAPDm ", lapdm);
3449 if (match(lapdm, exp)) {
3450 setverdict(pass);
3451 } else {
3452 repeat;
3453 }
3454 }
3455 [] L1CTL.receive { repeat; }
3456}
3457private function f_l1_exp_lapdm(template LapdmFrame exp, float t := 3.0) runs on ConnHdlr {
3458 timer T := t;
3459 T.start;
3460 alt {
3461 [] T.timeout {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02003462 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("Timeout waiting for LAPDm ", exp));
Harald Welte0472ab42018-03-12 15:02:26 +01003463 }
3464 [] as_l1_exp_lapdm(exp);
3465 }
3466}
3467
3468/* establish one Radio Link Layer via SABM -> UA. Use l3 for contention resolution */
3469private function f_est_rll_mo(uint3_t sapi, RslLinkId link_id, octetstring l3) runs on ConnHdlr {
3470 /* send SABM from MS -> BTS */
3471 f_tx_lapdm(ts_LAPDm_SABM(sapi, cr_MO_CMD, true, l3), link_id);
3472 /* expect RLL EST IND on Abis */
3473 alt {
3474 [l3 != ''O] RSL.receive(tr_RSL_EST_IND(g_chan_nr, link_id, l3));
3475 [l3 == ''O] RSL.receive(tr_RSL_EST_IND_NOL3(g_chan_nr, link_id));
3476 [] RSL.receive(tr_RSL_ERROR_IND(g_chan_nr, link_id, ?)) {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02003477 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Failing due to RSL_ERROR_IND");
Harald Welte0472ab42018-03-12 15:02:26 +01003478 }
3479 [] RSL.receive { repeat; }
3480 }
3481 /* expect UA from BTS -> MS */
3482 f_l1_exp_lapdm(tr_LAPDm_UA(sapi, cr_MT_RSP, true, l3));
3483}
3484
3485/* test if DISC on Um triggers RLL REL IND (TS 48.058 3.3) */
3486private function f_TC_rll_rel_ind(charstring id) runs on ConnHdlr {
3487 var RllTestCase tc := g_pars.spec.rll;
3488
3489 f_l1_tune(L1CTL);
3490 RSL.clear;
3491
3492 /* activate the logical channel */
3493 f_est_dchan();
3494 L1CTL.clear;
3495
3496 /* first establish the link-layer */
3497 f_est_rll_mo(tc.sapi, tc.link_id, tc.l3);
3498
3499 /* then send the DISC */
3500 f_tx_lapdm(ts_LAPDm_DISC(tc.sapi, cr_MO_CMD, true), tc.link_id);
3501 /* ... and expect the REL IND on the RSL side */
3502 alt {
3503 [] RSL.receive(tr_RSL_REL_IND(g_chan_nr, tc.link_id)) {
3504 setverdict(pass);
3505 }
Vadim Yanitskiy35677872018-10-04 17:30:21 +07003506 /* We also expect to receive the measurements */
3507 [] as_meas_res(verify_meas := false);
Harald Welte0472ab42018-03-12 15:02:26 +01003508 }
3509
3510 /* release the channel */
3511 f_rsl_chan_deact();
3512 f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
3513 f_rslem_unregister(0, g_chan_nr);
3514}
3515testcase TC_rll_rel_ind_DCCH_0() runs on test_CT {
3516 var RllTestCases tcs := {
3517 valueof(t_EITC(0, valueof(ts_RslLinkID_DCCH(0)), '01020304'O, true))
3518 };
3519 f_rll_testmatrix(tcs, refers(f_TC_rll_rel_ind));
3520}
3521
3522testcase TC_rll_rel_ind_ACCH_0() runs on test_CT {
3523 var RllTestCases tcs := {
3524 valueof(t_EITC(0, valueof(ts_RslLinkID_SACCH(0)), ''O, true))
3525 };
3526 f_rll_testmatrix(tcs, refers(f_TC_rll_rel_ind));
3527}
3528testcase TC_rll_rel_ind_DCCH_3() runs on test_CT {
3529 var RllTestCases tcs := {
3530 valueof(t_EITC(3, valueof(ts_RslLinkID_DCCH(3)), ''O, true))
3531 };
3532 f_rll_testmatrix(tcs, refers(f_TC_rll_rel_ind));
3533}
3534testcase TC_rll_rel_ind_ACCH_3() runs on test_CT {
3535 var RllTestCases tcs := {
3536 valueof(t_EITC(3, valueof(ts_RslLinkID_SACCH(3)), ''O, true))
3537 };
3538 f_rll_testmatrix(tcs, refers(f_TC_rll_rel_ind));
3539}
3540
3541/* test if RLL REL REQ triggers DISC on Um; UA/DM triggers RLL REL CONF (TS 48.058 3.4) */
3542private function f_TC_rll_rel_req(charstring id) runs on ConnHdlr {
3543 var RllTestCase tc := g_pars.spec.rll;
3544 f_l1_tune(L1CTL);
3545 RSL.clear;
3546
3547 /* activate the logical channel */
3548 f_est_dchan();
3549 L1CTL.clear;
3550
3551 /* first establish the link-layer */
3552 f_est_rll_mo(tc.sapi, tc.link_id, tc.l3);
3553
3554 /* then send the REL REQ via RSL */
3555 RSL.send(ts_RSL_REL_REQ(g_chan_nr, tc.link_id, RSL_REL_MODE_NORMAL));
3556 /* ... and expect the DISC on the Um side */
3557 alt {
Harald Weltebc6199f2018-05-10 19:38:18 +02003558 [] as_l1_exp_lapdm(tr_LAPDm_DISC(tc.sapi, cr_MT_CMD, true)) {
Harald Welte0472ab42018-03-12 15:02:26 +01003559 /* FIXME: send a UA in resposne to the DISC */
3560 }
3561 }
3562
3563 /* release the channel */
3564 f_rsl_chan_deact();
3565 f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
3566 f_rslem_unregister(0, g_chan_nr);
3567}
3568testcase TC_rll_rel_req() runs on test_CT {
3569 var RllTestCases tcs := {
3570 valueof(t_EITC(0, valueof(ts_RslLinkID_DCCH(0)), '01020304'O, true)),
3571 valueof(t_EITC(0, valueof(ts_RslLinkID_SACCH(0)), ''O, true)),
3572 valueof(t_EITC(3, valueof(ts_RslLinkID_DCCH(3)), ''O, true)),
3573 valueof(t_EITC(3, valueof(ts_RslLinkID_SACCH(3)), ''O, true))
3574 };
3575 f_rll_testmatrix(tcs, refers(f_TC_rll_rel_req));
3576}
3577
3578/* test if RLL DATA REQ triggers I-frames on Um (TS 48.058 3.5) */
3579testcase TC_rll_data_req() runs on test_CT {
3580}
3581
3582/* test if I-frames on Um trigger RLL DATA IND (TS 48.058 3.6) */
3583testcase TC_rll_data_ind() runs on test_CT {
3584}
3585
3586/* test if RLL UNIT DATA REQ triggers UI-frame on Um (TS 48.058 3.7) */
3587private function f_TC_rll_ud_req(charstring id) runs on ConnHdlr {
3588 var RllTestCase tc := g_pars.spec.rll;
3589
3590 f_l1_tune(L1CTL);
3591 RSL.clear;
3592
3593 f_est_dchan();
3594 L1CTL.clear;
3595
3596 /* Send UNITDATA REQ on RSL side */
3597 RSL.send(ts_RSL_UNITDATA_REQ(g_chan_nr, tc.link_id, tc.l3));
3598 /* Expect it to arrive on the other side */
3599 if (tc.link_id.c == SACCH) {
Harald Weltee613f962018-04-18 22:38:16 +02003600 f_l1_exp_lapdm(tr_LAPDm_B4_UI(tc.sapi, cr_MT_CMD, tc.l3));
Harald Welte0472ab42018-03-12 15:02:26 +01003601 } else {
Harald Weltee613f962018-04-18 22:38:16 +02003602 f_l1_exp_lapdm(tr_LAPDm_UI(tc.sapi, cr_MT_CMD, tc.l3));
Harald Welte0472ab42018-03-12 15:02:26 +01003603 }
3604
3605 /* release the channel */
3606 f_rsl_chan_deact();
3607 f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
3608 f_rslem_unregister(0, g_chan_nr);
3609}
3610testcase TC_rll_unit_data_req_DCCH() runs on test_CT {
3611 var octetstring l3 := f_rnd_octstring(15);
3612 var RllTestCases tcs := {
3613 valueof(t_EITC(0, valueof(ts_RslLinkID_DCCH(0)), l3, true)),
3614 valueof(t_EITC(3, valueof(ts_RslLinkID_DCCH(3)), l3, true))
3615 };
3616 f_rll_testmatrix(tcs, refers(f_TC_rll_ud_req));
3617}
3618testcase TC_rll_unit_data_req_ACCH() runs on test_CT {
3619 var octetstring l3 := f_rnd_octstring(19);
3620 var RllTestCases tcs := {
3621 valueof(t_EITC(0, valueof(ts_RslLinkID_SACCH(0)), l3, true)),
3622 valueof(t_EITC(3, valueof(ts_RslLinkID_SACCH(3)), l3, true))
3623 };
3624 f_rll_testmatrix(tcs, refers(f_TC_rll_ud_req));
3625}
3626
3627/* test if UI-frames on Um trigger RLL UNIT DATA IND (TS 48.058 3.8) */
3628private function f_TC_rll_ud_ind(charstring id) runs on ConnHdlr {
3629 var RllTestCase tc := g_pars.spec.rll;
3630
3631 f_l1_tune(L1CTL);
3632 RSL.clear;
3633
3634 f_est_dchan();
3635 L1CTL.clear;
3636
3637 /* Send LAPDm UI frame. There is no B4 format in uplink! */
Harald Weltee613f962018-04-18 22:38:16 +02003638 f_tx_lapdm(ts_LAPDm_UI(tc.sapi, cr_MO_CMD, tc.l3), tc.link_id);
Harald Welte0472ab42018-03-12 15:02:26 +01003639 /* Expdct RLL UNITDATA IND on RSL side */
3640 alt {
3641 [] RSL.receive(tr_RSL_UNITDATA_IND(g_chan_nr, tc.link_id, tc.l3)) {
3642 setverdict(pass);
3643 }
3644 [] RSL.receive { repeat; }
3645 }
3646
3647 /* release the channel */
3648 f_rsl_chan_deact();
3649 f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
3650 f_rslem_unregister(0, g_chan_nr);
3651}
3652testcase TC_rll_unit_data_ind_DCCH() runs on test_CT {
Stefan Sperlingc4181912018-07-25 17:03:08 +02003653 var octetstring l3 := f_rnd_octstring(20);
Harald Welte0472ab42018-03-12 15:02:26 +01003654 var RllTestCases tcs := {
3655 valueof(t_EITC(0, valueof(ts_RslLinkID_DCCH(0)), l3, true)),
3656 valueof(t_EITC(3, valueof(ts_RslLinkID_DCCH(3)), l3, true))
3657 };
3658 f_rll_testmatrix(tcs, refers(f_TC_rll_ud_ind));
3659}
3660testcase TC_rll_unit_data_ind_ACCH() runs on test_CT {
3661 var octetstring l3 := f_rnd_octstring(18);
3662 var RllTestCases tcs := {
3663 valueof(t_EITC(0, valueof(ts_RslLinkID_SACCH(0)), l3, true)),
3664 valueof(t_EITC(3, valueof(ts_RslLinkID_SACCH(3)), l3, true))
3665 };
3666 f_rll_testmatrix(tcs, refers(f_TC_rll_ud_ind));
3667}
3668
Harald Weltee613f962018-04-18 22:38:16 +02003669/***********************************************************************
3670 * Encryption Related
3671 ***********************************************************************/
3672
3673/* send UNITDATA_REQ from BTS to MS and expect it to arrive */
3674function f_unitdata_mt(RslLinkId link_id, octetstring l3) runs on ConnHdlr {
3675 RSL.send(ts_RSL_UNITDATA_REQ(g_chan_nr, link_id, l3));
3676 if (link_id.c == SACCH) {
3677 f_l1_exp_lapdm(tr_LAPDm_B4_UI(link_id.sapi, cr_MT_CMD, l3));
3678 } else {
3679 f_l1_exp_lapdm(tr_LAPDm_UI(link_id.sapi, cr_MT_CMD, l3));
3680 }
3681}
3682
Vadim Yanitskiyad131c82018-10-04 06:18:59 +07003683/* Expect (or not expect) other kinds of messages */
3684private altstep as_rsl_any_ind(boolean exp_any) runs on ConnHdlr {
3685 [exp_any] RSL.receive { repeat; }
3686 [not exp_any] RSL.receive {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02003687 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Unexpected RSL message!");
Vadim Yanitskiyad131c82018-10-04 06:18:59 +07003688 }
3689}
3690
Harald Weltee613f962018-04-18 22:38:16 +02003691/* Send UI frame from MS and expect it to arrive as RLL UNITDATA IND on Abis */
Vadim Yanitskiy8d8f91c2018-10-04 06:19:45 +07003692private function f_unitdata_mo(
Vadim Yanitskiy98e03152018-10-03 18:06:06 +07003693 RslLinkId link_id,
3694 octetstring l3,
3695 boolean exp_sacch := true, /* Should tolerate SACCH messages? */
Vadim Yanitskiyb9920502018-10-03 18:29:51 +07003696 boolean exp_any := false /* Should tolerate any other RSL messages? */
Vadim Yanitskiy98e03152018-10-03 18:06:06 +07003697) runs on ConnHdlr {
Harald Weltee613f962018-04-18 22:38:16 +02003698 timer T := 3.0;
3699 f_tx_lapdm(ts_LAPDm_UI(link_id.sapi, cr_MO_CMD, l3), link_id);
3700 T.start;
3701 /* Expect RLL UNITDATA IND on RSL side */
3702 alt {
3703 [] RSL.receive(tr_RSL_UNITDATA_IND(g_chan_nr, link_id, l3)) {
3704 setverdict(pass);
3705 }
Vadim Yanitskiye0b91a72018-10-04 15:44:40 +07003706 [exp_sacch] as_meas_res(verify_meas := false);
Vadim Yanitskiyad131c82018-10-04 06:18:59 +07003707 [] as_rsl_any_ind(exp_any);
Harald Weltee613f962018-04-18 22:38:16 +02003708 [] T.timeout {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02003709 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout waiting for UNIT_DATA_IND");
Harald Weltee613f962018-04-18 22:38:16 +02003710 }
Harald Weltee613f962018-04-18 22:38:16 +02003711 }
3712}
3713
Vadim Yanitskiy4d78a702018-10-03 03:59:34 +07003714/* Send I-frame from MS and expect it to arrive as RLL DATA IND on Abis */
3715private function f_data_mo(
3716 RslLinkId link_id,
3717 boolean p, uint3_t nr, uint3_t ns,
3718 octetstring l3,
3719 boolean exp_sacch := true, /* Should tolerate SACCH messages? */
Vadim Yanitskiyb9920502018-10-03 18:29:51 +07003720 boolean exp_any := false /* Should tolerate any other RSL messages? */
Vadim Yanitskiy4d78a702018-10-03 03:59:34 +07003721) runs on ConnHdlr {
3722 timer T := 3.0;
3723 f_tx_lapdm(ts_LAPDm_I(link_id.sapi, cr_MO_CMD, p, nr, ns, l3), link_id);
3724 T.start;
3725 /* Expect RLL DATA IND on RSL side */
3726 alt {
3727 [] RSL.receive(tr_RSL_DATA_IND(g_chan_nr, link_id, l3)) {
3728 setverdict(pass);
3729 }
Vadim Yanitskiye0b91a72018-10-04 15:44:40 +07003730 [exp_sacch] as_meas_res(verify_meas := false);
Vadim Yanitskiy4d78a702018-10-03 03:59:34 +07003731 [] as_rsl_any_ind(exp_any);
3732 [] T.timeout {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02003733 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout waiting for DATA_IND");
Vadim Yanitskiy4d78a702018-10-03 03:59:34 +07003734 }
3735 }
3736}
3737
Harald Weltee613f962018-04-18 22:38:16 +02003738/* Test channel activation with A5/n right from the beginning (like in assignment + hand-over) */
3739function f_TC_chan_act_encr(charstring id) runs on ConnHdlr {
3740 f_l1_tune(L1CTL);
3741 f_est_dchan(true);
3742
3743 /* now we actually need to transmit some data both ways to check if the encryption works */
3744 var L1ctlDlMessage dl;
3745
Stefan Sperling603d98e2018-07-25 16:47:28 +02003746 var octetstring l3 := f_rnd_octstring(20);
Harald Weltee613f962018-04-18 22:38:16 +02003747 var RslLinkId link_id := valueof(ts_RslLinkID_DCCH(0));
3748
3749 /* send UNITDATA_REQ from BTS to MS and expect it to arrive */
3750 f_unitdata_mt(link_id, l3);
3751
3752 /* Send UI frame from MS and expect it to arrive as RLL UNITDATA IND on Abis */
3753 f_unitdata_mo(link_id, l3);
3754
3755 /* release the channel */
3756 f_rsl_chan_deact();
3757 f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
3758 f_rslem_unregister(0, g_chan_nr);
3759}
3760testcase TC_chan_act_a51() runs on test_CT {
3761 var ConnHdlrPars pars := valueof(t_Pars(t_RslChanNr_Bm(1), ts_RSL_ChanMode_SIGN));
3762 pars.encr := valueof(ts_RSL_IE_EncrInfo(RSL_ALG_ID_A5_1, f_rnd_octstring(8)));
3763 f_testmatrix_each_chan(pars, refers(f_TC_chan_act_encr));
3764}
3765testcase TC_chan_act_a52() runs on test_CT {
3766 var ConnHdlrPars pars := valueof(t_Pars(t_RslChanNr_Bm(1), ts_RSL_ChanMode_SIGN));
3767 pars.encr := valueof(ts_RSL_IE_EncrInfo(RSL_ALG_ID_A5_2, f_rnd_octstring(8)));
3768 f_testmatrix_each_chan(pars, refers(f_TC_chan_act_encr));
3769}
3770testcase TC_chan_act_a53() runs on test_CT {
3771 var ConnHdlrPars pars := valueof(t_Pars(t_RslChanNr_Bm(1), ts_RSL_ChanMode_SIGN));
3772 pars.encr := valueof(ts_RSL_IE_EncrInfo(RSL_ALG_ID_A5_3, f_rnd_octstring(8)));
3773 f_testmatrix_each_chan(pars, refers(f_TC_chan_act_encr));
3774}
3775
3776
3777/* Test unencrypted channel activation followed by explicit ENCR CMD later */
3778function f_TC_encr_cmd(charstring id) runs on ConnHdlr {
3779 /* L3 payload doesn't matter, as it is passed transparently */
3780 var BIT3 l3_alg_id := f_alg_id_to_l3(g_pars.encr.alg_id);
3781 var octetstring l3 := enc_PDU_ML3_NW_MS(valueof(ts_RRM_CiphModeCmd(l3_alg_id)));
3782 var RslLinkId link_id := valueof(ts_RslLinkID_DCCH(0));
3783
3784 f_l1_tune(L1CTL);
3785
3786 /* first establish a dedicated channel in the clear */
3787 f_est_dchan(false);
3788
3789 /* Establish ABM */
3790 f_est_rll_mo(link_id.sapi, link_id, '23420815'O);
3791
3792 /* then send the RSL ENCR CMD with an actual RR CIPH MOD CMD inside */
3793 RSL.send(ts_RSL_ENCR_CMD(g_chan_nr, link_id, g_pars.encr.alg_id, g_pars.encr.key, l3));
3794 /* expect the L3 to arrive still unencrypted on the MS side */
3795 f_l1_exp_lapdm(tr_LAPDm_I(link_id.sapi, cr_MT_CMD, ?, ?, ?, l3));
3796
3797 /* configure L1 to apply ciphering */
3798 var uint8_t alg_id := f_alg_id_to_l1ctl(g_pars.encr.alg_id);
3799 f_L1CTL_CRYPTO_REQ(L1CTL, g_pars.chan_nr, alg_id, g_pars.encr.key);
3800
Vadim Yanitskiy4d78a702018-10-03 03:59:34 +07003801 /* send first ciphered I-frame in response and expect it on RSL */
3802 f_data_mo(link_id, true, 1, 0, '0a0b0c0d'O, exp_sacch := true);
Harald Weltee613f962018-04-18 22:38:16 +02003803
3804 /* now the BTS code should have detected the first properly encrypted uplink I-frame,
3805 * and hence enable encryption also on the downlink */
3806
3807 /* expect bi-directional communication work in encrypted mode */
3808 f_unitdata_mo(link_id, f_rnd_octstring(15));
3809 f_unitdata_mt(link_id, f_rnd_octstring(15));
3810
3811 /* release the channel */
3812 f_rsl_chan_deact();
3813 f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
3814 f_rslem_unregister(0, g_chan_nr);
3815}
3816testcase TC_encr_cmd_a51() runs on test_CT {
3817 var ConnHdlrPars pars := valueof(t_Pars(t_RslChanNr_Bm(1), ts_RSL_ChanMode_SIGN));
3818 pars.encr := valueof(ts_RSL_IE_EncrInfo(RSL_ALG_ID_A5_1, f_rnd_octstring(8)));
3819 f_testmatrix_each_chan(pars, refers(f_TC_encr_cmd));
3820}
3821testcase TC_encr_cmd_a52() runs on test_CT {
3822 var ConnHdlrPars pars := valueof(t_Pars(t_RslChanNr_Bm(1), ts_RSL_ChanMode_SIGN));
3823 pars.encr := valueof(ts_RSL_IE_EncrInfo(RSL_ALG_ID_A5_2, f_rnd_octstring(8)));
3824 f_testmatrix_each_chan(pars, refers(f_TC_encr_cmd));
3825}
3826testcase TC_encr_cmd_a53() runs on test_CT {
3827 var ConnHdlrPars pars := valueof(t_Pars(t_RslChanNr_Bm(1), ts_RSL_ChanMode_SIGN));
3828 pars.encr := valueof(ts_RSL_IE_EncrInfo(RSL_ALG_ID_A5_3, f_rnd_octstring(8)));
3829 f_testmatrix_each_chan(pars, refers(f_TC_encr_cmd));
3830}
3831
3832private function f_assert_lapdm(octetstring enc, template LapdmFrame exp_match, charstring name := "") {
3833 var LapdmFrame lf;
3834 var octetstring reenc;
3835
3836 /* decode the LAPDm frame */
3837 if (ischosen(exp_match.ab)) {
3838 lf.ab := dec_LapdmFrameAB(enc);
3839 } else {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02003840 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "unsupported frame type");
Harald Weltee613f962018-04-18 22:38:16 +02003841 }
3842
3843 /* check if decoder result matches expectation */
3844 if (not match(lf, exp_match)) {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02003845 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str(name, ": decoded LAPDm doesn't match"));
Harald Weltee613f962018-04-18 22:38:16 +02003846 } else {
3847 log(name, ": matched");
3848 setverdict(pass);
3849 }
3850
3851 /* test if re-encoded frame equals original input */
3852 reenc := enc_LapdmFrame(lf);
3853 if (enc != reenc) {
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02003854 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str(name, ": re-encoded LAPDm frame doesn't match"));
Harald Weltee613f962018-04-18 22:38:16 +02003855 } else {
3856 setverdict(pass);
3857 }
3858}
3859
3860testcase TC_lapdm_selftest() runs on test_CT {
3861 f_assert_lapdm('030301'O, tr_LAPDm_UI(0, true, ''O), "ui_s0_empty");
3862 f_assert_lapdm('0F0301'O, tr_LAPDm_UI(3, true, ''O), "ui_s3_empty");
3863 f_assert_lapdm('013F01'O, tr_LAPDm_SABM(0, false, true, ''O), "sabm_s0_empty");
3864 f_assert_lapdm('013F1123420815'O, tr_LAPDm_SABM(0, false, true, '23420815'O), "sabm_s0_l3");
3865 f_assert_lapdm('03E101'O, tr_LAPDm_RR(0, true, false, 7), "rr_s0_7");
3866 f_assert_lapdm('03000d063505'O, tr_LAPDm_I(0, true, false, 0, 0, '063505'O), "I/0/0");
3867 f_assert_lapdm('03e00d063505'O, tr_LAPDm_I(0, true, false, 7, 0, '063505'O), "I/7/0");
3868}
3869
Stefan Sperling4880be42018-08-07 18:12:59 +02003870/***********************************************************************
3871 * DTX Related (see GSM 05.08, section 8.3)
3872 ***********************************************************************/
3873
3874/* XXX These functions must be kept in sync with g_AllChannels defined on test_CT. */
3875function f_g_chan_is_tchf() runs on ConnHdlr return boolean {
3876 return (g_chan_nr == valueof(ts_RslChanNr_Bm(1)) or
3877 g_chan_nr == valueof(ts_RslChanNr_Bm(2)) or
3878 g_chan_nr == valueof(ts_RslChanNr_Bm(3)) or
3879 g_chan_nr == valueof(ts_RslChanNr_Bm(4)));
3880}
3881function f_g_chan_is_tchh() runs on ConnHdlr return boolean {
3882 return (g_chan_nr == valueof(ts_RslChanNr_Lm(5,0)) or
3883 g_chan_nr == valueof(ts_RslChanNr_Lm(5,1)));
3884}
3885function f_g_chan_is_sdcch4() runs on ConnHdlr return boolean {
3886 return (g_chan_nr == valueof(ts_RslChanNr_SDCCH4(0,0)) or
3887 g_chan_nr == valueof(ts_RslChanNr_SDCCH4(0,1)) or
3888 g_chan_nr == valueof(ts_RslChanNr_SDCCH4(0,2)) or
3889 g_chan_nr == valueof(ts_RslChanNr_SDCCH4(0,3)));
3890}
3891function f_g_chan_is_sdcch8() runs on ConnHdlr return boolean {
3892 return (g_chan_nr == valueof(ts_RslChanNr_SDCCH8(6,0)) or
3893 g_chan_nr == valueof(ts_RslChanNr_SDCCH8(6,1)) or
3894 g_chan_nr == valueof(ts_RslChanNr_SDCCH8(6,2)) or
3895 g_chan_nr == valueof(ts_RslChanNr_SDCCH8(6,3)) or
3896 g_chan_nr == valueof(ts_RslChanNr_SDCCH8(6,4)) or
3897 g_chan_nr == valueof(ts_RslChanNr_SDCCH8(6,5)) or
3898 g_chan_nr == valueof(ts_RslChanNr_SDCCH8(6,6)) or
3899 g_chan_nr == valueof(ts_RslChanNr_SDCCH8(6,7)));
3900}
3901
3902function f_test_l2_fill_frames(boolean dtxd) runs on ConnHdlr {
3903 var L1ctlDlMessage dl;
3904 var octetstring l2_fill_frame := '0303012B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B'O;
3905 var octetstring l2_fill_frame_sacch := substr(l2_fill_frame, 0, lengthof(l2_fill_frame) - 2);
3906 var GsmFrameNumber first_fn;
3907 var boolean is_first_frame := true;
Stefan Sperling91d4c9d2018-08-09 20:03:08 +02003908 var integer nfill_frames_sacch := 0;
3909 var integer nfill_frames_nonsacch := 0;
3910 var integer expected_fill_frames := 10000; /* initial value causes test failure if not overridden */
Stefan Sperling4880be42018-08-07 18:12:59 +02003911 /* Frames numbers (mod 104) for which a fill frame is expected on TCHF if DTX is enabled. */
3912 var Integers required_tdma_frames_dtx_tchf := { 52, 53, 54, 55, 56, 57, 58, 59 };
Stefan Sperling91d4c9d2018-08-09 20:03:08 +02003913 const integer frame_dtx_tchf_mod := 104;
3914 /* Frame numbers (mod 104) for which a fill frame is expected at the L1SAP level,
3915 * which operates in terms of blocks rather than frames. */
3916 var Integers required_tdma_blocks_dtx_tchf := { 52, 56 };
3917 const integer block_dtx_tchf_mod := 26;
Stefan Sperling4880be42018-08-07 18:12:59 +02003918 timer T := 5.0;
3919
3920 f_l1_tune(L1CTL);
3921 RSL.clear;
3922 L1CTL.clear;
3923
3924 /* activate TCHF signalling channel */
3925 f_est_dchan(false);
3926
3927 T.start;
3928 alt {
3929 [] L1CTL.receive(tr_L1CTL_DATA_IND(g_chan_nr, ?)) -> value dl {
3930 var GsmFrameNumber fn := dl.dl_info.frame_nr;
3931 var octetstring l2 := dl.payload.data_ind.payload;
3932
3933 if (is_first_frame) {
3934 is_first_frame := false;
3935 first_fn := dl.dl_info.frame_nr;
3936 }
3937
3938 if (dl.dl_info.link_id.c == SACCH) {
3939 l2 := substr(l2, 2, lengthof(l2) - 2); /* remove L1 header */
3940 if (not match(l2_fill_frame_sacch, l2)) {
3941 repeat;
3942 }
3943 } else if (not match(l2_fill_frame, l2)) {
3944 repeat;
3945 }
3946
3947 if (dtxd) {
3948 if (not f_g_chan_is_tchf()) {
3949 T.stop;
3950 f_rsl_chan_deact();
3951 f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02003952 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 +02003953 }
Stefan Sperling91d4c9d2018-08-09 20:03:08 +02003954 if (fn > first_fn + frame_dtx_tchf_mod) {
Stefan Sperling4880be42018-08-07 18:12:59 +02003955 T.stop;
3956 f_rsl_chan_deact();
3957 f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
Stefan Sperling91d4c9d2018-08-09 20:03:08 +02003958
3959 /* With DTX enabled we can expect at least 3 fill frames for every 104 frames.
3960 * 2 SACCH, 1 TCH/F */
3961 expected_fill_frames := 3;
3962
3963 if (nfill_frames_sacch + nfill_frames_nonsacch < expected_fill_frames) {
3964 log("received only ", nfill_frames_sacch, "+", nfill_frames_nonsacch,
3965 " (SACCH+other) out of ", expected_fill_frames, " expected fill frames");
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02003966 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Not enough fill frames received");
Stefan Sperling4880be42018-08-07 18:12:59 +02003967 } else {
3968 setverdict(pass);
3969 }
Stefan Sperling91d4c9d2018-08-09 20:03:08 +02003970 } else {
3971 if (dl.dl_info.link_id.c == SACCH) {
3972 nfill_frames_sacch := nfill_frames_sacch + 1;
Stefan Sperling4880be42018-08-07 18:12:59 +02003973 repeat;
3974 }
Stefan Sperling91d4c9d2018-08-09 20:03:08 +02003975 /* On DTX TCH/F channels, fill frames occur only for specific frame numbers mod 104.
3976 * Furthermore, the L1SAP layer gives us frame numbers for the start of a block so
3977 * we should only see the subset of frames numbers which correspond to a block boundary.
3978 * TCH/F blocks are defined to start at 0,4,8,13,17,21 (modulo 26) */
3979 for (var integer i := 0; i < lengthof(required_tdma_blocks_dtx_tchf); i := i + 1) {
3980 if (fn mod frame_dtx_tchf_mod == required_tdma_blocks_dtx_tchf[i]) {
3981 nfill_frames_nonsacch := nfill_frames_nonsacch + 1;
3982 repeat;
3983 }
3984 }
3985 log("Received DTX TCH fill frame with bad frame number: ", fn,
3986 " (mod ", frame_dtx_tchf_mod, ": ", fn mod frame_dtx_tchf_mod, ")",
3987 " (mod ", block_dtx_tchf_mod, ": ", fn mod block_dtx_tchf_mod, ")");
3988 f_rsl_chan_deact();
3989 f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02003990 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Unexpected L2 fill frame received on Um");
Stefan Sperling4880be42018-08-07 18:12:59 +02003991 }
Stefan Sperling4880be42018-08-07 18:12:59 +02003992 } else {
Stefan Sperling91d4c9d2018-08-09 20:03:08 +02003993 if (dl.dl_info.link_id.c == SACCH) {
3994 nfill_frames_sacch := nfill_frames_sacch + 1;
3995 } else {
3996 nfill_frames_nonsacch := nfill_frames_nonsacch + 1;
3997 }
3998 if (fn > first_fn + frame_dtx_tchf_mod) {
Stefan Sperling4880be42018-08-07 18:12:59 +02003999 T.stop;
4000 if (f_g_chan_is_tchf()) {
4001 /* Without DTX we can expect 25 fill frames for every 104 frames.
4002 * (24 FACCH + 1 SACCH filling) */
4003 expected_fill_frames := 25;
4004 } else if (f_g_chan_is_tchh()) {
4005 /* We can expect 2 fill frames for every 104 frames. */
4006 expected_fill_frames := 2;
4007 } else if (f_g_chan_is_sdcch4() or f_g_chan_is_sdcch8()) {
4008 /* We can expect 5 fill frames for every 104 frames. */
4009 expected_fill_frames := 5;
4010 } else {
4011 f_rsl_chan_deact();
4012 f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02004013 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Unknown channel type");
Stefan Sperling4880be42018-08-07 18:12:59 +02004014 }
4015
4016 f_rsl_chan_deact();
4017 f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
Stefan Sperling91d4c9d2018-08-09 20:03:08 +02004018
4019 if (nfill_frames_sacch + nfill_frames_nonsacch >= expected_fill_frames) {
Stefan Sperling4880be42018-08-07 18:12:59 +02004020 setverdict(pass);
4021 } else {
Stefan Sperling91d4c9d2018-08-09 20:03:08 +02004022 log("received only ", nfill_frames_sacch, "+", nfill_frames_nonsacch,
4023 " (SACCH+other) out of ", expected_fill_frames, " expected fill frames");
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02004024 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Not enough fill frames received");
Stefan Sperling4880be42018-08-07 18:12:59 +02004025 }
4026 } else {
4027 repeat;
4028 }
4029 }
4030 }
4031 [] L1CTL.receive { repeat; }
4032 [] T.timeout {
4033 f_rsl_chan_deact();
4034 f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
Daniel Willmann0fcc4d32018-10-23 20:32:19 +02004035 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout waiting for L2 fill frames on Um");
Stefan Sperling4880be42018-08-07 18:12:59 +02004036 }
4037 }
4038}
4039
4040function f_TC_tch_sign_l2_fill_frame(charstring id) runs on ConnHdlr {
4041 f_test_l2_fill_frames(false);
4042}
4043
4044function f_TC_tch_sign_l2_fill_frame_dtxd(charstring id) runs on ConnHdlr {
4045 f_test_l2_fill_frames(true);
4046}
4047
4048function f_tch_sign_l2_fill_frame(boolean dtxd) runs on test_CT {
4049 var ConnHdlr vc_conn;
4050 var ConnHdlrPars pars;
4051 pars.t_guard := 60.0;
4052 f_init(testcasename());
4053 for (var integer i := 0; i < sizeof(g_AllChannels); i := i + 1) {
4054 pars := valueof(t_Pars(g_AllChannels[i], ts_RSL_ChanMode_SIGN(dtxd)));
4055 if (dtxd) {
4056 if (i >= 4) { /* DTX is only allowed on TCH/F */
4057 break;
4058 }
4059 vc_conn := f_start_handler(refers(f_TC_tch_sign_l2_fill_frame_dtxd), pars);
4060 } else {
4061 vc_conn := f_start_handler(refers(f_TC_tch_sign_l2_fill_frame), pars);
4062 }
4063 vc_conn.done;
4064 }
4065}
4066
4067/* Verify that L2 fill frames are sent on TCH in signaling mode if
4068 * there is nothing to transmit while DTX is disabled on downlink. */
4069testcase TC_tch_sign_l2_fill_frame() runs on test_CT {
4070 f_tch_sign_l2_fill_frame(false);
4071}
4072
4073/* Verify that particular L2 fill frames are sent on TCH in signaling mode if
4074 * there is nothing to transmit while DTX is enabled on downlink. */
4075testcase TC_tch_sign_l2_fill_frame_dtxd() runs on test_CT {
4076 f_tch_sign_l2_fill_frame(true);
4077}
Harald Welte0472ab42018-03-12 15:02:26 +01004078
Stefan Sperling0ec1c262018-10-15 15:12:52 +02004079testcase TC_chopped_ipa_ping() runs on test_CT {
4080 IPA_Testing.f_run_TC_chopped_ipa_ping(mp_rsl_ip, mp_rsl_port, LISTEN_FOR_CLIENT);
4081}
4082
Stefan Sperlingaa1e60f2018-10-15 16:34:07 +02004083testcase TC_chopped_ipa_payload() runs on test_CT {
4084 IPA_Testing.f_run_TC_chopped_ipa_payload(mp_rsl_ip, mp_rsl_port, LISTEN_FOR_CLIENT);
4085}
4086
Harald Welte0472ab42018-03-12 15:02:26 +01004087/* test generation of RLL ERR IND based on Um errors (TS 48.058 3.9) */
4088/* protocol error as per 44.006 */
4089/* link layer failure (repetition of I-frame N200 times without ACK */
4090/* repetition of SABM or DISC N200 times without ACK */
4091/* receptiom of SABM in multi-frame established state */
4092
4093
4094
4095
Harald Welte883340c2018-02-28 18:59:29 +01004096
Harald Welte68e495b2018-02-25 00:05:57 +01004097/* TODO Areas:
4098
4099* channel activation
4100** with BS_Power / MS_Power, bypassing power control loop
4101** on primary vs. secondary TRX
Harald Welte68e495b2018-02-25 00:05:57 +01004102** with timing advance from initial activation on
4103* mode modify
4104** encryption
4105** multirate
4106* check DEACTIVATE SACCH
Harald Welte68e495b2018-02-25 00:05:57 +01004107** unsupported algorithm
4108* handover detection
4109* MS Power Control
4110* BS Power Control
4111* Physical Context
Harald Welte43c54642018-09-15 17:47:04 +03004112* CCCH Load Indication for RACH
Harald Welte68e495b2018-02-25 00:05:57 +01004113* SMS Broadcast Req / Cmd / CBCH LOad Ind
4114* RF resource ind
Harald Welte68e495b2018-02-25 00:05:57 +01004115* error handling
Harald Welte43c54642018-09-15 17:47:04 +03004116** discriminator error
Harald Welte68e495b2018-02-25 00:05:57 +01004117** type error
4118** sequence error
4119** IE duplicated?
Harald Welte883340c2018-02-28 18:59:29 +01004120* PCU interface
4121** TIME_IND from BTS->PCU
4122** DATA_IND from BTS->PCU
4123** verification of PCU-originated DATA_REQ arrival on Um/MS side
Harald Welte68e495b2018-02-25 00:05:57 +01004124
4125*/
Harald Welte70767382018-02-21 12:16:40 +01004126
4127control {
4128 execute( TC_chan_act_stress() );
4129 execute( TC_chan_act_react() );
4130 execute( TC_chan_deact_not_active() );
4131 execute( TC_chan_act_wrong_nr() );
Harald Welte629cc6b2018-03-11 17:19:05 +01004132 execute( TC_deact_sacch() );
Harald Welteea17b912018-03-11 22:29:31 +01004133 execute( TC_sacch_filling() );
4134 execute( TC_sacch_info_mod() );
Harald Welte075d84c2018-03-12 13:07:24 +01004135 execute( TC_sacch_multi() );
Harald Welte55700662018-03-12 13:15:43 +01004136 execute( TC_sacch_multi_chg() );
Harald Welte8c24c2b2018-02-26 08:31:31 +01004137 execute( TC_rach_content() );
4138 execute( TC_rach_count() );
Harald Welte54a2a2d2018-02-26 09:14:05 +01004139 execute( TC_rach_max_ta() );
Harald Welte70767382018-02-21 12:16:40 +01004140 execute( TC_meas_res_sign_tchf() );
4141 execute( TC_meas_res_sign_tchh() );
4142 execute( TC_meas_res_sign_sdcch4() );
4143 execute( TC_meas_res_sign_sdcch8() );
Harald Welte685d5982018-02-27 20:42:05 +01004144 execute( TC_meas_res_sign_tchh_toa256() );
Harald Welte70767382018-02-21 12:16:40 +01004145 execute( TC_conn_fail_crit() );
Harald Welte68e495b2018-02-25 00:05:57 +01004146 execute( TC_paging_imsi_80percent() );
4147 execute( TC_paging_tmsi_80percent() );
4148 execute( TC_paging_imsi_200percent() );
4149 execute( TC_paging_tmsi_200percent() );
Harald Welte01d982c2018-02-25 01:31:40 +01004150 execute( TC_rsl_protocol_error() );
4151 execute( TC_rsl_mand_ie_error() );
4152 execute( TC_rsl_ie_content_error() );
Harald Welte48494ca2018-02-25 16:59:50 +01004153 execute( TC_si_sched_default() );
Harald Welte0cae4552018-03-09 22:20:26 +01004154 execute( TC_si_sched_1() );
Harald Welte48494ca2018-02-25 16:59:50 +01004155 execute( TC_si_sched_2bis() );
4156 execute( TC_si_sched_2ter() );
4157 execute( TC_si_sched_2ter_2bis() );
4158 execute( TC_si_sched_2quater() );
4159 execute( TC_si_sched_13() );
4160 execute( TC_si_sched_13_2bis_2ter_2quater() );
Harald Weltea871a382018-02-25 02:03:14 +01004161 execute( TC_ipa_dlcx_not_active() );
Harald Weltea3f1df92018-02-25 12:49:55 +01004162 execute( TC_ipa_crcx_twice_not_active() );
4163 execute( TC_ipa_crcx_mdcx_dlcx_not_active() );
Harald Welte3ae11da2018-02-25 13:36:06 +01004164 execute( TC_ipa_crcx_mdcx_mdcx_dlcx_not_active() );
Harald Welte9912eb52018-02-25 13:30:15 +01004165 execute( TC_ipa_crcx_sdcch_not_active() );
Harald Welte883340c2018-02-28 18:59:29 +01004166
4167 execute( TC_pcu_act_req() );
4168 execute( TC_pcu_act_req_wrong_ts() );
4169 execute( TC_pcu_act_req_wrong_bts() );
4170 execute( TC_pcu_act_req_wrong_trx() );
4171 execute( TC_pcu_deact_req() );
4172 execute( TC_pcu_deact_req_wrong_ts() );
4173 execute( TC_pcu_ver_si13() );
4174 execute( TC_pcu_data_req_wrong_bts() );
4175 execute( TC_pcu_data_req_wrong_trx() );
4176 execute( TC_pcu_data_req_wrong_ts() );
4177 execute( TC_pcu_data_req_ts_inactive() );
4178 execute( TC_pcu_data_req_pdtch() );
4179 execute( TC_pcu_data_req_ptcch() );
4180 execute( TC_pcu_data_req_agch() );
4181 execute( TC_pcu_data_req_imm_ass_pch() );
4182 execute( TC_pcu_rach_content() );
4183 execute( TC_pcu_paging_from_rsl() );
Harald Welte3d04ae62018-04-04 20:29:05 +02004184
4185 execute( TC_dyn_osmo_pdch_act_deact() );
4186 execute( TC_dyn_osmo_pdch_unsol_deact() );
4187 execute( TC_dyn_osmo_pdch_double_act() );
4188 execute( TC_dyn_osmo_pdch_tchf_act() );
4189 execute( TC_dyn_osmo_pdch_tchh_act() );
Harald Welte9bbbfb52018-04-05 09:33:19 +02004190 execute( TC_dyn_ipa_pdch_act_deact() );
4191 execute( TC_dyn_ipa_pdch_tchf_act() );
4192 execute( TC_dyn_ipa_pdch_tchf_act_pdch_act_nack() );
4193 execute( TC_dyn_ipa_pdch_act_tchf_act_nack() );
Harald Welte0472ab42018-03-12 15:02:26 +01004194
4195 execute( TC_rll_est_ind() );
4196 execute( TC_rll_est_req_DCCH_3() );
4197 execute( TC_rll_est_req_ACCH_3() );
4198 execute( TC_rll_rel_ind_DCCH_0() );
4199 execute( TC_rll_rel_ind_DCCH_3() );
4200 execute( TC_rll_rel_ind_ACCH_0() );
4201 execute( TC_rll_rel_ind_ACCH_3() );
4202 execute( TC_rll_rel_req() );
4203 execute( TC_rll_unit_data_req_DCCH() );
4204 execute( TC_rll_unit_data_req_ACCH() );
4205 execute( TC_rll_unit_data_ind_DCCH() );
4206 execute( TC_rll_unit_data_ind_ACCH() );
Harald Weltee613f962018-04-18 22:38:16 +02004207
4208 execute( TC_chan_act_a51() );
4209 execute( TC_chan_act_a52() );
4210 execute( TC_chan_act_a53() );
4211 execute( TC_encr_cmd_a51() );
4212 execute( TC_encr_cmd_a52() );
4213 execute( TC_encr_cmd_a53() );
4214
4215 execute( TC_lapdm_selftest() );
Stefan Sperling4880be42018-08-07 18:12:59 +02004216
4217 execute( TC_tch_sign_l2_fill_frame() );
4218 execute( TC_tch_sign_l2_fill_frame_dtxd() );
Stefan Sperling0ec1c262018-10-15 15:12:52 +02004219
4220 execute( TC_chopped_ipa_ping() );
Stefan Sperlingaa1e60f2018-10-15 16:34:07 +02004221 execute( TC_chopped_ipa_payload() );
Harald Welte70767382018-02-21 12:16:40 +01004222}
4223
4224
4225}