blob: 5f715380a5f866b68c42d9b980c425564fd55872 [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 ***********************************************************************/
Harald Weltee8d750e2018-06-10 21:41:35 +02001772const MobileAllocation c_MA_null := {
1773 len := 0,
1774 ma := ''B
1775}
Harald Welte93640c62018-02-25 16:59:33 +01001776
Harald Weltee8d750e2018-06-10 21:41:35 +02001777template (value) ChannelDescription ts_ChanDesc(template (value) RslChannelNr chan_nr, uint3_t tsc := 7,
1778 uint12_t arfcn := 871) := {
1779 chan_nr := chan_nr,
1780 tsc := tsc,
1781 h := false,
1782 arfcn := arfcn,
1783 maio_hsn := omit
1784}
1785
1786private function f_fmt_ia_stats(integer num_tx, integer num_rx, integer num_del) return charstring {
1787 return int2str(num_tx) & " sent, "
1788 & int2str(num_rx) & " received, "
1789 & int2str(num_del) & " deleted";
1790}
1791
1792private function f_TC_imm_ass(integer num_total, float sleep_s, float exp_pass) runs on test_CT {
1793 var L1ctlDlMessage l1_dl;
1794 timer T := 10.0;
1795 var integer num_tx := 0;
1796 var integer num_rx := 0;
1797 var integer num_del := 0;
1798 var charstring res_str;
1799 var float rx_ratio;
1800
Harald Welte68e495b2018-02-25 00:05:57 +01001801 f_init(testcasename());
Harald Weltee8d750e2018-06-10 21:41:35 +02001802 f_init_l1ctl();
1803 f_l1_tune(L1CTL);
1804
1805 for (var integer i := 0; i < num_total; i := i+1) {
1806 var ChannelDescription ch_desc := valueof(ts_ChanDesc(valueof(t_RslChanNr_SDCCH4(0, 0))));
1807 var GsmRrMessage ia := valueof(ts_IMM_ASS(42, i, 5, ch_desc, c_MA_null));
1808 var octetstring ia_enc := enc_GsmRrMessage(ia);
Harald Welte68e495b2018-02-25 00:05:57 +01001809 RSL_CCHAN.send(ts_RSL_UD(ts_RSL_IMM_ASSIGN(ia_enc, 0)));
Harald Weltee8d750e2018-06-10 21:41:35 +02001810 num_tx := num_tx+1;
1811 f_sleep(sleep_s);
Harald Welte68e495b2018-02-25 00:05:57 +01001812 }
1813 /* FIXME: check if imm.ass arrive on Um side */
Harald Weltee8d750e2018-06-10 21:41:35 +02001814 T.start;
1815 alt {
1816 [] RSL_CCHAN.receive(tr_RSL_UD(tr_RSL_DELETE_IND(?, 0))) {
1817 num_del := num_del+1;
1818 repeat;
1819 }
1820 [] RSL_CCHAN.receive {
1821 repeat;
1822 }
1823 [] L1CTL.receive(tr_L1CTL_DATA_IND(t_RslChanNr_PCH_AGCH(0), ?)) -> value l1_dl {
1824 /* somehow dec_SystemInformation will try to decode even non-RR as SI */
1825 var GsmRrMessage rr := dec_GsmRrMessage(l1_dl.payload.data_ind.payload);
1826 if (not match(rr, tr_IMM_ASS(42, ?, 5, ?, ?))) {
1827 /* FIXME: Why are we seeing paging requests on PCH/AGCH? */
1828 //setverdict(fail, "Unexpected IMM-ASS values on AGCH: ", rr);
1829 //self.stop;
1830 } else {
1831 num_rx := num_rx+1;
1832 }
1833 repeat;
1834 }
1835 [] L1CTL.receive { repeat; }
1836 [] T.timeout { }
1837 }
1838 res_str := f_fmt_ia_stats(num_tx, num_rx, num_del);
1839 log("AGCH test: " & res_str);
1840 if (num_rx + num_del != num_tx) {
1841 setverdict(fail, "RX + DEL != TX ?!?: " & res_str);
1842 }
1843 rx_ratio := int2float(num_rx) / int2float(num_tx);
1844 if (rx_ratio < exp_pass*0.8 or rx_ratio > exp_pass*1.2) {
1845 setverdict(fail, "RX ratio ("&float2str(rx_ratio)&") far from expected ("&float2str(exp_pass)&") " & res_str);
1846 } else {
1847 setverdict(pass);
1848 }
Harald Welte68e495b2018-02-25 00:05:57 +01001849}
1850
Harald Weltee8d750e2018-06-10 21:41:35 +02001851/* send a long burst of 1000 IMM.ASS with 20ms spacing (50 per s); expect 75% of them to be deleted */
1852testcase TC_imm_ass_1000_20ms() runs on test_CT {
1853 f_TC_imm_ass(1000, 0.02, 0.25);
1854}
1855
1856/* send a short burst of 200 IMM.ASS without any spacing; expect 95% of them to be deleted */
1857testcase TC_imm_ass_200_0ms() runs on test_CT {
1858 f_TC_imm_ass(200, 0.0, 0.05);
1859}
1860
1861/* send 150 IMM.ASS at rate of 13/s; expect none of them to be deleted */
1862testcase TC_imm_ass_200_76ms() runs on test_CT {
1863 f_TC_imm_ass(150, 0.076, 1.00);
1864}
1865
1866
1867
Harald Welte48494ca2018-02-25 16:59:50 +01001868/***********************************************************************
1869 * BCCH
1870 ***********************************************************************/
1871
1872/* tuple of Frame Number + decoded SI */
1873type record SystemInformationFn {
1874 GsmFrameNumber frame_number,
1875 SystemInformation si
1876}
1877
1878/* an arbitrary-length vector of decoded SI + gsmtap header */
1879type record of SystemInformationFn SystemInformationVector;
1880
1881/* an array of SI-vectors indexed by TC value */
1882type SystemInformationVector SystemInformationVectorPerTc[8];
1883
1884/* determine if a given SI vector contains given SI type at least once */
1885function f_si_vecslot_contains(SystemInformationVector arr, RrMessageType key, boolean bcch_ext := false) return boolean {
1886 for (var integer i:= 0; i< sizeof(arr); i := i + 1) {
1887 var integer fn_mod51 := arr[i].frame_number mod 51;
1888 if (not bcch_ext and fn_mod51 == 2 or
1889 bcch_ext and fn_mod51 == 6) {
1890 if (arr[i].si.header.message_type == key) {
1891 return true;
1892 }
1893 }
1894 }
1895 return false;
1896}
1897
1898/* ensure a given TC slot of the SI vector contains given SI type at least once at TC */
1899function f_ensure_si_vec_contains(SystemInformationVectorPerTc arr, integer tc, RrMessageType key, boolean ext_bcch := false) {
1900 if (not f_si_vecslot_contains(arr[tc], key, ext_bcch)) {
1901 setverdict(fail, "No ", key, " in TC=", tc, "!");
1902 }
1903}
1904
1905/* check if a given SI vector contains given SI type at least once on any TC */
1906function f_si_vec_contains(SystemInformationVectorPerTc arr, RrMessageType key) return boolean {
1907 for (var integer tc:= 0; tc < sizeof(arr); tc := tc + 1) {
1908 if (f_si_vecslot_contains(arr[tc], key) or
1909 f_si_vecslot_contains(arr[tc], key, true)) {
1910 return true;
1911 }
1912 }
1913 return false;
1914}
1915
1916/* determine if a given SI vector contains given SI type at least N of M times */
1917function f_si_vecslot_contains_n_of_m(SystemInformationVector arr, RrMessageType key, boolean bcch_ext := false, integer n := 1, integer m := 4) return boolean {
1918 var integer count := 0;
1919 if (sizeof(arr) < m) {
1920 setverdict(fail, "Error: Insufficient SI in array");
1921 self.stop;
1922 }
1923 for (var integer i:= 0; i < m; i := i + 1) {
1924 var integer fn_mod51 := arr[i].frame_number mod 51;
1925 if (not bcch_ext and fn_mod51 == 2 or
1926 bcch_ext and fn_mod51 == 6) {
1927 if (arr[i].si.header.message_type == key) {
1928 count := count + 1;
1929 }
1930 }
1931 }
1932 if (count >= n) {
1933 return true;
1934 } else {
1935 return false;
1936 }
1937}
1938
1939/* ensure a given TC slot of the SI vector contains given SI type at least N out of M times at TC */
1940function f_ensure_si_vec_contains_n_of_m(SystemInformationVectorPerTc arr, integer tc, RrMessageType key, boolean ext_bcch := false, integer n, integer m) {
1941 if (not f_si_vecslot_contains_n_of_m(arr[tc], key, ext_bcch, n, m)) {
1942 setverdict(fail, "Not ", n, "/", m, " of ", key, " in TC=", tc, "!");
1943 }
1944}
1945
1946/* determine if a given SI vector contains given SI type at least once */
1947function f_si_vecslot_contains_only(SystemInformationVector arr, RrMessageType key, boolean bcch_ext := false) return boolean {
1948 for (var integer i:= 0; i< sizeof(arr); i := i + 1) {
1949 var integer fn_mod51 := arr[i].frame_number mod 51;
1950 if (not bcch_ext and fn_mod51 == 2 or
1951 bcch_ext and fn_mod51 == 6) {
1952 if (arr[i].si.header.message_type != key) {
1953 return false;
1954 }
1955 }
1956 }
1957 return true;
1958}
1959
1960/* ensure a given TC slot of the SI vector contains only given SI type */
1961function f_ensure_si_vec_contains_only(SystemInformationVectorPerTc arr, integer tc, RrMessageType key, boolean ext_bcch := false) {
1962 if (not f_si_vecslot_contains_only(arr[tc], key, ext_bcch)) {
1963 setverdict(fail, "Not all ", key, " in TC=", tc, "!");
1964 }
1965}
1966
1967/* SI configuration of cell, against which we validate actual SI messages */
1968type set SystemInformationConfig {
1969 boolean bcch_extended,
1970 boolean si1_present,
1971 boolean si2bis_present,
1972 boolean si2ter_present,
1973 boolean si2quater_present,
1974 boolean si7_present,
1975 boolean si8_present,
1976 boolean si9_present,
1977 boolean si13_present,
1978 boolean si13alt_present,
1979 boolean si15_present,
1980 boolean si16_present,
1981 boolean si17_present,
1982 boolean si2n_present,
1983 boolean si21_present,
1984 boolean si22_present
1985}
1986
1987/* validate the SI scheduling according to TS 45.002 version 14.1.0 Release 14, Section 6.3.1.3 */
1988function f_validate_si_scheduling(SystemInformationConfig cfg, SystemInformationVectorPerTc si_per_tc) {
1989 var integer i;
1990 for (i := 0; i < sizeof(si_per_tc); i := i + 1) {
1991 if (sizeof(si_per_tc[i]) == 0) {
Harald Welte544565a2018-03-02 10:34:08 +01001992 setverdict(fail, "No SI messages for TC=", i);
Harald Welte48494ca2018-02-25 16:59:50 +01001993 }
1994 }
1995 if (cfg.si1_present) {
1996 /* ii) System Information Type 1 needs to be sent if frequency hopping is in use or
1997 * when the NCH is present in a cell. If the MS finds another message on BCCH Norm
1998 * when TC = 0, it can assume that System Information Type 1 is not in use. */
1999 f_ensure_si_vec_contains(si_per_tc, 0, SYSTEM_INFORMATION_TYPE_1);
2000 /* make sure *ALL* contain SI1 */
2001 f_ensure_si_vec_contains_only(si_per_tc, 0, SYSTEM_INFORMATION_TYPE_1);
2002 }
2003 f_ensure_si_vec_contains(si_per_tc, 1, SYSTEM_INFORMATION_TYPE_2);
2004 /* iii) A SI 2 message will be sent at least every time TC = 1 */
2005 f_ensure_si_vec_contains(si_per_tc, 2, SYSTEM_INFORMATION_TYPE_3);
2006 f_ensure_si_vec_contains(si_per_tc, 6, SYSTEM_INFORMATION_TYPE_3);
2007 f_ensure_si_vec_contains(si_per_tc, 3, SYSTEM_INFORMATION_TYPE_4);
2008 f_ensure_si_vec_contains(si_per_tc, 7, SYSTEM_INFORMATION_TYPE_4);
2009
2010 /* iii) System information type 2 bis or 2 ter messages are sent if needed, as determined by the
2011 * system operator. If only one of them is needed, it is sent when TC = 5. If both are
2012 * needed, 2bis is sent when TC = 5 and 2ter is sent at least once within any of 4
2013 * consecutive occurrences of TC = 4. */
2014 if (cfg.si2bis_present and not cfg.si2ter_present) {
2015 f_ensure_si_vec_contains(si_per_tc, 5, SYSTEM_INFORMATION_TYPE_2bis);
2016 } else if (cfg.si2ter_present and not cfg.si2bis_present) {
2017 f_ensure_si_vec_contains(si_per_tc, 5, SYSTEM_INFORMATION_TYPE_2ter);
2018 } else if (cfg.si2ter_present and cfg.si2bis_present) {
2019 f_ensure_si_vec_contains(si_per_tc, 5, SYSTEM_INFORMATION_TYPE_2bis);
2020 f_ensure_si_vec_contains_n_of_m(si_per_tc, 4, SYSTEM_INFORMATION_TYPE_2ter, false, 1, 4);
2021 }
2022
2023 if (cfg.si7_present or cfg.si8_present) {
2024 /* vi) Use of System Information type 7 and 8 is not always necessary. It is necessary
2025 * if System Information type 4 does not contain all information needed for cell
2026 * selection and reselection. */
2027 if (not cfg.bcch_extended) {
2028 testcase.stop("Error: SI7/SI8 require BCCH Extd.");
2029 }
2030 if (cfg.si7_present) {
2031 f_ensure_si_vec_contains(si_per_tc, 7, SYSTEM_INFORMATION_TYPE_7, true);
2032 }
2033 if (cfg.si8_present) {
2034 f_ensure_si_vec_contains(si_per_tc, 3, SYSTEM_INFORMATION_TYPE_8, true);
2035 }
2036 }
2037
2038 if (cfg.si2quater_present) {
2039 /* iii) System information type 2 quater is sent if needed, as determined by the system
2040 * operator. If sent on BCCH Norm, it shall be sent when TC = 5 if neither of 2bis
2041 * and 2ter are used, otherwise it shall be sent at least once within any of 4
2042 * consecutive occurrences of TC = 4. If sent on BCCH Ext, it is sent at least once
2043 * within any of 4 consecutive occurrences of TC = 5. */
2044 if (not (cfg.bcch_extended)) {
2045 if (not (cfg.si2bis_present or cfg.si2ter_present)) {
2046 f_ensure_si_vec_contains(si_per_tc, 5, SYSTEM_INFORMATION_TYPE_2quater);
2047 } else {
2048 f_ensure_si_vec_contains_n_of_m(si_per_tc, 4, SYSTEM_INFORMATION_TYPE_2quater, false, 1, 4);
2049 }
2050 } else {
2051 f_ensure_si_vec_contains_n_of_m(si_per_tc, 5, SYSTEM_INFORMATION_TYPE_2quater, true, 1, 4);
2052 }
2053 }
2054 if (cfg.si9_present) {
2055 /* vi) System Information type 9 is sent in those blocks with TC = 4 which are specified
2056 * in system information type 3 as defined in 3GPP TS 44.018. */
2057 f_ensure_si_vec_contains(si_per_tc, 4, SYSTEM_INFORMATION_TYPE_9); // FIXME SI3
2058 }
2059 if (cfg.si13_present) {
2060 /* vii) System Information type 13 is only related to the GPRS service. System Information
2061 * Type 13 need only be sent if GPRS support is indicated in one or more of System
2062 * Information Type 3 or 4 or 7 or 8 messages. These messages also indicate if the
2063 * message is sent on the BCCH Norm or if the message is transmitted on the BCCH Ext.
2064 * In the case that the message is sent on the BCCH Norm, it is sent at least once
2065 * within any of 4 consecutive occurrences of TC=4. */
2066 if (not cfg.bcch_extended) {
2067 log("not-bccch-extended");
2068 f_ensure_si_vec_contains_n_of_m(si_per_tc, 4, SYSTEM_INFORMATION_TYPE_13, false, 1, 4);
2069 } else {
2070 log("bccch-extended");
2071 f_ensure_si_vec_contains(si_per_tc, 0, SYSTEM_INFORMATION_TYPE_13, true);
2072 }
2073 if (f_si_vec_contains(si_per_tc, SYSTEM_INFORMATION_TYPE_13alt)) {
2074 setverdict(fail, "Cannot have SI13alt and SI13");
2075 }
2076 }
2077 if (cfg.si16_present or cfg.si17_present) {
2078 /* viii) System Information type 16 and 17 are only related to the SoLSA service. They
2079 * should not be sent in a cell where network sharing is used (see rule xv). */
2080 if (cfg.si22_present) {
2081 testcase.stop("Error: Cannot have SI16/SI17 and SI22!");
2082 }
2083 if (f_si_vec_contains(si_per_tc, SYSTEM_INFORMATION_TYPE_22)) {
2084 setverdict(fail, "Cannot have SI16/SI17 and SI22!");
2085 }
2086 if (not cfg.bcch_extended) {
2087 testcase.stop("Error: SI16/SI17 requires BCCH Extd!");
2088 }
2089 if (cfg.si16_present) {
2090 f_ensure_si_vec_contains(si_per_tc, 6, SYSTEM_INFORMATION_TYPE_16, true);
2091 }
2092 if (cfg.si17_present) {
2093 f_ensure_si_vec_contains(si_per_tc, 2, SYSTEM_INFORMATION_TYPE_17, true);
2094 }
2095 }
2096
2097 /* ix) System Information type 18 and 20 are sent in order to transmit non-GSM
2098 * broadcast information. The frequency with which they are sent is determined by the
2099 * system operator. System Information type 9 identifies the scheduling of System
2100 * Information type 18 and 20 messages. */
2101
2102 /* x) System Information Type 19 is sent if COMPACT neighbours exist. If System
2103 * Information Type 19 is present, then its scheduling shall be indicated in System
2104 * Information Type 9. */
2105
2106 if (cfg.si15_present) {
2107 /* xi) System Information Type 15 is broadcast if dynamic ARFCN mapping is used in the
2108 * PLMN. If sent on BCCH Norm, it is sent at least once within any of 4 consecutive
2109 * occurrences of TC = 4. If sent on BCCH Ext, it is sent at least once within any of
2110 * 4 consecutive occurrences of TC = 1. */
2111 if (not cfg.bcch_extended) {
2112 f_ensure_si_vec_contains_n_of_m(si_per_tc, 4, SYSTEM_INFORMATION_TYPE_15, false, 1, 4);
2113 } else {
2114 f_ensure_si_vec_contains_n_of_m(si_per_tc, 1, SYSTEM_INFORMATION_TYPE_15, true, 1, 4);
2115 }
2116 }
2117 if (cfg.si13alt_present) {
2118 /* xii) System Information type 13 alt is only related to the GERAN Iu mode. System
2119 * Information Type 13 alt need only be sent if GERAN Iu mode support is indicated in
2120 * one or more of System Information Type 3 or 4 or 7 or 8 messages and SI 13 is not
2121 * broadcast. These messages also indicate if the message is sent on the BCCH Norm or
2122 * if the message is transmitted on the BCCH Ext. In the case that the message is sent
2123 * on the BCCH Norm, it is sent at least once within any of 4 consecutive occurrences
2124 * of TC = 4. */
2125 if (cfg.si13_present) {
2126 testcase.stop("Error: Cannot have SI13alt and SI13");
2127 }
2128 if (f_si_vec_contains(si_per_tc, SYSTEM_INFORMATION_TYPE_13)) {
2129 setverdict(fail, "Cannot have SI13alt and SI13");
2130 }
2131 if (not cfg.bcch_extended) {
2132 f_ensure_si_vec_contains_n_of_m(si_per_tc, 4, SYSTEM_INFORMATION_TYPE_13alt, false, 1, 4);
2133 } else {
2134 f_ensure_si_vec_contains(si_per_tc, 0, SYSTEM_INFORMATION_TYPE_13alt, true);
2135 }
2136 }
2137 if (cfg.si2n_present) {
2138 /* xiii) System Information Type 2n is optionally sent on BCCH Norm or BCCH Ext if needed,
2139 * as determined by the system operator. In the case that the message is sent on the
2140 * BCCH Norm, it is sent at least once within any of 4 consecutive occurrences of TC =
2141 * 4. If the message is sent on BCCH Ext, it is sent at least once within any of 2
2142 * consecutive occurrences of TC = 4. */
2143 if (not cfg.bcch_extended) {
2144 f_ensure_si_vec_contains_n_of_m(si_per_tc, 4, SYSTEM_INFORMATION_TYPE_2n, false, 1, 4);
2145 } else {
2146 f_ensure_si_vec_contains_n_of_m(si_per_tc, 4, SYSTEM_INFORMATION_TYPE_2n, true, 2, 4);
2147 }
2148 }
2149 if (cfg.si21_present) {
2150 /* xiv) System Information Type 21 is optionally sent on BCCH Norm or BCCH Ext, as
2151 * determined by the system operator. If Extended Access Barring is in use in the cell
2152 * then this message is sent at least once within any of 4 consecutive occurrences of
2153 * TC = 4 regardless if it is sent on BCCH Norm or BCCH Ext. If BCCH Ext is used in a
2154 * cell then this message shall only be sent on BCCH Ext. */
2155 if (not cfg.bcch_extended) {
2156 f_ensure_si_vec_contains_n_of_m(si_per_tc, 4, SYSTEM_INFORMATION_TYPE_21, false, 1, 4);
2157 } else {
2158 f_ensure_si_vec_contains_n_of_m(si_per_tc, 4, SYSTEM_INFORMATION_TYPE_21, true, 1, 4);
2159 if (f_si_vecslot_contains(si_per_tc[4], SYSTEM_INFORMATION_TYPE_21)) {
2160 setverdict(fail, "Cannot have SI21 on BCCH Norm if BCCH Extd enabled!");
2161 }
2162 }
2163 }
2164 if (cfg.si22_present) {
2165 /* xv) System Information Type 22 is sent if network sharing is in use in the cell. It
2166 * should not be sent in a cell where SoLSA is used (see rule viii). System
2167 * Information Type 22 instances shall be sent on BCCH Ext within any occurrence of TC
2168 * =2 and TC=6. */
2169 if (cfg.si16_present or cfg.si17_present) {
2170 testcase.stop("Error: Cannot have SI16/SI17 and SI22!");
2171 }
2172 if (f_si_vec_contains(si_per_tc, SYSTEM_INFORMATION_TYPE_16) or
2173 f_si_vec_contains(si_per_tc, SYSTEM_INFORMATION_TYPE_17)) {
2174 setverdict(fail, "Cannot have SI16/SI17 and SI22!");
2175 }
2176 if (not cfg.bcch_extended) {
2177 testcase.stop("Error: SI22 requires BCCH Extd!");
2178 } else {
2179 f_ensure_si_vec_contains_only(si_per_tc, 2, SYSTEM_INFORMATION_TYPE_22, true);
2180 f_ensure_si_vec_contains_only(si_per_tc, 6, SYSTEM_INFORMATION_TYPE_22, true);
2181 }
2182 }
2183}
2184
2185/* sample Systme Information for specified duration via L1CTL */
2186function f_l1_sample_si(L1CTL_PT pt, float duration := 8.0) return SystemInformationVectorPerTc {
2187 timer T := duration;
2188 var SystemInformationVectorPerTc si_per_tc;
2189 var L1ctlDlMessage l1_dl;
2190
2191 /* initialize all per-TC vectors empty */
2192 for (var integer i:= 0; i < sizeof(si_per_tc); i := i+1) {
2193 si_per_tc[i] := {};
2194 }
2195
2196 /* flush all previous L1 queued msgs */
2197 pt.clear;
2198
2199 T.start;
2200 alt {
Harald Weltef8df4cb2018-03-10 15:15:08 +01002201 [] pt.receive(tr_L1CTL_DATA_IND(t_RslChanNr_BCCH(0), ?)) -> value l1_dl {
Harald Welte48494ca2018-02-25 16:59:50 +01002202 /* somehow dec_SystemInformation will try to decode even non-RR as SI */
2203 if (not (l1_dl.payload.data_ind.payload[1] == '06'O)) {
2204 log("Ignoring non-RR SI ", l1_dl);
2205 repeat;
2206 }
2207 var SystemInformationFn sig := {
2208 frame_number := l1_dl.dl_info.frame_nr,
2209 si := dec_SystemInformation(l1_dl.payload.data_ind.payload)
2210 }
2211 var integer tc := f_gsm_compute_tc(sig.frame_number);
2212 log("SI received at TC=", tc, ": ", sig.si);
2213 /* append to the per-TC bucket */
2214 si_per_tc[tc] := si_per_tc[tc] & { sig };
2215 repeat;
2216 }
2217 [] pt.receive { repeat; }
2218 [] T.timeout { }
2219 }
2220
2221 for (var integer i:= 0; i < sizeof(si_per_tc); i := i+1) {
2222 log(testcasename(), ": TC=", i, " has #of SI=", sizeof(si_per_tc[i]));
2223 }
2224 log("si_per_tc=", si_per_tc);
2225 return si_per_tc;
2226}
2227
2228/* helper function: Set given SI via RSL + validate scheduling.
2229 * CALLER MUST MAKE SURE TO CHANGE GLOBAL si_cfg! */
2230function f_TC_si_sched() runs on test_CT {
2231 var SystemInformationVectorPerTc si_per_tc;
2232 f_init_l1ctl();
2233 f_l1_tune(L1CTL);
2234
2235 /* Sample + Validate Scheduling */
2236 si_per_tc := f_l1_sample_si(L1CTL);
2237 f_validate_si_scheduling(si_cfg, si_per_tc);
2238
2239 setverdict(pass);
2240}
2241
2242testcase TC_si_sched_default() runs on test_CT {
2243 f_init();
Harald Welte0cae4552018-03-09 22:20:26 +01002244 /* 2+3+4 are mandatory and set in f_init() */
2245 f_TC_si_sched();
Harald Welte294b0a22018-03-10 23:26:48 +01002246 f_shutdown();
Harald Welte0cae4552018-03-09 22:20:26 +01002247}
2248
2249testcase TC_si_sched_1() runs on test_CT {
2250 f_init();
2251 si_cfg.si1_present := true;
2252 f_rsl_bcch_fill_raw(RSL_SYSTEM_INFO_1, '5506198fb38000000000000000000000000000e504002b'O);
Harald Welte48494ca2018-02-25 16:59:50 +01002253 f_TC_si_sched();
Harald Welte294b0a22018-03-10 23:26:48 +01002254 f_shutdown();
Harald Welte48494ca2018-02-25 16:59:50 +01002255}
2256
2257testcase TC_si_sched_2bis() runs on test_CT {
2258 f_init();
2259 si_cfg.si2bis_present := true;
2260 f_rsl_bcch_fill_raw(RSL_SYSTEM_INFO_2bis, '550602bfe809b3ff00000000000000000000007900002b'O);
2261 f_TC_si_sched();
Harald Welte294b0a22018-03-10 23:26:48 +01002262 f_shutdown();
Harald Welte48494ca2018-02-25 16:59:50 +01002263}
2264
2265testcase TC_si_sched_2ter() runs on test_CT {
2266 f_init();
2267 si_cfg.si2ter_present := true;
2268 f_rsl_bcch_fill_raw(RSL_SYSTEM_INFO_2ter, '010603bf66b0aa0a00000002000000000000002b2b2b2b'O);
2269 f_TC_si_sched();
Harald Welte294b0a22018-03-10 23:26:48 +01002270 f_shutdown();
Harald Welte48494ca2018-02-25 16:59:50 +01002271}
2272
2273testcase TC_si_sched_2ter_2bis() runs on test_CT {
2274 f_init();
2275 si_cfg.si2bis_present := true;
2276 f_rsl_bcch_fill_raw(RSL_SYSTEM_INFO_2bis, '550602bfe809b3ff00000000000000000000007900002b'O);
2277 si_cfg.si2ter_present := true;
2278 f_rsl_bcch_fill_raw(RSL_SYSTEM_INFO_2ter, '010603bf66b0aa0a00000002000000000000002b2b2b2b'O);
2279 f_TC_si_sched();
Harald Welte294b0a22018-03-10 23:26:48 +01002280 f_shutdown();
Harald Welte48494ca2018-02-25 16:59:50 +01002281}
2282
2283testcase TC_si_sched_2quater() runs on test_CT {
2284 f_init();
2285 si_cfg.si2quater_present := true;
2286 f_rsl_bcch_fill_raw(RSL_SYSTEM_INFO_2quater, '050607a8a0364aa698d72ff424feee0506d5e7fff02043'O);
2287 f_TC_si_sched();
Harald Welte294b0a22018-03-10 23:26:48 +01002288 f_shutdown();
Harald Welte48494ca2018-02-25 16:59:50 +01002289}
2290
2291testcase TC_si_sched_13() runs on test_CT {
2292 f_init();
2293 si_cfg.si13_present := true;
Harald Welte5618c2a2018-04-15 16:24:46 +02002294 f_rsl_bcch_fill_raw(RSL_SYSTEM_INFO_13, '0106009000185a6fc9e08410ab2b2b2b2b2b2b2b2b2b2b'O);
Harald Welte48494ca2018-02-25 16:59:50 +01002295 f_TC_si_sched();
Harald Welte294b0a22018-03-10 23:26:48 +01002296 f_shutdown();
Harald Welte48494ca2018-02-25 16:59:50 +01002297}
2298
2299testcase TC_si_sched_13_2bis_2ter_2quater() runs on test_CT {
2300 f_init();
2301 si_cfg.si2bis_present := true;
2302 f_rsl_bcch_fill_raw(RSL_SYSTEM_INFO_2bis, '550602bfe809b3ff00000000000000000000007900002b'O);
2303 si_cfg.si2ter_present := true;
2304 f_rsl_bcch_fill_raw(RSL_SYSTEM_INFO_2ter, '010603bf66b0aa0a00000002000000000000002b2b2b2b'O);
2305 si_cfg.si2quater_present := true;
2306 f_rsl_bcch_fill_raw(RSL_SYSTEM_INFO_2quater, '050607a8a0364aa698d72ff424feee0506d5e7fff02043'O);
2307 si_cfg.si13_present := true;
Harald Welte5618c2a2018-04-15 16:24:46 +02002308 f_rsl_bcch_fill_raw(RSL_SYSTEM_INFO_13, '0106009000185a6fc9e08410ab2b2b2b2b2b2b2b2b2b2b'O);
Harald Welte48494ca2018-02-25 16:59:50 +01002309 f_TC_si_sched();
Harald Welte294b0a22018-03-10 23:26:48 +01002310 f_shutdown();
Harald Welte48494ca2018-02-25 16:59:50 +01002311}
2312
2313
Harald Welte68e495b2018-02-25 00:05:57 +01002314testcase TC_bcch_info() runs on test_CT {
2315 f_init(testcasename());
2316 /* FIXME: enable / disable individual BCCH info */
2317 //ts_RSL_BCCH_INFO(si_type, info);
2318 /* expect no ERROR REPORT after either of them *
2319 /* negative test: ensure ERROR REPORT on unsupported types */
Harald Welte294b0a22018-03-10 23:26:48 +01002320 f_shutdown();
Harald Welte68e495b2018-02-25 00:05:57 +01002321}
2322
Harald Welte93640c62018-02-25 16:59:33 +01002323/***********************************************************************
2324 * Low-Level Protocol Errors / ERROR REPORT
2325 ***********************************************************************/
2326
Harald Welte01d982c2018-02-25 01:31:40 +01002327private function f_exp_err_rep(template RSL_Cause cause) runs on test_CT {
2328 timer T := 5.0;
2329 T.start;
2330 alt {
2331 [] RSL_CCHAN.receive(tr_RSL_UD(tr_RSL_ERROR_REPORT(cause))) {
2332 setverdict(pass);
2333 }
2334 [] RSL_CCHAN.receive(tr_RSL_UD(tr_RSL_ERROR_REPORT(?))) {
2335 setverdict(fail, "Wrong cause in RSL ERR REP");
2336 }
2337 [] RSL_CCHAN.receive {
2338 repeat;
2339 }
2340 [] T.timeout {
2341 setverdict(fail, "Timeout waiting for RSL ERR REP");
2342 }
2343 }
2344}
2345
2346/* Provoke a protocol error (message too short) and match on ERROR REPORT */
2347testcase TC_rsl_protocol_error() runs on test_CT {
2348 f_init(testcasename());
2349 var RSL_Message rsl := valueof(ts_RSL_BCCH_INFO(RSL_SYSTEM_INFO_1, ''O));
2350 rsl.ies := omit;
2351 RSL_CCHAN.send(ts_RSL_UD(rsl));
2352
2353 f_exp_err_rep(RSL_ERR_PROTO);
2354}
2355
2356/* Provoke a mandatory IE error and match on ERROR REPORT */
2357testcase TC_rsl_mand_ie_error() runs on test_CT {
2358 f_init(testcasename());
2359
2360 var RSL_Message rsl := valueof(ts_RSL_BCCH_INFO(RSL_SYSTEM_INFO_1, ''O));
2361 rsl.ies := { rsl.ies[0] };
2362 RSL_CCHAN.send(ts_RSL_UD(rsl));
2363
2364 f_exp_err_rep(RSL_ERR_MAND_IE_ERROR);
2365}
2366
2367/* Provoke an IE content error and match on ERROR REPORT */
2368testcase TC_rsl_ie_content_error() runs on test_CT {
2369 f_init(testcasename());
2370 var RSL_Message rsl := valueof(ts_RSL_BCCH_INFO(RSL_SYSTEM_INFO_1, ''O));
2371 rsl.ies[1].body.sysinfo_type := RSL_SYSTEM_INFO_5;
2372 RSL_CCHAN.send(ts_RSL_UD(rsl));
2373
2374 f_exp_err_rep(RSL_ERR_IE_CONTENT);
2375}
2376
Harald Welte93640c62018-02-25 16:59:33 +01002377/***********************************************************************
2378 * IPA CRCX/MDCX/DLCS media stream handling
2379 ***********************************************************************/
2380
Harald Weltea871a382018-02-25 02:03:14 +01002381/* Send IPA DLCX to inactive lchan */
2382function f_TC_ipa_dlcx_not_active(charstring id) runs on ConnHdlr {
Harald Welte1eba3742018-02-25 12:48:14 +01002383 f_rsl_transceive(ts_RSL_IPA_DLCX(g_chan_nr, 0), tr_RSL_IPA_DLCX_ACK(g_chan_nr, ?, ?),
2384 "IPA DLCX ACK");
Harald Weltea871a382018-02-25 02:03:14 +01002385}
2386testcase TC_ipa_dlcx_not_active() runs on test_CT {
2387 var ConnHdlrPars pars := valueof(t_Pars(t_RslChanNr_Bm(1), ts_RSL_ChanMode_SIGN));
2388 f_init(testcasename());
2389 var ConnHdlr vc_conn := f_start_handler(refers(f_TC_ipa_dlcx_not_active), pars);
2390 vc_conn.done;
2391}
Harald Welte68e495b2018-02-25 00:05:57 +01002392
Harald Weltea3f1df92018-02-25 12:49:55 +01002393/* Send IPA CRCX twice to inactive lchan */
2394function f_TC_ipa_crcx_twice_not_active(charstring id) runs on ConnHdlr {
2395 f_rsl_transceive(ts_RSL_IPA_CRCX(g_chan_nr), tr_RSL_IPA_CRCX_ACK(g_chan_nr, ?, ?, ?),
2396 "IPA CRCX ACK");
2397 f_rsl_transceive(ts_RSL_IPA_CRCX(g_chan_nr), tr_RSL_IPA_CRCX_NACK(g_chan_nr, RSL_ERR_RES_UNAVAIL),
2398 "IPA CRCX NACK");
2399}
2400testcase TC_ipa_crcx_twice_not_active() runs on test_CT {
2401 var ConnHdlrPars pars := valueof(t_Pars(t_RslChanNr_Bm(1), ts_RSL_ChanMode_SIGN));
2402 f_init(testcasename());
2403 var ConnHdlr vc_conn := f_start_handler(refers(f_TC_ipa_crcx_twice_not_active), pars);
2404 vc_conn.done;
2405}
2406
2407/* Regular sequence of CRCX/MDCX/DLCX */
2408function f_TC_ipa_crcx_mdcx_dlcx_not_active(charstring id) runs on ConnHdlr {
2409 f_rsl_transceive(ts_RSL_IPA_CRCX(g_chan_nr), tr_RSL_IPA_CRCX_ACK(g_chan_nr, ?, ?, ?),
2410 "IPA CRCX ACK");
2411 var uint32_t remote_ip := f_rnd_int(c_UINT32_MAX);
2412 var uint16_t remote_port := f_rnd_int(c_UINT16_MAX);
2413 var uint7_t rtp_pt2 := f_rnd_int(127);
2414 var uint16_t fake_conn_id := 23; /* we're too lazy to read it out from the CRCX ACK above */
2415 f_rsl_transceive(ts_RSL_IPA_MDCX(g_chan_nr, fake_conn_id, remote_ip, remote_port, rtp_pt2),
2416 tr_RSL_IPA_MDCX_ACK(g_chan_nr, ?, ?, ?, rtp_pt2),
2417 "IPA MDCX ACK");
2418 f_rsl_transceive(ts_RSL_IPA_DLCX(g_chan_nr, fake_conn_id), tr_RSL_IPA_DLCX_ACK(g_chan_nr, ?, ?),
2419 "IPA DLCX ACK");
2420}
2421testcase TC_ipa_crcx_mdcx_dlcx_not_active() runs on test_CT {
2422 var ConnHdlrPars pars := valueof(t_Pars(t_RslChanNr_Bm(1), ts_RSL_ChanMode_SIGN));
2423 f_init(testcasename());
2424 var ConnHdlr vc_conn := f_start_handler(refers(f_TC_ipa_crcx_mdcx_dlcx_not_active), pars);
2425 vc_conn.done;
2426}
2427
Harald Welte3ae11da2018-02-25 13:36:06 +01002428/* Sequence of CRCX, 2x MDCX, DLCX */
2429function f_TC_ipa_crcx_mdcx_mdcx_dlcx_not_active(charstring id) runs on ConnHdlr {
2430 f_rsl_transceive(ts_RSL_IPA_CRCX(g_chan_nr), tr_RSL_IPA_CRCX_ACK(g_chan_nr, ?, ?, ?),
2431 "IPA CRCX ACK");
2432 var uint32_t remote_ip := f_rnd_int(c_UINT32_MAX);
2433 var uint16_t remote_port := f_rnd_int(c_UINT16_MAX);
2434 var uint7_t rtp_pt2 := f_rnd_int(127);
2435 var uint16_t fake_conn_id := 23; /* we're too lazy to read it out from the CRCX ACK above */
2436 f_rsl_transceive(ts_RSL_IPA_MDCX(g_chan_nr, fake_conn_id, remote_ip, remote_port, rtp_pt2),
2437 tr_RSL_IPA_MDCX_ACK(g_chan_nr, ?, ?, ?, rtp_pt2),
2438 "IPA MDCX ACK");
2439 /* Second MDCX */
2440 remote_ip := f_rnd_int(c_UINT32_MAX);
2441 remote_port := f_rnd_int(c_UINT16_MAX);
2442 f_rsl_transceive(ts_RSL_IPA_MDCX(g_chan_nr, fake_conn_id, remote_ip, remote_port, rtp_pt2),
2443 tr_RSL_IPA_MDCX_ACK(g_chan_nr, ?, ?, ?, rtp_pt2),
2444 "IPA MDCX ACK");
2445 f_rsl_transceive(ts_RSL_IPA_DLCX(g_chan_nr, fake_conn_id), tr_RSL_IPA_DLCX_ACK(g_chan_nr, ?, ?),
2446 "IPA DLCX ACK");
2447}
2448testcase TC_ipa_crcx_mdcx_mdcx_dlcx_not_active() runs on test_CT {
2449 var ConnHdlrPars pars := valueof(t_Pars(t_RslChanNr_Bm(1), ts_RSL_ChanMode_SIGN));
2450 f_init(testcasename());
2451 var ConnHdlr vc_conn := f_start_handler(refers(f_TC_ipa_crcx_mdcx_mdcx_dlcx_not_active), pars);
2452 vc_conn.done;
2453}
2454
Harald Welte9912eb52018-02-25 13:30:15 +01002455/* IPA CRCX on SDCCH/4 and SDCCH/8 (doesn't make sense) */
2456function f_TC_ipa_crcx_sdcch_not_active(charstring id) runs on ConnHdlr {
2457 f_rsl_transceive(ts_RSL_IPA_CRCX(g_chan_nr), tr_RSL_IPA_CRCX_NACK(g_chan_nr, ?),
2458 "IPA CRCX NACK");
2459}
2460testcase TC_ipa_crcx_sdcch_not_active() runs on test_CT {
2461 var ConnHdlrPars pars;
2462 var ConnHdlr vc_conn;
2463 f_init(testcasename());
2464
2465 pars := valueof(t_Pars(t_RslChanNr_SDCCH4(0,1), ts_RSL_ChanMode_SIGN));
2466 vc_conn := f_start_handler(refers(f_TC_ipa_crcx_sdcch_not_active), pars);
2467 vc_conn.done;
2468
2469 pars := valueof(t_Pars(t_RslChanNr_SDCCH8(6,5), ts_RSL_ChanMode_SIGN));
2470 vc_conn := f_start_handler(refers(f_TC_ipa_crcx_sdcch_not_active), pars);
2471 vc_conn.done;
2472}
2473
Harald Weltea3f1df92018-02-25 12:49:55 +01002474
Harald Welte883340c2018-02-28 18:59:29 +01002475/***********************************************************************
2476 * PCU Socket related tests
2477 ***********************************************************************/
2478
2479private function f_TC_pcu_act_req(uint8_t bts_nr, uint8_t trx_nr, uint8_t ts_nr, boolean exp_success)
2480runs on test_CT {
2481 timer T := 3.0;
2482
2483 /* we don't expect any RTS.req before PDCH are active */
2484 T.start;
2485 alt {
2486 [] PCU.receive(t_SD_PCUIF(g_pcu_conn_id, tr_PCUIF_RTS_REQ(bts_nr))) {
2487 setverdict(fail, "PCU RTS.req before PDCH active?");
2488 self.stop;
2489 }
2490 [] PCU.receive { repeat; }
2491 [] T.timeout { }
2492 }
2493
2494 /* Send PDCH activate request for known PDCH timeslot */
2495 PCU.send(t_SD_PCUIF(g_pcu_conn_id, ts_PCUIF_ACT_REQ(bts_nr, trx_nr, ts_nr)));
2496
2497 /* we now expect RTS.req for this timeslot (only) */
2498 T.start;
2499 alt {
2500 [exp_success] PCU.receive(t_SD_PCUIF(g_pcu_conn_id, tr_PCUIF_RTS_REQ(bts_nr, trx_nr, ts_nr))) {
2501 setverdict(pass);
2502 }
2503 [not exp_success] PCU.receive(t_SD_PCUIF(g_pcu_conn_id,
2504 tr_PCUIF_RTS_REQ(bts_nr, trx_nr, ts_nr))) {
2505 setverdict(fail, "Unexpected RTS.req for supposedly failing activation");
2506 self.stop;
2507 }
2508 [] PCU.receive(t_SD_PCUIF(g_pcu_conn_id, tr_PCUIF_RTS_REQ)) {
2509 setverdict(fail, "RTS.req for wrong TRX/TS");
2510 self.stop;
2511 }
2512 [] PCU.receive { repeat; }
2513 [exp_success] T.timeout {
2514 setverdict(fail, "Timeout waiting for PCU RTS.req");
2515 }
2516 [not exp_success] T.timeout {
2517 setverdict(pass);
2518 }
2519 }
2520}
2521
2522private function f_TC_pcu_deact_req(uint8_t bts_nr, uint8_t trx_nr, uint8_t ts_nr)
2523runs on test_CT {
2524 timer T := 3.0;
2525
2526 /* Send PDCH activate request for known PDCH timeslot */
2527 PCU.send(t_SD_PCUIF(g_pcu_conn_id, ts_PCUIF_DEACT_REQ(bts_nr, trx_nr, ts_nr)));
2528
2529 PCU.clear;
2530 /* we now expect no RTS.req for this timeslot */
2531 T.start;
2532 alt {
2533 [] PCU.receive(t_SD_PCUIF(g_pcu_conn_id, tr_PCUIF_RTS_REQ(bts_nr, trx_nr, ts_nr))) {
2534 setverdict(fail, "Received unexpected PCU RTS.req");
2535 self.stop;
2536 }
2537 [] PCU.receive { repeat; }
2538 [] T.timeout {
2539 setverdict(pass);
2540 }
2541 }
2542}
2543
2544/* PDCH activation via PCU socket; check for presence of RTS.req */
2545testcase TC_pcu_act_req() runs on test_CT {
2546 f_init();
2547 f_TC_pcu_act_req(0, 0, 7, true);
2548}
2549
2550/* PDCH activation via PCU socket on non-PDCU timeslot */
2551testcase TC_pcu_act_req_wrong_ts() runs on test_CT {
2552 f_init();
2553 f_TC_pcu_act_req(0, 0, 1, false);
2554}
2555
2556/* PDCH activation via PCU socket on wrong BTS */
2557testcase TC_pcu_act_req_wrong_bts() runs on test_CT {
2558 f_init();
2559 f_TC_pcu_act_req(23, 0, 7, false);
2560}
2561
2562/* PDCH activation via PCU socket on wrong TRX */
2563testcase TC_pcu_act_req_wrong_trx() runs on test_CT {
2564 f_init();
2565 f_TC_pcu_act_req(0, 23, 7, false);
2566}
2567
2568/* PDCH deactivation via PCU socket; check for absence of RTS.req */
2569testcase TC_pcu_deact_req() runs on test_CT {
2570 f_init();
2571 /* Activate PDCH */
2572 f_TC_pcu_act_req(0, 0, 7, true);
2573 f_sleep(1.0);
2574 /* and De-Activate again */
2575 f_TC_pcu_deact_req(0, 0, 7);
2576}
2577
2578/* Attempt to deactivate a PDCH on a non-PDCH timeslot */
2579testcase TC_pcu_deact_req_wrong_ts() runs on test_CT {
2580 f_init();
2581 f_TC_pcu_deact_req(0, 0, 1);
2582}
2583
2584/* Test the PCU->BTS Version and BTS->PCU SI13 handshake */
2585testcase TC_pcu_ver_si13() runs on test_CT {
2586 const octetstring si13 := '00010203040506070909'O;
2587 var PCUIF_send_data sd;
2588 timer T:= 3.0;
2589 f_init();
2590
2591 /* Set SI13 via RSL */
2592 f_rsl_bcch_fill_raw(RSL_SYSTEM_INFO_13, si13);
2593 PCU.send(t_SD_PCUIF(g_pcu_conn_id, ts_PCUIF_TXT_IND(0, PCU_VERSION, "BTS_Test v23")));
2594 T.start;
2595 alt {
2596 [] PCU.receive(t_SD_PCUIF(g_pcu_conn_id, tr_PCUIF_DATA_IND(0, 0, 0, ?, PCU_IF_SAPI_BCCH))) -> value sd {
2597 if (substr(sd.data.u.data_ind.data, 0, lengthof(si13)) == si13) {
2598 setverdict(pass);
2599 } else {
2600 repeat;
2601 }
2602 }
2603 [] PCU.receive { repeat; }
2604 [] T.timeout {
2605 setverdict(fail, "Timeout waiting for SI13");
2606 self.stop;
2607 }
2608 }
2609}
2610
2611private const octetstring c_PCU_DATA := '000102030405060708090a0b0c0d0e0f10111213141516'O;
2612
2613/* helper function to send a PCU DATA.req */
2614private function f_pcu_data_req(uint8_t bts_nr, uint8_t trx_nr, uint8_t ts_nr,
2615 uint8_t block_nr, uint32_t fn, PCUIF_Sapi sapi, octetstring data)
2616runs on test_CT
2617{
2618 PCU.send(t_SD_PCUIF(g_pcu_conn_id,
2619 ts_PCUIF_DATA_REQ(bts_nr, trx_nr, ts_nr, block_nr, fn, sapi, data)));
2620}
2621
2622/* helper function to wait for RTS.ind for given SAPI on given BTS/TRX/TS and then send */
2623private function f_pcu_wait_rts_and_data_req(uint8_t bts_nr, uint8_t trx_nr, uint8_t ts_nr,
2624 PCUIF_Sapi sapi, octetstring data)
2625runs on test_CT
2626{
2627 var PCUIF_send_data sd;
2628
2629 timer T := 3.0;
2630 T.start;
2631 alt {
2632 [] PCU.receive(t_SD_PCUIF(g_pcu_conn_id,
2633 tr_PCUIF_RTS_REQ(bts_nr, trx_nr, ts_nr, sapi))) -> value sd {
2634 f_pcu_data_req(bts_nr, trx_nr, ts_nr, sd.data.u.rts_req.block_nr,
2635 sd.data.u.rts_req.fn, sapi, data);
2636 }
2637 [] PCU.receive { repeat; }
2638 [] T.timeout {
2639 setverdict(fail, "Timeout waiting for RTS.ind");
2640 }
2641 }
2642}
2643
2644/* Send DATA.req on invalid BTS */
2645testcase TC_pcu_data_req_wrong_bts() runs on test_CT {
2646 f_init();
2647 f_TC_pcu_act_req(0, 0, 7, true);
2648 f_pcu_data_req(23, 0, 7, 0, 0, PCU_IF_SAPI_PDTCH, c_PCU_DATA);
2649 /* FIXME: how to check this wasn't actually sent and didn't crash BTS? */
2650 f_sleep(10.0);
2651}
2652
2653/* Send DATA.req on invalid TRX */
2654testcase TC_pcu_data_req_wrong_trx() runs on test_CT {
2655 f_init();
2656 f_TC_pcu_act_req(0, 0, 7, true);
2657 f_pcu_data_req(0, 100, 7, 0, 0, PCU_IF_SAPI_PDTCH, c_PCU_DATA);
2658 /* FIXME: how to check this wasn't actually sent and didn't crash BTS? */
2659 f_sleep(10.0);
2660}
2661
2662/* Send DATA.req on invalid timeslot */
2663testcase TC_pcu_data_req_wrong_ts() runs on test_CT {
2664 f_init();
2665 f_TC_pcu_act_req(0, 0, 7, true);
2666 f_pcu_data_req(0, 0, 70, 0, 0, PCU_IF_SAPI_PDTCH, c_PCU_DATA);
2667 /* FIXME: how to check this wasn't actually sent and didn't crash BTS? */
2668 f_sleep(10.0);
2669}
2670
2671/* Send DATA.req on timeslot that hasn't been activated */
2672testcase TC_pcu_data_req_ts_inactive() runs on test_CT {
2673 f_init();
2674 f_pcu_data_req(0, 0, 7, 0, 0, PCU_IF_SAPI_PDTCH, c_PCU_DATA);
2675 /* FIXME: how to check this wasn't actually sent and didn't crash BTS? */
2676 f_sleep(2.0);
2677}
2678
2679testcase TC_pcu_data_req_pdtch() runs on test_CT {
2680 f_init();
2681 f_TC_pcu_act_req(0, 0, 7, true);
2682 f_pcu_wait_rts_and_data_req(0, 0, 7, PCU_IF_SAPI_PDTCH, c_PCU_DATA);
2683 /* FIXME: how to check this was actually sent */
2684 f_sleep(2.0);
2685}
2686
2687testcase TC_pcu_data_req_ptcch() runs on test_CT {
2688 f_init();
2689 f_TC_pcu_act_req(0, 0, 7, true);
2690 f_pcu_wait_rts_and_data_req(0, 0, 7, PCU_IF_SAPI_PTCCH, c_PCU_DATA);
2691 /* FIXME: how to check this was actually sent */
2692 f_sleep(2.0);
2693}
2694
2695/* Send AGCH from PCU; check it appears on Um side */
2696testcase TC_pcu_data_req_agch() runs on test_CT {
2697 timer T := 3.0;
2698 f_init();
2699 f_init_l1ctl();
2700 f_l1_tune(L1CTL);
2701
2702 f_TC_pcu_act_req(0, 0, 7, true);
2703 f_pcu_data_req(0, 0, 7, 0, 0, PCU_IF_SAPI_AGCH, c_PCU_DATA);
2704
2705 T.start;
2706 alt {
Harald Weltef8df4cb2018-03-10 15:15:08 +01002707 [] L1CTL.receive(tr_L1CTL_DATA_IND(t_RslChanNr_PCH_AGCH(0), ?, c_PCU_DATA)) {
Harald Welte883340c2018-02-28 18:59:29 +01002708 setverdict(pass);
2709 }
2710 [] L1CTL.receive { repeat; }
2711 [] T.timeout {
2712 setverdict(fail, "Timeout waiting for PCU-originated AGCH block on Um");
2713 }
2714 }
2715}
2716
2717/* Send IMM.ASS from PCU for PCH; check it appears on Um side */
2718testcase TC_pcu_data_req_imm_ass_pch() runs on test_CT {
2719 var octetstring imm_ass := f_rnd_octstring(23);
2720 f_init();
2721 f_init_l1ctl();
2722 f_l1_tune(L1CTL);
2723
2724 /* append 3 last imsi digits so BTS can compute pagng group */
2725 var uint32_t fn := f_PCUIF_tx_imm_ass_pch(PCU, g_pcu_conn_id, imm_ass, '123459987'H);
2726
2727 timer T := 0.5;
2728 T.start;
2729 alt {
Harald Weltef8df4cb2018-03-10 15:15:08 +01002730 [] L1CTL.receive(tr_L1CTL_DATA_IND(t_RslChanNr_PCH_AGCH(0), ?, imm_ass)) {
Harald Welte883340c2018-02-28 18:59:29 +01002731 /* TODO: verify paging group */
2732 setverdict(pass);
2733 }
2734 [] L1CTL.receive { repeat; }
2735 [] T.timeout {
2736 setverdict(fail, "Timeout waiting for PCU-originated AGCH block on Um");
2737 }
2738 }
2739}
2740
2741/* Send RACH from Um side, expect it to show up on PCU socket */
2742testcase TC_pcu_rach_content() runs on test_CT {
2743 f_init();
2744 f_init_l1ctl();
2745 f_l1_tune(L1CTL);
2746
2747 var GsmFrameNumber fn_last := 0;
2748 for (var integer i := 0; i < 1000; i := i+1) {
2749 var OCT1 ra := f_rnd_ra_ps();
2750 var GsmFrameNumber fn := f_L1CTL_RACH(L1CTL, oct2int(ra));
2751 if (fn == fn_last) {
2752 setverdict(fail, "Two RACH in same FN?!?");
2753 self.stop;
2754 }
2755 fn_last := fn;
2756
2757 timer T := 2.0;
2758 T.start;
2759 alt {
2760 [] PCU.receive(t_SD_PCUIF(g_pcu_conn_id, tr_PCUIF_RACH_IND(0, oct2int(ra), 0, ?, fn))) {
2761 T.stop;
2762 }
2763 [] PCU.receive(t_SD_PCUIF(g_pcu_conn_id, tr_PCUIF_RACH_IND)) {
2764 setverdict(fail, "Unexpected RACH IND");
2765 self.stop;
2766 }
2767 [] PCU.receive { repeat; }
2768 [] T.timeout {
2769 setverdict(fail, "Timeout waiting for RACH IND");
2770 self.stop;
2771 }
2772 }
2773 }
2774 setverdict(pass);
2775}
2776
2777private function f_pad_oct(octetstring str, integer len, OCT1 pad) return octetstring {
2778 var integer strlen := lengthof(str);
2779 for (var integer i := 0; i < len-strlen; i := i+1) {
2780 str := str & pad;
2781 }
2782 return str;
2783}
2784
2785/* Send PAGING via RSL, expect it to shw up on PCU socket */
2786testcase TC_pcu_paging_from_rsl() runs on test_CT {
2787 f_init();
2788
2789 for (var integer i := 0; i < 100; i := i+1) {
2790 var MobileL3_CommonIE_Types.MobileIdentityLV mi;
2791 timer T := 3.0;
2792 if (i < 50) {
2793 mi := valueof(ts_MI_TMSI_LV(f_rnd_octstring(4)));
2794 } else {
2795 mi := valueof(ts_MI_IMSI_LV(f_gen_imsi(i)));
2796 }
2797 var octetstring mi_enc_lv := enc_MobileIdentityLV(mi);
2798 var octetstring mi_enc := substr(mi_enc_lv, 1, lengthof(mi_enc_lv)-1);
2799 var octetstring t_mi_lv := f_pad_oct(mi_enc_lv, 9, '00'O);
2800
2801 /* Send RSL PAGING COMMAND */
2802 RSL_CCHAN.send(ts_RSL_UD(ts_RSL_PAGING_CMD(mi_enc, i mod 4)));
2803 T.start;
2804 alt {
2805 [] PCU.receive(t_SD_PCUIF(g_pcu_conn_id, tr_PCUIF_PAG_REQ(0, t_mi_lv))) {
2806 }
2807 [] PCU.receive(t_SD_PCUIF(g_pcu_conn_id, tr_PCUIF_PAG_REQ)) {
2808 setverdict(fail, "Unexpected PAGING REQ");
2809 self.stop;
2810 }
2811 [] PCU.receive { repeat; }
2812 [] T.timeout {
2813 setverdict(fail, "Timeout waiting for PAGING REQ");
2814 self.stop;
2815 }
2816 }
2817 }
2818 setverdict(pass);
2819}
2820
Harald Welte3d04ae62018-04-04 20:29:05 +02002821/***********************************************************************
Harald Welte9bbbfb52018-04-05 09:33:19 +02002822 * Osmocom Style Dynamic Timeslot Support
Harald Welte3d04ae62018-04-04 20:29:05 +02002823 ***********************************************************************/
2824
2825private function f_dyn_osmo_pdch_act(integer pcu_conn_id, integer bts_nr, integer trx_nr)
2826runs on ConnHdlr {
2827 var PCUIF_send_data sd;
2828 /* Expect BTS to immediately acknowledge activation as PDCH */
2829 PCU.clear;
2830 f_rsl_chan_act(g_pars.chan_mode);
2831 /* expect INFO_IND on PCU interface listing TS as PDCH */
2832 alt {
2833 [] PCU.receive(t_SD_PCUIF(pcu_conn_id, tr_PCUIF_INFO_IND(bts_nr, ?))) -> value sd {
2834 if (substr(sd.data.u.info_ind.trx[trx_nr].pdch_mask, g_chan_nr.tn, 1) != '1'B) {
2835 setverdict(fail, "PCUIF_INFO_IND PDCH_MASK not '1' after PDCH ACT");
2836 self.stop;
2837 }
2838 }
2839 [] PCU.receive { repeat; }
2840 }
2841 /* try to activate this PDCH from the PCU point of view */
2842 PCU.send(t_SD_PCUIF(pcu_conn_id, ts_PCUIF_ACT_REQ(bts_nr, trx_nr, g_chan_nr.tn)));
2843 /* FIXME: is there a response? */
2844}
2845
2846private function f_dyn_osmo_pdch_deact(integer pcu_conn_id, integer bts_nr, integer trx_nr)
2847runs on ConnHdlr {
2848 var PCUIF_send_data sd;
2849 /* Send RSL CHAN REL (deactivate) */
2850 PCU.clear;
2851 RSL.send(ts_RSL_RF_CHAN_REL(g_chan_nr));
2852 /* expect BTS to ask PCU to deactivate the channel */
2853 alt {
2854 [] PCU.receive(t_SD_PCUIF(pcu_conn_id, tr_PCUIF_INFO_IND(bts_nr, ?))) -> value sd {
2855 if (substr(sd.data.u.info_ind.trx[trx_nr].pdch_mask, g_chan_nr.tn, 1) != '0'B) {
2856 setverdict(fail, "PCUIF_INFO_IND PDCH_MASK not '0' after PDCH DEACT");
2857 self.stop;
2858 }
2859 }
2860 [] PCU.receive { repeat; }
2861 }
2862 /* Emulate PCU asking BTS to deactivate PDCH */
2863 PCU.send(t_SD_PCUIF(pcu_conn_id, ts_PCUIF_DEACT_REQ(bts_nr, trx_nr, g_chan_nr.tn)));
2864 alt {
2865 [] RSL.receive(tr_RSL_RF_CHAN_REL_ACK(g_chan_nr)) {
2866 setverdict(pass);
2867 }
2868 [] RSL.receive { repeat; }
2869 }
2870}
2871
2872/* Activate Osmocom-style dynamic PDCH from BSC side */
2873function f_TC_dyn_osmo_pdch_act_deact(charstring id) runs on ConnHdlr {
2874 var PCUIF_Message first_info;
2875 var integer ts_nr := g_chan_nr.tn;
2876 var integer trx_nr := 0;
2877 var integer bts_nr := 0;
2878 var integer pcu_conn_id := -1;
2879
2880 f_init_pcu(PCU, id, pcu_conn_id, first_info);
2881
2882 f_dyn_osmo_pdch_act(pcu_conn_id, bts_nr, trx_nr);
2883 f_sleep(3.0);
2884 f_dyn_osmo_pdch_deact(pcu_conn_id, bts_nr, trx_nr);
2885 setverdict(pass);
2886}
2887testcase TC_dyn_osmo_pdch_act_deact() runs on test_CT {
2888 var ConnHdlrPars pars;
2889 var ConnHdlr vc_conn;
2890 f_init(testcasename());
2891
2892 pars := valueof(t_Pars(t_RslChanNr_PDCH(4), ts_RSL_ChanMode_SIGN));
2893 vc_conn := f_start_handler(refers(f_TC_dyn_osmo_pdch_act_deact), pars, true);
2894 vc_conn.done;
2895}
2896
2897/* send a RF CHAN REL for PDCH on an osmocom dynamci PDCH that's already inactive */
2898function f_TC_dyn_osmo_pdch_unsol_deact(charstring id) runs on ConnHdlr {
2899 var PCUIF_Message first_info;
Harald Welte3d04ae62018-04-04 20:29:05 +02002900 var integer pcu_conn_id := -1;
2901
2902 f_init_pcu(PCU, id, pcu_conn_id, first_info);
2903
Neels Hofmeyr9c50ca52018-05-08 20:37:54 +02002904 RSL.send(ts_RSL_RF_CHAN_REL(g_chan_nr));
2905 /* since the lchan is already released, we don't expect any PCU changes, just a rel ack. */
2906 RSL.receive(tr_RSL_RF_CHAN_REL_ACK(g_chan_nr));
Harald Welte3d04ae62018-04-04 20:29:05 +02002907 setverdict(pass);
2908}
2909testcase TC_dyn_osmo_pdch_unsol_deact() runs on test_CT {
2910 var ConnHdlrPars pars;
2911 var ConnHdlr vc_conn;
2912 f_init(testcasename());
2913
2914 pars := valueof(t_Pars(t_RslChanNr_PDCH(4), ts_RSL_ChanMode_SIGN));
2915 vc_conn := f_start_handler(refers(f_TC_dyn_osmo_pdch_unsol_deact), pars, true);
2916 vc_conn.done;
2917}
2918
2919/* try to RSL CHAN ACT a PDCH on an osmocom-style PDCH that's already active */
2920function f_TC_dyn_osmo_pdch_double_act(charstring id) runs on ConnHdlr {
2921 var PCUIF_Message first_info;
2922 var integer ts_nr := g_chan_nr.tn;
2923 var integer trx_nr := 0;
2924 var integer bts_nr := 0;
2925 var integer pcu_conn_id := -1;
2926
2927 f_init_pcu(PCU, id, pcu_conn_id, first_info);
2928
2929 f_dyn_osmo_pdch_act(pcu_conn_id, bts_nr, trx_nr);
Neels Hofmeyrdf936a22018-05-08 22:07:57 +02002930 /* Send a second Chan Activ and expect it to be NACKed */
2931 f_rsl_transceive(ts_RSL_CHAN_ACT(g_chan_nr, g_pars.chan_mode), tr_RSL_CHAN_ACT_NACK(g_chan_nr),
2932 "RSL CHAN ACT NACK");
Harald Welte3d04ae62018-04-04 20:29:05 +02002933 setverdict(pass);
2934}
2935testcase TC_dyn_osmo_pdch_double_act() runs on test_CT {
2936 var ConnHdlrPars pars;
2937 var ConnHdlr vc_conn;
2938 f_init(testcasename());
2939
2940 pars := valueof(t_Pars(t_RslChanNr_PDCH(4), ts_RSL_ChanMode_SIGN));
2941 vc_conn := f_start_handler(refers(f_TC_dyn_osmo_pdch_double_act), pars, true);
2942 vc_conn.done;
2943}
2944
2945/* try to RSL CHAN ACT a TCH/F on an osmocom-style PDCH */
2946function f_TC_dyn_osmo_pdch_tchf_act(charstring id) runs on ConnHdlr {
2947 var PCUIF_Message first_info;
2948 var integer ts_nr := g_chan_nr.tn;
2949 var integer trx_nr := 0;
2950 var integer bts_nr := 0;
2951 var integer pcu_conn_id := -1;
2952 var RslChannelNr chan_nr := valueof(t_RslChanNr_Bm(g_chan_nr.tn));
2953
2954 /* register for the TCH/F channel number */
2955 f_rslem_register(0, chan_nr);
2956
2957 f_init_pcu(PCU, id, pcu_conn_id, first_info);
2958
2959 f_rsl_transceive(ts_RSL_CHAN_ACT(chan_nr, g_pars.chan_mode), tr_RSL_CHAN_ACT_ACK(chan_nr),
2960 "RSL CHAN ACT");
2961 setverdict(pass);
2962}
2963testcase TC_dyn_osmo_pdch_tchf_act() runs on test_CT {
2964 var ConnHdlrPars pars;
2965 var ConnHdlr vc_conn;
2966 f_init(testcasename());
2967
2968 pars := valueof(t_Pars(t_RslChanNr_PDCH(4), ts_RSL_ChanMode_SIGN));
2969 vc_conn := f_start_handler(refers(f_TC_dyn_osmo_pdch_tchf_act), pars, true);
2970 vc_conn.done;
2971}
2972
2973/* try to RSL CHAN ACT the TCH/H on an osmocom-style PDCH */
2974function f_TC_dyn_osmo_pdch_tchh_act(charstring id) runs on ConnHdlr {
2975 var PCUIF_Message first_info;
2976 var integer ts_nr := g_chan_nr.tn;
2977 var integer trx_nr := 0;
2978 var integer bts_nr := 0;
2979 var integer pcu_conn_id := -1;
2980 var RslChannelNr chan_nr[2] := { valueof(t_RslChanNr_Lm(g_chan_nr.tn, 0)),
2981 valueof(t_RslChanNr_Lm(g_chan_nr.tn, 1)) };
2982
2983 /* register for the TCH/H channel numbers */
2984 f_rslem_register(0, chan_nr[0]);
2985 f_rslem_register(0, chan_nr[1]);
2986
2987 f_init_pcu(PCU, id, pcu_conn_id, first_info);
2988
2989 f_rsl_transceive(ts_RSL_CHAN_ACT(chan_nr[1], g_pars.chan_mode),
2990 tr_RSL_CHAN_ACT_ACK(chan_nr[1]), "RSL CHAN ACT [1]");
2991 f_rsl_transceive(ts_RSL_CHAN_ACT(chan_nr[0], g_pars.chan_mode),
2992 tr_RSL_CHAN_ACT_ACK(chan_nr[0]), "RSL CHAN ACT [0]");
2993 setverdict(pass);
2994}
2995testcase TC_dyn_osmo_pdch_tchh_act() runs on test_CT {
2996 var ConnHdlrPars pars;
2997 var ConnHdlr vc_conn;
2998 f_init(testcasename());
2999
3000 pars := valueof(t_Pars(t_RslChanNr_PDCH(4), ts_RSL_ChanMode_SIGN));
3001 vc_conn := f_start_handler(refers(f_TC_dyn_osmo_pdch_tchh_act), pars, true);
3002 vc_conn.done;
3003}
3004
Harald Welte9bbbfb52018-04-05 09:33:19 +02003005/***********************************************************************
3006 * IPA Style Dynamic Timeslot Support
3007 ***********************************************************************/
3008
3009private function f_dyn_ipa_pdch_act(integer pcu_conn_id, integer bts_nr, integer trx_nr)
3010runs on ConnHdlr {
3011 var PCUIF_send_data sd;
3012 /* Expect BTS to immediately acknowledge activation as PDCH */
3013 PCU.clear;
3014 RSL.send(ts_RSL_IPA_PDCH_ACT(g_chan_nr));
3015 /* expect INFO_IND on PCU interface listing TS as PDCH */
3016 alt {
3017 [] PCU.receive(t_SD_PCUIF(pcu_conn_id, tr_PCUIF_INFO_IND(bts_nr, ?))) -> value sd {
3018 if (substr(sd.data.u.info_ind.trx[trx_nr].pdch_mask, g_chan_nr.tn, 1) != '1'B) {
3019 setverdict(fail, "PCUIF_INFO_IND PDCH_MASK not '1' after PDCH ACT");
3020 self.stop;
3021 }
3022 }
3023 [] PCU.receive { repeat; }
3024 }
3025 /* try to activate this PDCH from the PCU point of view */
3026 PCU.send(t_SD_PCUIF(pcu_conn_id, ts_PCUIF_ACT_REQ(bts_nr, trx_nr, g_chan_nr.tn)));
3027 /* FIXME: is there a response? */
3028
3029 RSL.receive(tr_RSL_IPA_PDCH_ACT_ACK(g_chan_nr, ?));
3030}
3031
3032private function f_dyn_ipa_pdch_deact(integer pcu_conn_id, integer bts_nr, integer trx_nr)
3033runs on ConnHdlr {
3034 var PCUIF_send_data sd;
3035 /* Send RSL CHAN REL (deactivate) */
3036 RSL.send(ts_RSL_IPA_PDCH_DEACT(g_chan_nr));
3037 PCU.clear;
3038 /* expect BTS to ask PCU to deactivate the channel */
3039 alt {
3040 [] PCU.receive(t_SD_PCUIF(pcu_conn_id, tr_PCUIF_INFO_IND(bts_nr, ?))) -> value sd {
3041 if (substr(sd.data.u.info_ind.trx[trx_nr].pdch_mask, g_chan_nr.tn, 1) != '0'B) {
3042 setverdict(fail, "PCUIF_INFO_IND PDCH_MASK not '0' after PDCH DEACT");
3043 self.stop;
3044 }
3045 }
3046 [] PCU.receive { repeat; }
3047 }
3048 /* Emulate PCU asking BTS to deactivate PDCH */
3049 PCU.send(t_SD_PCUIF(pcu_conn_id, ts_PCUIF_DEACT_REQ(bts_nr, trx_nr, g_chan_nr.tn)));
3050 alt {
3051 [] RSL.receive(tr_RSL_IPA_PDCH_DEACT_ACK(g_chan_nr)) {
3052 setverdict(pass);
3053 }
3054 [] RSL.receive { repeat; }
3055 }
3056}
3057
3058/* Activate and de-activate an IPA-style dynamic TCH/F + PDCH */
3059function f_TC_dyn_ipa_pdch_act_deact(charstring id) runs on ConnHdlr {
3060 var PCUIF_Message first_info;
3061 var integer ts_nr := g_chan_nr.tn;
3062 var integer trx_nr := 0;
3063 var integer bts_nr := 0;
3064 var integer pcu_conn_id := -1;
3065
3066 f_init_pcu(PCU, id, pcu_conn_id, first_info);
3067
3068 f_dyn_ipa_pdch_act(pcu_conn_id, bts_nr, trx_nr);
3069 f_sleep(3.0);
3070 f_dyn_ipa_pdch_deact(pcu_conn_id, bts_nr, trx_nr);
3071
3072 setverdict(pass);
3073
3074}
3075testcase TC_dyn_ipa_pdch_act_deact() runs on test_CT {
3076 var ConnHdlrPars pars;
3077 var ConnHdlr vc_conn;
3078 f_init();
3079
3080 pars := valueof(t_Pars(t_RslChanNr_Bm(3), ts_RSL_ChanMode_SIGN));
3081 vc_conn := f_start_handler(refers(f_TC_dyn_ipa_pdch_act_deact), pars, true);
3082 vc_conn.done;
3083}
3084
3085/* try to RSL CHAN ACT a TCH/F on an IPA-style PDCH */
3086function f_TC_dyn_ipa_pdch_tchf_act(charstring id) runs on ConnHdlr {
3087 var PCUIF_Message first_info;
3088 var integer ts_nr := g_chan_nr.tn;
3089 var integer trx_nr := 0;
3090 var integer bts_nr := 0;
3091 var integer pcu_conn_id := -1;
3092
3093 f_init_pcu(PCU, id, pcu_conn_id, first_info);
3094
3095 f_rsl_transceive(ts_RSL_CHAN_ACT(g_chan_nr, g_pars.chan_mode), tr_RSL_CHAN_ACT_ACK(g_chan_nr),
3096 "RSL CHAN ACT");
3097 f_rsl_transceive(ts_RSL_RF_CHAN_REL(g_chan_nr), tr_RSL_RF_CHAN_REL_ACK(g_chan_nr),
3098 "RF CHAN REL", true);
3099 setverdict(pass);
3100}
3101testcase TC_dyn_ipa_pdch_tchf_act() runs on test_CT {
3102 var ConnHdlrPars pars;
3103 var ConnHdlr vc_conn;
3104 f_init(testcasename());
3105
3106 pars := valueof(t_Pars(t_RslChanNr_Bm(3), ts_RSL_ChanMode_SIGN));
3107 vc_conn := f_start_handler(refers(f_TC_dyn_ipa_pdch_tchf_act), pars, true);
3108 vc_conn.done;
3109}
3110
3111/* Activate IPA style dyn PDCH as TCH/F and then illegally try to activate it as PDCH, too */
3112function f_TC_dyn_ipa_pdch_tchf_act_pdch_act_nack(charstring id) runs on ConnHdlr {
3113 var PCUIF_Message first_info;
3114 var integer ts_nr := g_chan_nr.tn;
3115 var integer trx_nr := 0;
3116 var integer bts_nr := 0;
3117 var integer pcu_conn_id := -1;
3118
3119 f_init_pcu(PCU, id, pcu_conn_id, first_info);
3120
3121 f_rsl_transceive(ts_RSL_CHAN_ACT(g_chan_nr, g_pars.chan_mode), tr_RSL_CHAN_ACT_ACK(g_chan_nr),
3122 "RSL CHAN ACT");
3123
3124 RSL.send(ts_RSL_IPA_PDCH_ACT(g_chan_nr));
3125 alt {
3126 [] RSL.receive(tr_RSL_IPA_PDCH_ACT_NACK(g_chan_nr, ?));
3127 [] RSL.receive(tr_RSL_IPA_PDCH_ACT_ACK(g_chan_nr, ?)) {
3128 setverdict(fail, "Unexpected PDCH ACT ACK");
3129 self.stop;
3130 }
3131 [] RSL.receive { repeat; }
3132 }
3133
3134 f_rsl_transceive(ts_RSL_RF_CHAN_REL(g_chan_nr), tr_RSL_RF_CHAN_REL_ACK(g_chan_nr),
3135 "RF CHAN REL", true);
3136 setverdict(pass);
3137}
3138testcase TC_dyn_ipa_pdch_tchf_act_pdch_act_nack() runs on test_CT {
3139 var ConnHdlrPars pars;
3140 var ConnHdlr vc_conn;
3141 f_init(testcasename());
3142
3143 pars := valueof(t_Pars(t_RslChanNr_Bm(3), ts_RSL_ChanMode_SIGN));
3144 vc_conn := f_start_handler(refers(f_TC_dyn_ipa_pdch_tchf_act_pdch_act_nack), pars, true);
3145 vc_conn.done;
3146}
3147
3148/* try to RSL CHAN ACT a TCH/F on an IPA-style PDCH that's already in PDCH mode; expect NACK */
3149function f_TC_dyn_ipa_pdch_act_tchf_act_nack(charstring id) runs on ConnHdlr {
3150 var PCUIF_Message first_info;
3151 var integer ts_nr := g_chan_nr.tn;
3152 var integer trx_nr := 0;
3153 var integer bts_nr := 0;
3154 var integer pcu_conn_id := -1;
3155
3156 /* register for the TCH/F channel number */
3157 f_rslem_register(0, g_chan_nr);
3158
3159 f_init_pcu(PCU, id, pcu_conn_id, first_info);
3160
3161 f_dyn_ipa_pdch_act(pcu_conn_id, bts_nr, trx_nr);
3162
3163 f_rsl_transceive(ts_RSL_CHAN_ACT(g_chan_nr, g_pars.chan_mode), tr_RSL_CHAN_ACT_NACK(g_chan_nr),
3164 "RSL CHAN ACT");
3165
3166 f_dyn_ipa_pdch_deact(pcu_conn_id, bts_nr, trx_nr);
3167
3168 setverdict(pass);
3169}
3170testcase TC_dyn_ipa_pdch_act_tchf_act_nack() runs on test_CT {
3171 var ConnHdlrPars pars;
3172 var ConnHdlr vc_conn;
3173 f_init(testcasename());
3174
3175 pars := valueof(t_Pars(t_RslChanNr_Bm(3), ts_RSL_ChanMode_SIGN));
3176 vc_conn := f_start_handler(refers(f_TC_dyn_ipa_pdch_act_tchf_act_nack), pars, true);
3177 vc_conn.done;
3178}
3179
3180
Harald Welte0472ab42018-03-12 15:02:26 +01003181/***********************************************************************
3182 * LAPDm / RLL related
3183 ***********************************************************************/
3184
3185private function f_tx_lapdm(template (value) LapdmFrame l,
3186 template (value) RslLinkId link_id) runs on ConnHdlr {
3187 var octetstring l2 := enc_LapdmFrame(valueof(l));
3188 if (valueof(link_id.c) == SACCH) {
3189 /* prepend dummy L1 header */
3190 l2 := '0000'O & l2;
3191 }
3192 log("encoding ", l, " to ", l2);
3193 L1CTL.send(ts_L1CTL_DATA_REQ(g_chan_nr, link_id, l2));
3194}
3195
3196type record RllTestCase {
3197 uint3_t sapi,
3198 RslLinkId link_id,
3199 octetstring l3,
3200 boolean exp
3201}
3202type record of RllTestCase RllTestCases;
3203template RllTestCase t_EITC(uint3_t sapi, RslLinkId id, octetstring l3, boolean exp) := {
3204 sapi := sapi,
3205 link_id := id,
3206 l3 := l3,
3207 exp := exp
3208}
3209
3210/* execute the same callback function with a set of different parameters (tcs) on a
3211 * variety of logical channels */
3212private function f_rll_testmatrix(RllTestCases tcs, void_fn fn) runs on test_CT {
3213 var ConnHdlrPars pars;
3214 var ConnHdlr vc_conn;
3215 f_init(testcasename());
3216
3217 /* test on each of the channels we have */
3218 for (var integer i := 0; i < sizeof(g_AllChanTypes); i := i+1) {
3219 pars := valueof(t_Pars(g_AllChanTypes[i], ts_RSL_ChanMode_SIGN));
3220
3221 /* test each of the test cases on the current channel */
3222 for (var integer j := 0; j < sizeof(tcs); j := j+1) {
3223 pars.spec.rll := tcs[j];
3224 log(testcasename(), ": XXX Starting ", tcs[j] , " on ", g_AllChanTypes[i]);
3225 vc_conn := f_start_handler(fn, pars);
3226 vc_conn.done;
3227 }
3228 }
3229
3230 f_shutdown();
3231}
3232
3233/* test if SABM on Um triggers EST IND (TS 48.058 3.1) */
3234private function f_TC_rll_est_ind(charstring id) runs on ConnHdlr {
3235 var RllTestCase tc := g_pars.spec.rll;
3236 timer T := 3.0;
3237
3238 f_l1_tune(L1CTL);
3239 RSL.clear;
3240
3241 /* activate the logical channel */
3242 f_est_dchan();
3243 L1CTL.clear;
3244
3245 f_tx_lapdm(ts_LAPDm_SABM(tc.sapi, cr_MO_CMD, true, tc.l3), tc.link_id);
3246 T.start;
3247 alt {
3248 [tc.l3 != ''O] RSL.receive(tr_RSL_EST_IND(g_chan_nr, tc.link_id, tc.l3)) {
3249 if (tc.exp) {
3250 setverdict(pass);
3251 } else {
3252 setverdict(fail, "Unexpected EST IND with L3 in ", tc);
3253 }
3254 }
3255 [tc.l3 == ''O] RSL.receive(tr_RSL_EST_IND_NOL3(g_chan_nr, tc.link_id)) {
3256 if (tc.exp) {
3257 setverdict(pass);
3258 } else {
3259 setverdict(fail, "Unexpected EST IND without L3 in ", tc);
3260 }
3261 }
3262 [tc.exp] T.timeout {
3263 setverdict(fail, "Timeout waiting for EST IND");
3264 }
3265 [not tc.exp] T.timeout {
3266 setverdict(pass);
3267 }
3268 }
3269
3270 f_rsl_chan_deact();
3271 f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
3272 f_rslem_unregister(0, g_chan_nr);
3273}
3274testcase TC_rll_est_ind() runs on test_CT {
3275 var RllTestCases tcs := {
Harald Welte7aacbbf2018-05-09 16:56:41 +02003276 /* SAPI0 establishment (contention resolution) */
Harald Welte0472ab42018-03-12 15:02:26 +01003277 valueof(t_EITC(0, valueof(ts_RslLinkID_DCCH(0)), '01020304'O, true)),
Harald Welte7aacbbf2018-05-09 16:56:41 +02003278 /* normal SAPI0 establishment */
3279 valueof(t_EITC(0, valueof(ts_RslLinkID_DCCH(0)), ''O, true)),
Harald Welte0472ab42018-03-12 15:02:26 +01003280 /* SAPI 3 doesn't support contention resolution */
3281 valueof(t_EITC(3, valueof(ts_RslLinkID_DCCH(3)), '01020304'O, false)),
3282 valueof(t_EITC(3, valueof(ts_RslLinkID_SACCH(3)), '01020304'O, false)),
3283 /* normal SAPI3 establishment on main DCCH */
3284 valueof(t_EITC(3, valueof(ts_RslLinkID_DCCH(3)), ''O, true)),
3285 /* normal SAPI3 establishment on SACCH */
3286 valueof(t_EITC(3, valueof(ts_RslLinkID_SACCH(3)), ''O, true))
3287 };
3288 f_rll_testmatrix(tcs, refers(f_TC_rll_est_ind));
3289}
3290
3291/* test if RLL EST REQ trigeres SABM on Um; UA on Um triggers EST CONF (TS 48.058 3.2) */
3292private function f_TC_rll_est_req(charstring id) runs on ConnHdlr {
3293 var RllTestCase tc := g_pars.spec.rll;
3294 var L1ctlDlMessage dl;
3295 timer T := 3.0;
3296
3297 f_l1_tune(L1CTL);
3298 RSL.clear;
3299
3300 /* activate the logical channel */
3301 f_est_dchan();
3302 L1CTL.clear;
3303
3304 /* Send a RSL EST REQ for SAPI3 on main DCCH */
3305 RSL.send(ts_RSL_EST_REQ(g_chan_nr, tc.link_id));
3306 T.start;
3307 alt {
3308 [] L1CTL.receive(tr_L1CTL_DATA_IND(g_chan_nr, ?)) -> value dl {
3309 var LapdmFrame lapdm;
3310 var octetstring l2 := dl.payload.data_ind.payload;
3311 if (dl.dl_info.link_id.c == SACCH) {
3312 /* remove L1 header */
3313 l2 := substr(l2, 2, lengthof(l2)-2);
3314 }
3315 lapdm.ab := dec_LapdmFrameAB(l2);
3316 if (match(lapdm, tr_LAPDm_SABM(tc.sapi, cr_MT_CMD, true, ''O))) {
3317 setverdict(pass);
3318 } else {
3319 repeat;
3320 }
3321 }
3322 [] L1CTL.receive { repeat; }
3323 [] T.timeout {
3324 setverdict(fail, "Timeout waiting for SABM");
3325 self.stop;
3326 }
3327 }
3328
3329 f_rsl_chan_deact();
3330 f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
3331 f_rslem_unregister(0, g_chan_nr);
3332}
3333testcase TC_rll_est_req_DCCH_3() runs on test_CT {
3334 var RllTestCases tcs := {
3335 /* normal SAPI3 establishment on main DCCH */
3336 valueof(t_EITC(3, valueof(ts_RslLinkID_DCCH(3)), ''O, true))//,
3337 };
3338 f_rll_testmatrix(tcs, refers(f_TC_rll_est_req));
3339}
3340testcase TC_rll_est_req_ACCH_3() runs on test_CT {
3341 var RllTestCases tcs := {
3342 /* normal SAPI3 establishment on SACCH */
3343 valueof(t_EITC(3, valueof(ts_RslLinkID_SACCH(3)), ''O, true))
3344 }
3345 f_rll_testmatrix(tcs, refers(f_TC_rll_est_req));
3346}
3347
3348/* altstep to receive a LAPDm frame matching the given template */
3349private altstep as_l1_exp_lapdm(template LapdmFrame exp) runs on ConnHdlr {
3350 var L1ctlDlMessage dl;
3351 [] L1CTL.receive(tr_L1CTL_DATA_IND(g_chan_nr, ?)) -> value dl {
3352 var LapdmFrame lapdm;
3353 var octetstring l2 := dl.payload.data_ind.payload;
3354 if (dl.dl_info.link_id.c == SACCH) {
3355 /* remove L1 header */
3356 l2 := substr(l2, 2, lengthof(l2)-2);
3357 }
3358 if (ischosen(exp.ab)) {
3359 lapdm.ab := dec_LapdmFrameAB(l2);
3360 } else if (ischosen(exp.b4)) {
3361 lapdm.b4 := dec_LapdmFrameB4(l2);
3362 } else if (ischosen(exp.bbis)) {
3363 lapdm.bbis := dec_LapdmFrameBbis(l2);
3364 }
3365 log("Rx LAPDm ", lapdm);
3366 if (match(lapdm, exp)) {
3367 setverdict(pass);
3368 } else {
3369 repeat;
3370 }
3371 }
3372 [] L1CTL.receive { repeat; }
3373}
3374private function f_l1_exp_lapdm(template LapdmFrame exp, float t := 3.0) runs on ConnHdlr {
3375 timer T := t;
3376 T.start;
3377 alt {
3378 [] T.timeout {
3379 setverdict(fail, "Timeout waiting for LAPDm ", exp);
3380 self.stop;
3381 }
3382 [] as_l1_exp_lapdm(exp);
3383 }
3384}
3385
3386/* establish one Radio Link Layer via SABM -> UA. Use l3 for contention resolution */
3387private function f_est_rll_mo(uint3_t sapi, RslLinkId link_id, octetstring l3) runs on ConnHdlr {
3388 /* send SABM from MS -> BTS */
3389 f_tx_lapdm(ts_LAPDm_SABM(sapi, cr_MO_CMD, true, l3), link_id);
3390 /* expect RLL EST IND on Abis */
3391 alt {
3392 [l3 != ''O] RSL.receive(tr_RSL_EST_IND(g_chan_nr, link_id, l3));
3393 [l3 == ''O] RSL.receive(tr_RSL_EST_IND_NOL3(g_chan_nr, link_id));
3394 [] RSL.receive(tr_RSL_ERROR_IND(g_chan_nr, link_id, ?)) {
3395 setverdict(fail, "Failing due to RSL_ERROR_IND");
3396 self.stop;
3397 }
3398 [] RSL.receive { repeat; }
3399 }
3400 /* expect UA from BTS -> MS */
3401 f_l1_exp_lapdm(tr_LAPDm_UA(sapi, cr_MT_RSP, true, l3));
3402}
3403
3404/* test if DISC on Um triggers RLL REL IND (TS 48.058 3.3) */
3405private function f_TC_rll_rel_ind(charstring id) runs on ConnHdlr {
3406 var RllTestCase tc := g_pars.spec.rll;
3407
3408 f_l1_tune(L1CTL);
3409 RSL.clear;
3410
3411 /* activate the logical channel */
3412 f_est_dchan();
3413 L1CTL.clear;
3414
3415 /* first establish the link-layer */
3416 f_est_rll_mo(tc.sapi, tc.link_id, tc.l3);
3417
3418 /* then send the DISC */
3419 f_tx_lapdm(ts_LAPDm_DISC(tc.sapi, cr_MO_CMD, true), tc.link_id);
3420 /* ... and expect the REL IND on the RSL side */
3421 alt {
3422 [] RSL.receive(tr_RSL_REL_IND(g_chan_nr, tc.link_id)) {
3423 setverdict(pass);
3424 }
3425 }
3426
3427 /* release the channel */
3428 f_rsl_chan_deact();
3429 f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
3430 f_rslem_unregister(0, g_chan_nr);
3431}
3432testcase TC_rll_rel_ind_DCCH_0() runs on test_CT {
3433 var RllTestCases tcs := {
3434 valueof(t_EITC(0, valueof(ts_RslLinkID_DCCH(0)), '01020304'O, true))
3435 };
3436 f_rll_testmatrix(tcs, refers(f_TC_rll_rel_ind));
3437}
3438
3439testcase TC_rll_rel_ind_ACCH_0() runs on test_CT {
3440 var RllTestCases tcs := {
3441 valueof(t_EITC(0, valueof(ts_RslLinkID_SACCH(0)), ''O, true))
3442 };
3443 f_rll_testmatrix(tcs, refers(f_TC_rll_rel_ind));
3444}
3445testcase TC_rll_rel_ind_DCCH_3() runs on test_CT {
3446 var RllTestCases tcs := {
3447 valueof(t_EITC(3, valueof(ts_RslLinkID_DCCH(3)), ''O, true))
3448 };
3449 f_rll_testmatrix(tcs, refers(f_TC_rll_rel_ind));
3450}
3451testcase TC_rll_rel_ind_ACCH_3() runs on test_CT {
3452 var RllTestCases tcs := {
3453 valueof(t_EITC(3, valueof(ts_RslLinkID_SACCH(3)), ''O, true))
3454 };
3455 f_rll_testmatrix(tcs, refers(f_TC_rll_rel_ind));
3456}
3457
3458/* test if RLL REL REQ triggers DISC on Um; UA/DM triggers RLL REL CONF (TS 48.058 3.4) */
3459private function f_TC_rll_rel_req(charstring id) runs on ConnHdlr {
3460 var RllTestCase tc := g_pars.spec.rll;
3461 f_l1_tune(L1CTL);
3462 RSL.clear;
3463
3464 /* activate the logical channel */
3465 f_est_dchan();
3466 L1CTL.clear;
3467
3468 /* first establish the link-layer */
3469 f_est_rll_mo(tc.sapi, tc.link_id, tc.l3);
3470
3471 /* then send the REL REQ via RSL */
3472 RSL.send(ts_RSL_REL_REQ(g_chan_nr, tc.link_id, RSL_REL_MODE_NORMAL));
3473 /* ... and expect the DISC on the Um side */
3474 alt {
Harald Weltebc6199f2018-05-10 19:38:18 +02003475 [] as_l1_exp_lapdm(tr_LAPDm_DISC(tc.sapi, cr_MT_CMD, true)) {
Harald Welte0472ab42018-03-12 15:02:26 +01003476 /* FIXME: send a UA in resposne to the DISC */
3477 }
3478 }
3479
3480 /* release the channel */
3481 f_rsl_chan_deact();
3482 f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
3483 f_rslem_unregister(0, g_chan_nr);
3484}
3485testcase TC_rll_rel_req() runs on test_CT {
3486 var RllTestCases tcs := {
3487 valueof(t_EITC(0, valueof(ts_RslLinkID_DCCH(0)), '01020304'O, true)),
3488 valueof(t_EITC(0, valueof(ts_RslLinkID_SACCH(0)), ''O, true)),
3489 valueof(t_EITC(3, valueof(ts_RslLinkID_DCCH(3)), ''O, true)),
3490 valueof(t_EITC(3, valueof(ts_RslLinkID_SACCH(3)), ''O, true))
3491 };
3492 f_rll_testmatrix(tcs, refers(f_TC_rll_rel_req));
3493}
3494
3495/* test if RLL DATA REQ triggers I-frames on Um (TS 48.058 3.5) */
3496testcase TC_rll_data_req() runs on test_CT {
3497}
3498
3499/* test if I-frames on Um trigger RLL DATA IND (TS 48.058 3.6) */
3500testcase TC_rll_data_ind() runs on test_CT {
3501}
3502
3503/* test if RLL UNIT DATA REQ triggers UI-frame on Um (TS 48.058 3.7) */
3504private function f_TC_rll_ud_req(charstring id) runs on ConnHdlr {
3505 var RllTestCase tc := g_pars.spec.rll;
3506
3507 f_l1_tune(L1CTL);
3508 RSL.clear;
3509
3510 f_est_dchan();
3511 L1CTL.clear;
3512
3513 /* Send UNITDATA REQ on RSL side */
3514 RSL.send(ts_RSL_UNITDATA_REQ(g_chan_nr, tc.link_id, tc.l3));
3515 /* Expect it to arrive on the other side */
3516 if (tc.link_id.c == SACCH) {
Harald Weltee613f962018-04-18 22:38:16 +02003517 f_l1_exp_lapdm(tr_LAPDm_B4_UI(tc.sapi, cr_MT_CMD, tc.l3));
Harald Welte0472ab42018-03-12 15:02:26 +01003518 } else {
Harald Weltee613f962018-04-18 22:38:16 +02003519 f_l1_exp_lapdm(tr_LAPDm_UI(tc.sapi, cr_MT_CMD, tc.l3));
Harald Welte0472ab42018-03-12 15:02:26 +01003520 }
3521
3522 /* release the channel */
3523 f_rsl_chan_deact();
3524 f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
3525 f_rslem_unregister(0, g_chan_nr);
3526}
3527testcase TC_rll_unit_data_req_DCCH() runs on test_CT {
3528 var octetstring l3 := f_rnd_octstring(15);
3529 var RllTestCases tcs := {
3530 valueof(t_EITC(0, valueof(ts_RslLinkID_DCCH(0)), l3, true)),
3531 valueof(t_EITC(3, valueof(ts_RslLinkID_DCCH(3)), l3, true))
3532 };
3533 f_rll_testmatrix(tcs, refers(f_TC_rll_ud_req));
3534}
3535testcase TC_rll_unit_data_req_ACCH() runs on test_CT {
3536 var octetstring l3 := f_rnd_octstring(19);
3537 var RllTestCases tcs := {
3538 valueof(t_EITC(0, valueof(ts_RslLinkID_SACCH(0)), l3, true)),
3539 valueof(t_EITC(3, valueof(ts_RslLinkID_SACCH(3)), l3, true))
3540 };
3541 f_rll_testmatrix(tcs, refers(f_TC_rll_ud_req));
3542}
3543
3544/* test if UI-frames on Um trigger RLL UNIT DATA IND (TS 48.058 3.8) */
3545private function f_TC_rll_ud_ind(charstring id) runs on ConnHdlr {
3546 var RllTestCase tc := g_pars.spec.rll;
3547
3548 f_l1_tune(L1CTL);
3549 RSL.clear;
3550
3551 f_est_dchan();
3552 L1CTL.clear;
3553
3554 /* Send LAPDm UI frame. There is no B4 format in uplink! */
Harald Weltee613f962018-04-18 22:38:16 +02003555 f_tx_lapdm(ts_LAPDm_UI(tc.sapi, cr_MO_CMD, tc.l3), tc.link_id);
Harald Welte0472ab42018-03-12 15:02:26 +01003556 /* Expdct RLL UNITDATA IND on RSL side */
3557 alt {
3558 [] RSL.receive(tr_RSL_UNITDATA_IND(g_chan_nr, tc.link_id, tc.l3)) {
3559 setverdict(pass);
3560 }
3561 [] RSL.receive { repeat; }
3562 }
3563
3564 /* release the channel */
3565 f_rsl_chan_deact();
3566 f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
3567 f_rslem_unregister(0, g_chan_nr);
3568}
3569testcase TC_rll_unit_data_ind_DCCH() runs on test_CT {
3570 var octetstring l3 := f_rnd_octstring(15);
3571 var RllTestCases tcs := {
3572 valueof(t_EITC(0, valueof(ts_RslLinkID_DCCH(0)), l3, true)),
3573 valueof(t_EITC(3, valueof(ts_RslLinkID_DCCH(3)), l3, true))
3574 };
3575 f_rll_testmatrix(tcs, refers(f_TC_rll_ud_ind));
3576}
3577testcase TC_rll_unit_data_ind_ACCH() runs on test_CT {
3578 var octetstring l3 := f_rnd_octstring(18);
3579 var RllTestCases tcs := {
3580 valueof(t_EITC(0, valueof(ts_RslLinkID_SACCH(0)), l3, true)),
3581 valueof(t_EITC(3, valueof(ts_RslLinkID_SACCH(3)), l3, true))
3582 };
3583 f_rll_testmatrix(tcs, refers(f_TC_rll_ud_ind));
3584}
3585
Harald Weltee613f962018-04-18 22:38:16 +02003586/***********************************************************************
3587 * Encryption Related
3588 ***********************************************************************/
3589
3590/* send UNITDATA_REQ from BTS to MS and expect it to arrive */
3591function f_unitdata_mt(RslLinkId link_id, octetstring l3) runs on ConnHdlr {
3592 RSL.send(ts_RSL_UNITDATA_REQ(g_chan_nr, link_id, l3));
3593 if (link_id.c == SACCH) {
3594 f_l1_exp_lapdm(tr_LAPDm_B4_UI(link_id.sapi, cr_MT_CMD, l3));
3595 } else {
3596 f_l1_exp_lapdm(tr_LAPDm_UI(link_id.sapi, cr_MT_CMD, l3));
3597 }
3598}
3599
3600/* Send UI frame from MS and expect it to arrive as RLL UNITDATA IND on Abis */
3601function f_unitdata_mo(RslLinkId link_id, octetstring l3) runs on ConnHdlr {
3602 timer T := 3.0;
3603 f_tx_lapdm(ts_LAPDm_UI(link_id.sapi, cr_MO_CMD, l3), link_id);
3604 T.start;
3605 /* Expect RLL UNITDATA IND on RSL side */
3606 alt {
3607 [] RSL.receive(tr_RSL_UNITDATA_IND(g_chan_nr, link_id, l3)) {
3608 setverdict(pass);
3609 }
3610 [] T.timeout {
3611 setverdict(fail, "Timeout waiting for UNIT_DATA_IND");
3612 }
3613 [] RSL.receive { repeat; }
3614 }
3615}
3616
3617/* Test channel activation with A5/n right from the beginning (like in assignment + hand-over) */
3618function f_TC_chan_act_encr(charstring id) runs on ConnHdlr {
3619 f_l1_tune(L1CTL);
3620 f_est_dchan(true);
3621
3622 /* now we actually need to transmit some data both ways to check if the encryption works */
3623 var L1ctlDlMessage dl;
3624
3625 var octetstring l3 := f_rnd_octstring(16);
3626 var RslLinkId link_id := valueof(ts_RslLinkID_DCCH(0));
3627
3628 /* send UNITDATA_REQ from BTS to MS and expect it to arrive */
3629 f_unitdata_mt(link_id, l3);
3630
3631 /* Send UI frame from MS and expect it to arrive as RLL UNITDATA IND on Abis */
3632 f_unitdata_mo(link_id, l3);
3633
3634 /* release the channel */
3635 f_rsl_chan_deact();
3636 f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
3637 f_rslem_unregister(0, g_chan_nr);
3638}
3639testcase TC_chan_act_a51() runs on test_CT {
3640 var ConnHdlrPars pars := valueof(t_Pars(t_RslChanNr_Bm(1), ts_RSL_ChanMode_SIGN));
3641 pars.encr := valueof(ts_RSL_IE_EncrInfo(RSL_ALG_ID_A5_1, f_rnd_octstring(8)));
3642 f_testmatrix_each_chan(pars, refers(f_TC_chan_act_encr));
3643}
3644testcase TC_chan_act_a52() runs on test_CT {
3645 var ConnHdlrPars pars := valueof(t_Pars(t_RslChanNr_Bm(1), ts_RSL_ChanMode_SIGN));
3646 pars.encr := valueof(ts_RSL_IE_EncrInfo(RSL_ALG_ID_A5_2, f_rnd_octstring(8)));
3647 f_testmatrix_each_chan(pars, refers(f_TC_chan_act_encr));
3648}
3649testcase TC_chan_act_a53() runs on test_CT {
3650 var ConnHdlrPars pars := valueof(t_Pars(t_RslChanNr_Bm(1), ts_RSL_ChanMode_SIGN));
3651 pars.encr := valueof(ts_RSL_IE_EncrInfo(RSL_ALG_ID_A5_3, f_rnd_octstring(8)));
3652 f_testmatrix_each_chan(pars, refers(f_TC_chan_act_encr));
3653}
3654
3655
3656/* Test unencrypted channel activation followed by explicit ENCR CMD later */
3657function f_TC_encr_cmd(charstring id) runs on ConnHdlr {
3658 /* L3 payload doesn't matter, as it is passed transparently */
3659 var BIT3 l3_alg_id := f_alg_id_to_l3(g_pars.encr.alg_id);
3660 var octetstring l3 := enc_PDU_ML3_NW_MS(valueof(ts_RRM_CiphModeCmd(l3_alg_id)));
3661 var RslLinkId link_id := valueof(ts_RslLinkID_DCCH(0));
3662
3663 f_l1_tune(L1CTL);
3664
3665 /* first establish a dedicated channel in the clear */
3666 f_est_dchan(false);
3667
3668 /* Establish ABM */
3669 f_est_rll_mo(link_id.sapi, link_id, '23420815'O);
3670
3671 /* then send the RSL ENCR CMD with an actual RR CIPH MOD CMD inside */
3672 RSL.send(ts_RSL_ENCR_CMD(g_chan_nr, link_id, g_pars.encr.alg_id, g_pars.encr.key, l3));
3673 /* expect the L3 to arrive still unencrypted on the MS side */
3674 f_l1_exp_lapdm(tr_LAPDm_I(link_id.sapi, cr_MT_CMD, ?, ?, ?, l3));
3675
3676 /* configure L1 to apply ciphering */
3677 var uint8_t alg_id := f_alg_id_to_l1ctl(g_pars.encr.alg_id);
3678 f_L1CTL_CRYPTO_REQ(L1CTL, g_pars.chan_nr, alg_id, g_pars.encr.key);
3679
3680 /* send first ciphered I-frame in response */
3681 l3 := '0a0b0c0d'O;
3682 f_tx_lapdm(ts_LAPDm_I(link_id.sapi, cr_MO_CMD, true, 1, 0, l3), link_id);
3683 RSL.receive(tr_RSL_DATA_IND(g_chan_nr, link_id, l3));
3684
3685 /* now the BTS code should have detected the first properly encrypted uplink I-frame,
3686 * and hence enable encryption also on the downlink */
3687
3688 /* expect bi-directional communication work in encrypted mode */
3689 f_unitdata_mo(link_id, f_rnd_octstring(15));
3690 f_unitdata_mt(link_id, f_rnd_octstring(15));
3691
3692 /* release the channel */
3693 f_rsl_chan_deact();
3694 f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
3695 f_rslem_unregister(0, g_chan_nr);
3696}
3697testcase TC_encr_cmd_a51() runs on test_CT {
3698 var ConnHdlrPars pars := valueof(t_Pars(t_RslChanNr_Bm(1), ts_RSL_ChanMode_SIGN));
3699 pars.encr := valueof(ts_RSL_IE_EncrInfo(RSL_ALG_ID_A5_1, f_rnd_octstring(8)));
3700 f_testmatrix_each_chan(pars, refers(f_TC_encr_cmd));
3701}
3702testcase TC_encr_cmd_a52() runs on test_CT {
3703 var ConnHdlrPars pars := valueof(t_Pars(t_RslChanNr_Bm(1), ts_RSL_ChanMode_SIGN));
3704 pars.encr := valueof(ts_RSL_IE_EncrInfo(RSL_ALG_ID_A5_2, f_rnd_octstring(8)));
3705 f_testmatrix_each_chan(pars, refers(f_TC_encr_cmd));
3706}
3707testcase TC_encr_cmd_a53() runs on test_CT {
3708 var ConnHdlrPars pars := valueof(t_Pars(t_RslChanNr_Bm(1), ts_RSL_ChanMode_SIGN));
3709 pars.encr := valueof(ts_RSL_IE_EncrInfo(RSL_ALG_ID_A5_3, f_rnd_octstring(8)));
3710 f_testmatrix_each_chan(pars, refers(f_TC_encr_cmd));
3711}
3712
3713private function f_assert_lapdm(octetstring enc, template LapdmFrame exp_match, charstring name := "") {
3714 var LapdmFrame lf;
3715 var octetstring reenc;
3716
3717 /* decode the LAPDm frame */
3718 if (ischosen(exp_match.ab)) {
3719 lf.ab := dec_LapdmFrameAB(enc);
3720 } else {
3721 setverdict(fail, "unsupported frame type");
3722 self.stop;
3723 }
3724
3725 /* check if decoder result matches expectation */
3726 if (not match(lf, exp_match)) {
3727 setverdict(fail, name, ": decoded LAPDm doesn't match");
3728 } else {
3729 log(name, ": matched");
3730 setverdict(pass);
3731 }
3732
3733 /* test if re-encoded frame equals original input */
3734 reenc := enc_LapdmFrame(lf);
3735 if (enc != reenc) {
3736 setverdict(fail, name, ": re-encoded LAPDm frame doesn't match");
3737 } else {
3738 setverdict(pass);
3739 }
3740}
3741
3742testcase TC_lapdm_selftest() runs on test_CT {
3743 f_assert_lapdm('030301'O, tr_LAPDm_UI(0, true, ''O), "ui_s0_empty");
3744 f_assert_lapdm('0F0301'O, tr_LAPDm_UI(3, true, ''O), "ui_s3_empty");
3745 f_assert_lapdm('013F01'O, tr_LAPDm_SABM(0, false, true, ''O), "sabm_s0_empty");
3746 f_assert_lapdm('013F1123420815'O, tr_LAPDm_SABM(0, false, true, '23420815'O), "sabm_s0_l3");
3747 f_assert_lapdm('03E101'O, tr_LAPDm_RR(0, true, false, 7), "rr_s0_7");
3748 f_assert_lapdm('03000d063505'O, tr_LAPDm_I(0, true, false, 0, 0, '063505'O), "I/0/0");
3749 f_assert_lapdm('03e00d063505'O, tr_LAPDm_I(0, true, false, 7, 0, '063505'O), "I/7/0");
3750}
3751
Harald Welte0472ab42018-03-12 15:02:26 +01003752
3753/* test generation of RLL ERR IND based on Um errors (TS 48.058 3.9) */
3754/* protocol error as per 44.006 */
3755/* link layer failure (repetition of I-frame N200 times without ACK */
3756/* repetition of SABM or DISC N200 times without ACK */
3757/* receptiom of SABM in multi-frame established state */
3758
3759
3760
3761
Harald Welte883340c2018-02-28 18:59:29 +01003762
Harald Welte68e495b2018-02-25 00:05:57 +01003763/* TODO Areas:
3764
3765* channel activation
3766** with BS_Power / MS_Power, bypassing power control loop
3767** on primary vs. secondary TRX
Harald Welte68e495b2018-02-25 00:05:57 +01003768** with timing advance from initial activation on
3769* mode modify
3770** encryption
3771** multirate
3772* check DEACTIVATE SACCH
Harald Welte68e495b2018-02-25 00:05:57 +01003773** unsupported algorithm
3774* handover detection
3775* MS Power Control
3776* BS Power Control
3777* Physical Context
3778* SACCH info modify
Harald Welte68e495b2018-02-25 00:05:57 +01003779* CCCH Load Indication for PCH and RACH
3780* Delete Indication on AGCH overflow
3781* SMS Broadcast Req / Cmd / CBCH LOad Ind
3782* RF resource ind
Harald Welte68e495b2018-02-25 00:05:57 +01003783* error handling
3784* discriminator error
3785** type error
3786** sequence error
3787** IE duplicated?
Harald Welte883340c2018-02-28 18:59:29 +01003788* PCU interface
3789** TIME_IND from BTS->PCU
3790** DATA_IND from BTS->PCU
3791** verification of PCU-originated DATA_REQ arrival on Um/MS side
Harald Welte68e495b2018-02-25 00:05:57 +01003792
3793*/
Harald Welte70767382018-02-21 12:16:40 +01003794
3795control {
3796 execute( TC_chan_act_stress() );
3797 execute( TC_chan_act_react() );
3798 execute( TC_chan_deact_not_active() );
3799 execute( TC_chan_act_wrong_nr() );
Harald Welte629cc6b2018-03-11 17:19:05 +01003800 execute( TC_deact_sacch() );
Harald Welteea17b912018-03-11 22:29:31 +01003801 execute( TC_sacch_filling() );
3802 execute( TC_sacch_info_mod() );
Harald Welte075d84c2018-03-12 13:07:24 +01003803 execute( TC_sacch_multi() );
Harald Welte55700662018-03-12 13:15:43 +01003804 execute( TC_sacch_multi_chg() );
Harald Welte8c24c2b2018-02-26 08:31:31 +01003805 execute( TC_rach_content() );
3806 execute( TC_rach_count() );
Harald Welte54a2a2d2018-02-26 09:14:05 +01003807 execute( TC_rach_max_ta() );
Harald Welte70767382018-02-21 12:16:40 +01003808 execute( TC_meas_res_sign_tchf() );
3809 execute( TC_meas_res_sign_tchh() );
3810 execute( TC_meas_res_sign_sdcch4() );
3811 execute( TC_meas_res_sign_sdcch8() );
Harald Welte685d5982018-02-27 20:42:05 +01003812 execute( TC_meas_res_sign_tchh_toa256() );
Harald Welte70767382018-02-21 12:16:40 +01003813 execute( TC_conn_fail_crit() );
Harald Welte68e495b2018-02-25 00:05:57 +01003814 execute( TC_paging_imsi_80percent() );
3815 execute( TC_paging_tmsi_80percent() );
3816 execute( TC_paging_imsi_200percent() );
3817 execute( TC_paging_tmsi_200percent() );
Harald Welte01d982c2018-02-25 01:31:40 +01003818 execute( TC_rsl_protocol_error() );
3819 execute( TC_rsl_mand_ie_error() );
3820 execute( TC_rsl_ie_content_error() );
Harald Welte48494ca2018-02-25 16:59:50 +01003821 execute( TC_si_sched_default() );
Harald Welte0cae4552018-03-09 22:20:26 +01003822 execute( TC_si_sched_1() );
Harald Welte48494ca2018-02-25 16:59:50 +01003823 execute( TC_si_sched_2bis() );
3824 execute( TC_si_sched_2ter() );
3825 execute( TC_si_sched_2ter_2bis() );
3826 execute( TC_si_sched_2quater() );
3827 execute( TC_si_sched_13() );
3828 execute( TC_si_sched_13_2bis_2ter_2quater() );
Harald Weltea871a382018-02-25 02:03:14 +01003829 execute( TC_ipa_dlcx_not_active() );
Harald Weltea3f1df92018-02-25 12:49:55 +01003830 execute( TC_ipa_crcx_twice_not_active() );
3831 execute( TC_ipa_crcx_mdcx_dlcx_not_active() );
Harald Welte3ae11da2018-02-25 13:36:06 +01003832 execute( TC_ipa_crcx_mdcx_mdcx_dlcx_not_active() );
Harald Welte9912eb52018-02-25 13:30:15 +01003833 execute( TC_ipa_crcx_sdcch_not_active() );
Harald Welte883340c2018-02-28 18:59:29 +01003834
3835 execute( TC_pcu_act_req() );
3836 execute( TC_pcu_act_req_wrong_ts() );
3837 execute( TC_pcu_act_req_wrong_bts() );
3838 execute( TC_pcu_act_req_wrong_trx() );
3839 execute( TC_pcu_deact_req() );
3840 execute( TC_pcu_deact_req_wrong_ts() );
3841 execute( TC_pcu_ver_si13() );
3842 execute( TC_pcu_data_req_wrong_bts() );
3843 execute( TC_pcu_data_req_wrong_trx() );
3844 execute( TC_pcu_data_req_wrong_ts() );
3845 execute( TC_pcu_data_req_ts_inactive() );
3846 execute( TC_pcu_data_req_pdtch() );
3847 execute( TC_pcu_data_req_ptcch() );
3848 execute( TC_pcu_data_req_agch() );
3849 execute( TC_pcu_data_req_imm_ass_pch() );
3850 execute( TC_pcu_rach_content() );
3851 execute( TC_pcu_paging_from_rsl() );
Harald Welte3d04ae62018-04-04 20:29:05 +02003852
3853 execute( TC_dyn_osmo_pdch_act_deact() );
3854 execute( TC_dyn_osmo_pdch_unsol_deact() );
3855 execute( TC_dyn_osmo_pdch_double_act() );
3856 execute( TC_dyn_osmo_pdch_tchf_act() );
3857 execute( TC_dyn_osmo_pdch_tchh_act() );
Harald Welte9bbbfb52018-04-05 09:33:19 +02003858 execute( TC_dyn_ipa_pdch_act_deact() );
3859 execute( TC_dyn_ipa_pdch_tchf_act() );
3860 execute( TC_dyn_ipa_pdch_tchf_act_pdch_act_nack() );
3861 execute( TC_dyn_ipa_pdch_act_tchf_act_nack() );
Harald Welte0472ab42018-03-12 15:02:26 +01003862
3863 execute( TC_rll_est_ind() );
3864 execute( TC_rll_est_req_DCCH_3() );
3865 execute( TC_rll_est_req_ACCH_3() );
3866 execute( TC_rll_rel_ind_DCCH_0() );
3867 execute( TC_rll_rel_ind_DCCH_3() );
3868 execute( TC_rll_rel_ind_ACCH_0() );
3869 execute( TC_rll_rel_ind_ACCH_3() );
3870 execute( TC_rll_rel_req() );
3871 execute( TC_rll_unit_data_req_DCCH() );
3872 execute( TC_rll_unit_data_req_ACCH() );
3873 execute( TC_rll_unit_data_ind_DCCH() );
3874 execute( TC_rll_unit_data_ind_ACCH() );
Harald Weltee613f962018-04-18 22:38:16 +02003875
3876 execute( TC_chan_act_a51() );
3877 execute( TC_chan_act_a52() );
3878 execute( TC_chan_act_a53() );
3879 execute( TC_encr_cmd_a51() );
3880 execute( TC_encr_cmd_a52() );
3881 execute( TC_encr_cmd_a53() );
3882
3883 execute( TC_lapdm_selftest() );
Harald Welte70767382018-02-21 12:16:40 +01003884}
3885
3886
3887}