blob: 25ee3a2395933efee45e926e2455148c7a97e5cb [file] [log] [blame]
Harald Welte70767382018-02-21 12:16:40 +01001module BTS_Tests {
2
3import from General_Types all;
4import from GSM_Types all;
5import from GSM_RR_Types all;
6import from Osmocom_Types all;
7import from GSM_Types all;
8import from GSM_RR_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;
19import from RSL_Emulation all;
20
21import from IPL4asp_Types all;
22import from TRXC_Types all;
23import from TRXC_CodecPort all;
24import from TRXC_CodecPort_CtrlFunct all;
25
Harald Welte883340c2018-02-28 18:59:29 +010026import from PCUIF_Types all;
27import from PCUIF_CodecPort all;
28
Harald Welte7484fc42018-02-24 14:09:45 +010029import from MobileL3_CommonIE_Types all;
Harald Welte68e495b2018-02-25 00:05:57 +010030import from MobileL3_RRM_Types all;
31import from MobileL3_Types all;
32import from L3_Templates all;
Harald Welte7484fc42018-02-24 14:09:45 +010033
Harald Welte8da48242018-02-27 20:41:32 +010034import from Osmocom_VTY_Functions all;
35import from TELNETasp_PortType all;
36
Harald Welte70767382018-02-21 12:16:40 +010037/* The tests assume a BTS with the following timeslot configuration:
38 * TS0 : Combined CCCH + SDCCH/4
Harald Welte3d04ae62018-04-04 20:29:05 +020039 * TS1 : TCH/F
40 * TS2 : TCH/F
41 * TS3 : TCH/F_PDCH (IPA Style)
42 * TS4 : TCH/F_TCH/H_PDCH (Osmocom Style)
Harald Welte70767382018-02-21 12:16:40 +010043 * TS5 : TCH/H
44 * TS6 : SDCCH/8
45 * TS7 : PDCH
46 */
47
48modulepar {
49 charstring mp_rsl_ip := "127.0.0.2";
50 integer mp_rsl_port := 3003;
51 integer mp_trx0_arfcn := 871;
Harald Weltea4d8f352018-03-01 15:47:20 +010052 charstring mp_bb_trxc_ip := "127.0.0.1";
Harald Welteef3e1c92018-02-28 23:40:14 +010053 integer mp_bb_trxc_port := 6701;
Harald Welte883340c2018-02-28 18:59:29 +010054 charstring mp_pcu_socket := PCU_SOCK_DEFAULT;
Harald Welted5684392018-03-10 18:22:04 +010055 integer mp_tolerance_rxqual := 1;
56 integer mp_tolerance_rxlev := 3;
Neels Hofmeyr6a84b232018-04-03 19:12:36 +020057 charstring mp_ctrl_ip := "127.0.0.1";
58 integer mp_ctrl_port := 4238;
Pau Espin Pedrol752ffd52018-06-07 13:55:45 +020059 integer mp_rxlev_exp := 57;
Harald Welte70767382018-02-21 12:16:40 +010060}
61
Harald Welte629cc6b2018-03-11 17:19:05 +010062type record of RslChannelNr ChannelNrs;
63
Harald Welte70767382018-02-21 12:16:40 +010064type component test_CT extends CTRL_Adapter_CT {
Harald Welte68e495b2018-02-25 00:05:57 +010065 /* IPA Emulation component underneath RSL */
Harald Welte70767382018-02-21 12:16:40 +010066 var IPA_Emulation_CT vc_IPA;
Harald Welte68e495b2018-02-25 00:05:57 +010067 /* RSL Emulation component (for ConnHdlr tests) */
Harald Welte70767382018-02-21 12:16:40 +010068 var RSL_Emulation_CT vc_RSL;
Harald Welte68e495b2018-02-25 00:05:57 +010069 /* Direct RSL_CCHAN_PT */
Harald Welte70767382018-02-21 12:16:40 +010070 port RSL_CCHAN_PT RSL_CCHAN;
Harald Welte68e495b2018-02-25 00:05:57 +010071
72 /* L1CTL port (for classic tests) */
73 port L1CTL_PT L1CTL;
Harald Welte48494ca2018-02-25 16:59:50 +010074
Harald Welte54a2a2d2018-02-26 09:14:05 +010075 /* TRXC port (for classic tests) */
76 port TRXC_CODEC_PT BB_TRXC;
77 var integer g_bb_trxc_conn_id;
78
Harald Welte8da48242018-02-27 20:41:32 +010079 port TELNETasp_PT BTSVTY;
80
Harald Welte883340c2018-02-28 18:59:29 +010081 /* PCU Interface of BTS */
82 port PCUIF_CODEC_PT PCU;
83 var integer g_pcu_conn_id;
84 /* Last PCU INFO IND we received */
85 var PCUIF_Message g_pcu_last_info;
86
Harald Welte48494ca2018-02-25 16:59:50 +010087 /* SI configuration */
88 var SystemInformationConfig si_cfg := {
89 bcch_extended := false,
90 si1_present := false,
91 si2bis_present := false,
92 si2ter_present := false,
93 si2quater_present := false,
94 si7_present := false,
95 si8_present := false,
96 si9_present := false,
97 si13_present := false,
98 si13alt_present := false,
99 si15_present := false,
100 si16_present := false,
101 si17_present := false,
102 si2n_present := false,
103 si21_present := false,
104 si22_present := false
105 };
Harald Welte629cc6b2018-03-11 17:19:05 +0100106
107 /* all logical channels available on the BTS */
108 var ChannelNrs g_AllChannels;
Harald Welte0472ab42018-03-12 15:02:26 +0100109 var ChannelNrs g_AllChanTypes;
Harald Welte70767382018-02-21 12:16:40 +0100110}
111
112/* an individual call / channel */
113type component ConnHdlr extends RSL_DchanHdlr {
114 port L1CTL_PT L1CTL;
115
116 port TRXC_CODEC_PT BB_TRXC;
117 var integer g_bb_trxc_conn_id;
118
119 timer g_Tguard;
120 timer g_Tmeas_exp := 2.0; /* >= 103 SACCH multiframe ~ 500ms */
121
122 var ConnHdlrPars g_pars;
123 var uint8_t g_next_meas_res_nr := 0;
Harald Weltefa45e9e2018-03-10 18:59:03 +0100124 var boolean g_first_meas_res := true;
Harald Weltef26de0b2018-04-04 20:28:05 +0200125
126 /* PCU Interface of BTS */
127 port PCUIF_CODEC_PT PCU;
Harald Welte70767382018-02-21 12:16:40 +0100128}
129
130function f_init_rsl(charstring id) runs on test_CT {
131 vc_IPA := IPA_Emulation_CT.create(id & "-RSL-IPA");
132 vc_RSL := RSL_Emulation_CT.create(id & "-RSL");
133
134 map(vc_IPA:IPA_PORT, system:IPA_CODEC_PT);
135 connect(vc_IPA:IPA_RSL_PORT, vc_RSL:IPA_PT);
136 connect(self:RSL_CCHAN, vc_RSL:CCHAN_PT);
137
138 vc_IPA.start(IPA_Emulation.main_server(mp_rsl_ip, mp_rsl_port));
139 vc_RSL.start(RSL_Emulation.main(false));
140}
141
142type record ConnHdlrPars {
143 RslChannelNr chan_nr,
144 RSL_IE_ChannelMode chan_mode,
145 float t_guard,
Harald Welte0472ab42018-03-12 15:02:26 +0100146 ConnL1Pars l1_pars,
Harald Weltee613f962018-04-18 22:38:16 +0200147 TestSpecUnion spec optional,
148 RSL_IE_EncryptionInfo encr optional
Harald Welte0472ab42018-03-12 15:02:26 +0100149}
150
151/* Test-specific parameters */
152type union TestSpecUnion {
153 RllTestCase rll
Harald Welte70767382018-02-21 12:16:40 +0100154}
155
Harald Welte82ccef72018-02-25 16:17:33 +0100156template (value) RachControlParameters ts_RachCtrl_default := {
Harald Welte0fd1fb02018-03-10 17:19:50 +0100157 max_retrans := RACH_MAX_RETRANS_7,
158 tx_integer := '1001'B, /* 12 slots */
Harald Welte82ccef72018-02-25 16:17:33 +0100159 cell_barr_access := false,
160 re_not_allowed := true,
Harald Welteb9585f82018-03-10 17:18:47 +0100161 acc := '0000010000000000'B
Harald Welte82ccef72018-02-25 16:17:33 +0100162};
163
Harald Weltef10153f2018-02-25 16:34:05 +0100164template (value) CellSelectionParameters ts_CellSelPar_default := {
Harald Welte0fd1fb02018-03-10 17:19:50 +0100165 cell_resel_hyst_2dB := 2,
166 ms_txpwr_max_cch := 7,
Harald Weltef10153f2018-02-25 16:34:05 +0100167 acs := '0'B,
168 neci := true,
169 rxlev_access_min := 0
170}
171
172template (value) LocationAreaIdentification ts_LAI_default := {
173 mcc_mnc := '262F42'H,
174 lac := 42
175}
176
Harald Welte7484fc42018-02-24 14:09:45 +0100177/* Default SYSTEM INFORMATION 3 */
Harald Weltef8df4cb2018-03-10 15:15:08 +0100178template (value) SystemInformation ts_SI3_default := {
179 header := ts_RrHeader(SYSTEM_INFORMATION_TYPE_3, 18),
Harald Welte7484fc42018-02-24 14:09:45 +0100180 payload := {
181 si3 := {
182 cell_id := 23,
Harald Weltef10153f2018-02-25 16:34:05 +0100183 lai := ts_LAI_default,
Harald Welte7484fc42018-02-24 14:09:45 +0100184 ctrl_chan_desc := {
185 msc_r99 := true,
186 att := true,
187 bs_ag_blks_res := 1,
188 ccch_conf := CCHAN_DESC_1CCCH_COMBINED,
Harald Welte82ccef72018-02-25 16:17:33 +0100189 si22ind := false,
Harald Welte7484fc42018-02-24 14:09:45 +0100190 cbq3 := CBQ3_IU_MODE_NOT_SUPPORTED,
191 spare := '00'B,
192 bs_pa_mfrms := 0, /* 2 multiframes */
193 t3212 := 1 /* 6 minutes */
194 },
Harald Welte82ccef72018-02-25 16:17:33 +0100195 cell_options := {
Harald Welte7484fc42018-02-24 14:09:45 +0100196 dn_ind := false,
197 pwrc := false,
198 dtx := MS_MAY_USE_UL_DTX,
Harald Welte0fd1fb02018-03-10 17:19:50 +0100199 radio_link_tout_div4 := (32/4)-1
Harald Welte7484fc42018-02-24 14:09:45 +0100200 },
Harald Weltef10153f2018-02-25 16:34:05 +0100201 cell_sel_par := ts_CellSelPar_default,
Harald Welte82ccef72018-02-25 16:17:33 +0100202 rach_control := ts_RachCtrl_default,
Harald Welte3778acc2018-03-09 19:32:31 +0100203 rest_octets := '2B2B2B2B'O
Harald Welte7484fc42018-02-24 14:09:45 +0100204 }
205 }
206}
Harald Welte70767382018-02-21 12:16:40 +0100207
Harald Weltef8df4cb2018-03-10 15:15:08 +0100208template (value) SystemInformation ts_SI2_default := {
209 header := ts_RrHeader(SYSTEM_INFORMATION_TYPE_2, 22),
Harald Weltef10153f2018-02-25 16:34:05 +0100210 payload := {
211 si2 := {
212 bcch_freq_list := '00000000000000000000000000000000'O,
213 ncc_permitted := '11111111'B,
214 rach_control := ts_RachCtrl_default
215 }
216 }
217}
218
Harald Weltef8df4cb2018-03-10 15:15:08 +0100219template (value) SystemInformation ts_SI4_default := {
220 header := ts_RrHeader(SYSTEM_INFORMATION_TYPE_4, 12), /* no CBCH / restoct */
Harald Weltef10153f2018-02-25 16:34:05 +0100221 payload := {
222 si4 := {
223 lai := ts_LAI_default,
224 cell_sel_par := ts_CellSelPar_default,
225 rach_control := ts_RachCtrl_default,
226 cbch_chan_desc := omit,
227 cbch_mobile_alloc := omit,
228 rest_octets := ''O
229 }
230 }
231}
232
233function f_rsl_bcch_fill_raw(RSL_IE_SysinfoType rsl_si_type, octetstring si_enc)
234runs on test_CT {
235 log("Setting ", rsl_si_type, ": ", si_enc);
236 RSL_CCHAN.send(ts_RSL_UD(ts_RSL_BCCH_INFO(rsl_si_type, si_enc)));
237}
238
239function f_rsl_bcch_fill(RSL_IE_SysinfoType rsl_si_type, template (value) SystemInformation si_dec)
240runs on test_CT {
241 var octetstring si_enc := enc_SystemInformation(valueof(si_dec));
242 log("Setting ", rsl_si_type, ": ", si_dec);
243 f_rsl_bcch_fill_raw(rsl_si_type, si_enc);
244}
245
Harald Welte8da48242018-02-27 20:41:32 +0100246private function f_init_vty(charstring id) runs on test_CT {
247 map(self:BTSVTY, system:BTSVTY);
248 f_vty_set_prompts(BTSVTY);
249 f_vty_transceive(BTSVTY, "enable");
250}
251
Harald Welte883340c2018-02-28 18:59:29 +0100252/* PCU socket may at any time receive a new INFO.ind */
Harald Weltef26de0b2018-04-04 20:28:05 +0200253private altstep as_pcu_info_ind(PCUIF_CODEC_PT pt, integer pcu_conn_id,
254 out PCUIF_Message pcu_last_info) {
Harald Welte883340c2018-02-28 18:59:29 +0100255 var PCUIF_send_data sd;
Harald Weltef26de0b2018-04-04 20:28:05 +0200256 [] pt.receive(t_SD_PCUIF(pcu_conn_id, tr_PCUIF_INFO_IND(0, ?))) -> value sd {
257 pcu_last_info := sd.data;
Harald Welted378a252018-03-13 17:02:14 +0100258 }
Harald Weltef26de0b2018-04-04 20:28:05 +0200259 [] pt.receive(t_SD_PCUIF(pcu_conn_id, tr_PCUIF_INFO_IND(?, ?, ?))) -> value sd {
Harald Welted378a252018-03-13 17:02:14 +0100260 setverdict(fail, "Invalid PCU Version/BTS Number received");
261 self.stop;
Harald Welte883340c2018-02-28 18:59:29 +0100262 }
263}
264
Harald Weltef26de0b2018-04-04 20:28:05 +0200265private function f_init_pcu(PCUIF_CODEC_PT pt, charstring id,
266 out integer pcu_conn_id, out PCUIF_Message pcu_last_info) {
Harald Welte883340c2018-02-28 18:59:29 +0100267 timer T := 2.0;
268 var PCUIF_send_data sd;
Harald Welte84271622018-03-10 17:21:03 +0100269 if (mp_pcu_socket == "") {
Harald Weltef26de0b2018-04-04 20:28:05 +0200270 pcu_conn_id := -1;
Harald Welte84271622018-03-10 17:21:03 +0100271 return;
272 }
Harald Weltef26de0b2018-04-04 20:28:05 +0200273 pcu_conn_id := f_pcuif_connect(pt, mp_pcu_socket);
Harald Welte883340c2018-02-28 18:59:29 +0100274
275 T.start;
276 alt {
Harald Weltef26de0b2018-04-04 20:28:05 +0200277 [] as_pcu_info_ind(pt, pcu_conn_id, pcu_last_info);
Harald Welte883340c2018-02-28 18:59:29 +0100278 [] T.timeout {
279 setverdict(fail, "Timeout waiting for PCU INFO_IND");
280 self.stop;
281 }
282 }
283}
284
Harald Welte70767382018-02-21 12:16:40 +0100285/* global init function */
Harald Welte68e495b2018-02-25 00:05:57 +0100286function f_init(charstring id := "BTS-Test") runs on test_CT {
Harald Welte83f6dbf2018-06-03 18:26:50 +0200287 timer T := 10.0;
Harald Welte629cc6b2018-03-11 17:19:05 +0100288 g_AllChannels := {
289 /* TS 1..4: TCH/F */
290 valueof(ts_RslChanNr_Bm(1)), valueof(ts_RslChanNr_Bm(2)),
291 valueof(ts_RslChanNr_Bm(3)), valueof(ts_RslChanNr_Bm(4)),
292 /* TS 5: TCH/H */
293 valueof(ts_RslChanNr_Lm(5,0)), valueof(ts_RslChanNr_Lm(5,1)),
294 /* TS 0: SDCCH/4 */
295 valueof(ts_RslChanNr_SDCCH4(0,0)), valueof(ts_RslChanNr_SDCCH4(0,1)),
296 valueof(ts_RslChanNr_SDCCH4(0,2)), valueof(ts_RslChanNr_SDCCH4(0,3)),
297 /* TS 6: SDCCH/8 */
298 valueof(ts_RslChanNr_SDCCH8(6,0)), valueof(ts_RslChanNr_SDCCH8(6,1)),
299 valueof(ts_RslChanNr_SDCCH8(6,2)), valueof(ts_RslChanNr_SDCCH8(6,3)),
300 valueof(ts_RslChanNr_SDCCH8(6,4)), valueof(ts_RslChanNr_SDCCH8(6,5)),
301 valueof(ts_RslChanNr_SDCCH8(6,6)), valueof(ts_RslChanNr_SDCCH8(6,7))
302 };
Harald Welte0472ab42018-03-12 15:02:26 +0100303 g_AllChanTypes := {
304 /* TS 1..4: TCH/F */
305 //valueof(ts_RslChanNr_Bm(1)),
306 /* TS 5: TCH/H */
307 //valueof(ts_RslChanNr_Lm(5,1)),
308 /* TS 0: SDCCH/4 */
309 valueof(ts_RslChanNr_SDCCH4(0,2)),
310 /* TS 6: SDCCH/8 */
311 valueof(ts_RslChanNr_SDCCH8(6,4))
312 };
Harald Welte629cc6b2018-03-11 17:19:05 +0100313
Harald Welte70767382018-02-21 12:16:40 +0100314 f_init_rsl(id);
Harald Welte83f6dbf2018-06-03 18:26:50 +0200315 T.start;
316 alt {
317 [] RSL_CCHAN.receive(ASP_IPA_Event:{up_down := ASP_IPA_EVENT_UP});
318 [] T.timeout {
319 setverdict(fail, "Timeout waiting for ASP_IPA_EVENT_UP");
320 self.stop;
321 }
322 }
Harald Welte2d142592018-02-25 13:19:44 +0100323 f_sleep(0.5); /* workaround for OS#3000 */
Harald Welte8da48242018-02-27 20:41:32 +0100324 f_init_vty(id);
Neels Hofmeyr6a84b232018-04-03 19:12:36 +0200325 f_ipa_ctrl_start(mp_ctrl_ip, mp_ctrl_port);
Harald Welte7484fc42018-02-24 14:09:45 +0100326
327 /* Send SI3 to the BTS, it is needed for various computations */
Harald Weltef10153f2018-02-25 16:34:05 +0100328 f_rsl_bcch_fill(RSL_SYSTEM_INFO_3, ts_SI3_default);
329 /* SI2 + SI4 are required for SI testing as they are mandatory defaults */
330 f_rsl_bcch_fill(RSL_SYSTEM_INFO_2, ts_SI2_default);
331 f_rsl_bcch_fill(RSL_SYSTEM_INFO_4, ts_SI4_default);
Harald Welte57fe8232018-02-26 17:52:50 +0100332
Harald Weltef26de0b2018-04-04 20:28:05 +0200333 map(self:PCU, system:PCU);
334 f_init_pcu(PCU, id, g_pcu_conn_id, g_pcu_last_info);
Harald Welte883340c2018-02-28 18:59:29 +0100335
Harald Welte84271622018-03-10 17:21:03 +0100336 if (mp_bb_trxc_port != -1) {
337 var TrxcMessage ret;
338 /* start with a default moderate timing offset equalling TA=2 */
339 f_main_trxc_connect();
340 ret := f_TRXC_transceive(BB_TRXC, g_bb_trxc_conn_id, valueof(ts_TRXC_FAKE_TIMING(2*256)));
341 }
Harald Welte70767382018-02-21 12:16:40 +0100342}
343
Harald Welte294b0a22018-03-10 23:26:48 +0100344function f_shutdown() runs on test_CT {
345 /* shut down all "externally interfaced" components first to avoid unclean shutdown */
346 vc_IPA.stop;
347 vc_RSL.stop;
Neels Hofmeyr6a84b232018-04-03 19:12:36 +0200348 f_ipa_ctrl_stop();
Harald Welte294b0a22018-03-10 23:26:48 +0100349}
350
Harald Welte68e495b2018-02-25 00:05:57 +0100351/* Attach L1CTL to master test_CT (classic tests, non-handler mode) */
352function f_init_l1ctl() runs on test_CT {
353 map(self:L1CTL, system:L1CTL);
354 f_connect_reset(L1CTL);
355}
356
Harald Welte70767382018-02-21 12:16:40 +0100357type function void_fn(charstring id) runs on ConnHdlr;
358
359/* create a new test component */
Harald Weltef26de0b2018-04-04 20:28:05 +0200360function f_start_handler(void_fn fn, ConnHdlrPars pars, boolean pcu_comp := false)
Harald Welte70767382018-02-21 12:16:40 +0100361runs on test_CT return ConnHdlr {
362 var charstring id := testcasename();
363 var ConnHdlr vc_conn;
364
365 vc_conn := ConnHdlr.create(id);
366 /* connect to RSL Emulation main component */
367 connect(vc_conn:RSL, vc_RSL:CLIENT_PT);
368 connect(vc_conn:RSL_PROC, vc_RSL:RSL_PROC);
Harald Weltef26de0b2018-04-04 20:28:05 +0200369 if (pcu_comp) {
370 /* the ConnHdlr component wants to talk directly to the PCU, so disconnect
371 * it from the test_CT and connect it to the component. This obviously only
372 * works for one component, i.e. no concurrency */
373 unmap(self:PCU, system:PCU);
374 map(vc_conn:PCU, system:PCU);
375 }
Harald Welte70767382018-02-21 12:16:40 +0100376
377 vc_conn.start(f_handler_init(fn, id, pars));
378 return vc_conn;
379}
380
Harald Welte7484fc42018-02-24 14:09:45 +0100381template ASP_RSL_Unitdata ts_RSL_UD(template RSL_Message rsl, IpaStreamId sid := IPAC_PROTO_RSL_TRX0) := {
382 streamId := sid,
383 rsl := rsl
384}
385
386template ASP_RSL_Unitdata tr_RSL_UD(template RSL_Message rsl,
387 template IpaStreamId sid := IPAC_PROTO_RSL_TRX0) := {
388 streamId := sid,
389 rsl := rsl
390}
391
Harald Welte70767382018-02-21 12:16:40 +0100392private altstep as_Tguard() runs on ConnHdlr {
393 [] g_Tguard.timeout {
394 setverdict(fail, "Tguard timeout");
395 self.stop;
396 }
397}
398
Harald Welte68e495b2018-02-25 00:05:57 +0100399private function f_l1_tune(L1CTL_PT L1CTL) {
Pau Espin Pedrol752ffd52018-06-07 13:55:45 +0200400 f_L1CTL_FBSB(L1CTL, { false, mp_trx0_arfcn }, CCCH_MODE_COMBINED, mp_rxlev_exp);
Harald Welte70767382018-02-21 12:16:40 +0100401}
402
403private function f_trxc_connect() runs on ConnHdlr {
404 map(self:BB_TRXC, system:BB_TRXC);
405 var Result res;
Harald Weltea4d8f352018-03-01 15:47:20 +0100406 res := TRXC_CodecPort_CtrlFunct.f_IPL4_connect(BB_TRXC, mp_bb_trxc_ip, mp_bb_trxc_port,
407 "", -1, -1, {udp:={}}, {});
Harald Welte9220f632018-05-23 20:27:02 +0200408 if (not ispresent(res.connId)) {
409 setverdict(fail, "Could not connect to trx-control interface of trxcon, check your configuration");
410 self.stop;
411 }
Harald Welte70767382018-02-21 12:16:40 +0100412 g_bb_trxc_conn_id := res.connId;
413}
414
415private function f_trxc_fake_rssi(uint8_t rssi) runs on ConnHdlr {
Harald Weltef8df4cb2018-03-10 15:15:08 +0100416 var TrxcMessage ret;
417 ret := f_TRXC_transceive(BB_TRXC, g_bb_trxc_conn_id, valueof(ts_TRXC_FAKE_RSSI(rssi)));
Harald Welte70767382018-02-21 12:16:40 +0100418}
419
420private function f_trx_fake_toffs256(int16_t toffs256) runs on ConnHdlr {
Harald Weltef8df4cb2018-03-10 15:15:08 +0100421 var TrxcMessage ret;
422 ret := f_TRXC_transceive(BB_TRXC, g_bb_trxc_conn_id, valueof(ts_TRXC_FAKE_TIMING(toffs256)));
Harald Welte70767382018-02-21 12:16:40 +0100423}
424
425/* first function started in ConnHdlr component */
426private function f_handler_init(void_fn fn, charstring id, ConnHdlrPars pars)
427runs on ConnHdlr {
428 g_pars := pars;
429 g_chan_nr := pars.chan_nr;
430
431 map(self:L1CTL, system:L1CTL);
432 f_connect_reset(L1CTL);
433
Harald Welte84271622018-03-10 17:21:03 +0100434 if (mp_bb_trxc_port != -1) {
435 f_trxc_connect();
436 }
Harald Welte70767382018-02-21 12:16:40 +0100437
438 g_Tguard.start(pars.t_guard);
439 activate(as_Tguard());
440
441 f_rslem_register(0, pars.chan_nr);
442
443 /* call the user-supplied test case function */
444 fn.apply(id);
445}
446
Harald Welteb1726c92018-03-30 11:56:38 +0200447function f_rsl_transceive_ret(template RSL_Message tx, template RSL_Message exp_rx, charstring id,
448 boolean ignore_other := false)
449runs on ConnHdlr return RSL_Message {
450 var RSL_Message rx;
Harald Welte1eba3742018-02-25 12:48:14 +0100451 timer T := 3.0;
452 RSL.send(tx);
453 T.start;
Harald Welte70767382018-02-21 12:16:40 +0100454 alt {
Harald Welteb1726c92018-03-30 11:56:38 +0200455 [] RSL.receive(exp_rx) -> value rx {
Harald Welte1eba3742018-02-25 12:48:14 +0100456 T.stop;
457 setverdict(pass);
Harald Welte70767382018-02-21 12:16:40 +0100458 }
Harald Welte1eba3742018-02-25 12:48:14 +0100459 [] T.timeout {
460 setverdict(fail, "Timeout expecting " & id);
461 self.stop;
462 }
Harald Welte21240e62018-03-11 21:43:35 +0100463 [not ignore_other] as_l1_sacch();
464 [not ignore_other] as_meas_res();
465 [not ignore_other] as_l1_dcch();
466 [not ignore_other] RSL.receive {
Harald Welte1eba3742018-02-25 12:48:14 +0100467 setverdict(fail, "Unexpected RSL message received");
Harald Welteb1726c92018-03-30 11:56:38 +0200468 self.stop;
Harald Welte70767382018-02-21 12:16:40 +0100469 }
Harald Welte21240e62018-03-11 21:43:35 +0100470 [ignore_other] RSL.receive { repeat; }
Harald Welte70767382018-02-21 12:16:40 +0100471 }
Harald Welteb1726c92018-03-30 11:56:38 +0200472 return rx;
473}
474
475function f_rsl_transceive(template RSL_Message tx, template RSL_Message exp_rx, charstring id,
476 boolean ignore_other := false)
477runs on ConnHdlr {
478 var RSL_Message rx := f_rsl_transceive_ret(tx, exp_rx, id, ignore_other);
Harald Welte70767382018-02-21 12:16:40 +0100479}
480
Harald Weltee613f962018-04-18 22:38:16 +0200481function f_rsl_chan_act(RSL_IE_ChannelMode mode, boolean encr_enable := false)
482runs on ConnHdlr {
483 var RSL_Message ch_act := valueof(ts_RSL_CHAN_ACT(g_chan_nr, mode));
484 if (encr_enable) {
485 /* append encryption related IEs, if requested */
486 var RSL_IE_EncryptionInfo encr_info;
487 encr_info := valueof(ts_RSL_IE_EncrInfo(g_pars.encr.alg_id, g_pars.encr.key));
488 ch_act.ies := ch_act.ies & { valueof(t_RSL_IE(RSL_IE_ENCR_INFO, RSL_IE_Body:{encr_info :=
489encr_info})) };
490 }
491 f_rsl_transceive(ch_act, tr_RSL_CHAN_ACT_ACK(g_chan_nr), "RSL CHAN ACT");
Harald Welte1eba3742018-02-25 12:48:14 +0100492}
493
Harald Welte70767382018-02-21 12:16:40 +0100494function f_rsl_chan_deact() runs on ConnHdlr {
Harald Welte1eba3742018-02-25 12:48:14 +0100495 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 +0100496 "RF CHAN REL", true);
Harald Welte70767382018-02-21 12:16:40 +0100497}
498
Harald Welte70767382018-02-21 12:16:40 +0100499private template ConnHdlrPars t_Pars(template RslChannelNr chan_nr,
500 template RSL_IE_ChannelMode chan_mode,
501 float t_guard := 20.0) := {
502 chan_nr := valueof(chan_nr),
503 chan_mode := valueof(chan_mode),
504 t_guard := t_guard,
505 l1_pars := {
506 dtx_enabled := false,
Harald Welte685d5982018-02-27 20:42:05 +0100507 toa256_enabled := false,
Harald Welte70767382018-02-21 12:16:40 +0100508 meas_ul := {
509 full := {
510 rxlev := dbm2rxlev(-53),
511 rxqual := 0
512 },
513 sub := {
514 rxlev := dbm2rxlev(-53),
515 rxqual := 0
516 }
517 },
518 timing_offset_256syms := 0,
519 bs_power_level := 0,
520 ms_power_level := 0,
521 ms_actual_ta := 0
Harald Welte0472ab42018-03-12 15:02:26 +0100522 },
Harald Weltee613f962018-04-18 22:38:16 +0200523 spec := omit,
524 encr := omit
Harald Welte70767382018-02-21 12:16:40 +0100525}
526
Harald Welte93640c62018-02-25 16:59:33 +0100527/***********************************************************************
528 * Channel Activation / Deactivation
529 ***********************************************************************/
530
Harald Welte70767382018-02-21 12:16:40 +0100531/* Stress test: Do 500 channel activations/deactivations in rapid succession */
532function f_TC_chan_act_stress(charstring id) runs on ConnHdlr {
533 for (var integer i := 0; i < 500; i := i+1) {
534 f_rsl_chan_act(g_pars.chan_mode);
535 f_rsl_chan_deact();
536 }
537 setverdict(pass);
538}
539testcase TC_chan_act_stress() runs on test_CT {
540 var ConnHdlr vc_conn;
541 var ConnHdlrPars pars := valueof(t_Pars(t_RslChanNr_Bm(1), ts_RSL_ChanMode_SIGN));
542 f_init(testcasename());
543 vc_conn := f_start_handler(refers(f_TC_chan_act_stress), pars);
544 vc_conn.done;
Harald Welte294b0a22018-03-10 23:26:48 +0100545 f_shutdown();
Harald Welte70767382018-02-21 12:16:40 +0100546}
547
548/* Test if re-activation of an already active channel fails as expected */
549function f_TC_chan_act_react(charstring id) runs on ConnHdlr {
550 f_rsl_chan_act(g_pars.chan_mode);
551 /* attempt to activate the same lchan again -> expect reject */
552 RSL.send(ts_RSL_CHAN_ACT(g_chan_nr, g_pars.chan_mode));
553 alt {
554 [] RSL.receive(tr_RSL_CHAN_ACT_ACK(g_chan_nr)) {
555 setverdict(fail, "Unexpected CHAN ACT ACK on double activation");
556 }
557 [] RSL.receive(tr_RSL_CHAN_ACT_NACK(g_chan_nr)) {
558 setverdict(pass);
559 }
560 }
561 f_rsl_chan_deact();
562}
563testcase TC_chan_act_react() runs on test_CT {
564 var ConnHdlr vc_conn;
565 var ConnHdlrPars pars := valueof(t_Pars(t_RslChanNr_Bm(1), ts_RSL_ChanMode_SIGN));
Harald Welte294b0a22018-03-10 23:26:48 +0100566 f_init();
Harald Welte70767382018-02-21 12:16:40 +0100567 vc_conn := f_start_handler(refers(f_TC_chan_act_react), pars);
568 vc_conn.done;
Harald Welte294b0a22018-03-10 23:26:48 +0100569 f_shutdown();
Harald Welte70767382018-02-21 12:16:40 +0100570}
571
572/* Attempt to de-activate a channel that's not active */
573function f_TC_chan_deact_not_active(charstring id) runs on ConnHdlr {
574 timer T := 3.0;
575 RSL.send(ts_RSL_RF_CHAN_REL(g_chan_nr));
576 T.start;
577 alt {
578 [] RSL.receive(tr_RSL_RF_CHAN_REL_ACK(g_chan_nr)) {
579 setverdict(pass);
580 }
581 [] T.timeout {
582 setverdict(fail, "Timeout expecting RF_CHAN_REL_ACK");
583 }
584 }
585}
586testcase TC_chan_deact_not_active() runs on test_CT {
587 var ConnHdlrPars pars := valueof(t_Pars(t_RslChanNr_Bm(1), ts_RSL_ChanMode_SIGN));
Harald Welte294b0a22018-03-10 23:26:48 +0100588 f_init();
Harald Welte70767382018-02-21 12:16:40 +0100589 var ConnHdlr vc_conn := f_start_handler(refers(f_TC_chan_deact_not_active), pars);
590 vc_conn.done;
Harald Welte294b0a22018-03-10 23:26:48 +0100591 f_shutdown();
Harald Welte70767382018-02-21 12:16:40 +0100592}
593
594/* attempt to activate channel with wrong RSL Channel Nr IE; expect NACK */
595function f_TC_chan_act_wrong_nr(charstring id) runs on ConnHdlr {
596 RSL.send(ts_RSL_CHAN_ACT(g_chan_nr, g_pars.chan_mode));
597 alt {
598 [] RSL.receive(tr_RSL_CHAN_ACT_ACK(g_chan_nr)) {
599 setverdict(fail, "Unexpected CHAN ACT ACK");
600 }
601 [] RSL.receive(tr_RSL_CHAN_ACT_NACK(g_chan_nr)) {
602 setverdict(pass);
603 }
604 }
605}
606private type record WrongChanNrCase {
607 RslChannelNr chan_nr,
608 charstring description
609}
610private type record of WrongChanNrCase WrongChanNrCases;
611private template WrongChanNrCase t_WCN(template RslChannelNr chan_nr, charstring desc) := {
612 chan_nr := chan_nr,
613 description := desc
614}
615
616testcase TC_chan_act_wrong_nr() runs on test_CT {
617 var ConnHdlr vc_conn;
618 var ConnHdlrPars pars;
619
Harald Welte294b0a22018-03-10 23:26:48 +0100620 f_init();
Harald Welte70767382018-02-21 12:16:40 +0100621
622 var WrongChanNrCases wrong := {
623 valueof(t_WCN(t_RslChanNr_RACH(0), "RACH is not a dedicated channel")),
624 valueof(t_WCN(t_RslChanNr_RACH(1), "RACH doesn't exist on timeslot")),
625 valueof(t_WCN(t_RslChanNr_BCCH(0), "BCCH is not a dedicated channel")),
626 valueof(t_WCN(t_RslChanNr_PCH_AGCH(0), "PCH/AGCH is not a dedicated channel")),
627 valueof(t_WCN(t_RslChanNr_Bm(0), "TS0 cannot be TCH/F")),
628 valueof(t_WCN(t_RslChanNr_Lm(0, 0), "TS0 cannot be TCH/H")),
629 valueof(t_WCN(t_RslChanNr_Lm(0, 1), "TS0 cannot be TCH/H")),
630 valueof(t_WCN(t_RslChanNr_PDCH(0), "TS0 cannot be PDCH")),
631 valueof(t_WCN(t_RslChanNr_SDCCH8(0, 0), "TS0 cannot be SDCCH/8")),
632 valueof(t_WCN(t_RslChanNr_SDCCH8(0, 7), "TS0 cannot be SDCCH/8")),
633 valueof(t_WCN(t_RslChanNr_SDCCH4(7, 0), "TS7 cannot be SDCCH/4")),
634 valueof(t_WCN(t_RslChanNr_SDCCH4(7, 3), "TS7 cannot be SDCCH/4")),
635 valueof(t_WCN(t_RslChanNr_Lm(1, 0), "TS1 cannot be TCH/H"))
636 };
637
638 for (var integer i := 0; i < sizeof(wrong); i := i+1) {
639 pars := valueof(t_Pars(wrong[i].chan_nr, ts_RSL_ChanMode_SIGN));
640 vc_conn := f_start_handler(refers(f_TC_chan_act_wrong_nr), pars);
641 vc_conn.done;
642 }
Harald Welte294b0a22018-03-10 23:26:48 +0100643 f_shutdown();
Harald Welte70767382018-02-21 12:16:40 +0100644}
645
Harald Weltee613f962018-04-18 22:38:16 +0200646/* execute the same callback function on a variety of logical channels */
647private function f_testmatrix_each_chan(ConnHdlrPars pars, void_fn fn) runs on test_CT {
648 var ConnHdlr vc_conn;
649 f_init(testcasename());
650
651 /* test on each of the channels we have */
652 for (var integer i := 0; i < sizeof(g_AllChanTypes); i := i+1) {
653 pars.chan_nr := valueof(g_AllChanTypes[i]);
654
655 log(testcasename(), ": XXX Starting on ", g_AllChanTypes[i]);
656 vc_conn := f_start_handler(fn, pars);
657 vc_conn.done;
658 }
659
660 f_shutdown();
661}
662
Harald Welte93640c62018-02-25 16:59:33 +0100663/***********************************************************************
Harald Welte629cc6b2018-03-11 17:19:05 +0100664 * SACCH handling
665 ***********************************************************************/
666
667private function f_exp_sacch(boolean exp) runs on ConnHdlr {
668 timer T_sacch := 3.0;
669 T_sacch.start;
670 alt {
671 [not exp] L1CTL.receive(tr_L1CTL_DATA_IND(g_chan_nr, tr_RslLinkID_SACCH(0))) {
672 setverdict(fail, "Received SACCH when not expecting it");
673 }
674 [not exp] T_sacch.timeout {
675 setverdict(pass);
676 }
677 [exp] L1CTL.receive(tr_L1CTL_DATA_IND(g_chan_nr, tr_RslLinkID_SACCH(0))) {
678 setverdict(pass);
679 }
680 [exp] T_sacch.timeout {
681 setverdict(fail, "Timeout waiting for SACCH on ", g_chan_nr);
682 }
683 [] L1CTL.receive { repeat; }
684 [] RSL.receive { repeat; }
685 }
686}
687
688/* Test if DEACTIVATE SACCH actualy deactivates its transmission (TS 48.058 4.6) */
689private function f_TC_deact_sacch(charstring id) runs on ConnHdlr {
690 f_l1_tune(L1CTL);
691 RSL.clear;
692
693 /* activate the logical channel */
694 f_est_dchan();
695 L1CTL.clear;
696
697 /* check that SACCH actually are received as expected */
698 f_exp_sacch(true);
699
700 /* deactivate SACCH on the logical channel */
701 RSL.send(ts_RSL_DEACT_SACCH(g_chan_nr));
702 f_sleep(1.0);
703 L1CTL.clear;
704
705 /* check that no SACCH are received anymore */
706 f_exp_sacch(false);
707
708 /* release the channel */
709 f_rsl_chan_deact();
710 f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
711}
712testcase TC_deact_sacch() runs on test_CT {
713 var ConnHdlr vc_conn;
714 var ConnHdlrPars pars;
715 f_init();
716 for (var integer i := 0; i < sizeof(g_AllChannels); i := i+1) {
717 //for (var integer i := 0; i < 1; i := i+1) {
718 pars := valueof(t_Pars(g_AllChannels[i], ts_RSL_ChanMode_SIGN));
719 log(testcasename(), ": Starting for ", g_AllChannels[i]);
720 vc_conn := f_start_handler(refers(f_TC_deact_sacch), pars);
721 vc_conn.done;
722 }
723 /* TODO: do the above in parallel, rather than sequentially? */
724 f_shutdown();
725}
726
Harald Welte55700662018-03-12 13:15:43 +0100727/* verify that given SACCH payload is present */
Harald Welteea17b912018-03-11 22:29:31 +0100728private function f_sacch_present(template octetstring l3_exp) runs on ConnHdlr {
729 var L1ctlDlMessage dl;
730 /* check that the specified SI5 value is actually sent */
731 timer T_sacch := 3.0;
732 L1CTL.clear;
733 T_sacch.start;
734 alt {
735 [] L1CTL.receive(tr_L1CTL_DATA_IND(g_chan_nr, tr_RslLinkID_SACCH(0))) -> value dl {
736 var octetstring l3 := substr(dl.payload.data_ind.payload, 4, 19);
737 if (match(l3, l3_exp)) {
738 setverdict(pass);
739 } else {
740 repeat;
741 }
742 }
743 [] L1CTL.receive { repeat; }
744 [] T_sacch.timeout {
745 setverdict(fail, "Timeout waiting for SACCH ", l3_exp);
746 self.stop;
747 }
748 }
749}
750
Harald Welte55700662018-03-12 13:15:43 +0100751/* verify that given SACCH payload is not present */
752private function f_sacch_missing(template octetstring l3_exp) runs on ConnHdlr {
753 var L1ctlDlMessage dl;
754 /* check that the specified SI5 value is actually sent */
755 timer T_sacch := 3.0;
756 L1CTL.clear;
757 T_sacch.start;
758 alt {
759 [] L1CTL.receive(tr_L1CTL_DATA_IND(g_chan_nr, tr_RslLinkID_SACCH(0))) -> value dl {
760 var octetstring l3 := substr(dl.payload.data_ind.payload, 4, 19);
761 if (match(l3, l3_exp)) {
762 setverdict(fail, "Received unexpected SACCH ", dl);
763 self.stop;
764 } else {
765 repeat;
766 }
767 }
768 [] L1CTL.receive { repeat; }
769 [] T_sacch.timeout {
770 setverdict(pass);
771 }
772 }
773}
774
Harald Welte629cc6b2018-03-11 17:19:05 +0100775/* Test for default SACCH FILL transmitted in DL SACCH (all channel types) */
Harald Welteea17b912018-03-11 22:29:31 +0100776private function f_TC_sacch_filling(charstring id) runs on ConnHdlr {
777 /* Set a known default SACCH filling for SI5 */
778 var octetstring si5 := f_rnd_octstring(19);
779 RSL.send(ts_RSL_SACCH_FILL(RSL_SYSTEM_INFO_5, si5));
780
781 f_l1_tune(L1CTL);
782 RSL.clear;
783
784 /* activate the logical channel */
785 f_est_dchan();
786
787 /* check that the specified SI5 value is actually sent */
788 f_sacch_present(si5);
789
790 /* release the channel */
791 RSL.clear;
792 f_rsl_chan_deact();
793 f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
794}
795testcase TC_sacch_filling() runs on test_CT {
796 var ConnHdlr vc_conn;
797 var ConnHdlrPars pars;
798 f_init();
799 for (var integer i := 0; i < sizeof(g_AllChannels); i := i+1) {
800 pars := valueof(t_Pars(g_AllChannels[i], ts_RSL_ChanMode_SIGN));
801 log(testcasename(), ": Starting for ", g_AllChannels[i]);
802 vc_conn := f_start_handler(refers(f_TC_sacch_filling), pars);
803 vc_conn.done;
804 }
805 /* TODO: do the above in parallel, rather than sequentially? */
806 f_shutdown();
807}
808
Harald Welte629cc6b2018-03-11 17:19:05 +0100809/* Test for lchan-specific SACCH INFO MODIFY (TS 48.058 4.12) */
Harald Welteea17b912018-03-11 22:29:31 +0100810private function f_TC_sacch_info_mod(charstring id) runs on ConnHdlr {
811 /* Set a known default SACCH filling for SI5 */
812 var octetstring si5 := f_rnd_octstring(19);
813 var octetstring si5_diff := f_rnd_octstring(19);
814 RSL.send(ts_RSL_SACCH_FILL(RSL_SYSTEM_INFO_5, si5));
815
816 f_l1_tune(L1CTL);
817 RSL.clear;
818
819 log("Activating channel, expecting standard SI5");
820 /* activate the logical channel */
821 f_est_dchan();
822 /* check that the specified SI5 value is actually sent */
823 f_sacch_present(si5);
824
825 /* set channel-specific different SI5 */
826 log("Setting channel specific SACCH INFO, expecting it");
827 RSL.send(ts_RSL_SACCH_INF_MOD(g_chan_nr, RSL_SYSTEM_INFO_5, si5_diff))
828 /* check that the specified lchan-specific value is now used */
829 f_sacch_present(si5_diff);
830
831 /* deactivate the channel and re-activate it, this should result in default SI5 */
832 log("De-activating and re-activating channel, expecting standard SI5");
833 f_rsl_chan_deact();
834 f_rsl_chan_act(valueof(ts_RSL_ChanMode_SIGN));
835 /* Verify that the TRX-wide default SACCH filling is present again */
836 f_sacch_present(si5);
837
838 /* release the channel */
839 RSL.clear;
840 f_rsl_chan_deact();
841 f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
842}
843testcase TC_sacch_info_mod() runs on test_CT {
844 var ConnHdlr vc_conn;
845 var ConnHdlrPars pars;
846 f_init();
847 for (var integer i := 0; i < sizeof(g_AllChannels); i := i+1) {
848 pars := valueof(t_Pars(g_AllChannels[i], ts_RSL_ChanMode_SIGN));
849 log(testcasename(), ": Starting for ", g_AllChannels[i]);
850 vc_conn := f_start_handler(refers(f_TC_sacch_info_mod), pars);
851 vc_conn.done;
852 }
853 /* TODO: do the above in parallel, rather than sequentially? */
854 f_shutdown();
855}
856
Harald Welte075d84c2018-03-12 13:07:24 +0100857/* Test SACCH scheduling of multiple different SI message types */
858private function f_TC_sacch_multi(charstring id) runs on ConnHdlr {
859 var octetstring si5 := f_rnd_octstring(19);
860 var octetstring si5bis := f_rnd_octstring(19);
861 var octetstring si5ter := f_rnd_octstring(19);
862 var octetstring si6 := f_rnd_octstring(19);
863
864 RSL.send(ts_RSL_SACCH_FILL(RSL_SYSTEM_INFO_5, si5));
865 RSL.send(ts_RSL_SACCH_FILL(RSL_SYSTEM_INFO_5bis, si5bis));
866 RSL.send(ts_RSL_SACCH_FILL(RSL_SYSTEM_INFO_5ter, si5ter));
867 RSL.send(ts_RSL_SACCH_FILL(RSL_SYSTEM_INFO_6, si6));
868
869 f_l1_tune(L1CTL);
870 RSL.clear;
871
872 /* activate the logical channel */
873 f_est_dchan();
874 L1CTL.clear;
875
876 /* check that SACCH actually are received as expected */
877 f_sacch_present(si5);
878 f_sacch_present(si5bis);
879 f_sacch_present(si5ter);
880 f_sacch_present(si6);
881
882 /* release the channel */
883 f_rsl_chan_deact();
884 f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
885}
886testcase TC_sacch_multi() runs on test_CT {
887 var ConnHdlr vc_conn;
888 var ConnHdlrPars pars;
889 f_init();
890 for (var integer i := 0; i < sizeof(g_AllChannels); i := i+1) {
891 pars := valueof(t_Pars(g_AllChannels[i], ts_RSL_ChanMode_SIGN));
892 log(testcasename(), ": Starting for ", g_AllChannels[i]);
893 vc_conn := f_start_handler(refers(f_TC_sacch_multi), pars);
894 vc_conn.done;
895 }
896 /* TODO: do the above in parallel, rather than sequentially? */
897 f_shutdown();
898}
899
Harald Welte55700662018-03-12 13:15:43 +0100900/* Test if SACH information is modified as expected */
901private function f_TC_sacch_multi_chg(charstring id) runs on ConnHdlr {
902 var octetstring si5 := f_rnd_octstring(19);
903 var octetstring si6 := f_rnd_octstring(19);
904
905 /* First, configure both SI5 and SI6 to be transmitted */
906 RSL.send(ts_RSL_SACCH_FILL(RSL_SYSTEM_INFO_5, si5));
907 RSL.send(ts_RSL_SACCH_FILL(RSL_SYSTEM_INFO_6, si6));
908
909 f_l1_tune(L1CTL);
910 RSL.clear;
911
912 /* activate the logical channel */
913 f_est_dchan();
914 L1CTL.clear;
915
916 /* check that SACCH actually are received as expected */
917 f_sacch_present(si5);
918 f_sacch_present(si6);
919
920 /* disable SI6 */
921 RSL.send(ts_RSL_SACCH_FILL(RSL_SYSTEM_INFO_6, ''O));
922
923 /* check that SI5 is still transmitted */
924 f_sacch_present(si5);
925 /* check if SI6 is now gone */
926 f_sacch_missing(si6);
927
928 /* release the channel */
929 f_rsl_chan_deact();
930 f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
931}
932testcase TC_sacch_multi_chg() runs on test_CT {
933 var ConnHdlr vc_conn;
934 var ConnHdlrPars pars;
935 f_init();
936 for (var integer i := 0; i < sizeof(g_AllChannels); i := i+1) {
937 pars := valueof(t_Pars(g_AllChannels[i], ts_RSL_ChanMode_SIGN));
938 log(testcasename(), ": Starting for ", g_AllChannels[i]);
939 vc_conn := f_start_handler(refers(f_TC_sacch_multi_chg), pars);
940 vc_conn.done;
941 }
942 /* TODO: do the above in parallel, rather than sequentially? */
943 f_shutdown();
944}
945
Harald Welte075d84c2018-03-12 13:07:24 +0100946/* TODO: Test for SACCH information present in RSL CHAN ACT (overrides FILLING) */
947/* TODO: Test for SACCH transmission rules in the context of special CHAN ACT (HO) */
Harald Welte629cc6b2018-03-11 17:19:05 +0100948
949
950/***********************************************************************
Harald Welte93640c62018-02-25 16:59:33 +0100951 * RACH Handling
952 ***********************************************************************/
953
Harald Welte8c24c2b2018-02-26 08:31:31 +0100954/* like L1SAP_IS_PACKET_RACH */
955private function ra_is_ps(OCT1 ra) return boolean {
Harald Welte56c05802018-02-28 21:39:35 +0100956 if ((ra and4b 'F0'O == '70'O) and (ra and4b '0F'O != '0F'O)) {
Harald Welte8c24c2b2018-02-26 08:31:31 +0100957 return true;
958 }
959 return false;
960}
961
962/* generate a random RACH for circuit-switched */
963private function f_rnd_ra_cs() return OCT1 {
964 var OCT1 ra;
965 do {
966 ra := f_rnd_octstring(1);
967 } while (ra_is_ps(ra));
968 return ra;
969}
970
Harald Welte883340c2018-02-28 18:59:29 +0100971/* generate a random RACH for packet-switched */
972private function f_rnd_ra_ps() return OCT1 {
973 var OCT1 ra;
974 do {
975 ra := f_rnd_octstring(1);
976 } while (not ra_is_ps(ra));
977 return ra;
978}
979
Harald Welte8c24c2b2018-02-26 08:31:31 +0100980/* Send 1000 RACH requests and check their RA+FN on the RSL side */
981testcase TC_rach_content() runs on test_CT {
982 f_init(testcasename());
983 f_init_l1ctl();
Harald Welte68e495b2018-02-25 00:05:57 +0100984 f_l1_tune(L1CTL);
Harald Welte70767382018-02-21 12:16:40 +0100985
Harald Welte8c24c2b2018-02-26 08:31:31 +0100986 var GsmFrameNumber fn_last := 0;
987 for (var integer i := 0; i < 1000; i := i+1) {
988 var OCT1 ra := f_rnd_ra_cs();
989 var GsmFrameNumber fn := f_L1CTL_RACH(L1CTL, oct2int(ra));
990 if (fn == fn_last) {
991 setverdict(fail, "Two RACH in same FN?!?");
992 self.stop;
993 }
994 fn_last := fn;
995
996 timer T := 5.0;
Harald Welte56c05802018-02-28 21:39:35 +0100997 T.start;
Harald Welte8c24c2b2018-02-26 08:31:31 +0100998 alt {
999 [] RSL_CCHAN.receive(tr_RSL_UD(tr_RSL_CHAN_RQD(ra, fn, ?))) {
1000 T.stop;
1001 }
1002 [] RSL_CCHAN.receive(tr_RSL_UD(tr_RSL_CHAN_RQD(?, ?, ?))) {
1003 setverdict(fail, "Unexpected CHAN RQD");
1004 self.stop;
1005 }
1006 [] RSL_CCHAN.receive { repeat; }
1007 [] T.timeout {
1008 setverdict(fail, "Timeout waiting for CHAN RQD");
1009 self.stop;
1010 }
1011 }
1012 }
1013 setverdict(pass);
Harald Welte294b0a22018-03-10 23:26:48 +01001014 f_shutdown();
Harald Welte70767382018-02-21 12:16:40 +01001015}
Harald Welte8c24c2b2018-02-26 08:31:31 +01001016
1017/* Send 1000 RACH Requests (flood ~ 89/s) and count if count(Abis) == count(Um) */
1018testcase TC_rach_count() runs on test_CT {
Harald Welte294b0a22018-03-10 23:26:48 +01001019 f_init();
Harald Welte8c24c2b2018-02-26 08:31:31 +01001020 f_init_l1ctl();
Harald Welte294b0a22018-03-10 23:26:48 +01001021 f_sleep(1.0);
Harald Welte8c24c2b2018-02-26 08:31:31 +01001022 f_l1_tune(L1CTL);
1023
1024 var GsmFrameNumber fn_last := 0;
1025 for (var integer i := 0; i < 1000; i := i+1) {
1026 var OCT1 ra := f_rnd_ra_cs();
1027 var GsmFrameNumber fn := f_L1CTL_RACH(L1CTL, oct2int(ra));
1028 if (fn == fn_last) {
1029 setverdict(fail, "Two RACH in same FN?!?");
1030 self.stop;
1031 }
1032 fn_last := fn;
1033 }
1034 var integer rsl_chrqd := 0;
1035 timer T := 3.0;
Harald Welte56c05802018-02-28 21:39:35 +01001036 T.start;
Harald Welte8c24c2b2018-02-26 08:31:31 +01001037 alt {
1038 [] RSL_CCHAN.receive(tr_RSL_UD(tr_RSL_CHAN_RQD(?,?))) {
1039 rsl_chrqd := rsl_chrqd + 1;
Harald Weltec3a3f452018-02-26 17:37:47 +01001040 f_timer_safe_restart(T);
Harald Welte8c24c2b2018-02-26 08:31:31 +01001041 repeat;
1042 }
1043 [] RSL_CCHAN.receive { repeat; }
1044 [] T.timeout { }
1045 }
1046 if (rsl_chrqd == 1000) {
1047 setverdict(pass);
1048 } else {
1049 setverdict(fail, "Received only ", rsl_chrqd, " out of 1000 RACH");
1050 }
Harald Welte294b0a22018-03-10 23:26:48 +01001051 f_shutdown();
Harald Welte70767382018-02-21 12:16:40 +01001052}
1053
Harald Welte54a2a2d2018-02-26 09:14:05 +01001054private function f_main_trxc_connect() runs on test_CT {
1055 map(self:BB_TRXC, system:BB_TRXC);
1056 var Result res;
Harald Welted3a88a62018-03-01 16:04:52 +01001057 res := TRXC_CodecPort_CtrlFunct.f_IPL4_connect(BB_TRXC, mp_bb_trxc_ip, mp_bb_trxc_port,
1058 "", -1, -1, {udp:={}}, {});
Harald Welte9220f632018-05-23 20:27:02 +02001059 if (not ispresent(res.connId)) {
1060 setverdict(fail, "Could not connect to trx-control interface of trxcon, check your configuration");
1061 self.stop;
1062 }
Harald Welte54a2a2d2018-02-26 09:14:05 +01001063 g_bb_trxc_conn_id := res.connId;
1064}
1065
1066private function f_rach_toffs(int16_t toffs256, boolean expect_pass) runs on test_CT {
Harald Weltef8df4cb2018-03-10 15:15:08 +01001067 var TrxcMessage ret;
Harald Welte54a2a2d2018-02-26 09:14:05 +01001068 /* tell fake_trx to use a given timing offset for all bursts */
Harald Weltef8df4cb2018-03-10 15:15:08 +01001069 ret := f_TRXC_transceive(BB_TRXC, g_bb_trxc_conn_id, valueof(ts_TRXC_FAKE_TIMING(toffs256)));
Harald Welte54a2a2d2018-02-26 09:14:05 +01001070 f_sleep(0.5);
1071
1072 /* Transmit RACH request + wait for confirmation */
1073 var OCT1 ra := f_rnd_ra_cs();
1074 var GsmFrameNumber fn := f_L1CTL_RACH(L1CTL, oct2int(ra));
1075
1076 /* Check for expected result */
1077 timer T := 1.5;
1078 T.start;
1079 alt {
1080 [expect_pass] RSL_CCHAN.receive(tr_RSL_UD(tr_RSL_CHAN_RQD(ra, fn))) {
1081 setverdict(pass);
1082 }
1083 [not expect_pass] RSL_CCHAN.receive(tr_RSL_UD(tr_RSL_CHAN_RQD(ra, fn))) {
Harald Welteb3e30942018-03-02 10:33:42 +01001084 setverdict(fail, "RACH passed but was expected to be dropped: ", toffs256);
Harald Welte54a2a2d2018-02-26 09:14:05 +01001085 }
1086 [] RSL_CCHAN.receive { repeat; }
1087 [not expect_pass] T.timeout {
1088 setverdict(pass);
1089 }
1090 [expect_pass] T.timeout {
1091 setverdict(fail, "Timeout waiting for CHAN RQD");
1092 }
1093 }
1094}
1095
1096/* Test if dropping of RACH Based on NM_ATT_MAX_TA works */
1097testcase TC_rach_max_ta() runs on test_CT {
1098 f_init(testcasename());
1099 f_init_l1ctl();
1100 f_l1_tune(L1CTL);
Harald Welte54a2a2d2018-02-26 09:14:05 +01001101 f_sleep(1.0);
1102
1103 /* default max-ta is 63 (full range of GSM timing advance */
1104
Vadim Yanitskiyc81d6e42018-03-05 22:39:01 +07001105 /* We allow early arrival up to 2 symbols */
1106 f_rach_toffs(-1*256, true);
1107 f_rach_toffs(-2*256, true);
Harald Welte54a2a2d2018-02-26 09:14:05 +01001108 f_rach_toffs(-10*256, false);
1109
1110 /* 0 / 32 / 63 bits is legal / permitted */
1111 f_rach_toffs(0, true);
1112 f_rach_toffs(32*256, true);
1113 f_rach_toffs(63*256, true);
1114
1115 /* more than 63 bits is not legal / permitted */
1116 f_rach_toffs(64*256, false);
1117 f_rach_toffs(127*256, false);
Harald Welte294b0a22018-03-10 23:26:48 +01001118 f_shutdown();
Harald Welte54a2a2d2018-02-26 09:14:05 +01001119}
Harald Welte8c24c2b2018-02-26 08:31:31 +01001120
Harald Welte93640c62018-02-25 16:59:33 +01001121/***********************************************************************
1122 * Measurement Processing / Reporting
1123 ***********************************************************************/
1124
Harald Welte70767382018-02-21 12:16:40 +01001125template LapdmAddressField ts_LapdmAddr(LapdmSapi sapi, boolean c_r) := {
1126 spare := '0'B,
1127 lpd := 0,
1128 sapi := sapi,
1129 c_r := c_r,
1130 ea := true
1131}
1132
Harald Welted879bd92018-03-12 15:01:23 +01001133template LapdmFrameAB ts_LAPDm_AB(LapdmSapi sapi, boolean c_r, boolean p, octetstring pl) := {
Harald Welte70767382018-02-21 12:16:40 +01001134 addr := ts_LapdmAddr(sapi, c_r),
Harald Welted879bd92018-03-12 15:01:23 +01001135 ctrl := ts_LapdmCtrlUI(p),
Harald Welte70767382018-02-21 12:16:40 +01001136 len := 0, /* overwritten */
1137 m := false,
1138 el := 1,
1139 payload := pl
1140}
1141
1142/* handle incoming downlink SACCH and respond with uplink SACCH (meas res) */
1143altstep as_l1_sacch() runs on ConnHdlr {
1144 var L1ctlDlMessage l1_dl;
Harald Weltef8df4cb2018-03-10 15:15:08 +01001145 [] L1CTL.receive(tr_L1CTL_DATA_IND(g_chan_nr, tr_RslLinkID_SACCH(?))) -> value l1_dl {
Harald Welte70767382018-02-21 12:16:40 +01001146 log("SACCH received: ", l1_dl.payload.data_ind.payload);
1147 var GsmRrL3Message meas_rep := valueof(ts_MEAS_REP(true, 23, 23, 0, 0, omit));
Harald Welted879bd92018-03-12 15:01:23 +01001148 var LapdmFrameAB lb := valueof(ts_LAPDm_AB(0, false, false, enc_GsmRrL3Message(meas_rep)));
Harald Welte70767382018-02-21 12:16:40 +01001149 log("LAPDm: ", lb);
Harald Welted879bd92018-03-12 15:01:23 +01001150 var octetstring pl := '0000'O & enc_LapdmFrameAB(lb);
Harald Weltef8df4cb2018-03-10 15:15:08 +01001151 L1CTL.send(ts_L1CTL_DATA_REQ(g_chan_nr, ts_RslLinkID_SACCH(0), pl));
Harald Welte70767382018-02-21 12:16:40 +01001152 repeat;
1153 }
1154}
1155
1156altstep as_l1_dcch() runs on ConnHdlr {
1157 var L1ctlDlMessage l1_dl;
Harald Weltef8df4cb2018-03-10 15:15:08 +01001158 [] L1CTL.receive(tr_L1CTL_DATA_IND(g_chan_nr, tr_RslLinkID_DCCH(?))) -> value l1_dl {
Harald Welte70767382018-02-21 12:16:40 +01001159 log("DCCH received: ", l1_dl.payload.data_ind.payload);
1160 var octetstring pl := '010301'O;
Harald Weltef8df4cb2018-03-10 15:15:08 +01001161 L1CTL.send(ts_L1CTL_DATA_REQ(g_chan_nr, ts_RslLinkID_DCCH(0), pl));
Harald Welte70767382018-02-21 12:16:40 +01001162 repeat;
1163 }
1164}
1165
1166type record MeasElem {
1167 uint6_t rxlev,
1168 uint3_t rxqual
1169}
1170
1171type record MeasElemFS {
1172 MeasElem full,
1173 MeasElem sub
1174}
1175
1176type record ConnL1Pars {
1177 boolean dtx_enabled,
Harald Welte685d5982018-02-27 20:42:05 +01001178 boolean toa256_enabled,
Harald Welte70767382018-02-21 12:16:40 +01001179 MeasElemFS meas_ul,
1180 int16_t timing_offset_256syms,
1181 uint5_t bs_power_level,
1182 uint5_t ms_power_level,
1183 uint8_t ms_actual_ta
1184}
1185
1186/* Convert tiing offset from 1/256th symbol to RSL Timing Offset */
1187private function toffs256s_to_rsl(int16_t toffs256s) return uint8_t {
1188 return 63 + (toffs256s/256);
1189}
1190
Harald Welted5684392018-03-10 18:22:04 +01001191private function f_max(integer a, integer b) return integer {
1192 if (a > b) {
1193 return a;
1194 } else {
1195 return b;
1196 }
1197}
1198
1199private function f_min(integer a, integer b) return integer {
1200 if (a < b) {
1201 return a;
1202 } else {
1203 return b;
1204 }
1205}
1206
1207/* compute negative tolerance val-tolerance, ensure >= min */
1208private function f_tolerance_neg(integer val, integer min, integer tolerance) return integer {
1209 val := val - tolerance;
1210 return f_max(val, min);
1211}
1212
1213/* compute positive tolerance val+tolerance, ensure <= max */
1214private function f_tolerance_pos(integer val, integer max, integer tolerance) return integer {
1215 val := val + tolerance;
1216 return f_min(val, max);
1217}
1218
1219/* return a template of (val-tolerance .. val+tolerance) ensuring it is within (min .. max) */
1220private function f_tolerance(integer val, integer min, integer max, integer tolerance)
1221return template integer {
1222 var template integer ret;
1223 ret := (f_tolerance_neg(val, min, tolerance) .. f_tolerance_pos(val, max, tolerance));
1224 return ret;
1225}
1226
1227
Harald Welte70767382018-02-21 12:16:40 +01001228/* build a template for matching measurement results against */
1229private function f_build_meas_res_tmpl() runs on ConnHdlr return template RSL_Message {
1230 var ConnL1Pars l1p := g_pars.l1_pars;
1231 var template RSL_IE_UplinkMeas ul_meas := {
1232 len := 3,
1233 rfu := '0'B,
1234 dtx_d := l1p.dtx_enabled,
Harald Welted5684392018-03-10 18:22:04 +01001235 rxlev_f_u := f_tolerance(l1p.meas_ul.full.rxlev, 0, 63, mp_tolerance_rxlev),
Harald Welte70767382018-02-21 12:16:40 +01001236 reserved1 := '00'B,
Harald Welted5684392018-03-10 18:22:04 +01001237 rxlev_s_u := f_tolerance(l1p.meas_ul.sub.rxlev, 0, 63, mp_tolerance_rxlev),
Harald Welte70767382018-02-21 12:16:40 +01001238 reserved2 := '00'B,
Harald Welted5684392018-03-10 18:22:04 +01001239 rxq_f_u := f_tolerance(l1p.meas_ul.full.rxqual, 0, 7, mp_tolerance_rxqual),
1240 rxq_s_u := f_tolerance(l1p.meas_ul.sub.rxqual, 0, 7, mp_tolerance_rxqual),
Harald Welte70767382018-02-21 12:16:40 +01001241 supp_meas_info := omit
1242 };
Harald Welte685d5982018-02-27 20:42:05 +01001243 if (l1p.toa256_enabled) {
1244 ul_meas.len := 5;
1245 ul_meas.supp_meas_info := int2oct(l1p.timing_offset_256syms, 2);
1246 }
Harald Welte70767382018-02-21 12:16:40 +01001247 /* HACK HACK HACK FIXME HACK HACK HACK see https://osmocom.org/issues/2988 */
1248 ul_meas.rxlev_f_u := ?;
1249 ul_meas.rxlev_s_u := ?;
1250 ul_meas.rxq_f_u := ?;
1251 ul_meas.rxq_s_u := ?;
1252 var template RSL_IE_BS_Power bs_power := {
1253 reserved := 0,
1254 epc := false,
1255 fpc := false,
1256 power_level := l1p.bs_power_level
1257 };
1258 var template RSL_IE_L1Info l1_info := {
1259 ms_power_lvl := l1p.ms_power_level,
1260 fpc := false,
1261 reserved := 0,
1262 actual_ta := l1p.ms_actual_ta
1263 };
1264 var uint8_t offs := toffs256s_to_rsl(l1p.timing_offset_256syms);
1265 var template uint8_t t_toffs := (offs-1 .. offs+1); /* some tolerance */
1266 return tr_RSL_MEAS_RES_OSMO(g_chan_nr, g_next_meas_res_nr, ul_meas, bs_power, l1_info,
1267 ?, t_toffs);
1268}
1269
1270/* verify we regularly receive measurement reports with incrementing numbers */
1271altstep as_meas_res() runs on ConnHdlr {
1272 var RSL_Message rsl;
1273 [] RSL.receive(f_build_meas_res_tmpl()) -> value rsl {
1274 /* increment counter of next to-be-expected meas rep */
1275 g_next_meas_res_nr := (g_next_meas_res_nr + 1) mod 256;
1276 /* Re-start the timer expecting the next MEAS RES */
Harald Weltec3a3f452018-02-26 17:37:47 +01001277 f_timer_safe_restart(g_Tmeas_exp);
Harald Welte70767382018-02-21 12:16:40 +01001278 repeat;
1279 }
1280 [] RSL.receive(tr_RSL_MEAS_RES(g_chan_nr, g_next_meas_res_nr)) -> value rsl {
Harald Weltefa45e9e2018-03-10 18:59:03 +01001281 /* increment counter of next to-be-expected meas rep */
1282 g_next_meas_res_nr := (g_next_meas_res_nr + 1) mod 256;
1283 if (g_first_meas_res) {
1284 g_first_meas_res := false;
1285 repeat;
1286 } else {
1287 setverdict(fail, "Received unspecific MEAS RES ", rsl);
1288 self.stop;
1289 }
Harald Welte70767382018-02-21 12:16:40 +01001290 }
1291 [] RSL.receive(tr_RSL_MEAS_RES(?)) -> value rsl {
1292 setverdict(fail, "Received unexpected MEAS RES ", rsl);
1293 self.stop;
1294 }
1295 [] g_Tmeas_exp.timeout {
1296 setverdict(fail, "Didn't receive expected measurement result")
1297 self.stop;
1298 }
1299}
1300
Harald Weltee613f962018-04-18 22:38:16 +02001301private function f_alg_id_to_l1ctl(RSL_AlgId rsl_alg_id) return uint8_t {
1302 select (rsl_alg_id) {
1303 case (RSL_ALG_ID_A5_0) { return 0; }
1304 case (RSL_ALG_ID_A5_1) { return 1; }
1305 case (RSL_ALG_ID_A5_2) { return 2; }
1306 case (RSL_ALG_ID_A5_3) { return 3; }
1307 case (RSL_ALG_ID_A5_4) { return 4; }
1308 case (RSL_ALG_ID_A5_5) { return 5; }
1309 case (RSL_ALG_ID_A5_6) { return 6; }
1310 case (RSL_ALG_ID_A5_7) { return 7; }
1311 case else {
1312 setverdict(fail, "Unknwon Algorithm ID");
1313 self.stop;
1314 }
1315 }
1316}
1317
1318private function f_alg_id_to_l3(RSL_AlgId rsl_alg_id) return BIT3 {
1319 select (rsl_alg_id) {
1320 case (RSL_ALG_ID_A5_1) { return '000'B; }
1321 case (RSL_ALG_ID_A5_2) { return '001'B; }
1322 case (RSL_ALG_ID_A5_3) { return '010'B; }
1323 case (RSL_ALG_ID_A5_4) { return '011'B; }
1324 case (RSL_ALG_ID_A5_5) { return '100'B; }
1325 case (RSL_ALG_ID_A5_6) { return '101'B; }
1326 case (RSL_ALG_ID_A5_7) { return '110'B; }
1327 case else {
1328 setverdict(fail, "Unknwon Algorithm ID");
1329 self.stop;
1330 }
1331 }
1332}
1333
1334
Harald Welte70767382018-02-21 12:16:40 +01001335/* Establish dedicated channel: L1CTL + RSL side */
Harald Weltee613f962018-04-18 22:38:16 +02001336private function f_est_dchan(boolean encr_enable := false) runs on ConnHdlr {
Harald Welte70767382018-02-21 12:16:40 +01001337 var GsmFrameNumber fn;
1338 var ImmediateAssignment imm_ass;
1339 var integer ra := 23;
1340
1341 fn := f_L1CTL_RACH(L1CTL, ra);
1342 /* This arrives on CCHAN, so we cannot test for receiving CHAN RQDhere */
1343 //RSL.receive(tr_RSL_CHAN_RQD(int2oct(23,1)));
1344
1345 /* Activate channel on BTS side */
Harald Weltee613f962018-04-18 22:38:16 +02001346 f_rsl_chan_act(g_pars.chan_mode, encr_enable);
Harald Welte70767382018-02-21 12:16:40 +01001347
1348 /* Send IMM.ASS via CCHAN */
1349 var ChannelDescription ch_desc := {
1350 chan_nr := g_pars.chan_nr,
1351 tsc := 7,
1352 h := false,
1353 arfcn := mp_trx0_arfcn,
1354 maio_hsn := omit
1355 };
1356 var MobileAllocation ma := {
1357 len := 0,
1358 ma := ''B
1359 };
1360 var GsmRrMessage rr_msg := valueof(ts_IMM_ASS(ra, fn, 0, ch_desc, ma));
1361 RSL.send(ts_RSL_IMM_ASSIGN(enc_GsmRrMessage(rr_msg)));
1362
1363 /* receive IMM.ASS on MS side */
1364 var ImmediateAssignment ia_um;
1365 ia_um := f_L1CTL_WAIT_IMM_ASS(L1CTL, ra, fn);
1366 /* enable dedicated mode */
1367 f_L1CTL_DM_EST_REQ_IA(L1CTL, ia_um);
Harald Weltee613f962018-04-18 22:38:16 +02001368 /* enable encryption, if requested */
1369 if (encr_enable) {
1370 var uint8_t alg_id := f_alg_id_to_l1ctl(g_pars.encr.alg_id);
1371 f_L1CTL_CRYPTO_REQ(L1CTL, g_pars.chan_nr, alg_id, g_pars.encr.key);
1372 }
Harald Weltefa45e9e2018-03-10 18:59:03 +01001373
1374 g_first_meas_res := true;
Harald Welte70767382018-02-21 12:16:40 +01001375}
1376
1377/* establish DChan, verify existance + contents of measurement reports */
1378function f_TC_meas_res_periodic(charstring id) runs on ConnHdlr {
Harald Welte68e495b2018-02-25 00:05:57 +01001379 f_l1_tune(L1CTL);
Harald Welte70767382018-02-21 12:16:40 +01001380 RSL.clear;
1381
Harald Welte5398d5e2018-03-10 19:00:24 +01001382 if (mp_bb_trxc_port != -1) {
1383 g_pars.l1_pars.meas_ul.full.rxlev := dbm2rxlev(-100);
1384 f_trxc_fake_rssi(100);
Harald Welte70767382018-02-21 12:16:40 +01001385
Harald Welte5398d5e2018-03-10 19:00:24 +01001386 g_pars.l1_pars.timing_offset_256syms := 512; /* 2 symbols */
1387 f_trx_fake_toffs256(g_pars.l1_pars.timing_offset_256syms);
1388 } else {
1389 g_pars.l1_pars.timing_offset_256syms := 0; /* FIXME */
1390 g_pars.l1_pars.meas_ul.full.rxlev := dbm2rxlev(-55); /* FIXME */
1391 }
1392 g_pars.l1_pars.meas_ul.sub.rxlev := g_pars.l1_pars.meas_ul.full.rxlev;
Harald Welte70767382018-02-21 12:16:40 +01001393
1394 f_est_dchan();
1395
1396 /* run for a number of seconds, send SACCH + FACCH from MS side and verify
1397 * RSL measurement reports on Abis side */
1398 timer T := 8.0;
1399 T.start;
1400 alt {
1401 [] as_l1_sacch();
1402 [] as_meas_res();
1403 [] as_l1_dcch();
1404 [] L1CTL.receive { repeat; }
1405 [g_Tmeas_exp.running] T.timeout {
1406 /* as_meas_res() would have done setverdict(fail) / self.stop in case
1407 * of any earlier errors, so if we reach this timeout, we're good */
1408 setverdict(pass);
1409 }
1410 [] T.timeout {
1411 setverdict(fail, "No MEAS RES received at all");
1412 }
1413 }
1414 f_rsl_chan_deact();
Harald Welte3dc20462018-03-10 23:03:38 +01001415 f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
Harald Welte70767382018-02-21 12:16:40 +01001416}
Harald Welte0472ab42018-03-12 15:02:26 +01001417
Harald Welte70767382018-02-21 12:16:40 +01001418testcase TC_meas_res_sign_tchf() runs on test_CT {
1419 var ConnHdlr vc_conn;
1420 var ConnHdlrPars pars;
1421 f_init(testcasename());
1422 for (var integer tn := 1; tn <= 4; tn := tn+1) {
1423 pars := valueof(t_Pars(t_RslChanNr_Bm(tn), ts_RSL_ChanMode_SIGN));
1424 vc_conn := f_start_handler(refers(f_TC_meas_res_periodic), pars);
1425 vc_conn.done;
1426 }
Harald Welte294b0a22018-03-10 23:26:48 +01001427 f_shutdown();
Harald Welte70767382018-02-21 12:16:40 +01001428}
1429testcase TC_meas_res_sign_tchh() runs on test_CT {
1430 var ConnHdlr vc_conn;
1431 var ConnHdlrPars pars;
1432 f_init(testcasename());
1433 for (var integer ss := 0; ss <= 1; ss := ss+1) {
1434 pars := valueof(t_Pars(t_RslChanNr_Lm(5, ss), ts_RSL_ChanMode_SIGN));
1435 vc_conn := f_start_handler(refers(f_TC_meas_res_periodic), pars);
1436 vc_conn.done;
1437 }
Harald Welte294b0a22018-03-10 23:26:48 +01001438 f_shutdown();
Harald Welte70767382018-02-21 12:16:40 +01001439}
1440testcase TC_meas_res_sign_sdcch4() runs on test_CT {
1441 var ConnHdlr vc_conn;
1442 var ConnHdlrPars pars;
1443 f_init(testcasename());
1444 for (var integer ss := 0; ss <= 3; ss := ss+1) {
1445 pars := valueof(t_Pars(t_RslChanNr_SDCCH4(0, ss), ts_RSL_ChanMode_SIGN));
1446 vc_conn := f_start_handler(refers(f_TC_meas_res_periodic), pars);
1447 vc_conn.done;
1448 }
Harald Welte294b0a22018-03-10 23:26:48 +01001449 f_shutdown();
Harald Welte70767382018-02-21 12:16:40 +01001450}
1451testcase TC_meas_res_sign_sdcch8() runs on test_CT {
1452 var ConnHdlr vc_conn;
1453 var ConnHdlrPars pars;
1454 f_init(testcasename());
1455 for (var integer ss := 0; ss <= 7; ss := ss+1) {
1456 pars := valueof(t_Pars(t_RslChanNr_SDCCH8(6, ss), ts_RSL_ChanMode_SIGN));
1457 vc_conn := f_start_handler(refers(f_TC_meas_res_periodic), pars);
1458 vc_conn.done;
1459 }
Harald Welte294b0a22018-03-10 23:26:48 +01001460 f_shutdown();
Harald Welte70767382018-02-21 12:16:40 +01001461}
Harald Welte685d5982018-02-27 20:42:05 +01001462testcase TC_meas_res_sign_tchh_toa256() runs on test_CT {
1463 var ConnHdlr vc_conn;
1464 var ConnHdlrPars pars;
1465 f_init(testcasename());
1466 f_vty_config(BTSVTY, "bts 0", "supp-meas-info toa256");
1467 for (var integer ss := 0; ss <= 1; ss := ss+1) {
1468 pars := valueof(t_Pars(t_RslChanNr_Lm(5, ss), ts_RSL_ChanMode_SIGN));
1469 pars.l1_pars.toa256_enabled := true;
1470 vc_conn := f_start_handler(refers(f_TC_meas_res_periodic), pars);
1471 vc_conn.done;
1472 }
Harald Welte294b0a22018-03-10 23:26:48 +01001473 f_shutdown();
Harald Welte685d5982018-02-27 20:42:05 +01001474}
1475
Harald Welte70767382018-02-21 12:16:40 +01001476
Harald Welte0472ab42018-03-12 15:02:26 +01001477/* 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 +01001478private function f_TC_conn_fail_crit(charstring id) runs on ConnHdlr {
Harald Welte68e495b2018-02-25 00:05:57 +01001479 f_l1_tune(L1CTL);
Harald Welte70767382018-02-21 12:16:40 +01001480 RSL.clear;
1481
1482 f_est_dchan();
1483 f_sleep(2.0);
Harald Weltef8df4cb2018-03-10 15:15:08 +01001484 L1CTL.send(ts_L1CTL_DM_REL_REQ(g_chan_nr));
Harald Welte70767382018-02-21 12:16:40 +01001485
1486 timer T := 40.0;
1487 T.start;
1488 alt {
1489 [] RSL.receive(tr_RSL_CONN_FAIL_IND(g_chan_nr, ?)) {
1490 setverdict(pass)
1491 }
1492 [] RSL.receive { repeat };
1493 [] T.timeout {
1494 setverdict(fail, "No CONN FAIL IND received");
1495 }
1496 }
1497 f_rsl_chan_deact();
1498}
1499testcase TC_conn_fail_crit() runs on test_CT {
1500 var ConnHdlr vc_conn;
1501 var ConnHdlrPars pars;
1502 f_init(testcasename());
1503 pars := valueof(t_Pars(t_RslChanNr_SDCCH8(6, 3), ts_RSL_ChanMode_SIGN));
1504 pars.t_guard := 60.0;
1505 vc_conn := f_start_handler(refers(f_TC_conn_fail_crit), pars);
1506 vc_conn.done;
1507}
1508
Harald Welte93640c62018-02-25 16:59:33 +01001509/***********************************************************************
1510 * Paging
1511 ***********************************************************************/
1512
Harald Welte68e495b2018-02-25 00:05:57 +01001513function tmsi_is_dummy(TMSIP_TMSI_V tmsi) return boolean {
1514 if (tmsi == 'FFFFFFFF'O) {
1515 return true;
1516 } else {
1517 return false;
1518 }
1519}
Harald Welte70767382018-02-21 12:16:40 +01001520
Harald Welte68e495b2018-02-25 00:05:57 +01001521altstep as_l1_count_paging(inout integer num_paging_rcv_msgs, inout integer num_paging_rcv_ids)
1522runs on test_CT {
1523 var L1ctlDlMessage dl;
Harald Weltef8df4cb2018-03-10 15:15:08 +01001524 [] L1CTL.receive(tr_L1CTL_DATA_IND(t_RslChanNr_PCH_AGCH(0), ?, c_DummyUI)) {
Harald Welte68e495b2018-02-25 00:05:57 +01001525 repeat;
1526 }
Harald Weltef8df4cb2018-03-10 15:15:08 +01001527 [] L1CTL.receive(tr_L1CTL_DATA_IND(t_RslChanNr_PCH_AGCH(0))) -> value dl {
Harald Welte68e495b2018-02-25 00:05:57 +01001528 var octetstring without_plen :=
1529 substr(dl.payload.data_ind.payload, 1, lengthof(dl.payload.data_ind.payload)-1);
1530 var PDU_ML3_NW_MS rr := dec_PDU_ML3_NW_MS(without_plen);
1531 if (match(rr, tr_PAGING_REQ1)) {
1532 num_paging_rcv_msgs := num_paging_rcv_msgs + 1;
1533 num_paging_rcv_ids := num_paging_rcv_ids + 1;
1534 if (isvalue(rr.msgs.rrm.pagingReq_Type1.mobileIdentity2)) {
1535 num_paging_rcv_ids := num_paging_rcv_ids + 1;
1536 }
1537 } else if (match(rr, tr_PAGING_REQ2)) {
1538 num_paging_rcv_msgs := num_paging_rcv_msgs + 1;
1539 if (not tmsi_is_dummy(rr.msgs.rrm.pagingReq_Type2.mobileIdentity1)) {
1540 num_paging_rcv_ids := num_paging_rcv_ids + 1;
1541 }
1542 if (not tmsi_is_dummy(rr.msgs.rrm.pagingReq_Type2.mobileIdentity2)) {
1543 num_paging_rcv_ids := num_paging_rcv_ids + 1;
1544 }
1545 if (isvalue(rr.msgs.rrm.pagingReq_Type2.mobileIdentity3)) {
1546 num_paging_rcv_ids := num_paging_rcv_ids + 1;
1547 }
1548 } else if (match(rr, tr_PAGING_REQ3)) {
1549 num_paging_rcv_msgs := num_paging_rcv_msgs + 1;
1550 if (not tmsi_is_dummy(rr.msgs.rrm.pagingReq_Type3.mobileIdentity1)) {
1551 num_paging_rcv_ids := num_paging_rcv_ids + 1;
1552 }
1553 if (not tmsi_is_dummy(rr.msgs.rrm.pagingReq_Type3.mobileIdentity2)) {
1554 num_paging_rcv_ids := num_paging_rcv_ids + 1;
1555 }
1556 if (not tmsi_is_dummy(rr.msgs.rrm.pagingReq_Type3.mobileIdentity3)) {
1557 num_paging_rcv_ids := num_paging_rcv_ids + 1;
1558 }
1559 if (not tmsi_is_dummy(rr.msgs.rrm.pagingReq_Type3.mobileIdentity4)) {
1560 num_paging_rcv_ids := num_paging_rcv_ids + 1;
1561 }
1562 }
1563 repeat;
1564 }
1565}
1566
1567type record PagingTestCfg {
1568 boolean combined_ccch,
1569 integer bs_ag_blks_res,
1570 float load_factor,
1571 boolean exp_load_ind,
1572 boolean exp_overload,
1573 boolean use_tmsi
1574}
1575
1576type record PagingTestState {
1577 integer num_paging_sent,
1578 integer num_paging_rcv_msgs,
1579 integer num_paging_rcv_ids,
1580 integer num_overload
1581}
1582
1583/* receive + ignore RSL RF RES IND */
1584altstep as_rsl_res_ind() runs on test_CT {
1585 [] RSL_CCHAN.receive(tr_RSL_UD(tr_RSL_RF_RES_IND)) {
1586 repeat;
1587 }
1588}
1589
1590/* Helper function for paging related testing */
1591private function f_TC_paging(PagingTestCfg cfg) runs on test_CT return PagingTestState {
1592 f_init(testcasename());
1593 f_init_l1ctl();
1594 f_l1_tune(L1CTL);
1595
1596 var PagingTestState st := {
1597 num_paging_sent := 0,
1598 num_paging_rcv_msgs := 0,
1599 num_paging_rcv_ids := 0,
1600 num_overload := 0
1601 };
1602
1603 var float max_pch_blocks_per_sec := f_pch_block_rate_est(cfg.combined_ccch, cfg.bs_ag_blks_res);
1604 var float max_pch_imsi_per_sec;
1605 if (cfg.use_tmsi) {
1606 max_pch_imsi_per_sec := max_pch_blocks_per_sec * 4.0; /* Type 3 */
1607 } else {
1608 max_pch_imsi_per_sec := max_pch_blocks_per_sec * 2.0; /* Type 1 */
1609 }
1610 var float pch_blocks_per_sec := max_pch_imsi_per_sec * cfg.load_factor;
1611 var float interval := 1.0 / pch_blocks_per_sec;
1612 log("pch_blocks_per_sec=", pch_blocks_per_sec, " interval=", interval);
1613
1614 for (var integer i := 0; i < float2int(20.0/interval); i := i+1) {
1615 /* build mobile Identity */
1616 var MobileL3_CommonIE_Types.MobileIdentityLV mi;
1617 if (cfg.use_tmsi) {
1618 mi := valueof(ts_MI_TMSI_LV(f_rnd_octstring(4)));
1619 } else {
1620 mi := valueof(ts_MI_IMSI_LV(f_gen_imsi(i)));
1621 }
1622 var octetstring mi_enc_lv := enc_MobileIdentityLV(mi);
1623 var octetstring mi_enc := substr(mi_enc_lv, 1, lengthof(mi_enc_lv)-1);
1624
1625 /* Send RSL PAGING COMMAND */
1626 RSL_CCHAN.send(ts_RSL_UD(ts_RSL_PAGING_CMD(mi_enc, i mod 4)));
1627 st.num_paging_sent := st.num_paging_sent + 1;
1628
1629 /* Wait for interval to next PAGING COMMAND */
1630 timer T_itv := interval;
1631 T_itv.start;
1632 alt {
1633 /* check for presence of CCCH LOAD IND (paging load) */
1634 [cfg.exp_overload] RSL_CCHAN.receive(tr_RSL_UD(tr_RSL_PAGING_LOAD_IND(0))) {
1635 st.num_overload := st.num_overload + 1;
1636 repeat;
1637 }
1638 [not cfg.exp_overload] RSL_CCHAN.receive(tr_RSL_UD(tr_RSL_PAGING_LOAD_IND(0))) {
1639 setverdict(fail, "Unexpected PCH Overload");
1640 }
1641 [cfg.exp_load_ind] RSL_CCHAN.receive(tr_RSL_UD(tr_RSL_PAGING_LOAD_IND)) {
1642 log("Rx LOAD_IND");
1643 /* FIXME: analyze/verify interval + contents */
1644 repeat;
1645 }
1646 /* check if paging requests arrive on Um side */
1647 [] as_l1_count_paging(st.num_paging_rcv_msgs, st.num_paging_rcv_ids);
1648 [] L1CTL.receive { repeat; }
1649 [] T_itv.timeout { }
1650 [] as_rsl_res_ind();
1651 }
1652 }
1653
1654 /* wait for max 18s for paging queue to drain (size: 200, ~ 13 per s -> 15s) */
1655 timer T_wait := 18.0;
1656 T_wait.start;
1657 alt {
1658 [] as_l1_count_paging(st.num_paging_rcv_msgs, st.num_paging_rcv_ids);
1659 [] L1CTL.receive { repeat; }
1660 /* 65535 == empty paging queue, we can terminate*/
1661 [] RSL_CCHAN.receive(tr_RSL_UD(tr_RSL_PAGING_LOAD_IND(65535))) { }
1662 [] RSL_CCHAN.receive(tr_RSL_UD(tr_RSL_PAGING_LOAD_IND)) { repeat; }
1663 [] T_wait.timeout {
1664 setverdict(fail, "Waiting for empty paging queue");
1665 }
1666 [] as_rsl_res_ind();
1667 }
1668
Harald Welte294b0a22018-03-10 23:26:48 +01001669 f_shutdown();
1670
Harald Welte68e495b2018-02-25 00:05:57 +01001671 log("num_paging_sent=", st.num_paging_sent, " rcvd_msgs=", st.num_paging_rcv_msgs,
1672 " rcvd_ids=", st.num_paging_rcv_ids);
1673 return st;
1674}
1675
1676/* Create ~ 80% paging load (IMSI only) sustained for about 20s, verifying that
1677 * - the number of Mobile Identities on Um PCH match the number of pages on RSL
1678 * - that CCCH LOAD IND (PCH) are being generated
1679 * - that CCCH LOAD IND (PCH) [no load] is received after paging flood is over */
1680testcase TC_paging_imsi_80percent() runs on test_CT {
1681 var PagingTestCfg cfg := {
1682 combined_ccch := true,
1683 bs_ag_blks_res := 1,
1684 load_factor := 0.8,
1685 exp_load_ind := true,
1686 exp_overload := false,
1687 use_tmsi := false
1688 };
1689 var PagingTestState st := f_TC_paging(cfg);
1690 if (st.num_paging_sent != st.num_paging_rcv_ids) {
1691 setverdict(fail, "Expected ", st.num_paging_sent, " pagings but have ",
1692 st.num_paging_rcv_ids);
1693 } else {
1694 setverdict(pass);
1695 }
1696}
1697
1698/* Create ~ 80% paging load (TMSI only) sustained for about 20s, verifying that
1699 * - the number of Mobile Identities on Um PCH match the number of pages on RSL
1700 * - that CCCH LOAD IND (PCH) are being generated
1701 * - that CCCH LOAD IND (PCH) [no load] is received after paging flood is over */
1702testcase TC_paging_tmsi_80percent() runs on test_CT {
1703 var PagingTestCfg cfg := {
1704 combined_ccch := true,
1705 bs_ag_blks_res := 1,
1706 load_factor := 0.8,
1707 exp_load_ind := true,
1708 exp_overload := false,
1709 use_tmsi := true
1710 };
1711 var PagingTestState st := f_TC_paging(cfg);
1712 if (st.num_paging_sent != st.num_paging_rcv_ids) {
1713 setverdict(fail, "Expected ", st.num_paging_sent, " pagings but have ",
1714 st.num_paging_rcv_ids);
1715 } else {
1716 setverdict(pass);
1717 }
1718}
1719
1720/* Create ~ 200% paging load (IMSI only) sustained for about 20s, verifying that
1721 * - the number of Mobile Identities on Um PCH are ~ 82% of the number of pages on RSL
1722 * - that CCCH LOAD IND (PCH) are being generated and reach 0 at some point
1723 * - that CCCH LOAD IND (PCH) [no load] is received after paging flood is over */
1724testcase TC_paging_imsi_200percent() runs on test_CT {
1725 var PagingTestCfg cfg := {
1726 combined_ccch := true,
1727 bs_ag_blks_res := 1,
1728 load_factor := 2.0,
1729 exp_load_ind := true,
1730 exp_overload := true,
1731 use_tmsi := false
1732 };
1733 var PagingTestState st := f_TC_paging(cfg);
1734 /* We expect about 80-85% to pass, given that we can fill the paging buffer of 200
1735 * slots and will fully drain that buffer before returning */
1736 var template integer tpl := (st.num_paging_sent*80/100 .. st.num_paging_sent *85/100);
1737 if (not match(st.num_paging_rcv_ids, tpl)) {
1738 setverdict(fail, "Expected ", tpl, " pagings but have ", st.num_paging_rcv_ids);
1739 } else {
1740 setverdict(pass);
1741 }
1742}
1743
1744/* Create ~ 200% paging load (TMSI only) sustained for about 20s, verifying that
1745 * - the number of Mobile Identities on Um PCH are ~ 82% of the number of pages on RSL
1746 * - that CCCH LOAD IND (PCH) are being generated and reach 0 at some point
1747 * - that CCCH LOAD IND (PCH) [no load] is received after paging flood is over */
1748testcase TC_paging_tmsi_200percent() runs on test_CT {
1749 var PagingTestCfg cfg := {
1750 combined_ccch := true,
1751 bs_ag_blks_res := 1,
1752 load_factor := 2.0,
1753 exp_load_ind := true,
1754 exp_overload := true,
1755 use_tmsi := true
1756 };
1757 var PagingTestState st := f_TC_paging(cfg);
1758 /* We expect about 70% to pass, given that we can fill the paging buffer of 200
1759 * slots and will fully drain that buffer before returning */
Harald Welte0803cde2018-04-15 21:36:54 +02001760 var template integer tpl := (st.num_paging_sent*66/100 .. st.num_paging_sent *72/100);
Harald Welte68e495b2018-02-25 00:05:57 +01001761 if (not match(st.num_paging_rcv_ids, tpl)) {
1762 setverdict(fail, "Expected ", tpl, " pagings but have ", st.num_paging_rcv_ids);
1763 } else {
1764 setverdict(pass);
1765 }
1766}
1767
1768
Harald Welte93640c62018-02-25 16:59:33 +01001769/***********************************************************************
1770 * Immediate Assignment / AGCH
1771 ***********************************************************************/
1772
Harald Welte68e495b2018-02-25 00:05:57 +01001773testcase TC_imm_ass() runs on test_CT {
1774 f_init(testcasename());
1775 for (var integer i := 0; i < 1000; i := i+1) {
1776 var octetstring ia_enc := f_rnd_octstring(8);
1777 RSL_CCHAN.send(ts_RSL_UD(ts_RSL_IMM_ASSIGN(ia_enc, 0)));
1778 f_sleep(0.02);
1779 }
1780 /* FIXME: check if imm.ass arrive on Um side */
1781 /* FIXME: check for DELETE INDICATION */
1782 f_sleep(100.0);
Harald Welte294b0a22018-03-10 23:26:48 +01001783 f_shutdown();
Harald Welte68e495b2018-02-25 00:05:57 +01001784}
1785
Harald Welte48494ca2018-02-25 16:59:50 +01001786/***********************************************************************
1787 * BCCH
1788 ***********************************************************************/
1789
1790/* tuple of Frame Number + decoded SI */
1791type record SystemInformationFn {
1792 GsmFrameNumber frame_number,
1793 SystemInformation si
1794}
1795
1796/* an arbitrary-length vector of decoded SI + gsmtap header */
1797type record of SystemInformationFn SystemInformationVector;
1798
1799/* an array of SI-vectors indexed by TC value */
1800type SystemInformationVector SystemInformationVectorPerTc[8];
1801
1802/* determine if a given SI vector contains given SI type at least once */
1803function f_si_vecslot_contains(SystemInformationVector arr, RrMessageType key, boolean bcch_ext := false) return boolean {
1804 for (var integer i:= 0; i< sizeof(arr); i := i + 1) {
1805 var integer fn_mod51 := arr[i].frame_number mod 51;
1806 if (not bcch_ext and fn_mod51 == 2 or
1807 bcch_ext and fn_mod51 == 6) {
1808 if (arr[i].si.header.message_type == key) {
1809 return true;
1810 }
1811 }
1812 }
1813 return false;
1814}
1815
1816/* ensure a given TC slot of the SI vector contains given SI type at least once at TC */
1817function f_ensure_si_vec_contains(SystemInformationVectorPerTc arr, integer tc, RrMessageType key, boolean ext_bcch := false) {
1818 if (not f_si_vecslot_contains(arr[tc], key, ext_bcch)) {
1819 setverdict(fail, "No ", key, " in TC=", tc, "!");
1820 }
1821}
1822
1823/* check if a given SI vector contains given SI type at least once on any TC */
1824function f_si_vec_contains(SystemInformationVectorPerTc arr, RrMessageType key) return boolean {
1825 for (var integer tc:= 0; tc < sizeof(arr); tc := tc + 1) {
1826 if (f_si_vecslot_contains(arr[tc], key) or
1827 f_si_vecslot_contains(arr[tc], key, true)) {
1828 return true;
1829 }
1830 }
1831 return false;
1832}
1833
1834/* determine if a given SI vector contains given SI type at least N of M times */
1835function f_si_vecslot_contains_n_of_m(SystemInformationVector arr, RrMessageType key, boolean bcch_ext := false, integer n := 1, integer m := 4) return boolean {
1836 var integer count := 0;
1837 if (sizeof(arr) < m) {
1838 setverdict(fail, "Error: Insufficient SI in array");
1839 self.stop;
1840 }
1841 for (var integer i:= 0; i < m; i := i + 1) {
1842 var integer fn_mod51 := arr[i].frame_number mod 51;
1843 if (not bcch_ext and fn_mod51 == 2 or
1844 bcch_ext and fn_mod51 == 6) {
1845 if (arr[i].si.header.message_type == key) {
1846 count := count + 1;
1847 }
1848 }
1849 }
1850 if (count >= n) {
1851 return true;
1852 } else {
1853 return false;
1854 }
1855}
1856
1857/* ensure a given TC slot of the SI vector contains given SI type at least N out of M times at TC */
1858function f_ensure_si_vec_contains_n_of_m(SystemInformationVectorPerTc arr, integer tc, RrMessageType key, boolean ext_bcch := false, integer n, integer m) {
1859 if (not f_si_vecslot_contains_n_of_m(arr[tc], key, ext_bcch, n, m)) {
1860 setverdict(fail, "Not ", n, "/", m, " of ", key, " in TC=", tc, "!");
1861 }
1862}
1863
1864/* determine if a given SI vector contains given SI type at least once */
1865function f_si_vecslot_contains_only(SystemInformationVector arr, RrMessageType key, boolean bcch_ext := false) return boolean {
1866 for (var integer i:= 0; i< sizeof(arr); i := i + 1) {
1867 var integer fn_mod51 := arr[i].frame_number mod 51;
1868 if (not bcch_ext and fn_mod51 == 2 or
1869 bcch_ext and fn_mod51 == 6) {
1870 if (arr[i].si.header.message_type != key) {
1871 return false;
1872 }
1873 }
1874 }
1875 return true;
1876}
1877
1878/* ensure a given TC slot of the SI vector contains only given SI type */
1879function f_ensure_si_vec_contains_only(SystemInformationVectorPerTc arr, integer tc, RrMessageType key, boolean ext_bcch := false) {
1880 if (not f_si_vecslot_contains_only(arr[tc], key, ext_bcch)) {
1881 setverdict(fail, "Not all ", key, " in TC=", tc, "!");
1882 }
1883}
1884
1885/* SI configuration of cell, against which we validate actual SI messages */
1886type set SystemInformationConfig {
1887 boolean bcch_extended,
1888 boolean si1_present,
1889 boolean si2bis_present,
1890 boolean si2ter_present,
1891 boolean si2quater_present,
1892 boolean si7_present,
1893 boolean si8_present,
1894 boolean si9_present,
1895 boolean si13_present,
1896 boolean si13alt_present,
1897 boolean si15_present,
1898 boolean si16_present,
1899 boolean si17_present,
1900 boolean si2n_present,
1901 boolean si21_present,
1902 boolean si22_present
1903}
1904
1905/* validate the SI scheduling according to TS 45.002 version 14.1.0 Release 14, Section 6.3.1.3 */
1906function f_validate_si_scheduling(SystemInformationConfig cfg, SystemInformationVectorPerTc si_per_tc) {
1907 var integer i;
1908 for (i := 0; i < sizeof(si_per_tc); i := i + 1) {
1909 if (sizeof(si_per_tc[i]) == 0) {
Harald Welte544565a2018-03-02 10:34:08 +01001910 setverdict(fail, "No SI messages for TC=", i);
Harald Welte48494ca2018-02-25 16:59:50 +01001911 }
1912 }
1913 if (cfg.si1_present) {
1914 /* ii) System Information Type 1 needs to be sent if frequency hopping is in use or
1915 * when the NCH is present in a cell. If the MS finds another message on BCCH Norm
1916 * when TC = 0, it can assume that System Information Type 1 is not in use. */
1917 f_ensure_si_vec_contains(si_per_tc, 0, SYSTEM_INFORMATION_TYPE_1);
1918 /* make sure *ALL* contain SI1 */
1919 f_ensure_si_vec_contains_only(si_per_tc, 0, SYSTEM_INFORMATION_TYPE_1);
1920 }
1921 f_ensure_si_vec_contains(si_per_tc, 1, SYSTEM_INFORMATION_TYPE_2);
1922 /* iii) A SI 2 message will be sent at least every time TC = 1 */
1923 f_ensure_si_vec_contains(si_per_tc, 2, SYSTEM_INFORMATION_TYPE_3);
1924 f_ensure_si_vec_contains(si_per_tc, 6, SYSTEM_INFORMATION_TYPE_3);
1925 f_ensure_si_vec_contains(si_per_tc, 3, SYSTEM_INFORMATION_TYPE_4);
1926 f_ensure_si_vec_contains(si_per_tc, 7, SYSTEM_INFORMATION_TYPE_4);
1927
1928 /* iii) System information type 2 bis or 2 ter messages are sent if needed, as determined by the
1929 * system operator. If only one of them is needed, it is sent when TC = 5. If both are
1930 * needed, 2bis is sent when TC = 5 and 2ter is sent at least once within any of 4
1931 * consecutive occurrences of TC = 4. */
1932 if (cfg.si2bis_present and not cfg.si2ter_present) {
1933 f_ensure_si_vec_contains(si_per_tc, 5, SYSTEM_INFORMATION_TYPE_2bis);
1934 } else if (cfg.si2ter_present and not cfg.si2bis_present) {
1935 f_ensure_si_vec_contains(si_per_tc, 5, SYSTEM_INFORMATION_TYPE_2ter);
1936 } else if (cfg.si2ter_present and cfg.si2bis_present) {
1937 f_ensure_si_vec_contains(si_per_tc, 5, SYSTEM_INFORMATION_TYPE_2bis);
1938 f_ensure_si_vec_contains_n_of_m(si_per_tc, 4, SYSTEM_INFORMATION_TYPE_2ter, false, 1, 4);
1939 }
1940
1941 if (cfg.si7_present or cfg.si8_present) {
1942 /* vi) Use of System Information type 7 and 8 is not always necessary. It is necessary
1943 * if System Information type 4 does not contain all information needed for cell
1944 * selection and reselection. */
1945 if (not cfg.bcch_extended) {
1946 testcase.stop("Error: SI7/SI8 require BCCH Extd.");
1947 }
1948 if (cfg.si7_present) {
1949 f_ensure_si_vec_contains(si_per_tc, 7, SYSTEM_INFORMATION_TYPE_7, true);
1950 }
1951 if (cfg.si8_present) {
1952 f_ensure_si_vec_contains(si_per_tc, 3, SYSTEM_INFORMATION_TYPE_8, true);
1953 }
1954 }
1955
1956 if (cfg.si2quater_present) {
1957 /* iii) System information type 2 quater is sent if needed, as determined by the system
1958 * operator. If sent on BCCH Norm, it shall be sent when TC = 5 if neither of 2bis
1959 * and 2ter are used, otherwise it shall be sent at least once within any of 4
1960 * consecutive occurrences of TC = 4. If sent on BCCH Ext, it is sent at least once
1961 * within any of 4 consecutive occurrences of TC = 5. */
1962 if (not (cfg.bcch_extended)) {
1963 if (not (cfg.si2bis_present or cfg.si2ter_present)) {
1964 f_ensure_si_vec_contains(si_per_tc, 5, SYSTEM_INFORMATION_TYPE_2quater);
1965 } else {
1966 f_ensure_si_vec_contains_n_of_m(si_per_tc, 4, SYSTEM_INFORMATION_TYPE_2quater, false, 1, 4);
1967 }
1968 } else {
1969 f_ensure_si_vec_contains_n_of_m(si_per_tc, 5, SYSTEM_INFORMATION_TYPE_2quater, true, 1, 4);
1970 }
1971 }
1972 if (cfg.si9_present) {
1973 /* vi) System Information type 9 is sent in those blocks with TC = 4 which are specified
1974 * in system information type 3 as defined in 3GPP TS 44.018. */
1975 f_ensure_si_vec_contains(si_per_tc, 4, SYSTEM_INFORMATION_TYPE_9); // FIXME SI3
1976 }
1977 if (cfg.si13_present) {
1978 /* vii) System Information type 13 is only related to the GPRS service. System Information
1979 * Type 13 need only be sent if GPRS support is indicated in one or more of System
1980 * Information Type 3 or 4 or 7 or 8 messages. These messages also indicate if the
1981 * message is sent on the BCCH Norm or if the message is transmitted on the BCCH Ext.
1982 * In the case that the message is sent on the BCCH Norm, it is sent at least once
1983 * within any of 4 consecutive occurrences of TC=4. */
1984 if (not cfg.bcch_extended) {
1985 log("not-bccch-extended");
1986 f_ensure_si_vec_contains_n_of_m(si_per_tc, 4, SYSTEM_INFORMATION_TYPE_13, false, 1, 4);
1987 } else {
1988 log("bccch-extended");
1989 f_ensure_si_vec_contains(si_per_tc, 0, SYSTEM_INFORMATION_TYPE_13, true);
1990 }
1991 if (f_si_vec_contains(si_per_tc, SYSTEM_INFORMATION_TYPE_13alt)) {
1992 setverdict(fail, "Cannot have SI13alt and SI13");
1993 }
1994 }
1995 if (cfg.si16_present or cfg.si17_present) {
1996 /* viii) System Information type 16 and 17 are only related to the SoLSA service. They
1997 * should not be sent in a cell where network sharing is used (see rule xv). */
1998 if (cfg.si22_present) {
1999 testcase.stop("Error: Cannot have SI16/SI17 and SI22!");
2000 }
2001 if (f_si_vec_contains(si_per_tc, SYSTEM_INFORMATION_TYPE_22)) {
2002 setverdict(fail, "Cannot have SI16/SI17 and SI22!");
2003 }
2004 if (not cfg.bcch_extended) {
2005 testcase.stop("Error: SI16/SI17 requires BCCH Extd!");
2006 }
2007 if (cfg.si16_present) {
2008 f_ensure_si_vec_contains(si_per_tc, 6, SYSTEM_INFORMATION_TYPE_16, true);
2009 }
2010 if (cfg.si17_present) {
2011 f_ensure_si_vec_contains(si_per_tc, 2, SYSTEM_INFORMATION_TYPE_17, true);
2012 }
2013 }
2014
2015 /* ix) System Information type 18 and 20 are sent in order to transmit non-GSM
2016 * broadcast information. The frequency with which they are sent is determined by the
2017 * system operator. System Information type 9 identifies the scheduling of System
2018 * Information type 18 and 20 messages. */
2019
2020 /* x) System Information Type 19 is sent if COMPACT neighbours exist. If System
2021 * Information Type 19 is present, then its scheduling shall be indicated in System
2022 * Information Type 9. */
2023
2024 if (cfg.si15_present) {
2025 /* xi) System Information Type 15 is broadcast if dynamic ARFCN mapping is used in the
2026 * PLMN. If sent on BCCH Norm, it is sent at least once within any of 4 consecutive
2027 * occurrences of TC = 4. If sent on BCCH Ext, it is sent at least once within any of
2028 * 4 consecutive occurrences of TC = 1. */
2029 if (not cfg.bcch_extended) {
2030 f_ensure_si_vec_contains_n_of_m(si_per_tc, 4, SYSTEM_INFORMATION_TYPE_15, false, 1, 4);
2031 } else {
2032 f_ensure_si_vec_contains_n_of_m(si_per_tc, 1, SYSTEM_INFORMATION_TYPE_15, true, 1, 4);
2033 }
2034 }
2035 if (cfg.si13alt_present) {
2036 /* xii) System Information type 13 alt is only related to the GERAN Iu mode. System
2037 * Information Type 13 alt need only be sent if GERAN Iu mode support is indicated in
2038 * one or more of System Information Type 3 or 4 or 7 or 8 messages and SI 13 is not
2039 * broadcast. These messages also indicate if the message is sent on the BCCH Norm or
2040 * if the message is transmitted on the BCCH Ext. In the case that the message is sent
2041 * on the BCCH Norm, it is sent at least once within any of 4 consecutive occurrences
2042 * of TC = 4. */
2043 if (cfg.si13_present) {
2044 testcase.stop("Error: Cannot have SI13alt and SI13");
2045 }
2046 if (f_si_vec_contains(si_per_tc, SYSTEM_INFORMATION_TYPE_13)) {
2047 setverdict(fail, "Cannot have SI13alt and SI13");
2048 }
2049 if (not cfg.bcch_extended) {
2050 f_ensure_si_vec_contains_n_of_m(si_per_tc, 4, SYSTEM_INFORMATION_TYPE_13alt, false, 1, 4);
2051 } else {
2052 f_ensure_si_vec_contains(si_per_tc, 0, SYSTEM_INFORMATION_TYPE_13alt, true);
2053 }
2054 }
2055 if (cfg.si2n_present) {
2056 /* xiii) System Information Type 2n is optionally sent on BCCH Norm or BCCH Ext if needed,
2057 * as determined by the system operator. In the case that the message is sent on the
2058 * BCCH Norm, it is sent at least once within any of 4 consecutive occurrences of TC =
2059 * 4. If the message is sent on BCCH Ext, it is sent at least once within any of 2
2060 * consecutive occurrences of TC = 4. */
2061 if (not cfg.bcch_extended) {
2062 f_ensure_si_vec_contains_n_of_m(si_per_tc, 4, SYSTEM_INFORMATION_TYPE_2n, false, 1, 4);
2063 } else {
2064 f_ensure_si_vec_contains_n_of_m(si_per_tc, 4, SYSTEM_INFORMATION_TYPE_2n, true, 2, 4);
2065 }
2066 }
2067 if (cfg.si21_present) {
2068 /* xiv) System Information Type 21 is optionally sent on BCCH Norm or BCCH Ext, as
2069 * determined by the system operator. If Extended Access Barring is in use in the cell
2070 * then this message is sent at least once within any of 4 consecutive occurrences of
2071 * TC = 4 regardless if it is sent on BCCH Norm or BCCH Ext. If BCCH Ext is used in a
2072 * cell then this message shall only be sent on BCCH Ext. */
2073 if (not cfg.bcch_extended) {
2074 f_ensure_si_vec_contains_n_of_m(si_per_tc, 4, SYSTEM_INFORMATION_TYPE_21, false, 1, 4);
2075 } else {
2076 f_ensure_si_vec_contains_n_of_m(si_per_tc, 4, SYSTEM_INFORMATION_TYPE_21, true, 1, 4);
2077 if (f_si_vecslot_contains(si_per_tc[4], SYSTEM_INFORMATION_TYPE_21)) {
2078 setverdict(fail, "Cannot have SI21 on BCCH Norm if BCCH Extd enabled!");
2079 }
2080 }
2081 }
2082 if (cfg.si22_present) {
2083 /* xv) System Information Type 22 is sent if network sharing is in use in the cell. It
2084 * should not be sent in a cell where SoLSA is used (see rule viii). System
2085 * Information Type 22 instances shall be sent on BCCH Ext within any occurrence of TC
2086 * =2 and TC=6. */
2087 if (cfg.si16_present or cfg.si17_present) {
2088 testcase.stop("Error: Cannot have SI16/SI17 and SI22!");
2089 }
2090 if (f_si_vec_contains(si_per_tc, SYSTEM_INFORMATION_TYPE_16) or
2091 f_si_vec_contains(si_per_tc, SYSTEM_INFORMATION_TYPE_17)) {
2092 setverdict(fail, "Cannot have SI16/SI17 and SI22!");
2093 }
2094 if (not cfg.bcch_extended) {
2095 testcase.stop("Error: SI22 requires BCCH Extd!");
2096 } else {
2097 f_ensure_si_vec_contains_only(si_per_tc, 2, SYSTEM_INFORMATION_TYPE_22, true);
2098 f_ensure_si_vec_contains_only(si_per_tc, 6, SYSTEM_INFORMATION_TYPE_22, true);
2099 }
2100 }
2101}
2102
2103/* sample Systme Information for specified duration via L1CTL */
2104function f_l1_sample_si(L1CTL_PT pt, float duration := 8.0) return SystemInformationVectorPerTc {
2105 timer T := duration;
2106 var SystemInformationVectorPerTc si_per_tc;
2107 var L1ctlDlMessage l1_dl;
2108
2109 /* initialize all per-TC vectors empty */
2110 for (var integer i:= 0; i < sizeof(si_per_tc); i := i+1) {
2111 si_per_tc[i] := {};
2112 }
2113
2114 /* flush all previous L1 queued msgs */
2115 pt.clear;
2116
2117 T.start;
2118 alt {
Harald Weltef8df4cb2018-03-10 15:15:08 +01002119 [] pt.receive(tr_L1CTL_DATA_IND(t_RslChanNr_BCCH(0), ?)) -> value l1_dl {
Harald Welte48494ca2018-02-25 16:59:50 +01002120 /* somehow dec_SystemInformation will try to decode even non-RR as SI */
2121 if (not (l1_dl.payload.data_ind.payload[1] == '06'O)) {
2122 log("Ignoring non-RR SI ", l1_dl);
2123 repeat;
2124 }
2125 var SystemInformationFn sig := {
2126 frame_number := l1_dl.dl_info.frame_nr,
2127 si := dec_SystemInformation(l1_dl.payload.data_ind.payload)
2128 }
2129 var integer tc := f_gsm_compute_tc(sig.frame_number);
2130 log("SI received at TC=", tc, ": ", sig.si);
2131 /* append to the per-TC bucket */
2132 si_per_tc[tc] := si_per_tc[tc] & { sig };
2133 repeat;
2134 }
2135 [] pt.receive { repeat; }
2136 [] T.timeout { }
2137 }
2138
2139 for (var integer i:= 0; i < sizeof(si_per_tc); i := i+1) {
2140 log(testcasename(), ": TC=", i, " has #of SI=", sizeof(si_per_tc[i]));
2141 }
2142 log("si_per_tc=", si_per_tc);
2143 return si_per_tc;
2144}
2145
2146/* helper function: Set given SI via RSL + validate scheduling.
2147 * CALLER MUST MAKE SURE TO CHANGE GLOBAL si_cfg! */
2148function f_TC_si_sched() runs on test_CT {
2149 var SystemInformationVectorPerTc si_per_tc;
2150 f_init_l1ctl();
2151 f_l1_tune(L1CTL);
2152
2153 /* Sample + Validate Scheduling */
2154 si_per_tc := f_l1_sample_si(L1CTL);
2155 f_validate_si_scheduling(si_cfg, si_per_tc);
2156
2157 setverdict(pass);
2158}
2159
2160testcase TC_si_sched_default() runs on test_CT {
2161 f_init();
Harald Welte0cae4552018-03-09 22:20:26 +01002162 /* 2+3+4 are mandatory and set in f_init() */
2163 f_TC_si_sched();
Harald Welte294b0a22018-03-10 23:26:48 +01002164 f_shutdown();
Harald Welte0cae4552018-03-09 22:20:26 +01002165}
2166
2167testcase TC_si_sched_1() runs on test_CT {
2168 f_init();
2169 si_cfg.si1_present := true;
2170 f_rsl_bcch_fill_raw(RSL_SYSTEM_INFO_1, '5506198fb38000000000000000000000000000e504002b'O);
Harald Welte48494ca2018-02-25 16:59:50 +01002171 f_TC_si_sched();
Harald Welte294b0a22018-03-10 23:26:48 +01002172 f_shutdown();
Harald Welte48494ca2018-02-25 16:59:50 +01002173}
2174
2175testcase TC_si_sched_2bis() runs on test_CT {
2176 f_init();
2177 si_cfg.si2bis_present := true;
2178 f_rsl_bcch_fill_raw(RSL_SYSTEM_INFO_2bis, '550602bfe809b3ff00000000000000000000007900002b'O);
2179 f_TC_si_sched();
Harald Welte294b0a22018-03-10 23:26:48 +01002180 f_shutdown();
Harald Welte48494ca2018-02-25 16:59:50 +01002181}
2182
2183testcase TC_si_sched_2ter() runs on test_CT {
2184 f_init();
2185 si_cfg.si2ter_present := true;
2186 f_rsl_bcch_fill_raw(RSL_SYSTEM_INFO_2ter, '010603bf66b0aa0a00000002000000000000002b2b2b2b'O);
2187 f_TC_si_sched();
Harald Welte294b0a22018-03-10 23:26:48 +01002188 f_shutdown();
Harald Welte48494ca2018-02-25 16:59:50 +01002189}
2190
2191testcase TC_si_sched_2ter_2bis() runs on test_CT {
2192 f_init();
2193 si_cfg.si2bis_present := true;
2194 f_rsl_bcch_fill_raw(RSL_SYSTEM_INFO_2bis, '550602bfe809b3ff00000000000000000000007900002b'O);
2195 si_cfg.si2ter_present := true;
2196 f_rsl_bcch_fill_raw(RSL_SYSTEM_INFO_2ter, '010603bf66b0aa0a00000002000000000000002b2b2b2b'O);
2197 f_TC_si_sched();
Harald Welte294b0a22018-03-10 23:26:48 +01002198 f_shutdown();
Harald Welte48494ca2018-02-25 16:59:50 +01002199}
2200
2201testcase TC_si_sched_2quater() runs on test_CT {
2202 f_init();
2203 si_cfg.si2quater_present := true;
2204 f_rsl_bcch_fill_raw(RSL_SYSTEM_INFO_2quater, '050607a8a0364aa698d72ff424feee0506d5e7fff02043'O);
2205 f_TC_si_sched();
Harald Welte294b0a22018-03-10 23:26:48 +01002206 f_shutdown();
Harald Welte48494ca2018-02-25 16:59:50 +01002207}
2208
2209testcase TC_si_sched_13() runs on test_CT {
2210 f_init();
2211 si_cfg.si13_present := true;
Harald Welte5618c2a2018-04-15 16:24:46 +02002212 f_rsl_bcch_fill_raw(RSL_SYSTEM_INFO_13, '0106009000185a6fc9e08410ab2b2b2b2b2b2b2b2b2b2b'O);
Harald Welte48494ca2018-02-25 16:59:50 +01002213 f_TC_si_sched();
Harald Welte294b0a22018-03-10 23:26:48 +01002214 f_shutdown();
Harald Welte48494ca2018-02-25 16:59:50 +01002215}
2216
2217testcase TC_si_sched_13_2bis_2ter_2quater() runs on test_CT {
2218 f_init();
2219 si_cfg.si2bis_present := true;
2220 f_rsl_bcch_fill_raw(RSL_SYSTEM_INFO_2bis, '550602bfe809b3ff00000000000000000000007900002b'O);
2221 si_cfg.si2ter_present := true;
2222 f_rsl_bcch_fill_raw(RSL_SYSTEM_INFO_2ter, '010603bf66b0aa0a00000002000000000000002b2b2b2b'O);
2223 si_cfg.si2quater_present := true;
2224 f_rsl_bcch_fill_raw(RSL_SYSTEM_INFO_2quater, '050607a8a0364aa698d72ff424feee0506d5e7fff02043'O);
2225 si_cfg.si13_present := true;
Harald Welte5618c2a2018-04-15 16:24:46 +02002226 f_rsl_bcch_fill_raw(RSL_SYSTEM_INFO_13, '0106009000185a6fc9e08410ab2b2b2b2b2b2b2b2b2b2b'O);
Harald Welte48494ca2018-02-25 16:59:50 +01002227 f_TC_si_sched();
Harald Welte294b0a22018-03-10 23:26:48 +01002228 f_shutdown();
Harald Welte48494ca2018-02-25 16:59:50 +01002229}
2230
2231
Harald Welte68e495b2018-02-25 00:05:57 +01002232testcase TC_bcch_info() runs on test_CT {
2233 f_init(testcasename());
2234 /* FIXME: enable / disable individual BCCH info */
2235 //ts_RSL_BCCH_INFO(si_type, info);
2236 /* expect no ERROR REPORT after either of them *
2237 /* negative test: ensure ERROR REPORT on unsupported types */
Harald Welte294b0a22018-03-10 23:26:48 +01002238 f_shutdown();
Harald Welte68e495b2018-02-25 00:05:57 +01002239}
2240
Harald Welte93640c62018-02-25 16:59:33 +01002241/***********************************************************************
2242 * Low-Level Protocol Errors / ERROR REPORT
2243 ***********************************************************************/
2244
Harald Welte01d982c2018-02-25 01:31:40 +01002245private function f_exp_err_rep(template RSL_Cause cause) runs on test_CT {
2246 timer T := 5.0;
2247 T.start;
2248 alt {
2249 [] RSL_CCHAN.receive(tr_RSL_UD(tr_RSL_ERROR_REPORT(cause))) {
2250 setverdict(pass);
2251 }
2252 [] RSL_CCHAN.receive(tr_RSL_UD(tr_RSL_ERROR_REPORT(?))) {
2253 setverdict(fail, "Wrong cause in RSL ERR REP");
2254 }
2255 [] RSL_CCHAN.receive {
2256 repeat;
2257 }
2258 [] T.timeout {
2259 setverdict(fail, "Timeout waiting for RSL ERR REP");
2260 }
2261 }
2262}
2263
2264/* Provoke a protocol error (message too short) and match on ERROR REPORT */
2265testcase TC_rsl_protocol_error() runs on test_CT {
2266 f_init(testcasename());
2267 var RSL_Message rsl := valueof(ts_RSL_BCCH_INFO(RSL_SYSTEM_INFO_1, ''O));
2268 rsl.ies := omit;
2269 RSL_CCHAN.send(ts_RSL_UD(rsl));
2270
2271 f_exp_err_rep(RSL_ERR_PROTO);
2272}
2273
2274/* Provoke a mandatory IE error and match on ERROR REPORT */
2275testcase TC_rsl_mand_ie_error() runs on test_CT {
2276 f_init(testcasename());
2277
2278 var RSL_Message rsl := valueof(ts_RSL_BCCH_INFO(RSL_SYSTEM_INFO_1, ''O));
2279 rsl.ies := { rsl.ies[0] };
2280 RSL_CCHAN.send(ts_RSL_UD(rsl));
2281
2282 f_exp_err_rep(RSL_ERR_MAND_IE_ERROR);
2283}
2284
2285/* Provoke an IE content error and match on ERROR REPORT */
2286testcase TC_rsl_ie_content_error() runs on test_CT {
2287 f_init(testcasename());
2288 var RSL_Message rsl := valueof(ts_RSL_BCCH_INFO(RSL_SYSTEM_INFO_1, ''O));
2289 rsl.ies[1].body.sysinfo_type := RSL_SYSTEM_INFO_5;
2290 RSL_CCHAN.send(ts_RSL_UD(rsl));
2291
2292 f_exp_err_rep(RSL_ERR_IE_CONTENT);
2293}
2294
Harald Welte93640c62018-02-25 16:59:33 +01002295/***********************************************************************
2296 * IPA CRCX/MDCX/DLCS media stream handling
2297 ***********************************************************************/
2298
Harald Weltea871a382018-02-25 02:03:14 +01002299/* Send IPA DLCX to inactive lchan */
2300function f_TC_ipa_dlcx_not_active(charstring id) runs on ConnHdlr {
Harald Welte1eba3742018-02-25 12:48:14 +01002301 f_rsl_transceive(ts_RSL_IPA_DLCX(g_chan_nr, 0), tr_RSL_IPA_DLCX_ACK(g_chan_nr, ?, ?),
2302 "IPA DLCX ACK");
Harald Weltea871a382018-02-25 02:03:14 +01002303}
2304testcase TC_ipa_dlcx_not_active() runs on test_CT {
2305 var ConnHdlrPars pars := valueof(t_Pars(t_RslChanNr_Bm(1), ts_RSL_ChanMode_SIGN));
2306 f_init(testcasename());
2307 var ConnHdlr vc_conn := f_start_handler(refers(f_TC_ipa_dlcx_not_active), pars);
2308 vc_conn.done;
2309}
Harald Welte68e495b2018-02-25 00:05:57 +01002310
Harald Weltea3f1df92018-02-25 12:49:55 +01002311/* Send IPA CRCX twice to inactive lchan */
2312function f_TC_ipa_crcx_twice_not_active(charstring id) runs on ConnHdlr {
2313 f_rsl_transceive(ts_RSL_IPA_CRCX(g_chan_nr), tr_RSL_IPA_CRCX_ACK(g_chan_nr, ?, ?, ?),
2314 "IPA CRCX ACK");
2315 f_rsl_transceive(ts_RSL_IPA_CRCX(g_chan_nr), tr_RSL_IPA_CRCX_NACK(g_chan_nr, RSL_ERR_RES_UNAVAIL),
2316 "IPA CRCX NACK");
2317}
2318testcase TC_ipa_crcx_twice_not_active() runs on test_CT {
2319 var ConnHdlrPars pars := valueof(t_Pars(t_RslChanNr_Bm(1), ts_RSL_ChanMode_SIGN));
2320 f_init(testcasename());
2321 var ConnHdlr vc_conn := f_start_handler(refers(f_TC_ipa_crcx_twice_not_active), pars);
2322 vc_conn.done;
2323}
2324
2325/* Regular sequence of CRCX/MDCX/DLCX */
2326function f_TC_ipa_crcx_mdcx_dlcx_not_active(charstring id) runs on ConnHdlr {
2327 f_rsl_transceive(ts_RSL_IPA_CRCX(g_chan_nr), tr_RSL_IPA_CRCX_ACK(g_chan_nr, ?, ?, ?),
2328 "IPA CRCX ACK");
2329 var uint32_t remote_ip := f_rnd_int(c_UINT32_MAX);
2330 var uint16_t remote_port := f_rnd_int(c_UINT16_MAX);
2331 var uint7_t rtp_pt2 := f_rnd_int(127);
2332 var uint16_t fake_conn_id := 23; /* we're too lazy to read it out from the CRCX ACK above */
2333 f_rsl_transceive(ts_RSL_IPA_MDCX(g_chan_nr, fake_conn_id, remote_ip, remote_port, rtp_pt2),
2334 tr_RSL_IPA_MDCX_ACK(g_chan_nr, ?, ?, ?, rtp_pt2),
2335 "IPA MDCX ACK");
2336 f_rsl_transceive(ts_RSL_IPA_DLCX(g_chan_nr, fake_conn_id), tr_RSL_IPA_DLCX_ACK(g_chan_nr, ?, ?),
2337 "IPA DLCX ACK");
2338}
2339testcase TC_ipa_crcx_mdcx_dlcx_not_active() runs on test_CT {
2340 var ConnHdlrPars pars := valueof(t_Pars(t_RslChanNr_Bm(1), ts_RSL_ChanMode_SIGN));
2341 f_init(testcasename());
2342 var ConnHdlr vc_conn := f_start_handler(refers(f_TC_ipa_crcx_mdcx_dlcx_not_active), pars);
2343 vc_conn.done;
2344}
2345
Harald Welte3ae11da2018-02-25 13:36:06 +01002346/* Sequence of CRCX, 2x MDCX, DLCX */
2347function f_TC_ipa_crcx_mdcx_mdcx_dlcx_not_active(charstring id) runs on ConnHdlr {
2348 f_rsl_transceive(ts_RSL_IPA_CRCX(g_chan_nr), tr_RSL_IPA_CRCX_ACK(g_chan_nr, ?, ?, ?),
2349 "IPA CRCX ACK");
2350 var uint32_t remote_ip := f_rnd_int(c_UINT32_MAX);
2351 var uint16_t remote_port := f_rnd_int(c_UINT16_MAX);
2352 var uint7_t rtp_pt2 := f_rnd_int(127);
2353 var uint16_t fake_conn_id := 23; /* we're too lazy to read it out from the CRCX ACK above */
2354 f_rsl_transceive(ts_RSL_IPA_MDCX(g_chan_nr, fake_conn_id, remote_ip, remote_port, rtp_pt2),
2355 tr_RSL_IPA_MDCX_ACK(g_chan_nr, ?, ?, ?, rtp_pt2),
2356 "IPA MDCX ACK");
2357 /* Second MDCX */
2358 remote_ip := f_rnd_int(c_UINT32_MAX);
2359 remote_port := f_rnd_int(c_UINT16_MAX);
2360 f_rsl_transceive(ts_RSL_IPA_MDCX(g_chan_nr, fake_conn_id, remote_ip, remote_port, rtp_pt2),
2361 tr_RSL_IPA_MDCX_ACK(g_chan_nr, ?, ?, ?, rtp_pt2),
2362 "IPA MDCX ACK");
2363 f_rsl_transceive(ts_RSL_IPA_DLCX(g_chan_nr, fake_conn_id), tr_RSL_IPA_DLCX_ACK(g_chan_nr, ?, ?),
2364 "IPA DLCX ACK");
2365}
2366testcase TC_ipa_crcx_mdcx_mdcx_dlcx_not_active() runs on test_CT {
2367 var ConnHdlrPars pars := valueof(t_Pars(t_RslChanNr_Bm(1), ts_RSL_ChanMode_SIGN));
2368 f_init(testcasename());
2369 var ConnHdlr vc_conn := f_start_handler(refers(f_TC_ipa_crcx_mdcx_mdcx_dlcx_not_active), pars);
2370 vc_conn.done;
2371}
2372
Harald Welte9912eb52018-02-25 13:30:15 +01002373/* IPA CRCX on SDCCH/4 and SDCCH/8 (doesn't make sense) */
2374function f_TC_ipa_crcx_sdcch_not_active(charstring id) runs on ConnHdlr {
2375 f_rsl_transceive(ts_RSL_IPA_CRCX(g_chan_nr), tr_RSL_IPA_CRCX_NACK(g_chan_nr, ?),
2376 "IPA CRCX NACK");
2377}
2378testcase TC_ipa_crcx_sdcch_not_active() runs on test_CT {
2379 var ConnHdlrPars pars;
2380 var ConnHdlr vc_conn;
2381 f_init(testcasename());
2382
2383 pars := valueof(t_Pars(t_RslChanNr_SDCCH4(0,1), ts_RSL_ChanMode_SIGN));
2384 vc_conn := f_start_handler(refers(f_TC_ipa_crcx_sdcch_not_active), pars);
2385 vc_conn.done;
2386
2387 pars := valueof(t_Pars(t_RslChanNr_SDCCH8(6,5), ts_RSL_ChanMode_SIGN));
2388 vc_conn := f_start_handler(refers(f_TC_ipa_crcx_sdcch_not_active), pars);
2389 vc_conn.done;
2390}
2391
Harald Weltea3f1df92018-02-25 12:49:55 +01002392
Harald Welte883340c2018-02-28 18:59:29 +01002393/***********************************************************************
2394 * PCU Socket related tests
2395 ***********************************************************************/
2396
2397private function f_TC_pcu_act_req(uint8_t bts_nr, uint8_t trx_nr, uint8_t ts_nr, boolean exp_success)
2398runs on test_CT {
2399 timer T := 3.0;
2400
2401 /* we don't expect any RTS.req before PDCH are active */
2402 T.start;
2403 alt {
2404 [] PCU.receive(t_SD_PCUIF(g_pcu_conn_id, tr_PCUIF_RTS_REQ(bts_nr))) {
2405 setverdict(fail, "PCU RTS.req before PDCH active?");
2406 self.stop;
2407 }
2408 [] PCU.receive { repeat; }
2409 [] T.timeout { }
2410 }
2411
2412 /* Send PDCH activate request for known PDCH timeslot */
2413 PCU.send(t_SD_PCUIF(g_pcu_conn_id, ts_PCUIF_ACT_REQ(bts_nr, trx_nr, ts_nr)));
2414
2415 /* we now expect RTS.req for this timeslot (only) */
2416 T.start;
2417 alt {
2418 [exp_success] PCU.receive(t_SD_PCUIF(g_pcu_conn_id, tr_PCUIF_RTS_REQ(bts_nr, trx_nr, ts_nr))) {
2419 setverdict(pass);
2420 }
2421 [not exp_success] PCU.receive(t_SD_PCUIF(g_pcu_conn_id,
2422 tr_PCUIF_RTS_REQ(bts_nr, trx_nr, ts_nr))) {
2423 setverdict(fail, "Unexpected RTS.req for supposedly failing activation");
2424 self.stop;
2425 }
2426 [] PCU.receive(t_SD_PCUIF(g_pcu_conn_id, tr_PCUIF_RTS_REQ)) {
2427 setverdict(fail, "RTS.req for wrong TRX/TS");
2428 self.stop;
2429 }
2430 [] PCU.receive { repeat; }
2431 [exp_success] T.timeout {
2432 setverdict(fail, "Timeout waiting for PCU RTS.req");
2433 }
2434 [not exp_success] T.timeout {
2435 setverdict(pass);
2436 }
2437 }
2438}
2439
2440private function f_TC_pcu_deact_req(uint8_t bts_nr, uint8_t trx_nr, uint8_t ts_nr)
2441runs on test_CT {
2442 timer T := 3.0;
2443
2444 /* Send PDCH activate request for known PDCH timeslot */
2445 PCU.send(t_SD_PCUIF(g_pcu_conn_id, ts_PCUIF_DEACT_REQ(bts_nr, trx_nr, ts_nr)));
2446
2447 PCU.clear;
2448 /* we now expect no RTS.req for this timeslot */
2449 T.start;
2450 alt {
2451 [] PCU.receive(t_SD_PCUIF(g_pcu_conn_id, tr_PCUIF_RTS_REQ(bts_nr, trx_nr, ts_nr))) {
2452 setverdict(fail, "Received unexpected PCU RTS.req");
2453 self.stop;
2454 }
2455 [] PCU.receive { repeat; }
2456 [] T.timeout {
2457 setverdict(pass);
2458 }
2459 }
2460}
2461
2462/* PDCH activation via PCU socket; check for presence of RTS.req */
2463testcase TC_pcu_act_req() runs on test_CT {
2464 f_init();
2465 f_TC_pcu_act_req(0, 0, 7, true);
2466}
2467
2468/* PDCH activation via PCU socket on non-PDCU timeslot */
2469testcase TC_pcu_act_req_wrong_ts() runs on test_CT {
2470 f_init();
2471 f_TC_pcu_act_req(0, 0, 1, false);
2472}
2473
2474/* PDCH activation via PCU socket on wrong BTS */
2475testcase TC_pcu_act_req_wrong_bts() runs on test_CT {
2476 f_init();
2477 f_TC_pcu_act_req(23, 0, 7, false);
2478}
2479
2480/* PDCH activation via PCU socket on wrong TRX */
2481testcase TC_pcu_act_req_wrong_trx() runs on test_CT {
2482 f_init();
2483 f_TC_pcu_act_req(0, 23, 7, false);
2484}
2485
2486/* PDCH deactivation via PCU socket; check for absence of RTS.req */
2487testcase TC_pcu_deact_req() runs on test_CT {
2488 f_init();
2489 /* Activate PDCH */
2490 f_TC_pcu_act_req(0, 0, 7, true);
2491 f_sleep(1.0);
2492 /* and De-Activate again */
2493 f_TC_pcu_deact_req(0, 0, 7);
2494}
2495
2496/* Attempt to deactivate a PDCH on a non-PDCH timeslot */
2497testcase TC_pcu_deact_req_wrong_ts() runs on test_CT {
2498 f_init();
2499 f_TC_pcu_deact_req(0, 0, 1);
2500}
2501
2502/* Test the PCU->BTS Version and BTS->PCU SI13 handshake */
2503testcase TC_pcu_ver_si13() runs on test_CT {
2504 const octetstring si13 := '00010203040506070909'O;
2505 var PCUIF_send_data sd;
2506 timer T:= 3.0;
2507 f_init();
2508
2509 /* Set SI13 via RSL */
2510 f_rsl_bcch_fill_raw(RSL_SYSTEM_INFO_13, si13);
2511 PCU.send(t_SD_PCUIF(g_pcu_conn_id, ts_PCUIF_TXT_IND(0, PCU_VERSION, "BTS_Test v23")));
2512 T.start;
2513 alt {
2514 [] PCU.receive(t_SD_PCUIF(g_pcu_conn_id, tr_PCUIF_DATA_IND(0, 0, 0, ?, PCU_IF_SAPI_BCCH))) -> value sd {
2515 if (substr(sd.data.u.data_ind.data, 0, lengthof(si13)) == si13) {
2516 setverdict(pass);
2517 } else {
2518 repeat;
2519 }
2520 }
2521 [] PCU.receive { repeat; }
2522 [] T.timeout {
2523 setverdict(fail, "Timeout waiting for SI13");
2524 self.stop;
2525 }
2526 }
2527}
2528
2529private const octetstring c_PCU_DATA := '000102030405060708090a0b0c0d0e0f10111213141516'O;
2530
2531/* helper function to send a PCU DATA.req */
2532private function f_pcu_data_req(uint8_t bts_nr, uint8_t trx_nr, uint8_t ts_nr,
2533 uint8_t block_nr, uint32_t fn, PCUIF_Sapi sapi, octetstring data)
2534runs on test_CT
2535{
2536 PCU.send(t_SD_PCUIF(g_pcu_conn_id,
2537 ts_PCUIF_DATA_REQ(bts_nr, trx_nr, ts_nr, block_nr, fn, sapi, data)));
2538}
2539
2540/* helper function to wait for RTS.ind for given SAPI on given BTS/TRX/TS and then send */
2541private function f_pcu_wait_rts_and_data_req(uint8_t bts_nr, uint8_t trx_nr, uint8_t ts_nr,
2542 PCUIF_Sapi sapi, octetstring data)
2543runs on test_CT
2544{
2545 var PCUIF_send_data sd;
2546
2547 timer T := 3.0;
2548 T.start;
2549 alt {
2550 [] PCU.receive(t_SD_PCUIF(g_pcu_conn_id,
2551 tr_PCUIF_RTS_REQ(bts_nr, trx_nr, ts_nr, sapi))) -> value sd {
2552 f_pcu_data_req(bts_nr, trx_nr, ts_nr, sd.data.u.rts_req.block_nr,
2553 sd.data.u.rts_req.fn, sapi, data);
2554 }
2555 [] PCU.receive { repeat; }
2556 [] T.timeout {
2557 setverdict(fail, "Timeout waiting for RTS.ind");
2558 }
2559 }
2560}
2561
2562/* Send DATA.req on invalid BTS */
2563testcase TC_pcu_data_req_wrong_bts() runs on test_CT {
2564 f_init();
2565 f_TC_pcu_act_req(0, 0, 7, true);
2566 f_pcu_data_req(23, 0, 7, 0, 0, PCU_IF_SAPI_PDTCH, c_PCU_DATA);
2567 /* FIXME: how to check this wasn't actually sent and didn't crash BTS? */
2568 f_sleep(10.0);
2569}
2570
2571/* Send DATA.req on invalid TRX */
2572testcase TC_pcu_data_req_wrong_trx() runs on test_CT {
2573 f_init();
2574 f_TC_pcu_act_req(0, 0, 7, true);
2575 f_pcu_data_req(0, 100, 7, 0, 0, PCU_IF_SAPI_PDTCH, c_PCU_DATA);
2576 /* FIXME: how to check this wasn't actually sent and didn't crash BTS? */
2577 f_sleep(10.0);
2578}
2579
2580/* Send DATA.req on invalid timeslot */
2581testcase TC_pcu_data_req_wrong_ts() runs on test_CT {
2582 f_init();
2583 f_TC_pcu_act_req(0, 0, 7, true);
2584 f_pcu_data_req(0, 0, 70, 0, 0, PCU_IF_SAPI_PDTCH, c_PCU_DATA);
2585 /* FIXME: how to check this wasn't actually sent and didn't crash BTS? */
2586 f_sleep(10.0);
2587}
2588
2589/* Send DATA.req on timeslot that hasn't been activated */
2590testcase TC_pcu_data_req_ts_inactive() runs on test_CT {
2591 f_init();
2592 f_pcu_data_req(0, 0, 7, 0, 0, PCU_IF_SAPI_PDTCH, c_PCU_DATA);
2593 /* FIXME: how to check this wasn't actually sent and didn't crash BTS? */
2594 f_sleep(2.0);
2595}
2596
2597testcase TC_pcu_data_req_pdtch() runs on test_CT {
2598 f_init();
2599 f_TC_pcu_act_req(0, 0, 7, true);
2600 f_pcu_wait_rts_and_data_req(0, 0, 7, PCU_IF_SAPI_PDTCH, c_PCU_DATA);
2601 /* FIXME: how to check this was actually sent */
2602 f_sleep(2.0);
2603}
2604
2605testcase TC_pcu_data_req_ptcch() runs on test_CT {
2606 f_init();
2607 f_TC_pcu_act_req(0, 0, 7, true);
2608 f_pcu_wait_rts_and_data_req(0, 0, 7, PCU_IF_SAPI_PTCCH, c_PCU_DATA);
2609 /* FIXME: how to check this was actually sent */
2610 f_sleep(2.0);
2611}
2612
2613/* Send AGCH from PCU; check it appears on Um side */
2614testcase TC_pcu_data_req_agch() runs on test_CT {
2615 timer T := 3.0;
2616 f_init();
2617 f_init_l1ctl();
2618 f_l1_tune(L1CTL);
2619
2620 f_TC_pcu_act_req(0, 0, 7, true);
2621 f_pcu_data_req(0, 0, 7, 0, 0, PCU_IF_SAPI_AGCH, c_PCU_DATA);
2622
2623 T.start;
2624 alt {
Harald Weltef8df4cb2018-03-10 15:15:08 +01002625 [] L1CTL.receive(tr_L1CTL_DATA_IND(t_RslChanNr_PCH_AGCH(0), ?, c_PCU_DATA)) {
Harald Welte883340c2018-02-28 18:59:29 +01002626 setverdict(pass);
2627 }
2628 [] L1CTL.receive { repeat; }
2629 [] T.timeout {
2630 setverdict(fail, "Timeout waiting for PCU-originated AGCH block on Um");
2631 }
2632 }
2633}
2634
2635/* Send IMM.ASS from PCU for PCH; check it appears on Um side */
2636testcase TC_pcu_data_req_imm_ass_pch() runs on test_CT {
2637 var octetstring imm_ass := f_rnd_octstring(23);
2638 f_init();
2639 f_init_l1ctl();
2640 f_l1_tune(L1CTL);
2641
2642 /* append 3 last imsi digits so BTS can compute pagng group */
2643 var uint32_t fn := f_PCUIF_tx_imm_ass_pch(PCU, g_pcu_conn_id, imm_ass, '123459987'H);
2644
2645 timer T := 0.5;
2646 T.start;
2647 alt {
Harald Weltef8df4cb2018-03-10 15:15:08 +01002648 [] L1CTL.receive(tr_L1CTL_DATA_IND(t_RslChanNr_PCH_AGCH(0), ?, imm_ass)) {
Harald Welte883340c2018-02-28 18:59:29 +01002649 /* TODO: verify paging group */
2650 setverdict(pass);
2651 }
2652 [] L1CTL.receive { repeat; }
2653 [] T.timeout {
2654 setverdict(fail, "Timeout waiting for PCU-originated AGCH block on Um");
2655 }
2656 }
2657}
2658
2659/* Send RACH from Um side, expect it to show up on PCU socket */
2660testcase TC_pcu_rach_content() runs on test_CT {
2661 f_init();
2662 f_init_l1ctl();
2663 f_l1_tune(L1CTL);
2664
2665 var GsmFrameNumber fn_last := 0;
2666 for (var integer i := 0; i < 1000; i := i+1) {
2667 var OCT1 ra := f_rnd_ra_ps();
2668 var GsmFrameNumber fn := f_L1CTL_RACH(L1CTL, oct2int(ra));
2669 if (fn == fn_last) {
2670 setverdict(fail, "Two RACH in same FN?!?");
2671 self.stop;
2672 }
2673 fn_last := fn;
2674
2675 timer T := 2.0;
2676 T.start;
2677 alt {
2678 [] PCU.receive(t_SD_PCUIF(g_pcu_conn_id, tr_PCUIF_RACH_IND(0, oct2int(ra), 0, ?, fn))) {
2679 T.stop;
2680 }
2681 [] PCU.receive(t_SD_PCUIF(g_pcu_conn_id, tr_PCUIF_RACH_IND)) {
2682 setverdict(fail, "Unexpected RACH IND");
2683 self.stop;
2684 }
2685 [] PCU.receive { repeat; }
2686 [] T.timeout {
2687 setverdict(fail, "Timeout waiting for RACH IND");
2688 self.stop;
2689 }
2690 }
2691 }
2692 setverdict(pass);
2693}
2694
2695private function f_pad_oct(octetstring str, integer len, OCT1 pad) return octetstring {
2696 var integer strlen := lengthof(str);
2697 for (var integer i := 0; i < len-strlen; i := i+1) {
2698 str := str & pad;
2699 }
2700 return str;
2701}
2702
2703/* Send PAGING via RSL, expect it to shw up on PCU socket */
2704testcase TC_pcu_paging_from_rsl() runs on test_CT {
2705 f_init();
2706
2707 for (var integer i := 0; i < 100; i := i+1) {
2708 var MobileL3_CommonIE_Types.MobileIdentityLV mi;
2709 timer T := 3.0;
2710 if (i < 50) {
2711 mi := valueof(ts_MI_TMSI_LV(f_rnd_octstring(4)));
2712 } else {
2713 mi := valueof(ts_MI_IMSI_LV(f_gen_imsi(i)));
2714 }
2715 var octetstring mi_enc_lv := enc_MobileIdentityLV(mi);
2716 var octetstring mi_enc := substr(mi_enc_lv, 1, lengthof(mi_enc_lv)-1);
2717 var octetstring t_mi_lv := f_pad_oct(mi_enc_lv, 9, '00'O);
2718
2719 /* Send RSL PAGING COMMAND */
2720 RSL_CCHAN.send(ts_RSL_UD(ts_RSL_PAGING_CMD(mi_enc, i mod 4)));
2721 T.start;
2722 alt {
2723 [] PCU.receive(t_SD_PCUIF(g_pcu_conn_id, tr_PCUIF_PAG_REQ(0, t_mi_lv))) {
2724 }
2725 [] PCU.receive(t_SD_PCUIF(g_pcu_conn_id, tr_PCUIF_PAG_REQ)) {
2726 setverdict(fail, "Unexpected PAGING REQ");
2727 self.stop;
2728 }
2729 [] PCU.receive { repeat; }
2730 [] T.timeout {
2731 setverdict(fail, "Timeout waiting for PAGING REQ");
2732 self.stop;
2733 }
2734 }
2735 }
2736 setverdict(pass);
2737}
2738
Harald Welte3d04ae62018-04-04 20:29:05 +02002739/***********************************************************************
Harald Welte9bbbfb52018-04-05 09:33:19 +02002740 * Osmocom Style Dynamic Timeslot Support
Harald Welte3d04ae62018-04-04 20:29:05 +02002741 ***********************************************************************/
2742
2743private function f_dyn_osmo_pdch_act(integer pcu_conn_id, integer bts_nr, integer trx_nr)
2744runs on ConnHdlr {
2745 var PCUIF_send_data sd;
2746 /* Expect BTS to immediately acknowledge activation as PDCH */
2747 PCU.clear;
2748 f_rsl_chan_act(g_pars.chan_mode);
2749 /* expect INFO_IND on PCU interface listing TS as PDCH */
2750 alt {
2751 [] PCU.receive(t_SD_PCUIF(pcu_conn_id, tr_PCUIF_INFO_IND(bts_nr, ?))) -> value sd {
2752 if (substr(sd.data.u.info_ind.trx[trx_nr].pdch_mask, g_chan_nr.tn, 1) != '1'B) {
2753 setverdict(fail, "PCUIF_INFO_IND PDCH_MASK not '1' after PDCH ACT");
2754 self.stop;
2755 }
2756 }
2757 [] PCU.receive { repeat; }
2758 }
2759 /* try to activate this PDCH from the PCU point of view */
2760 PCU.send(t_SD_PCUIF(pcu_conn_id, ts_PCUIF_ACT_REQ(bts_nr, trx_nr, g_chan_nr.tn)));
2761 /* FIXME: is there a response? */
2762}
2763
2764private function f_dyn_osmo_pdch_deact(integer pcu_conn_id, integer bts_nr, integer trx_nr)
2765runs on ConnHdlr {
2766 var PCUIF_send_data sd;
2767 /* Send RSL CHAN REL (deactivate) */
2768 PCU.clear;
2769 RSL.send(ts_RSL_RF_CHAN_REL(g_chan_nr));
2770 /* expect BTS to ask PCU to deactivate the channel */
2771 alt {
2772 [] PCU.receive(t_SD_PCUIF(pcu_conn_id, tr_PCUIF_INFO_IND(bts_nr, ?))) -> value sd {
2773 if (substr(sd.data.u.info_ind.trx[trx_nr].pdch_mask, g_chan_nr.tn, 1) != '0'B) {
2774 setverdict(fail, "PCUIF_INFO_IND PDCH_MASK not '0' after PDCH DEACT");
2775 self.stop;
2776 }
2777 }
2778 [] PCU.receive { repeat; }
2779 }
2780 /* Emulate PCU asking BTS to deactivate PDCH */
2781 PCU.send(t_SD_PCUIF(pcu_conn_id, ts_PCUIF_DEACT_REQ(bts_nr, trx_nr, g_chan_nr.tn)));
2782 alt {
2783 [] RSL.receive(tr_RSL_RF_CHAN_REL_ACK(g_chan_nr)) {
2784 setverdict(pass);
2785 }
2786 [] RSL.receive { repeat; }
2787 }
2788}
2789
2790/* Activate Osmocom-style dynamic PDCH from BSC side */
2791function f_TC_dyn_osmo_pdch_act_deact(charstring id) runs on ConnHdlr {
2792 var PCUIF_Message first_info;
2793 var integer ts_nr := g_chan_nr.tn;
2794 var integer trx_nr := 0;
2795 var integer bts_nr := 0;
2796 var integer pcu_conn_id := -1;
2797
2798 f_init_pcu(PCU, id, pcu_conn_id, first_info);
2799
2800 f_dyn_osmo_pdch_act(pcu_conn_id, bts_nr, trx_nr);
2801 f_sleep(3.0);
2802 f_dyn_osmo_pdch_deact(pcu_conn_id, bts_nr, trx_nr);
2803 setverdict(pass);
2804}
2805testcase TC_dyn_osmo_pdch_act_deact() runs on test_CT {
2806 var ConnHdlrPars pars;
2807 var ConnHdlr vc_conn;
2808 f_init(testcasename());
2809
2810 pars := valueof(t_Pars(t_RslChanNr_PDCH(4), ts_RSL_ChanMode_SIGN));
2811 vc_conn := f_start_handler(refers(f_TC_dyn_osmo_pdch_act_deact), pars, true);
2812 vc_conn.done;
2813}
2814
2815/* send a RF CHAN REL for PDCH on an osmocom dynamci PDCH that's already inactive */
2816function f_TC_dyn_osmo_pdch_unsol_deact(charstring id) runs on ConnHdlr {
2817 var PCUIF_Message first_info;
Harald Welte3d04ae62018-04-04 20:29:05 +02002818 var integer pcu_conn_id := -1;
2819
2820 f_init_pcu(PCU, id, pcu_conn_id, first_info);
2821
Neels Hofmeyr9c50ca52018-05-08 20:37:54 +02002822 RSL.send(ts_RSL_RF_CHAN_REL(g_chan_nr));
2823 /* since the lchan is already released, we don't expect any PCU changes, just a rel ack. */
2824 RSL.receive(tr_RSL_RF_CHAN_REL_ACK(g_chan_nr));
Harald Welte3d04ae62018-04-04 20:29:05 +02002825 setverdict(pass);
2826}
2827testcase TC_dyn_osmo_pdch_unsol_deact() runs on test_CT {
2828 var ConnHdlrPars pars;
2829 var ConnHdlr vc_conn;
2830 f_init(testcasename());
2831
2832 pars := valueof(t_Pars(t_RslChanNr_PDCH(4), ts_RSL_ChanMode_SIGN));
2833 vc_conn := f_start_handler(refers(f_TC_dyn_osmo_pdch_unsol_deact), pars, true);
2834 vc_conn.done;
2835}
2836
2837/* try to RSL CHAN ACT a PDCH on an osmocom-style PDCH that's already active */
2838function f_TC_dyn_osmo_pdch_double_act(charstring id) runs on ConnHdlr {
2839 var PCUIF_Message first_info;
2840 var integer ts_nr := g_chan_nr.tn;
2841 var integer trx_nr := 0;
2842 var integer bts_nr := 0;
2843 var integer pcu_conn_id := -1;
2844
2845 f_init_pcu(PCU, id, pcu_conn_id, first_info);
2846
2847 f_dyn_osmo_pdch_act(pcu_conn_id, bts_nr, trx_nr);
Neels Hofmeyrdf936a22018-05-08 22:07:57 +02002848 /* Send a second Chan Activ and expect it to be NACKed */
2849 f_rsl_transceive(ts_RSL_CHAN_ACT(g_chan_nr, g_pars.chan_mode), tr_RSL_CHAN_ACT_NACK(g_chan_nr),
2850 "RSL CHAN ACT NACK");
Harald Welte3d04ae62018-04-04 20:29:05 +02002851 setverdict(pass);
2852}
2853testcase TC_dyn_osmo_pdch_double_act() runs on test_CT {
2854 var ConnHdlrPars pars;
2855 var ConnHdlr vc_conn;
2856 f_init(testcasename());
2857
2858 pars := valueof(t_Pars(t_RslChanNr_PDCH(4), ts_RSL_ChanMode_SIGN));
2859 vc_conn := f_start_handler(refers(f_TC_dyn_osmo_pdch_double_act), pars, true);
2860 vc_conn.done;
2861}
2862
2863/* try to RSL CHAN ACT a TCH/F on an osmocom-style PDCH */
2864function f_TC_dyn_osmo_pdch_tchf_act(charstring id) runs on ConnHdlr {
2865 var PCUIF_Message first_info;
2866 var integer ts_nr := g_chan_nr.tn;
2867 var integer trx_nr := 0;
2868 var integer bts_nr := 0;
2869 var integer pcu_conn_id := -1;
2870 var RslChannelNr chan_nr := valueof(t_RslChanNr_Bm(g_chan_nr.tn));
2871
2872 /* register for the TCH/F channel number */
2873 f_rslem_register(0, chan_nr);
2874
2875 f_init_pcu(PCU, id, pcu_conn_id, first_info);
2876
2877 f_rsl_transceive(ts_RSL_CHAN_ACT(chan_nr, g_pars.chan_mode), tr_RSL_CHAN_ACT_ACK(chan_nr),
2878 "RSL CHAN ACT");
2879 setverdict(pass);
2880}
2881testcase TC_dyn_osmo_pdch_tchf_act() runs on test_CT {
2882 var ConnHdlrPars pars;
2883 var ConnHdlr vc_conn;
2884 f_init(testcasename());
2885
2886 pars := valueof(t_Pars(t_RslChanNr_PDCH(4), ts_RSL_ChanMode_SIGN));
2887 vc_conn := f_start_handler(refers(f_TC_dyn_osmo_pdch_tchf_act), pars, true);
2888 vc_conn.done;
2889}
2890
2891/* try to RSL CHAN ACT the TCH/H on an osmocom-style PDCH */
2892function f_TC_dyn_osmo_pdch_tchh_act(charstring id) runs on ConnHdlr {
2893 var PCUIF_Message first_info;
2894 var integer ts_nr := g_chan_nr.tn;
2895 var integer trx_nr := 0;
2896 var integer bts_nr := 0;
2897 var integer pcu_conn_id := -1;
2898 var RslChannelNr chan_nr[2] := { valueof(t_RslChanNr_Lm(g_chan_nr.tn, 0)),
2899 valueof(t_RslChanNr_Lm(g_chan_nr.tn, 1)) };
2900
2901 /* register for the TCH/H channel numbers */
2902 f_rslem_register(0, chan_nr[0]);
2903 f_rslem_register(0, chan_nr[1]);
2904
2905 f_init_pcu(PCU, id, pcu_conn_id, first_info);
2906
2907 f_rsl_transceive(ts_RSL_CHAN_ACT(chan_nr[1], g_pars.chan_mode),
2908 tr_RSL_CHAN_ACT_ACK(chan_nr[1]), "RSL CHAN ACT [1]");
2909 f_rsl_transceive(ts_RSL_CHAN_ACT(chan_nr[0], g_pars.chan_mode),
2910 tr_RSL_CHAN_ACT_ACK(chan_nr[0]), "RSL CHAN ACT [0]");
2911 setverdict(pass);
2912}
2913testcase TC_dyn_osmo_pdch_tchh_act() runs on test_CT {
2914 var ConnHdlrPars pars;
2915 var ConnHdlr vc_conn;
2916 f_init(testcasename());
2917
2918 pars := valueof(t_Pars(t_RslChanNr_PDCH(4), ts_RSL_ChanMode_SIGN));
2919 vc_conn := f_start_handler(refers(f_TC_dyn_osmo_pdch_tchh_act), pars, true);
2920 vc_conn.done;
2921}
2922
Harald Welte9bbbfb52018-04-05 09:33:19 +02002923/***********************************************************************
2924 * IPA Style Dynamic Timeslot Support
2925 ***********************************************************************/
2926
2927private function f_dyn_ipa_pdch_act(integer pcu_conn_id, integer bts_nr, integer trx_nr)
2928runs on ConnHdlr {
2929 var PCUIF_send_data sd;
2930 /* Expect BTS to immediately acknowledge activation as PDCH */
2931 PCU.clear;
2932 RSL.send(ts_RSL_IPA_PDCH_ACT(g_chan_nr));
2933 /* expect INFO_IND on PCU interface listing TS as PDCH */
2934 alt {
2935 [] PCU.receive(t_SD_PCUIF(pcu_conn_id, tr_PCUIF_INFO_IND(bts_nr, ?))) -> value sd {
2936 if (substr(sd.data.u.info_ind.trx[trx_nr].pdch_mask, g_chan_nr.tn, 1) != '1'B) {
2937 setverdict(fail, "PCUIF_INFO_IND PDCH_MASK not '1' after PDCH ACT");
2938 self.stop;
2939 }
2940 }
2941 [] PCU.receive { repeat; }
2942 }
2943 /* try to activate this PDCH from the PCU point of view */
2944 PCU.send(t_SD_PCUIF(pcu_conn_id, ts_PCUIF_ACT_REQ(bts_nr, trx_nr, g_chan_nr.tn)));
2945 /* FIXME: is there a response? */
2946
2947 RSL.receive(tr_RSL_IPA_PDCH_ACT_ACK(g_chan_nr, ?));
2948}
2949
2950private function f_dyn_ipa_pdch_deact(integer pcu_conn_id, integer bts_nr, integer trx_nr)
2951runs on ConnHdlr {
2952 var PCUIF_send_data sd;
2953 /* Send RSL CHAN REL (deactivate) */
2954 RSL.send(ts_RSL_IPA_PDCH_DEACT(g_chan_nr));
2955 PCU.clear;
2956 /* expect BTS to ask PCU to deactivate the channel */
2957 alt {
2958 [] PCU.receive(t_SD_PCUIF(pcu_conn_id, tr_PCUIF_INFO_IND(bts_nr, ?))) -> value sd {
2959 if (substr(sd.data.u.info_ind.trx[trx_nr].pdch_mask, g_chan_nr.tn, 1) != '0'B) {
2960 setverdict(fail, "PCUIF_INFO_IND PDCH_MASK not '0' after PDCH DEACT");
2961 self.stop;
2962 }
2963 }
2964 [] PCU.receive { repeat; }
2965 }
2966 /* Emulate PCU asking BTS to deactivate PDCH */
2967 PCU.send(t_SD_PCUIF(pcu_conn_id, ts_PCUIF_DEACT_REQ(bts_nr, trx_nr, g_chan_nr.tn)));
2968 alt {
2969 [] RSL.receive(tr_RSL_IPA_PDCH_DEACT_ACK(g_chan_nr)) {
2970 setverdict(pass);
2971 }
2972 [] RSL.receive { repeat; }
2973 }
2974}
2975
2976/* Activate and de-activate an IPA-style dynamic TCH/F + PDCH */
2977function f_TC_dyn_ipa_pdch_act_deact(charstring id) runs on ConnHdlr {
2978 var PCUIF_Message first_info;
2979 var integer ts_nr := g_chan_nr.tn;
2980 var integer trx_nr := 0;
2981 var integer bts_nr := 0;
2982 var integer pcu_conn_id := -1;
2983
2984 f_init_pcu(PCU, id, pcu_conn_id, first_info);
2985
2986 f_dyn_ipa_pdch_act(pcu_conn_id, bts_nr, trx_nr);
2987 f_sleep(3.0);
2988 f_dyn_ipa_pdch_deact(pcu_conn_id, bts_nr, trx_nr);
2989
2990 setverdict(pass);
2991
2992}
2993testcase TC_dyn_ipa_pdch_act_deact() runs on test_CT {
2994 var ConnHdlrPars pars;
2995 var ConnHdlr vc_conn;
2996 f_init();
2997
2998 pars := valueof(t_Pars(t_RslChanNr_Bm(3), ts_RSL_ChanMode_SIGN));
2999 vc_conn := f_start_handler(refers(f_TC_dyn_ipa_pdch_act_deact), pars, true);
3000 vc_conn.done;
3001}
3002
3003/* try to RSL CHAN ACT a TCH/F on an IPA-style PDCH */
3004function f_TC_dyn_ipa_pdch_tchf_act(charstring id) runs on ConnHdlr {
3005 var PCUIF_Message first_info;
3006 var integer ts_nr := g_chan_nr.tn;
3007 var integer trx_nr := 0;
3008 var integer bts_nr := 0;
3009 var integer pcu_conn_id := -1;
3010
3011 f_init_pcu(PCU, id, pcu_conn_id, first_info);
3012
3013 f_rsl_transceive(ts_RSL_CHAN_ACT(g_chan_nr, g_pars.chan_mode), tr_RSL_CHAN_ACT_ACK(g_chan_nr),
3014 "RSL CHAN ACT");
3015 f_rsl_transceive(ts_RSL_RF_CHAN_REL(g_chan_nr), tr_RSL_RF_CHAN_REL_ACK(g_chan_nr),
3016 "RF CHAN REL", true);
3017 setverdict(pass);
3018}
3019testcase TC_dyn_ipa_pdch_tchf_act() runs on test_CT {
3020 var ConnHdlrPars pars;
3021 var ConnHdlr vc_conn;
3022 f_init(testcasename());
3023
3024 pars := valueof(t_Pars(t_RslChanNr_Bm(3), ts_RSL_ChanMode_SIGN));
3025 vc_conn := f_start_handler(refers(f_TC_dyn_ipa_pdch_tchf_act), pars, true);
3026 vc_conn.done;
3027}
3028
3029/* Activate IPA style dyn PDCH as TCH/F and then illegally try to activate it as PDCH, too */
3030function f_TC_dyn_ipa_pdch_tchf_act_pdch_act_nack(charstring id) runs on ConnHdlr {
3031 var PCUIF_Message first_info;
3032 var integer ts_nr := g_chan_nr.tn;
3033 var integer trx_nr := 0;
3034 var integer bts_nr := 0;
3035 var integer pcu_conn_id := -1;
3036
3037 f_init_pcu(PCU, id, pcu_conn_id, first_info);
3038
3039 f_rsl_transceive(ts_RSL_CHAN_ACT(g_chan_nr, g_pars.chan_mode), tr_RSL_CHAN_ACT_ACK(g_chan_nr),
3040 "RSL CHAN ACT");
3041
3042 RSL.send(ts_RSL_IPA_PDCH_ACT(g_chan_nr));
3043 alt {
3044 [] RSL.receive(tr_RSL_IPA_PDCH_ACT_NACK(g_chan_nr, ?));
3045 [] RSL.receive(tr_RSL_IPA_PDCH_ACT_ACK(g_chan_nr, ?)) {
3046 setverdict(fail, "Unexpected PDCH ACT ACK");
3047 self.stop;
3048 }
3049 [] RSL.receive { repeat; }
3050 }
3051
3052 f_rsl_transceive(ts_RSL_RF_CHAN_REL(g_chan_nr), tr_RSL_RF_CHAN_REL_ACK(g_chan_nr),
3053 "RF CHAN REL", true);
3054 setverdict(pass);
3055}
3056testcase TC_dyn_ipa_pdch_tchf_act_pdch_act_nack() runs on test_CT {
3057 var ConnHdlrPars pars;
3058 var ConnHdlr vc_conn;
3059 f_init(testcasename());
3060
3061 pars := valueof(t_Pars(t_RslChanNr_Bm(3), ts_RSL_ChanMode_SIGN));
3062 vc_conn := f_start_handler(refers(f_TC_dyn_ipa_pdch_tchf_act_pdch_act_nack), pars, true);
3063 vc_conn.done;
3064}
3065
3066/* try to RSL CHAN ACT a TCH/F on an IPA-style PDCH that's already in PDCH mode; expect NACK */
3067function f_TC_dyn_ipa_pdch_act_tchf_act_nack(charstring id) runs on ConnHdlr {
3068 var PCUIF_Message first_info;
3069 var integer ts_nr := g_chan_nr.tn;
3070 var integer trx_nr := 0;
3071 var integer bts_nr := 0;
3072 var integer pcu_conn_id := -1;
3073
3074 /* register for the TCH/F channel number */
3075 f_rslem_register(0, g_chan_nr);
3076
3077 f_init_pcu(PCU, id, pcu_conn_id, first_info);
3078
3079 f_dyn_ipa_pdch_act(pcu_conn_id, bts_nr, trx_nr);
3080
3081 f_rsl_transceive(ts_RSL_CHAN_ACT(g_chan_nr, g_pars.chan_mode), tr_RSL_CHAN_ACT_NACK(g_chan_nr),
3082 "RSL CHAN ACT");
3083
3084 f_dyn_ipa_pdch_deact(pcu_conn_id, bts_nr, trx_nr);
3085
3086 setverdict(pass);
3087}
3088testcase TC_dyn_ipa_pdch_act_tchf_act_nack() runs on test_CT {
3089 var ConnHdlrPars pars;
3090 var ConnHdlr vc_conn;
3091 f_init(testcasename());
3092
3093 pars := valueof(t_Pars(t_RslChanNr_Bm(3), ts_RSL_ChanMode_SIGN));
3094 vc_conn := f_start_handler(refers(f_TC_dyn_ipa_pdch_act_tchf_act_nack), pars, true);
3095 vc_conn.done;
3096}
3097
3098
Harald Welte0472ab42018-03-12 15:02:26 +01003099/***********************************************************************
3100 * LAPDm / RLL related
3101 ***********************************************************************/
3102
3103private function f_tx_lapdm(template (value) LapdmFrame l,
3104 template (value) RslLinkId link_id) runs on ConnHdlr {
3105 var octetstring l2 := enc_LapdmFrame(valueof(l));
3106 if (valueof(link_id.c) == SACCH) {
3107 /* prepend dummy L1 header */
3108 l2 := '0000'O & l2;
3109 }
3110 log("encoding ", l, " to ", l2);
3111 L1CTL.send(ts_L1CTL_DATA_REQ(g_chan_nr, link_id, l2));
3112}
3113
3114type record RllTestCase {
3115 uint3_t sapi,
3116 RslLinkId link_id,
3117 octetstring l3,
3118 boolean exp
3119}
3120type record of RllTestCase RllTestCases;
3121template RllTestCase t_EITC(uint3_t sapi, RslLinkId id, octetstring l3, boolean exp) := {
3122 sapi := sapi,
3123 link_id := id,
3124 l3 := l3,
3125 exp := exp
3126}
3127
3128/* execute the same callback function with a set of different parameters (tcs) on a
3129 * variety of logical channels */
3130private function f_rll_testmatrix(RllTestCases tcs, void_fn fn) runs on test_CT {
3131 var ConnHdlrPars pars;
3132 var ConnHdlr vc_conn;
3133 f_init(testcasename());
3134
3135 /* test on each of the channels we have */
3136 for (var integer i := 0; i < sizeof(g_AllChanTypes); i := i+1) {
3137 pars := valueof(t_Pars(g_AllChanTypes[i], ts_RSL_ChanMode_SIGN));
3138
3139 /* test each of the test cases on the current channel */
3140 for (var integer j := 0; j < sizeof(tcs); j := j+1) {
3141 pars.spec.rll := tcs[j];
3142 log(testcasename(), ": XXX Starting ", tcs[j] , " on ", g_AllChanTypes[i]);
3143 vc_conn := f_start_handler(fn, pars);
3144 vc_conn.done;
3145 }
3146 }
3147
3148 f_shutdown();
3149}
3150
3151/* test if SABM on Um triggers EST IND (TS 48.058 3.1) */
3152private function f_TC_rll_est_ind(charstring id) runs on ConnHdlr {
3153 var RllTestCase tc := g_pars.spec.rll;
3154 timer T := 3.0;
3155
3156 f_l1_tune(L1CTL);
3157 RSL.clear;
3158
3159 /* activate the logical channel */
3160 f_est_dchan();
3161 L1CTL.clear;
3162
3163 f_tx_lapdm(ts_LAPDm_SABM(tc.sapi, cr_MO_CMD, true, tc.l3), tc.link_id);
3164 T.start;
3165 alt {
3166 [tc.l3 != ''O] RSL.receive(tr_RSL_EST_IND(g_chan_nr, tc.link_id, tc.l3)) {
3167 if (tc.exp) {
3168 setverdict(pass);
3169 } else {
3170 setverdict(fail, "Unexpected EST IND with L3 in ", tc);
3171 }
3172 }
3173 [tc.l3 == ''O] RSL.receive(tr_RSL_EST_IND_NOL3(g_chan_nr, tc.link_id)) {
3174 if (tc.exp) {
3175 setverdict(pass);
3176 } else {
3177 setverdict(fail, "Unexpected EST IND without L3 in ", tc);
3178 }
3179 }
3180 [tc.exp] T.timeout {
3181 setverdict(fail, "Timeout waiting for EST IND");
3182 }
3183 [not tc.exp] T.timeout {
3184 setverdict(pass);
3185 }
3186 }
3187
3188 f_rsl_chan_deact();
3189 f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
3190 f_rslem_unregister(0, g_chan_nr);
3191}
3192testcase TC_rll_est_ind() runs on test_CT {
3193 var RllTestCases tcs := {
Harald Welte7aacbbf2018-05-09 16:56:41 +02003194 /* SAPI0 establishment (contention resolution) */
Harald Welte0472ab42018-03-12 15:02:26 +01003195 valueof(t_EITC(0, valueof(ts_RslLinkID_DCCH(0)), '01020304'O, true)),
Harald Welte7aacbbf2018-05-09 16:56:41 +02003196 /* normal SAPI0 establishment */
3197 valueof(t_EITC(0, valueof(ts_RslLinkID_DCCH(0)), ''O, true)),
Harald Welte0472ab42018-03-12 15:02:26 +01003198 /* SAPI 3 doesn't support contention resolution */
3199 valueof(t_EITC(3, valueof(ts_RslLinkID_DCCH(3)), '01020304'O, false)),
3200 valueof(t_EITC(3, valueof(ts_RslLinkID_SACCH(3)), '01020304'O, false)),
3201 /* normal SAPI3 establishment on main DCCH */
3202 valueof(t_EITC(3, valueof(ts_RslLinkID_DCCH(3)), ''O, true)),
3203 /* normal SAPI3 establishment on SACCH */
3204 valueof(t_EITC(3, valueof(ts_RslLinkID_SACCH(3)), ''O, true))
3205 };
3206 f_rll_testmatrix(tcs, refers(f_TC_rll_est_ind));
3207}
3208
3209/* test if RLL EST REQ trigeres SABM on Um; UA on Um triggers EST CONF (TS 48.058 3.2) */
3210private function f_TC_rll_est_req(charstring id) runs on ConnHdlr {
3211 var RllTestCase tc := g_pars.spec.rll;
3212 var L1ctlDlMessage dl;
3213 timer T := 3.0;
3214
3215 f_l1_tune(L1CTL);
3216 RSL.clear;
3217
3218 /* activate the logical channel */
3219 f_est_dchan();
3220 L1CTL.clear;
3221
3222 /* Send a RSL EST REQ for SAPI3 on main DCCH */
3223 RSL.send(ts_RSL_EST_REQ(g_chan_nr, tc.link_id));
3224 T.start;
3225 alt {
3226 [] L1CTL.receive(tr_L1CTL_DATA_IND(g_chan_nr, ?)) -> value dl {
3227 var LapdmFrame lapdm;
3228 var octetstring l2 := dl.payload.data_ind.payload;
3229 if (dl.dl_info.link_id.c == SACCH) {
3230 /* remove L1 header */
3231 l2 := substr(l2, 2, lengthof(l2)-2);
3232 }
3233 lapdm.ab := dec_LapdmFrameAB(l2);
3234 if (match(lapdm, tr_LAPDm_SABM(tc.sapi, cr_MT_CMD, true, ''O))) {
3235 setverdict(pass);
3236 } else {
3237 repeat;
3238 }
3239 }
3240 [] L1CTL.receive { repeat; }
3241 [] T.timeout {
3242 setverdict(fail, "Timeout waiting for SABM");
3243 self.stop;
3244 }
3245 }
3246
3247 f_rsl_chan_deact();
3248 f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
3249 f_rslem_unregister(0, g_chan_nr);
3250}
3251testcase TC_rll_est_req_DCCH_3() runs on test_CT {
3252 var RllTestCases tcs := {
3253 /* normal SAPI3 establishment on main DCCH */
3254 valueof(t_EITC(3, valueof(ts_RslLinkID_DCCH(3)), ''O, true))//,
3255 };
3256 f_rll_testmatrix(tcs, refers(f_TC_rll_est_req));
3257}
3258testcase TC_rll_est_req_ACCH_3() runs on test_CT {
3259 var RllTestCases tcs := {
3260 /* normal SAPI3 establishment on SACCH */
3261 valueof(t_EITC(3, valueof(ts_RslLinkID_SACCH(3)), ''O, true))
3262 }
3263 f_rll_testmatrix(tcs, refers(f_TC_rll_est_req));
3264}
3265
3266/* altstep to receive a LAPDm frame matching the given template */
3267private altstep as_l1_exp_lapdm(template LapdmFrame exp) runs on ConnHdlr {
3268 var L1ctlDlMessage dl;
3269 [] L1CTL.receive(tr_L1CTL_DATA_IND(g_chan_nr, ?)) -> value dl {
3270 var LapdmFrame lapdm;
3271 var octetstring l2 := dl.payload.data_ind.payload;
3272 if (dl.dl_info.link_id.c == SACCH) {
3273 /* remove L1 header */
3274 l2 := substr(l2, 2, lengthof(l2)-2);
3275 }
3276 if (ischosen(exp.ab)) {
3277 lapdm.ab := dec_LapdmFrameAB(l2);
3278 } else if (ischosen(exp.b4)) {
3279 lapdm.b4 := dec_LapdmFrameB4(l2);
3280 } else if (ischosen(exp.bbis)) {
3281 lapdm.bbis := dec_LapdmFrameBbis(l2);
3282 }
3283 log("Rx LAPDm ", lapdm);
3284 if (match(lapdm, exp)) {
3285 setverdict(pass);
3286 } else {
3287 repeat;
3288 }
3289 }
3290 [] L1CTL.receive { repeat; }
3291}
3292private function f_l1_exp_lapdm(template LapdmFrame exp, float t := 3.0) runs on ConnHdlr {
3293 timer T := t;
3294 T.start;
3295 alt {
3296 [] T.timeout {
3297 setverdict(fail, "Timeout waiting for LAPDm ", exp);
3298 self.stop;
3299 }
3300 [] as_l1_exp_lapdm(exp);
3301 }
3302}
3303
3304/* establish one Radio Link Layer via SABM -> UA. Use l3 for contention resolution */
3305private function f_est_rll_mo(uint3_t sapi, RslLinkId link_id, octetstring l3) runs on ConnHdlr {
3306 /* send SABM from MS -> BTS */
3307 f_tx_lapdm(ts_LAPDm_SABM(sapi, cr_MO_CMD, true, l3), link_id);
3308 /* expect RLL EST IND on Abis */
3309 alt {
3310 [l3 != ''O] RSL.receive(tr_RSL_EST_IND(g_chan_nr, link_id, l3));
3311 [l3 == ''O] RSL.receive(tr_RSL_EST_IND_NOL3(g_chan_nr, link_id));
3312 [] RSL.receive(tr_RSL_ERROR_IND(g_chan_nr, link_id, ?)) {
3313 setverdict(fail, "Failing due to RSL_ERROR_IND");
3314 self.stop;
3315 }
3316 [] RSL.receive { repeat; }
3317 }
3318 /* expect UA from BTS -> MS */
3319 f_l1_exp_lapdm(tr_LAPDm_UA(sapi, cr_MT_RSP, true, l3));
3320}
3321
3322/* test if DISC on Um triggers RLL REL IND (TS 48.058 3.3) */
3323private function f_TC_rll_rel_ind(charstring id) runs on ConnHdlr {
3324 var RllTestCase tc := g_pars.spec.rll;
3325
3326 f_l1_tune(L1CTL);
3327 RSL.clear;
3328
3329 /* activate the logical channel */
3330 f_est_dchan();
3331 L1CTL.clear;
3332
3333 /* first establish the link-layer */
3334 f_est_rll_mo(tc.sapi, tc.link_id, tc.l3);
3335
3336 /* then send the DISC */
3337 f_tx_lapdm(ts_LAPDm_DISC(tc.sapi, cr_MO_CMD, true), tc.link_id);
3338 /* ... and expect the REL IND on the RSL side */
3339 alt {
3340 [] RSL.receive(tr_RSL_REL_IND(g_chan_nr, tc.link_id)) {
3341 setverdict(pass);
3342 }
3343 }
3344
3345 /* release the channel */
3346 f_rsl_chan_deact();
3347 f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
3348 f_rslem_unregister(0, g_chan_nr);
3349}
3350testcase TC_rll_rel_ind_DCCH_0() runs on test_CT {
3351 var RllTestCases tcs := {
3352 valueof(t_EITC(0, valueof(ts_RslLinkID_DCCH(0)), '01020304'O, true))
3353 };
3354 f_rll_testmatrix(tcs, refers(f_TC_rll_rel_ind));
3355}
3356
3357testcase TC_rll_rel_ind_ACCH_0() runs on test_CT {
3358 var RllTestCases tcs := {
3359 valueof(t_EITC(0, valueof(ts_RslLinkID_SACCH(0)), ''O, true))
3360 };
3361 f_rll_testmatrix(tcs, refers(f_TC_rll_rel_ind));
3362}
3363testcase TC_rll_rel_ind_DCCH_3() runs on test_CT {
3364 var RllTestCases tcs := {
3365 valueof(t_EITC(3, valueof(ts_RslLinkID_DCCH(3)), ''O, true))
3366 };
3367 f_rll_testmatrix(tcs, refers(f_TC_rll_rel_ind));
3368}
3369testcase TC_rll_rel_ind_ACCH_3() runs on test_CT {
3370 var RllTestCases tcs := {
3371 valueof(t_EITC(3, valueof(ts_RslLinkID_SACCH(3)), ''O, true))
3372 };
3373 f_rll_testmatrix(tcs, refers(f_TC_rll_rel_ind));
3374}
3375
3376/* test if RLL REL REQ triggers DISC on Um; UA/DM triggers RLL REL CONF (TS 48.058 3.4) */
3377private function f_TC_rll_rel_req(charstring id) runs on ConnHdlr {
3378 var RllTestCase tc := g_pars.spec.rll;
3379 f_l1_tune(L1CTL);
3380 RSL.clear;
3381
3382 /* activate the logical channel */
3383 f_est_dchan();
3384 L1CTL.clear;
3385
3386 /* first establish the link-layer */
3387 f_est_rll_mo(tc.sapi, tc.link_id, tc.l3);
3388
3389 /* then send the REL REQ via RSL */
3390 RSL.send(ts_RSL_REL_REQ(g_chan_nr, tc.link_id, RSL_REL_MODE_NORMAL));
3391 /* ... and expect the DISC on the Um side */
3392 alt {
Harald Weltebc6199f2018-05-10 19:38:18 +02003393 [] as_l1_exp_lapdm(tr_LAPDm_DISC(tc.sapi, cr_MT_CMD, true)) {
Harald Welte0472ab42018-03-12 15:02:26 +01003394 /* FIXME: send a UA in resposne to the DISC */
3395 }
3396 }
3397
3398 /* release the channel */
3399 f_rsl_chan_deact();
3400 f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
3401 f_rslem_unregister(0, g_chan_nr);
3402}
3403testcase TC_rll_rel_req() runs on test_CT {
3404 var RllTestCases tcs := {
3405 valueof(t_EITC(0, valueof(ts_RslLinkID_DCCH(0)), '01020304'O, true)),
3406 valueof(t_EITC(0, valueof(ts_RslLinkID_SACCH(0)), ''O, true)),
3407 valueof(t_EITC(3, valueof(ts_RslLinkID_DCCH(3)), ''O, true)),
3408 valueof(t_EITC(3, valueof(ts_RslLinkID_SACCH(3)), ''O, true))
3409 };
3410 f_rll_testmatrix(tcs, refers(f_TC_rll_rel_req));
3411}
3412
3413/* test if RLL DATA REQ triggers I-frames on Um (TS 48.058 3.5) */
3414testcase TC_rll_data_req() runs on test_CT {
3415}
3416
3417/* test if I-frames on Um trigger RLL DATA IND (TS 48.058 3.6) */
3418testcase TC_rll_data_ind() runs on test_CT {
3419}
3420
3421/* test if RLL UNIT DATA REQ triggers UI-frame on Um (TS 48.058 3.7) */
3422private function f_TC_rll_ud_req(charstring id) runs on ConnHdlr {
3423 var RllTestCase tc := g_pars.spec.rll;
3424
3425 f_l1_tune(L1CTL);
3426 RSL.clear;
3427
3428 f_est_dchan();
3429 L1CTL.clear;
3430
3431 /* Send UNITDATA REQ on RSL side */
3432 RSL.send(ts_RSL_UNITDATA_REQ(g_chan_nr, tc.link_id, tc.l3));
3433 /* Expect it to arrive on the other side */
3434 if (tc.link_id.c == SACCH) {
Harald Weltee613f962018-04-18 22:38:16 +02003435 f_l1_exp_lapdm(tr_LAPDm_B4_UI(tc.sapi, cr_MT_CMD, tc.l3));
Harald Welte0472ab42018-03-12 15:02:26 +01003436 } else {
Harald Weltee613f962018-04-18 22:38:16 +02003437 f_l1_exp_lapdm(tr_LAPDm_UI(tc.sapi, cr_MT_CMD, tc.l3));
Harald Welte0472ab42018-03-12 15:02:26 +01003438 }
3439
3440 /* release the channel */
3441 f_rsl_chan_deact();
3442 f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
3443 f_rslem_unregister(0, g_chan_nr);
3444}
3445testcase TC_rll_unit_data_req_DCCH() runs on test_CT {
3446 var octetstring l3 := f_rnd_octstring(15);
3447 var RllTestCases tcs := {
3448 valueof(t_EITC(0, valueof(ts_RslLinkID_DCCH(0)), l3, true)),
3449 valueof(t_EITC(3, valueof(ts_RslLinkID_DCCH(3)), l3, true))
3450 };
3451 f_rll_testmatrix(tcs, refers(f_TC_rll_ud_req));
3452}
3453testcase TC_rll_unit_data_req_ACCH() runs on test_CT {
3454 var octetstring l3 := f_rnd_octstring(19);
3455 var RllTestCases tcs := {
3456 valueof(t_EITC(0, valueof(ts_RslLinkID_SACCH(0)), l3, true)),
3457 valueof(t_EITC(3, valueof(ts_RslLinkID_SACCH(3)), l3, true))
3458 };
3459 f_rll_testmatrix(tcs, refers(f_TC_rll_ud_req));
3460}
3461
3462/* test if UI-frames on Um trigger RLL UNIT DATA IND (TS 48.058 3.8) */
3463private function f_TC_rll_ud_ind(charstring id) runs on ConnHdlr {
3464 var RllTestCase tc := g_pars.spec.rll;
3465
3466 f_l1_tune(L1CTL);
3467 RSL.clear;
3468
3469 f_est_dchan();
3470 L1CTL.clear;
3471
3472 /* Send LAPDm UI frame. There is no B4 format in uplink! */
Harald Weltee613f962018-04-18 22:38:16 +02003473 f_tx_lapdm(ts_LAPDm_UI(tc.sapi, cr_MO_CMD, tc.l3), tc.link_id);
Harald Welte0472ab42018-03-12 15:02:26 +01003474 /* Expdct RLL UNITDATA IND on RSL side */
3475 alt {
3476 [] RSL.receive(tr_RSL_UNITDATA_IND(g_chan_nr, tc.link_id, tc.l3)) {
3477 setverdict(pass);
3478 }
3479 [] RSL.receive { repeat; }
3480 }
3481
3482 /* release the channel */
3483 f_rsl_chan_deact();
3484 f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
3485 f_rslem_unregister(0, g_chan_nr);
3486}
3487testcase TC_rll_unit_data_ind_DCCH() runs on test_CT {
3488 var octetstring l3 := f_rnd_octstring(15);
3489 var RllTestCases tcs := {
3490 valueof(t_EITC(0, valueof(ts_RslLinkID_DCCH(0)), l3, true)),
3491 valueof(t_EITC(3, valueof(ts_RslLinkID_DCCH(3)), l3, true))
3492 };
3493 f_rll_testmatrix(tcs, refers(f_TC_rll_ud_ind));
3494}
3495testcase TC_rll_unit_data_ind_ACCH() runs on test_CT {
3496 var octetstring l3 := f_rnd_octstring(18);
3497 var RllTestCases tcs := {
3498 valueof(t_EITC(0, valueof(ts_RslLinkID_SACCH(0)), l3, true)),
3499 valueof(t_EITC(3, valueof(ts_RslLinkID_SACCH(3)), l3, true))
3500 };
3501 f_rll_testmatrix(tcs, refers(f_TC_rll_ud_ind));
3502}
3503
Harald Weltee613f962018-04-18 22:38:16 +02003504/***********************************************************************
3505 * Encryption Related
3506 ***********************************************************************/
3507
3508/* send UNITDATA_REQ from BTS to MS and expect it to arrive */
3509function f_unitdata_mt(RslLinkId link_id, octetstring l3) runs on ConnHdlr {
3510 RSL.send(ts_RSL_UNITDATA_REQ(g_chan_nr, link_id, l3));
3511 if (link_id.c == SACCH) {
3512 f_l1_exp_lapdm(tr_LAPDm_B4_UI(link_id.sapi, cr_MT_CMD, l3));
3513 } else {
3514 f_l1_exp_lapdm(tr_LAPDm_UI(link_id.sapi, cr_MT_CMD, l3));
3515 }
3516}
3517
3518/* Send UI frame from MS and expect it to arrive as RLL UNITDATA IND on Abis */
3519function f_unitdata_mo(RslLinkId link_id, octetstring l3) runs on ConnHdlr {
3520 timer T := 3.0;
3521 f_tx_lapdm(ts_LAPDm_UI(link_id.sapi, cr_MO_CMD, l3), link_id);
3522 T.start;
3523 /* Expect RLL UNITDATA IND on RSL side */
3524 alt {
3525 [] RSL.receive(tr_RSL_UNITDATA_IND(g_chan_nr, link_id, l3)) {
3526 setverdict(pass);
3527 }
3528 [] T.timeout {
3529 setverdict(fail, "Timeout waiting for UNIT_DATA_IND");
3530 }
3531 [] RSL.receive { repeat; }
3532 }
3533}
3534
3535/* Test channel activation with A5/n right from the beginning (like in assignment + hand-over) */
3536function f_TC_chan_act_encr(charstring id) runs on ConnHdlr {
3537 f_l1_tune(L1CTL);
3538 f_est_dchan(true);
3539
3540 /* now we actually need to transmit some data both ways to check if the encryption works */
3541 var L1ctlDlMessage dl;
3542
3543 var octetstring l3 := f_rnd_octstring(16);
3544 var RslLinkId link_id := valueof(ts_RslLinkID_DCCH(0));
3545
3546 /* send UNITDATA_REQ from BTS to MS and expect it to arrive */
3547 f_unitdata_mt(link_id, l3);
3548
3549 /* Send UI frame from MS and expect it to arrive as RLL UNITDATA IND on Abis */
3550 f_unitdata_mo(link_id, l3);
3551
3552 /* release the channel */
3553 f_rsl_chan_deact();
3554 f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
3555 f_rslem_unregister(0, g_chan_nr);
3556}
3557testcase TC_chan_act_a51() runs on test_CT {
3558 var ConnHdlrPars pars := valueof(t_Pars(t_RslChanNr_Bm(1), ts_RSL_ChanMode_SIGN));
3559 pars.encr := valueof(ts_RSL_IE_EncrInfo(RSL_ALG_ID_A5_1, f_rnd_octstring(8)));
3560 f_testmatrix_each_chan(pars, refers(f_TC_chan_act_encr));
3561}
3562testcase TC_chan_act_a52() runs on test_CT {
3563 var ConnHdlrPars pars := valueof(t_Pars(t_RslChanNr_Bm(1), ts_RSL_ChanMode_SIGN));
3564 pars.encr := valueof(ts_RSL_IE_EncrInfo(RSL_ALG_ID_A5_2, f_rnd_octstring(8)));
3565 f_testmatrix_each_chan(pars, refers(f_TC_chan_act_encr));
3566}
3567testcase TC_chan_act_a53() runs on test_CT {
3568 var ConnHdlrPars pars := valueof(t_Pars(t_RslChanNr_Bm(1), ts_RSL_ChanMode_SIGN));
3569 pars.encr := valueof(ts_RSL_IE_EncrInfo(RSL_ALG_ID_A5_3, f_rnd_octstring(8)));
3570 f_testmatrix_each_chan(pars, refers(f_TC_chan_act_encr));
3571}
3572
3573
3574/* Test unencrypted channel activation followed by explicit ENCR CMD later */
3575function f_TC_encr_cmd(charstring id) runs on ConnHdlr {
3576 /* L3 payload doesn't matter, as it is passed transparently */
3577 var BIT3 l3_alg_id := f_alg_id_to_l3(g_pars.encr.alg_id);
3578 var octetstring l3 := enc_PDU_ML3_NW_MS(valueof(ts_RRM_CiphModeCmd(l3_alg_id)));
3579 var RslLinkId link_id := valueof(ts_RslLinkID_DCCH(0));
3580
3581 f_l1_tune(L1CTL);
3582
3583 /* first establish a dedicated channel in the clear */
3584 f_est_dchan(false);
3585
3586 /* Establish ABM */
3587 f_est_rll_mo(link_id.sapi, link_id, '23420815'O);
3588
3589 /* then send the RSL ENCR CMD with an actual RR CIPH MOD CMD inside */
3590 RSL.send(ts_RSL_ENCR_CMD(g_chan_nr, link_id, g_pars.encr.alg_id, g_pars.encr.key, l3));
3591 /* expect the L3 to arrive still unencrypted on the MS side */
3592 f_l1_exp_lapdm(tr_LAPDm_I(link_id.sapi, cr_MT_CMD, ?, ?, ?, l3));
3593
3594 /* configure L1 to apply ciphering */
3595 var uint8_t alg_id := f_alg_id_to_l1ctl(g_pars.encr.alg_id);
3596 f_L1CTL_CRYPTO_REQ(L1CTL, g_pars.chan_nr, alg_id, g_pars.encr.key);
3597
3598 /* send first ciphered I-frame in response */
3599 l3 := '0a0b0c0d'O;
3600 f_tx_lapdm(ts_LAPDm_I(link_id.sapi, cr_MO_CMD, true, 1, 0, l3), link_id);
3601 RSL.receive(tr_RSL_DATA_IND(g_chan_nr, link_id, l3));
3602
3603 /* now the BTS code should have detected the first properly encrypted uplink I-frame,
3604 * and hence enable encryption also on the downlink */
3605
3606 /* expect bi-directional communication work in encrypted mode */
3607 f_unitdata_mo(link_id, f_rnd_octstring(15));
3608 f_unitdata_mt(link_id, f_rnd_octstring(15));
3609
3610 /* release the channel */
3611 f_rsl_chan_deact();
3612 f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
3613 f_rslem_unregister(0, g_chan_nr);
3614}
3615testcase TC_encr_cmd_a51() runs on test_CT {
3616 var ConnHdlrPars pars := valueof(t_Pars(t_RslChanNr_Bm(1), ts_RSL_ChanMode_SIGN));
3617 pars.encr := valueof(ts_RSL_IE_EncrInfo(RSL_ALG_ID_A5_1, f_rnd_octstring(8)));
3618 f_testmatrix_each_chan(pars, refers(f_TC_encr_cmd));
3619}
3620testcase TC_encr_cmd_a52() runs on test_CT {
3621 var ConnHdlrPars pars := valueof(t_Pars(t_RslChanNr_Bm(1), ts_RSL_ChanMode_SIGN));
3622 pars.encr := valueof(ts_RSL_IE_EncrInfo(RSL_ALG_ID_A5_2, f_rnd_octstring(8)));
3623 f_testmatrix_each_chan(pars, refers(f_TC_encr_cmd));
3624}
3625testcase TC_encr_cmd_a53() runs on test_CT {
3626 var ConnHdlrPars pars := valueof(t_Pars(t_RslChanNr_Bm(1), ts_RSL_ChanMode_SIGN));
3627 pars.encr := valueof(ts_RSL_IE_EncrInfo(RSL_ALG_ID_A5_3, f_rnd_octstring(8)));
3628 f_testmatrix_each_chan(pars, refers(f_TC_encr_cmd));
3629}
3630
3631private function f_assert_lapdm(octetstring enc, template LapdmFrame exp_match, charstring name := "") {
3632 var LapdmFrame lf;
3633 var octetstring reenc;
3634
3635 /* decode the LAPDm frame */
3636 if (ischosen(exp_match.ab)) {
3637 lf.ab := dec_LapdmFrameAB(enc);
3638 } else {
3639 setverdict(fail, "unsupported frame type");
3640 self.stop;
3641 }
3642
3643 /* check if decoder result matches expectation */
3644 if (not match(lf, exp_match)) {
3645 setverdict(fail, name, ": decoded LAPDm doesn't match");
3646 } else {
3647 log(name, ": matched");
3648 setverdict(pass);
3649 }
3650
3651 /* test if re-encoded frame equals original input */
3652 reenc := enc_LapdmFrame(lf);
3653 if (enc != reenc) {
3654 setverdict(fail, name, ": re-encoded LAPDm frame doesn't match");
3655 } else {
3656 setverdict(pass);
3657 }
3658}
3659
3660testcase TC_lapdm_selftest() runs on test_CT {
3661 f_assert_lapdm('030301'O, tr_LAPDm_UI(0, true, ''O), "ui_s0_empty");
3662 f_assert_lapdm('0F0301'O, tr_LAPDm_UI(3, true, ''O), "ui_s3_empty");
3663 f_assert_lapdm('013F01'O, tr_LAPDm_SABM(0, false, true, ''O), "sabm_s0_empty");
3664 f_assert_lapdm('013F1123420815'O, tr_LAPDm_SABM(0, false, true, '23420815'O), "sabm_s0_l3");
3665 f_assert_lapdm('03E101'O, tr_LAPDm_RR(0, true, false, 7), "rr_s0_7");
3666 f_assert_lapdm('03000d063505'O, tr_LAPDm_I(0, true, false, 0, 0, '063505'O), "I/0/0");
3667 f_assert_lapdm('03e00d063505'O, tr_LAPDm_I(0, true, false, 7, 0, '063505'O), "I/7/0");
3668}
3669
Harald Welte0472ab42018-03-12 15:02:26 +01003670
3671/* test generation of RLL ERR IND based on Um errors (TS 48.058 3.9) */
3672/* protocol error as per 44.006 */
3673/* link layer failure (repetition of I-frame N200 times without ACK */
3674/* repetition of SABM or DISC N200 times without ACK */
3675/* receptiom of SABM in multi-frame established state */
3676
3677
3678
3679
Harald Welte883340c2018-02-28 18:59:29 +01003680
Harald Welte68e495b2018-02-25 00:05:57 +01003681/* TODO Areas:
3682
3683* channel activation
3684** with BS_Power / MS_Power, bypassing power control loop
3685** on primary vs. secondary TRX
Harald Welte68e495b2018-02-25 00:05:57 +01003686** with timing advance from initial activation on
3687* mode modify
3688** encryption
3689** multirate
3690* check DEACTIVATE SACCH
Harald Welte68e495b2018-02-25 00:05:57 +01003691** unsupported algorithm
3692* handover detection
3693* MS Power Control
3694* BS Power Control
3695* Physical Context
3696* SACCH info modify
Harald Welte68e495b2018-02-25 00:05:57 +01003697* CCCH Load Indication for PCH and RACH
3698* Delete Indication on AGCH overflow
3699* SMS Broadcast Req / Cmd / CBCH LOad Ind
3700* RF resource ind
Harald Welte68e495b2018-02-25 00:05:57 +01003701* error handling
3702* discriminator error
3703** type error
3704** sequence error
3705** IE duplicated?
Harald Welte883340c2018-02-28 18:59:29 +01003706* PCU interface
3707** TIME_IND from BTS->PCU
3708** DATA_IND from BTS->PCU
3709** verification of PCU-originated DATA_REQ arrival on Um/MS side
Harald Welte68e495b2018-02-25 00:05:57 +01003710
3711*/
Harald Welte70767382018-02-21 12:16:40 +01003712
3713control {
3714 execute( TC_chan_act_stress() );
3715 execute( TC_chan_act_react() );
3716 execute( TC_chan_deact_not_active() );
3717 execute( TC_chan_act_wrong_nr() );
Harald Welte629cc6b2018-03-11 17:19:05 +01003718 execute( TC_deact_sacch() );
Harald Welteea17b912018-03-11 22:29:31 +01003719 execute( TC_sacch_filling() );
3720 execute( TC_sacch_info_mod() );
Harald Welte075d84c2018-03-12 13:07:24 +01003721 execute( TC_sacch_multi() );
Harald Welte55700662018-03-12 13:15:43 +01003722 execute( TC_sacch_multi_chg() );
Harald Welte8c24c2b2018-02-26 08:31:31 +01003723 execute( TC_rach_content() );
3724 execute( TC_rach_count() );
Harald Welte54a2a2d2018-02-26 09:14:05 +01003725 execute( TC_rach_max_ta() );
Harald Welte70767382018-02-21 12:16:40 +01003726 execute( TC_meas_res_sign_tchf() );
3727 execute( TC_meas_res_sign_tchh() );
3728 execute( TC_meas_res_sign_sdcch4() );
3729 execute( TC_meas_res_sign_sdcch8() );
Harald Welte685d5982018-02-27 20:42:05 +01003730 execute( TC_meas_res_sign_tchh_toa256() );
Harald Welte70767382018-02-21 12:16:40 +01003731 execute( TC_conn_fail_crit() );
Harald Welte68e495b2018-02-25 00:05:57 +01003732 execute( TC_paging_imsi_80percent() );
3733 execute( TC_paging_tmsi_80percent() );
3734 execute( TC_paging_imsi_200percent() );
3735 execute( TC_paging_tmsi_200percent() );
Harald Welte01d982c2018-02-25 01:31:40 +01003736 execute( TC_rsl_protocol_error() );
3737 execute( TC_rsl_mand_ie_error() );
3738 execute( TC_rsl_ie_content_error() );
Harald Welte48494ca2018-02-25 16:59:50 +01003739 execute( TC_si_sched_default() );
Harald Welte0cae4552018-03-09 22:20:26 +01003740 execute( TC_si_sched_1() );
Harald Welte48494ca2018-02-25 16:59:50 +01003741 execute( TC_si_sched_2bis() );
3742 execute( TC_si_sched_2ter() );
3743 execute( TC_si_sched_2ter_2bis() );
3744 execute( TC_si_sched_2quater() );
3745 execute( TC_si_sched_13() );
3746 execute( TC_si_sched_13_2bis_2ter_2quater() );
Harald Weltea871a382018-02-25 02:03:14 +01003747 execute( TC_ipa_dlcx_not_active() );
Harald Weltea3f1df92018-02-25 12:49:55 +01003748 execute( TC_ipa_crcx_twice_not_active() );
3749 execute( TC_ipa_crcx_mdcx_dlcx_not_active() );
Harald Welte3ae11da2018-02-25 13:36:06 +01003750 execute( TC_ipa_crcx_mdcx_mdcx_dlcx_not_active() );
Harald Welte9912eb52018-02-25 13:30:15 +01003751 execute( TC_ipa_crcx_sdcch_not_active() );
Harald Welte883340c2018-02-28 18:59:29 +01003752
3753 execute( TC_pcu_act_req() );
3754 execute( TC_pcu_act_req_wrong_ts() );
3755 execute( TC_pcu_act_req_wrong_bts() );
3756 execute( TC_pcu_act_req_wrong_trx() );
3757 execute( TC_pcu_deact_req() );
3758 execute( TC_pcu_deact_req_wrong_ts() );
3759 execute( TC_pcu_ver_si13() );
3760 execute( TC_pcu_data_req_wrong_bts() );
3761 execute( TC_pcu_data_req_wrong_trx() );
3762 execute( TC_pcu_data_req_wrong_ts() );
3763 execute( TC_pcu_data_req_ts_inactive() );
3764 execute( TC_pcu_data_req_pdtch() );
3765 execute( TC_pcu_data_req_ptcch() );
3766 execute( TC_pcu_data_req_agch() );
3767 execute( TC_pcu_data_req_imm_ass_pch() );
3768 execute( TC_pcu_rach_content() );
3769 execute( TC_pcu_paging_from_rsl() );
Harald Welte3d04ae62018-04-04 20:29:05 +02003770
3771 execute( TC_dyn_osmo_pdch_act_deact() );
3772 execute( TC_dyn_osmo_pdch_unsol_deact() );
3773 execute( TC_dyn_osmo_pdch_double_act() );
3774 execute( TC_dyn_osmo_pdch_tchf_act() );
3775 execute( TC_dyn_osmo_pdch_tchh_act() );
Harald Welte9bbbfb52018-04-05 09:33:19 +02003776 execute( TC_dyn_ipa_pdch_act_deact() );
3777 execute( TC_dyn_ipa_pdch_tchf_act() );
3778 execute( TC_dyn_ipa_pdch_tchf_act_pdch_act_nack() );
3779 execute( TC_dyn_ipa_pdch_act_tchf_act_nack() );
Harald Welte0472ab42018-03-12 15:02:26 +01003780
3781 execute( TC_rll_est_ind() );
3782 execute( TC_rll_est_req_DCCH_3() );
3783 execute( TC_rll_est_req_ACCH_3() );
3784 execute( TC_rll_rel_ind_DCCH_0() );
3785 execute( TC_rll_rel_ind_DCCH_3() );
3786 execute( TC_rll_rel_ind_ACCH_0() );
3787 execute( TC_rll_rel_ind_ACCH_3() );
3788 execute( TC_rll_rel_req() );
3789 execute( TC_rll_unit_data_req_DCCH() );
3790 execute( TC_rll_unit_data_req_ACCH() );
3791 execute( TC_rll_unit_data_ind_DCCH() );
3792 execute( TC_rll_unit_data_ind_ACCH() );
Harald Weltee613f962018-04-18 22:38:16 +02003793
3794 execute( TC_chan_act_a51() );
3795 execute( TC_chan_act_a52() );
3796 execute( TC_chan_act_a53() );
3797 execute( TC_encr_cmd_a51() );
3798 execute( TC_encr_cmd_a52() );
3799 execute( TC_encr_cmd_a53() );
3800
3801 execute( TC_lapdm_selftest() );
Harald Welte70767382018-02-21 12:16:40 +01003802}
3803
3804
3805}