blob: 2d596276fe86e38184e4198b81824eab13fa169c [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;
Harald Welte82ccef72018-02-25 16:17:33 +01008import from GSM_SystemInformation all;
Harald Welte70767382018-02-21 12:16:40 +01009import from L1CTL_PortType all;
10import from L1CTL_Types all;
11import from LAPDm_Types all;
12import from Osmocom_CTRL_Adapter all;
Neels Hofmeyr6a84b232018-04-03 19:12:36 +020013import from Osmocom_CTRL_Functions all;
Harald Welte70767382018-02-21 12:16:40 +010014
15import from RSL_Types all;
Harald Welte7484fc42018-02-24 14:09:45 +010016import from IPA_Types all;
Harald Welte70767382018-02-21 12:16:40 +010017import from IPA_Emulation all;
Stefan Sperling0ec1c262018-10-15 15:12:52 +020018import from IPA_Testing all;
Harald Welte70767382018-02-21 12:16:40 +010019import 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;
Neels Hofmeyr6a84b232018-04-03 19:12:36 +020055 charstring mp_ctrl_ip := "127.0.0.1";
56 integer mp_ctrl_port := 4238;
Pau Espin Pedrol121724c2018-09-28 15:58:12 +020057 integer mp_tolerance_rxqual := 1;
58 integer mp_tolerance_rxlev := 3;
59 integer mp_tolerance_timing_offset_256syms := 0;
Pau Espin Pedrol752ffd52018-06-07 13:55:45 +020060 integer mp_rxlev_exp := 57;
Pau Espin Pedroled359cb2018-09-28 16:08:24 +020061 integer mp_ms_power_level_exp := 7;
Pau Espin Pedrol121724c2018-09-28 15:58:12 +020062 integer mp_ms_actual_ta_exp := 0;
63 integer mp_timing_offset_256syms_exp := 512;
Harald Welte70767382018-02-21 12:16:40 +010064}
65
Harald Welte629cc6b2018-03-11 17:19:05 +010066type record of RslChannelNr ChannelNrs;
67
Harald Welte70767382018-02-21 12:16:40 +010068type component test_CT extends CTRL_Adapter_CT {
Harald Welte68e495b2018-02-25 00:05:57 +010069 /* IPA Emulation component underneath RSL */
Harald Welte70767382018-02-21 12:16:40 +010070 var IPA_Emulation_CT vc_IPA;
Harald Welte68e495b2018-02-25 00:05:57 +010071 /* RSL Emulation component (for ConnHdlr tests) */
Harald Welte70767382018-02-21 12:16:40 +010072 var RSL_Emulation_CT vc_RSL;
Harald Welte68e495b2018-02-25 00:05:57 +010073 /* Direct RSL_CCHAN_PT */
Harald Welte70767382018-02-21 12:16:40 +010074 port RSL_CCHAN_PT RSL_CCHAN;
Harald Welte68e495b2018-02-25 00:05:57 +010075
76 /* L1CTL port (for classic tests) */
77 port L1CTL_PT L1CTL;
Harald Welte48494ca2018-02-25 16:59:50 +010078
Harald Welte54a2a2d2018-02-26 09:14:05 +010079 /* TRXC port (for classic tests) */
80 port TRXC_CODEC_PT BB_TRXC;
81 var integer g_bb_trxc_conn_id;
82
Harald Weltef50e3ae2018-09-10 10:27:56 +020083 /* VTY connections to both BTS and BSC */
Harald Welte8da48242018-02-27 20:41:32 +010084 port TELNETasp_PT BTSVTY;
Harald Weltef50e3ae2018-09-10 10:27:56 +020085 port TELNETasp_PT BSCVTY;
Harald Welte8da48242018-02-27 20:41:32 +010086
Harald Welte883340c2018-02-28 18:59:29 +010087 /* PCU Interface of BTS */
88 port PCUIF_CODEC_PT PCU;
89 var integer g_pcu_conn_id;
90 /* Last PCU INFO IND we received */
91 var PCUIF_Message g_pcu_last_info;
92
Harald Welte48494ca2018-02-25 16:59:50 +010093 /* SI configuration */
94 var SystemInformationConfig si_cfg := {
95 bcch_extended := false,
96 si1_present := false,
97 si2bis_present := false,
98 si2ter_present := false,
99 si2quater_present := false,
100 si7_present := false,
101 si8_present := false,
102 si9_present := false,
103 si13_present := false,
104 si13alt_present := false,
105 si15_present := false,
106 si16_present := false,
107 si17_present := false,
108 si2n_present := false,
109 si21_present := false,
110 si22_present := false
111 };
Harald Welte629cc6b2018-03-11 17:19:05 +0100112
113 /* all logical channels available on the BTS */
114 var ChannelNrs g_AllChannels;
Harald Welte0472ab42018-03-12 15:02:26 +0100115 var ChannelNrs g_AllChanTypes;
Harald Welte70767382018-02-21 12:16:40 +0100116}
117
118/* an individual call / channel */
119type component ConnHdlr extends RSL_DchanHdlr {
120 port L1CTL_PT L1CTL;
121
122 port TRXC_CODEC_PT BB_TRXC;
123 var integer g_bb_trxc_conn_id;
124
125 timer g_Tguard;
126 timer g_Tmeas_exp := 2.0; /* >= 103 SACCH multiframe ~ 500ms */
127
128 var ConnHdlrPars g_pars;
129 var uint8_t g_next_meas_res_nr := 0;
Harald Weltefa45e9e2018-03-10 18:59:03 +0100130 var boolean g_first_meas_res := true;
Harald Weltef26de0b2018-04-04 20:28:05 +0200131
132 /* PCU Interface of BTS */
133 port PCUIF_CODEC_PT PCU;
Harald Welte70767382018-02-21 12:16:40 +0100134}
135
136function f_init_rsl(charstring id) runs on test_CT {
137 vc_IPA := IPA_Emulation_CT.create(id & "-RSL-IPA");
138 vc_RSL := RSL_Emulation_CT.create(id & "-RSL");
139
140 map(vc_IPA:IPA_PORT, system:IPA_CODEC_PT);
141 connect(vc_IPA:IPA_RSL_PORT, vc_RSL:IPA_PT);
142 connect(self:RSL_CCHAN, vc_RSL:CCHAN_PT);
143
144 vc_IPA.start(IPA_Emulation.main_server(mp_rsl_ip, mp_rsl_port));
145 vc_RSL.start(RSL_Emulation.main(false));
146}
147
148type record ConnHdlrPars {
149 RslChannelNr chan_nr,
150 RSL_IE_ChannelMode chan_mode,
151 float t_guard,
Harald Welte0472ab42018-03-12 15:02:26 +0100152 ConnL1Pars l1_pars,
Harald Weltee613f962018-04-18 22:38:16 +0200153 TestSpecUnion spec optional,
154 RSL_IE_EncryptionInfo encr optional
Harald Welte0472ab42018-03-12 15:02:26 +0100155}
156
157/* Test-specific parameters */
158type union TestSpecUnion {
159 RllTestCase rll
Harald Welte70767382018-02-21 12:16:40 +0100160}
161
Harald Welte82ccef72018-02-25 16:17:33 +0100162template (value) RachControlParameters ts_RachCtrl_default := {
Harald Welte0fd1fb02018-03-10 17:19:50 +0100163 max_retrans := RACH_MAX_RETRANS_7,
164 tx_integer := '1001'B, /* 12 slots */
Harald Welte82ccef72018-02-25 16:17:33 +0100165 cell_barr_access := false,
166 re_not_allowed := true,
Harald Welteb9585f82018-03-10 17:18:47 +0100167 acc := '0000010000000000'B
Harald Welte82ccef72018-02-25 16:17:33 +0100168};
169
Harald Weltef10153f2018-02-25 16:34:05 +0100170template (value) CellSelectionParameters ts_CellSelPar_default := {
Harald Welte0fd1fb02018-03-10 17:19:50 +0100171 cell_resel_hyst_2dB := 2,
Pau Espin Pedroled359cb2018-09-28 16:08:24 +0200172 ms_txpwr_max_cch := mp_ms_power_level_exp,
Harald Weltef10153f2018-02-25 16:34:05 +0100173 acs := '0'B,
174 neci := true,
175 rxlev_access_min := 0
176}
177
178template (value) LocationAreaIdentification ts_LAI_default := {
179 mcc_mnc := '262F42'H,
180 lac := 42
181}
182
Harald Welte7484fc42018-02-24 14:09:45 +0100183/* Default SYSTEM INFORMATION 3 */
Harald Weltef8df4cb2018-03-10 15:15:08 +0100184template (value) SystemInformation ts_SI3_default := {
185 header := ts_RrHeader(SYSTEM_INFORMATION_TYPE_3, 18),
Harald Welte7484fc42018-02-24 14:09:45 +0100186 payload := {
187 si3 := {
188 cell_id := 23,
Harald Weltef10153f2018-02-25 16:34:05 +0100189 lai := ts_LAI_default,
Harald Welte7484fc42018-02-24 14:09:45 +0100190 ctrl_chan_desc := {
191 msc_r99 := true,
192 att := true,
193 bs_ag_blks_res := 1,
194 ccch_conf := CCHAN_DESC_1CCCH_COMBINED,
Harald Welte82ccef72018-02-25 16:17:33 +0100195 si22ind := false,
Harald Welte7484fc42018-02-24 14:09:45 +0100196 cbq3 := CBQ3_IU_MODE_NOT_SUPPORTED,
197 spare := '00'B,
198 bs_pa_mfrms := 0, /* 2 multiframes */
199 t3212 := 1 /* 6 minutes */
200 },
Harald Welte82ccef72018-02-25 16:17:33 +0100201 cell_options := {
Harald Welte7484fc42018-02-24 14:09:45 +0100202 dn_ind := false,
203 pwrc := false,
204 dtx := MS_MAY_USE_UL_DTX,
Harald Welte0fd1fb02018-03-10 17:19:50 +0100205 radio_link_tout_div4 := (32/4)-1
Harald Welte7484fc42018-02-24 14:09:45 +0100206 },
Harald Weltef10153f2018-02-25 16:34:05 +0100207 cell_sel_par := ts_CellSelPar_default,
Harald Welte82ccef72018-02-25 16:17:33 +0100208 rach_control := ts_RachCtrl_default,
Harald Welte3778acc2018-03-09 19:32:31 +0100209 rest_octets := '2B2B2B2B'O
Harald Welte7484fc42018-02-24 14:09:45 +0100210 }
211 }
212}
Harald Welte70767382018-02-21 12:16:40 +0100213
Harald Weltef8df4cb2018-03-10 15:15:08 +0100214template (value) SystemInformation ts_SI2_default := {
215 header := ts_RrHeader(SYSTEM_INFORMATION_TYPE_2, 22),
Harald Weltef10153f2018-02-25 16:34:05 +0100216 payload := {
217 si2 := {
218 bcch_freq_list := '00000000000000000000000000000000'O,
219 ncc_permitted := '11111111'B,
220 rach_control := ts_RachCtrl_default
221 }
222 }
223}
224
Harald Weltef8df4cb2018-03-10 15:15:08 +0100225template (value) SystemInformation ts_SI4_default := {
226 header := ts_RrHeader(SYSTEM_INFORMATION_TYPE_4, 12), /* no CBCH / restoct */
Harald Weltef10153f2018-02-25 16:34:05 +0100227 payload := {
228 si4 := {
229 lai := ts_LAI_default,
230 cell_sel_par := ts_CellSelPar_default,
231 rach_control := ts_RachCtrl_default,
232 cbch_chan_desc := omit,
233 cbch_mobile_alloc := omit,
234 rest_octets := ''O
235 }
236 }
237}
238
239function f_rsl_bcch_fill_raw(RSL_IE_SysinfoType rsl_si_type, octetstring si_enc)
240runs on test_CT {
241 log("Setting ", rsl_si_type, ": ", si_enc);
242 RSL_CCHAN.send(ts_RSL_UD(ts_RSL_BCCH_INFO(rsl_si_type, si_enc)));
243}
244
245function f_rsl_bcch_fill(RSL_IE_SysinfoType rsl_si_type, template (value) SystemInformation si_dec)
246runs on test_CT {
247 var octetstring si_enc := enc_SystemInformation(valueof(si_dec));
248 log("Setting ", rsl_si_type, ": ", si_dec);
249 f_rsl_bcch_fill_raw(rsl_si_type, si_enc);
250}
251
Harald Welte8da48242018-02-27 20:41:32 +0100252private function f_init_vty(charstring id) runs on test_CT {
253 map(self:BTSVTY, system:BTSVTY);
254 f_vty_set_prompts(BTSVTY);
255 f_vty_transceive(BTSVTY, "enable");
256}
257
Harald Weltef50e3ae2018-09-10 10:27:56 +0200258private function f_init_vty_bsc() runs on test_CT {
259 map(self:BSCVTY, system:BSCVTY);
260 f_vty_set_prompts(BSCVTY, "OsmoBSC");
261 f_vty_transceive(BSCVTY, "enable");
262}
263
Harald Welte883340c2018-02-28 18:59:29 +0100264/* PCU socket may at any time receive a new INFO.ind */
Harald Weltef26de0b2018-04-04 20:28:05 +0200265private altstep as_pcu_info_ind(PCUIF_CODEC_PT pt, integer pcu_conn_id,
266 out PCUIF_Message pcu_last_info) {
Harald Welte883340c2018-02-28 18:59:29 +0100267 var PCUIF_send_data sd;
Harald Weltef26de0b2018-04-04 20:28:05 +0200268 [] pt.receive(t_SD_PCUIF(pcu_conn_id, tr_PCUIF_INFO_IND(0, ?))) -> value sd {
269 pcu_last_info := sd.data;
Harald Welted378a252018-03-13 17:02:14 +0100270 }
Harald Weltef26de0b2018-04-04 20:28:05 +0200271 [] pt.receive(t_SD_PCUIF(pcu_conn_id, tr_PCUIF_INFO_IND(?, ?, ?))) -> value sd {
Harald Welted378a252018-03-13 17:02:14 +0100272 setverdict(fail, "Invalid PCU Version/BTS Number received");
Daniel Willmann17ddd852018-07-05 17:33:20 +0200273 mtc.stop;
Harald Welte883340c2018-02-28 18:59:29 +0100274 }
275}
276
Harald Weltef26de0b2018-04-04 20:28:05 +0200277private function f_init_pcu(PCUIF_CODEC_PT pt, charstring id,
278 out integer pcu_conn_id, out PCUIF_Message pcu_last_info) {
Harald Welte883340c2018-02-28 18:59:29 +0100279 timer T := 2.0;
280 var PCUIF_send_data sd;
Harald Welte84271622018-03-10 17:21:03 +0100281 if (mp_pcu_socket == "") {
Harald Weltef26de0b2018-04-04 20:28:05 +0200282 pcu_conn_id := -1;
Harald Welte84271622018-03-10 17:21:03 +0100283 return;
284 }
Harald Weltef26de0b2018-04-04 20:28:05 +0200285 pcu_conn_id := f_pcuif_connect(pt, mp_pcu_socket);
Harald Welte883340c2018-02-28 18:59:29 +0100286
287 T.start;
288 alt {
Harald Weltef26de0b2018-04-04 20:28:05 +0200289 [] as_pcu_info_ind(pt, pcu_conn_id, pcu_last_info);
Harald Welte883340c2018-02-28 18:59:29 +0100290 [] T.timeout {
291 setverdict(fail, "Timeout waiting for PCU INFO_IND");
Daniel Willmann17ddd852018-07-05 17:33:20 +0200292 mtc.stop;
Harald Welte883340c2018-02-28 18:59:29 +0100293 }
294 }
295}
296
Harald Welte70767382018-02-21 12:16:40 +0100297/* global init function */
Harald Welte68e495b2018-02-25 00:05:57 +0100298function f_init(charstring id := "BTS-Test") runs on test_CT {
Harald Welte83f6dbf2018-06-03 18:26:50 +0200299 timer T := 10.0;
Harald Welte629cc6b2018-03-11 17:19:05 +0100300 g_AllChannels := {
301 /* TS 1..4: TCH/F */
302 valueof(ts_RslChanNr_Bm(1)), valueof(ts_RslChanNr_Bm(2)),
303 valueof(ts_RslChanNr_Bm(3)), valueof(ts_RslChanNr_Bm(4)),
304 /* TS 5: TCH/H */
305 valueof(ts_RslChanNr_Lm(5,0)), valueof(ts_RslChanNr_Lm(5,1)),
306 /* TS 0: SDCCH/4 */
307 valueof(ts_RslChanNr_SDCCH4(0,0)), valueof(ts_RslChanNr_SDCCH4(0,1)),
308 valueof(ts_RslChanNr_SDCCH4(0,2)), valueof(ts_RslChanNr_SDCCH4(0,3)),
309 /* TS 6: SDCCH/8 */
310 valueof(ts_RslChanNr_SDCCH8(6,0)), valueof(ts_RslChanNr_SDCCH8(6,1)),
311 valueof(ts_RslChanNr_SDCCH8(6,2)), valueof(ts_RslChanNr_SDCCH8(6,3)),
312 valueof(ts_RslChanNr_SDCCH8(6,4)), valueof(ts_RslChanNr_SDCCH8(6,5)),
313 valueof(ts_RslChanNr_SDCCH8(6,6)), valueof(ts_RslChanNr_SDCCH8(6,7))
314 };
Harald Welte0472ab42018-03-12 15:02:26 +0100315 g_AllChanTypes := {
316 /* TS 1..4: TCH/F */
Vadim Yanitskiyb0970092018-07-27 02:40:43 +0700317 valueof(ts_RslChanNr_Bm(1)),
Harald Welte0472ab42018-03-12 15:02:26 +0100318 /* TS 5: TCH/H */
Vadim Yanitskiy7b8c5222018-09-16 16:55:48 +0700319 valueof(ts_RslChanNr_Lm(5,1)),
Harald Welte0472ab42018-03-12 15:02:26 +0100320 /* TS 0: SDCCH/4 */
321 valueof(ts_RslChanNr_SDCCH4(0,2)),
322 /* TS 6: SDCCH/8 */
323 valueof(ts_RslChanNr_SDCCH8(6,4))
324 };
Harald Welte629cc6b2018-03-11 17:19:05 +0100325
Harald Welte70767382018-02-21 12:16:40 +0100326 f_init_rsl(id);
Harald Welte83f6dbf2018-06-03 18:26:50 +0200327 T.start;
328 alt {
329 [] RSL_CCHAN.receive(ASP_IPA_Event:{up_down := ASP_IPA_EVENT_UP});
330 [] T.timeout {
331 setverdict(fail, "Timeout waiting for ASP_IPA_EVENT_UP");
Daniel Willmann17ddd852018-07-05 17:33:20 +0200332 mtc.stop;
Harald Welte83f6dbf2018-06-03 18:26:50 +0200333 }
334 }
Harald Welte2d142592018-02-25 13:19:44 +0100335 f_sleep(0.5); /* workaround for OS#3000 */
Harald Welte8da48242018-02-27 20:41:32 +0100336 f_init_vty(id);
Neels Hofmeyr6a84b232018-04-03 19:12:36 +0200337 f_ipa_ctrl_start(mp_ctrl_ip, mp_ctrl_port);
Harald Welte7484fc42018-02-24 14:09:45 +0100338
339 /* Send SI3 to the BTS, it is needed for various computations */
Harald Weltef10153f2018-02-25 16:34:05 +0100340 f_rsl_bcch_fill(RSL_SYSTEM_INFO_3, ts_SI3_default);
341 /* SI2 + SI4 are required for SI testing as they are mandatory defaults */
342 f_rsl_bcch_fill(RSL_SYSTEM_INFO_2, ts_SI2_default);
343 f_rsl_bcch_fill(RSL_SYSTEM_INFO_4, ts_SI4_default);
Harald Welte57fe8232018-02-26 17:52:50 +0100344
Harald Weltef26de0b2018-04-04 20:28:05 +0200345 map(self:PCU, system:PCU);
346 f_init_pcu(PCU, id, g_pcu_conn_id, g_pcu_last_info);
Harald Welte883340c2018-02-28 18:59:29 +0100347
Harald Welte84271622018-03-10 17:21:03 +0100348 if (mp_bb_trxc_port != -1) {
349 var TrxcMessage ret;
350 /* start with a default moderate timing offset equalling TA=2 */
351 f_main_trxc_connect();
352 ret := f_TRXC_transceive(BB_TRXC, g_bb_trxc_conn_id, valueof(ts_TRXC_FAKE_TIMING(2*256)));
353 }
Harald Welte70767382018-02-21 12:16:40 +0100354}
355
Harald Welte294b0a22018-03-10 23:26:48 +0100356function f_shutdown() runs on test_CT {
Daniel Willmanncc7bbeb2018-07-03 16:33:56 +0200357 /* mtc.stop cleanly stops testcase execution to avoid unclean shutdown */
Daniel Willmannb85a6292018-07-25 22:53:32 +0200358 all component.stop;
Daniel Willmanncc7bbeb2018-07-03 16:33:56 +0200359 mtc.stop;
Harald Welte294b0a22018-03-10 23:26:48 +0100360}
361
Harald Welte68e495b2018-02-25 00:05:57 +0100362/* Attach L1CTL to master test_CT (classic tests, non-handler mode) */
363function f_init_l1ctl() runs on test_CT {
364 map(self:L1CTL, system:L1CTL);
365 f_connect_reset(L1CTL);
366}
367
Harald Welte70767382018-02-21 12:16:40 +0100368type function void_fn(charstring id) runs on ConnHdlr;
369
370/* create a new test component */
Harald Weltef26de0b2018-04-04 20:28:05 +0200371function f_start_handler(void_fn fn, ConnHdlrPars pars, boolean pcu_comp := false)
Harald Welte70767382018-02-21 12:16:40 +0100372runs on test_CT return ConnHdlr {
373 var charstring id := testcasename();
374 var ConnHdlr vc_conn;
375
376 vc_conn := ConnHdlr.create(id);
377 /* connect to RSL Emulation main component */
378 connect(vc_conn:RSL, vc_RSL:CLIENT_PT);
379 connect(vc_conn:RSL_PROC, vc_RSL:RSL_PROC);
Harald Weltef26de0b2018-04-04 20:28:05 +0200380 if (pcu_comp) {
381 /* the ConnHdlr component wants to talk directly to the PCU, so disconnect
382 * it from the test_CT and connect it to the component. This obviously only
383 * works for one component, i.e. no concurrency */
384 unmap(self:PCU, system:PCU);
385 map(vc_conn:PCU, system:PCU);
386 }
Harald Welte70767382018-02-21 12:16:40 +0100387
388 vc_conn.start(f_handler_init(fn, id, pars));
389 return vc_conn;
390}
391
Harald Welte7484fc42018-02-24 14:09:45 +0100392template ASP_RSL_Unitdata ts_RSL_UD(template RSL_Message rsl, IpaStreamId sid := IPAC_PROTO_RSL_TRX0) := {
393 streamId := sid,
394 rsl := rsl
395}
396
397template ASP_RSL_Unitdata tr_RSL_UD(template RSL_Message rsl,
398 template IpaStreamId sid := IPAC_PROTO_RSL_TRX0) := {
399 streamId := sid,
400 rsl := rsl
401}
402
Harald Welte70767382018-02-21 12:16:40 +0100403private altstep as_Tguard() runs on ConnHdlr {
404 [] g_Tguard.timeout {
405 setverdict(fail, "Tguard timeout");
Daniel Willmann17ddd852018-07-05 17:33:20 +0200406 mtc.stop;
Harald Welte70767382018-02-21 12:16:40 +0100407 }
408}
409
Harald Welte68e495b2018-02-25 00:05:57 +0100410private function f_l1_tune(L1CTL_PT L1CTL) {
Pau Espin Pedrol752ffd52018-06-07 13:55:45 +0200411 f_L1CTL_FBSB(L1CTL, { false, mp_trx0_arfcn }, CCCH_MODE_COMBINED, mp_rxlev_exp);
Harald Welte70767382018-02-21 12:16:40 +0100412}
413
414private function f_trxc_connect() runs on ConnHdlr {
415 map(self:BB_TRXC, system:BB_TRXC);
416 var Result res;
Harald Weltea4d8f352018-03-01 15:47:20 +0100417 res := TRXC_CodecPort_CtrlFunct.f_IPL4_connect(BB_TRXC, mp_bb_trxc_ip, mp_bb_trxc_port,
418 "", -1, -1, {udp:={}}, {});
Harald Welte9220f632018-05-23 20:27:02 +0200419 if (not ispresent(res.connId)) {
420 setverdict(fail, "Could not connect to trx-control interface of trxcon, check your configuration");
Daniel Willmann17ddd852018-07-05 17:33:20 +0200421 mtc.stop;
Harald Welte9220f632018-05-23 20:27:02 +0200422 }
Harald Welte70767382018-02-21 12:16:40 +0100423 g_bb_trxc_conn_id := res.connId;
424}
425
426private function f_trxc_fake_rssi(uint8_t rssi) runs on ConnHdlr {
Harald Weltef8df4cb2018-03-10 15:15:08 +0100427 var TrxcMessage ret;
428 ret := f_TRXC_transceive(BB_TRXC, g_bb_trxc_conn_id, valueof(ts_TRXC_FAKE_RSSI(rssi)));
Harald Welte70767382018-02-21 12:16:40 +0100429}
430
431private function f_trx_fake_toffs256(int16_t toffs256) runs on ConnHdlr {
Harald Weltef8df4cb2018-03-10 15:15:08 +0100432 var TrxcMessage ret;
433 ret := f_TRXC_transceive(BB_TRXC, g_bb_trxc_conn_id, valueof(ts_TRXC_FAKE_TIMING(toffs256)));
Harald Welte70767382018-02-21 12:16:40 +0100434}
435
436/* first function started in ConnHdlr component */
437private function f_handler_init(void_fn fn, charstring id, ConnHdlrPars pars)
438runs on ConnHdlr {
439 g_pars := pars;
440 g_chan_nr := pars.chan_nr;
441
442 map(self:L1CTL, system:L1CTL);
443 f_connect_reset(L1CTL);
444
Harald Welte84271622018-03-10 17:21:03 +0100445 if (mp_bb_trxc_port != -1) {
446 f_trxc_connect();
447 }
Harald Welte70767382018-02-21 12:16:40 +0100448
449 g_Tguard.start(pars.t_guard);
450 activate(as_Tguard());
451
452 f_rslem_register(0, pars.chan_nr);
453
454 /* call the user-supplied test case function */
455 fn.apply(id);
456}
457
Harald Welteb1726c92018-03-30 11:56:38 +0200458function f_rsl_transceive_ret(template RSL_Message tx, template RSL_Message exp_rx, charstring id,
459 boolean ignore_other := false)
460runs on ConnHdlr return RSL_Message {
461 var RSL_Message rx;
Harald Welte1eba3742018-02-25 12:48:14 +0100462 timer T := 3.0;
463 RSL.send(tx);
464 T.start;
Harald Welte70767382018-02-21 12:16:40 +0100465 alt {
Harald Welteb1726c92018-03-30 11:56:38 +0200466 [] RSL.receive(exp_rx) -> value rx {
Harald Welte1eba3742018-02-25 12:48:14 +0100467 T.stop;
468 setverdict(pass);
Harald Welte70767382018-02-21 12:16:40 +0100469 }
Harald Welte1eba3742018-02-25 12:48:14 +0100470 [] T.timeout {
471 setverdict(fail, "Timeout expecting " & id);
Daniel Willmann17ddd852018-07-05 17:33:20 +0200472 mtc.stop;
Harald Welte1eba3742018-02-25 12:48:14 +0100473 }
Harald Welte21240e62018-03-11 21:43:35 +0100474 [not ignore_other] as_l1_sacch();
475 [not ignore_other] as_meas_res();
476 [not ignore_other] as_l1_dcch();
477 [not ignore_other] RSL.receive {
Harald Welte1eba3742018-02-25 12:48:14 +0100478 setverdict(fail, "Unexpected RSL message received");
Daniel Willmann17ddd852018-07-05 17:33:20 +0200479 mtc.stop;
Harald Welte70767382018-02-21 12:16:40 +0100480 }
Harald Welte21240e62018-03-11 21:43:35 +0100481 [ignore_other] RSL.receive { repeat; }
Harald Welte70767382018-02-21 12:16:40 +0100482 }
Harald Welteb1726c92018-03-30 11:56:38 +0200483 return rx;
484}
485
486function f_rsl_transceive(template RSL_Message tx, template RSL_Message exp_rx, charstring id,
487 boolean ignore_other := false)
488runs on ConnHdlr {
489 var RSL_Message rx := f_rsl_transceive_ret(tx, exp_rx, id, ignore_other);
Harald Welte70767382018-02-21 12:16:40 +0100490}
491
Harald Weltee613f962018-04-18 22:38:16 +0200492function f_rsl_chan_act(RSL_IE_ChannelMode mode, boolean encr_enable := false)
493runs on ConnHdlr {
494 var RSL_Message ch_act := valueof(ts_RSL_CHAN_ACT(g_chan_nr, mode));
495 if (encr_enable) {
496 /* append encryption related IEs, if requested */
497 var RSL_IE_EncryptionInfo encr_info;
498 encr_info := valueof(ts_RSL_IE_EncrInfo(g_pars.encr.alg_id, g_pars.encr.key));
499 ch_act.ies := ch_act.ies & { valueof(t_RSL_IE(RSL_IE_ENCR_INFO, RSL_IE_Body:{encr_info :=
500encr_info})) };
501 }
502 f_rsl_transceive(ch_act, tr_RSL_CHAN_ACT_ACK(g_chan_nr), "RSL CHAN ACT");
Harald Welte1eba3742018-02-25 12:48:14 +0100503}
504
Harald Welte70767382018-02-21 12:16:40 +0100505function f_rsl_chan_deact() runs on ConnHdlr {
Harald Welte1eba3742018-02-25 12:48:14 +0100506 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 +0100507 "RF CHAN REL", true);
Harald Welte70767382018-02-21 12:16:40 +0100508}
509
Harald Welte70767382018-02-21 12:16:40 +0100510private template ConnHdlrPars t_Pars(template RslChannelNr chan_nr,
511 template RSL_IE_ChannelMode chan_mode,
512 float t_guard := 20.0) := {
513 chan_nr := valueof(chan_nr),
514 chan_mode := valueof(chan_mode),
515 t_guard := t_guard,
516 l1_pars := {
517 dtx_enabled := false,
Harald Welte685d5982018-02-27 20:42:05 +0100518 toa256_enabled := false,
Harald Welte70767382018-02-21 12:16:40 +0100519 meas_ul := {
520 full := {
521 rxlev := dbm2rxlev(-53),
522 rxqual := 0
523 },
524 sub := {
525 rxlev := dbm2rxlev(-53),
526 rxqual := 0
527 }
528 },
Pau Espin Pedrol121724c2018-09-28 15:58:12 +0200529 timing_offset_256syms := mp_timing_offset_256syms_exp,
Harald Welte70767382018-02-21 12:16:40 +0100530 bs_power_level := 0,
Pau Espin Pedroled359cb2018-09-28 16:08:24 +0200531 ms_power_level := mp_ms_power_level_exp,
Pau Espin Pedrol121724c2018-09-28 15:58:12 +0200532 ms_actual_ta := mp_ms_actual_ta_exp
Harald Welte0472ab42018-03-12 15:02:26 +0100533 },
Harald Weltee613f962018-04-18 22:38:16 +0200534 spec := omit,
535 encr := omit
Harald Welte70767382018-02-21 12:16:40 +0100536}
537
Harald Welte93640c62018-02-25 16:59:33 +0100538/***********************************************************************
539 * Channel Activation / Deactivation
540 ***********************************************************************/
541
Harald Welte70767382018-02-21 12:16:40 +0100542/* Stress test: Do 500 channel activations/deactivations in rapid succession */
543function f_TC_chan_act_stress(charstring id) runs on ConnHdlr {
544 for (var integer i := 0; i < 500; i := i+1) {
545 f_rsl_chan_act(g_pars.chan_mode);
546 f_rsl_chan_deact();
547 }
548 setverdict(pass);
549}
550testcase TC_chan_act_stress() runs on test_CT {
551 var ConnHdlr vc_conn;
552 var ConnHdlrPars pars := valueof(t_Pars(t_RslChanNr_Bm(1), ts_RSL_ChanMode_SIGN));
553 f_init(testcasename());
554 vc_conn := f_start_handler(refers(f_TC_chan_act_stress), pars);
555 vc_conn.done;
Harald Welte294b0a22018-03-10 23:26:48 +0100556 f_shutdown();
Harald Welte70767382018-02-21 12:16:40 +0100557}
558
559/* Test if re-activation of an already active channel fails as expected */
560function f_TC_chan_act_react(charstring id) runs on ConnHdlr {
561 f_rsl_chan_act(g_pars.chan_mode);
562 /* attempt to activate the same lchan again -> expect reject */
563 RSL.send(ts_RSL_CHAN_ACT(g_chan_nr, g_pars.chan_mode));
564 alt {
565 [] RSL.receive(tr_RSL_CHAN_ACT_ACK(g_chan_nr)) {
566 setverdict(fail, "Unexpected CHAN ACT ACK on double activation");
Daniel Willmann17ddd852018-07-05 17:33:20 +0200567 mtc.stop;
Harald Welte70767382018-02-21 12:16:40 +0100568 }
569 [] RSL.receive(tr_RSL_CHAN_ACT_NACK(g_chan_nr)) {
570 setverdict(pass);
571 }
572 }
573 f_rsl_chan_deact();
574}
575testcase TC_chan_act_react() runs on test_CT {
576 var ConnHdlr vc_conn;
577 var ConnHdlrPars pars := valueof(t_Pars(t_RslChanNr_Bm(1), ts_RSL_ChanMode_SIGN));
Harald Welte294b0a22018-03-10 23:26:48 +0100578 f_init();
Harald Welte70767382018-02-21 12:16:40 +0100579 vc_conn := f_start_handler(refers(f_TC_chan_act_react), pars);
580 vc_conn.done;
Harald Welte294b0a22018-03-10 23:26:48 +0100581 f_shutdown();
Harald Welte70767382018-02-21 12:16:40 +0100582}
583
584/* Attempt to de-activate a channel that's not active */
585function f_TC_chan_deact_not_active(charstring id) runs on ConnHdlr {
586 timer T := 3.0;
587 RSL.send(ts_RSL_RF_CHAN_REL(g_chan_nr));
588 T.start;
589 alt {
590 [] RSL.receive(tr_RSL_RF_CHAN_REL_ACK(g_chan_nr)) {
591 setverdict(pass);
592 }
593 [] T.timeout {
594 setverdict(fail, "Timeout expecting RF_CHAN_REL_ACK");
Daniel Willmann17ddd852018-07-05 17:33:20 +0200595 mtc.stop;
Harald Welte70767382018-02-21 12:16:40 +0100596 }
597 }
598}
599testcase TC_chan_deact_not_active() runs on test_CT {
600 var ConnHdlrPars pars := valueof(t_Pars(t_RslChanNr_Bm(1), ts_RSL_ChanMode_SIGN));
Harald Welte294b0a22018-03-10 23:26:48 +0100601 f_init();
Harald Welte70767382018-02-21 12:16:40 +0100602 var ConnHdlr vc_conn := f_start_handler(refers(f_TC_chan_deact_not_active), pars);
603 vc_conn.done;
Harald Welte294b0a22018-03-10 23:26:48 +0100604 f_shutdown();
Harald Welte70767382018-02-21 12:16:40 +0100605}
606
607/* attempt to activate channel with wrong RSL Channel Nr IE; expect NACK */
608function f_TC_chan_act_wrong_nr(charstring id) runs on ConnHdlr {
609 RSL.send(ts_RSL_CHAN_ACT(g_chan_nr, g_pars.chan_mode));
610 alt {
611 [] RSL.receive(tr_RSL_CHAN_ACT_ACK(g_chan_nr)) {
612 setverdict(fail, "Unexpected CHAN ACT ACK");
Daniel Willmann17ddd852018-07-05 17:33:20 +0200613 mtc.stop;
Harald Welte70767382018-02-21 12:16:40 +0100614 }
615 [] RSL.receive(tr_RSL_CHAN_ACT_NACK(g_chan_nr)) {
616 setverdict(pass);
617 }
618 }
619}
620private type record WrongChanNrCase {
621 RslChannelNr chan_nr,
622 charstring description
623}
624private type record of WrongChanNrCase WrongChanNrCases;
625private template WrongChanNrCase t_WCN(template RslChannelNr chan_nr, charstring desc) := {
626 chan_nr := chan_nr,
627 description := desc
628}
629
630testcase TC_chan_act_wrong_nr() runs on test_CT {
631 var ConnHdlr vc_conn;
632 var ConnHdlrPars pars;
633
Harald Welte294b0a22018-03-10 23:26:48 +0100634 f_init();
Harald Welte70767382018-02-21 12:16:40 +0100635
636 var WrongChanNrCases wrong := {
637 valueof(t_WCN(t_RslChanNr_RACH(0), "RACH is not a dedicated channel")),
638 valueof(t_WCN(t_RslChanNr_RACH(1), "RACH doesn't exist on timeslot")),
639 valueof(t_WCN(t_RslChanNr_BCCH(0), "BCCH is not a dedicated channel")),
640 valueof(t_WCN(t_RslChanNr_PCH_AGCH(0), "PCH/AGCH is not a dedicated channel")),
641 valueof(t_WCN(t_RslChanNr_Bm(0), "TS0 cannot be TCH/F")),
642 valueof(t_WCN(t_RslChanNr_Lm(0, 0), "TS0 cannot be TCH/H")),
643 valueof(t_WCN(t_RslChanNr_Lm(0, 1), "TS0 cannot be TCH/H")),
644 valueof(t_WCN(t_RslChanNr_PDCH(0), "TS0 cannot be PDCH")),
645 valueof(t_WCN(t_RslChanNr_SDCCH8(0, 0), "TS0 cannot be SDCCH/8")),
646 valueof(t_WCN(t_RslChanNr_SDCCH8(0, 7), "TS0 cannot be SDCCH/8")),
647 valueof(t_WCN(t_RslChanNr_SDCCH4(7, 0), "TS7 cannot be SDCCH/4")),
648 valueof(t_WCN(t_RslChanNr_SDCCH4(7, 3), "TS7 cannot be SDCCH/4")),
649 valueof(t_WCN(t_RslChanNr_Lm(1, 0), "TS1 cannot be TCH/H"))
650 };
651
652 for (var integer i := 0; i < sizeof(wrong); i := i+1) {
653 pars := valueof(t_Pars(wrong[i].chan_nr, ts_RSL_ChanMode_SIGN));
654 vc_conn := f_start_handler(refers(f_TC_chan_act_wrong_nr), pars);
655 vc_conn.done;
656 }
Harald Welte294b0a22018-03-10 23:26:48 +0100657 f_shutdown();
Harald Welte70767382018-02-21 12:16:40 +0100658}
659
Harald Weltee613f962018-04-18 22:38:16 +0200660/* execute the same callback function on a variety of logical channels */
661private function f_testmatrix_each_chan(ConnHdlrPars pars, void_fn fn) runs on test_CT {
662 var ConnHdlr vc_conn;
663 f_init(testcasename());
664
665 /* test on each of the channels we have */
666 for (var integer i := 0; i < sizeof(g_AllChanTypes); i := i+1) {
667 pars.chan_nr := valueof(g_AllChanTypes[i]);
668
669 log(testcasename(), ": XXX Starting on ", g_AllChanTypes[i]);
670 vc_conn := f_start_handler(fn, pars);
671 vc_conn.done;
672 }
673
674 f_shutdown();
675}
676
Harald Welte93640c62018-02-25 16:59:33 +0100677/***********************************************************************
Harald Welte629cc6b2018-03-11 17:19:05 +0100678 * SACCH handling
679 ***********************************************************************/
680
681private function f_exp_sacch(boolean exp) runs on ConnHdlr {
682 timer T_sacch := 3.0;
683 T_sacch.start;
684 alt {
685 [not exp] L1CTL.receive(tr_L1CTL_DATA_IND(g_chan_nr, tr_RslLinkID_SACCH(0))) {
686 setverdict(fail, "Received SACCH when not expecting it");
Daniel Willmann17ddd852018-07-05 17:33:20 +0200687 mtc.stop;
Harald Welte629cc6b2018-03-11 17:19:05 +0100688 }
689 [not exp] T_sacch.timeout {
690 setverdict(pass);
691 }
692 [exp] L1CTL.receive(tr_L1CTL_DATA_IND(g_chan_nr, tr_RslLinkID_SACCH(0))) {
693 setverdict(pass);
694 }
695 [exp] T_sacch.timeout {
696 setverdict(fail, "Timeout waiting for SACCH on ", g_chan_nr);
Daniel Willmann17ddd852018-07-05 17:33:20 +0200697 mtc.stop;
Harald Welte629cc6b2018-03-11 17:19:05 +0100698 }
699 [] L1CTL.receive { repeat; }
700 [] RSL.receive { repeat; }
701 }
702}
703
704/* Test if DEACTIVATE SACCH actualy deactivates its transmission (TS 48.058 4.6) */
705private function f_TC_deact_sacch(charstring id) runs on ConnHdlr {
706 f_l1_tune(L1CTL);
707 RSL.clear;
708
709 /* activate the logical channel */
710 f_est_dchan();
711 L1CTL.clear;
712
713 /* check that SACCH actually are received as expected */
714 f_exp_sacch(true);
715
716 /* deactivate SACCH on the logical channel */
717 RSL.send(ts_RSL_DEACT_SACCH(g_chan_nr));
718 f_sleep(1.0);
719 L1CTL.clear;
720
721 /* check that no SACCH are received anymore */
722 f_exp_sacch(false);
723
724 /* release the channel */
725 f_rsl_chan_deact();
726 f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
727}
728testcase TC_deact_sacch() runs on test_CT {
729 var ConnHdlr vc_conn;
730 var ConnHdlrPars pars;
731 f_init();
732 for (var integer i := 0; i < sizeof(g_AllChannels); i := i+1) {
733 //for (var integer i := 0; i < 1; i := i+1) {
734 pars := valueof(t_Pars(g_AllChannels[i], ts_RSL_ChanMode_SIGN));
735 log(testcasename(), ": Starting for ", g_AllChannels[i]);
736 vc_conn := f_start_handler(refers(f_TC_deact_sacch), pars);
737 vc_conn.done;
738 }
739 /* TODO: do the above in parallel, rather than sequentially? */
740 f_shutdown();
741}
742
Harald Welte55700662018-03-12 13:15:43 +0100743/* verify that given SACCH payload is present */
Harald Welteea17b912018-03-11 22:29:31 +0100744private function f_sacch_present(template octetstring l3_exp) runs on ConnHdlr {
745 var L1ctlDlMessage dl;
746 /* check that the specified SI5 value is actually sent */
747 timer T_sacch := 3.0;
748 L1CTL.clear;
749 T_sacch.start;
750 alt {
751 [] L1CTL.receive(tr_L1CTL_DATA_IND(g_chan_nr, tr_RslLinkID_SACCH(0))) -> value dl {
752 var octetstring l3 := substr(dl.payload.data_ind.payload, 4, 19);
753 if (match(l3, l3_exp)) {
754 setverdict(pass);
755 } else {
756 repeat;
757 }
758 }
759 [] L1CTL.receive { repeat; }
760 [] T_sacch.timeout {
761 setverdict(fail, "Timeout waiting for SACCH ", l3_exp);
Daniel Willmann17ddd852018-07-05 17:33:20 +0200762 mtc.stop;
Harald Welteea17b912018-03-11 22:29:31 +0100763 }
764 }
765}
766
Harald Welte55700662018-03-12 13:15:43 +0100767/* verify that given SACCH payload is not present */
768private function f_sacch_missing(template octetstring l3_exp) runs on ConnHdlr {
769 var L1ctlDlMessage dl;
770 /* check that the specified SI5 value is actually sent */
771 timer T_sacch := 3.0;
772 L1CTL.clear;
773 T_sacch.start;
774 alt {
775 [] L1CTL.receive(tr_L1CTL_DATA_IND(g_chan_nr, tr_RslLinkID_SACCH(0))) -> value dl {
776 var octetstring l3 := substr(dl.payload.data_ind.payload, 4, 19);
777 if (match(l3, l3_exp)) {
778 setverdict(fail, "Received unexpected SACCH ", dl);
Daniel Willmann3487a852018-07-05 15:41:59 +0200779 mtc.stop;
Harald Welte55700662018-03-12 13:15:43 +0100780 } else {
781 repeat;
782 }
783 }
784 [] L1CTL.receive { repeat; }
785 [] T_sacch.timeout {
786 setverdict(pass);
787 }
788 }
789}
790
Harald Welte629cc6b2018-03-11 17:19:05 +0100791/* Test for default SACCH FILL transmitted in DL SACCH (all channel types) */
Harald Welteea17b912018-03-11 22:29:31 +0100792private function f_TC_sacch_filling(charstring id) runs on ConnHdlr {
793 /* Set a known default SACCH filling for SI5 */
794 var octetstring si5 := f_rnd_octstring(19);
795 RSL.send(ts_RSL_SACCH_FILL(RSL_SYSTEM_INFO_5, si5));
796
797 f_l1_tune(L1CTL);
798 RSL.clear;
799
800 /* activate the logical channel */
801 f_est_dchan();
802
803 /* check that the specified SI5 value is actually sent */
804 f_sacch_present(si5);
805
806 /* release the channel */
807 RSL.clear;
808 f_rsl_chan_deact();
809 f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
810}
811testcase TC_sacch_filling() runs on test_CT {
812 var ConnHdlr vc_conn;
813 var ConnHdlrPars pars;
814 f_init();
815 for (var integer i := 0; i < sizeof(g_AllChannels); i := i+1) {
816 pars := valueof(t_Pars(g_AllChannels[i], ts_RSL_ChanMode_SIGN));
817 log(testcasename(), ": Starting for ", g_AllChannels[i]);
818 vc_conn := f_start_handler(refers(f_TC_sacch_filling), pars);
819 vc_conn.done;
820 }
821 /* TODO: do the above in parallel, rather than sequentially? */
822 f_shutdown();
823}
824
Harald Welte629cc6b2018-03-11 17:19:05 +0100825/* Test for lchan-specific SACCH INFO MODIFY (TS 48.058 4.12) */
Harald Welteea17b912018-03-11 22:29:31 +0100826private function f_TC_sacch_info_mod(charstring id) runs on ConnHdlr {
827 /* Set a known default SACCH filling for SI5 */
828 var octetstring si5 := f_rnd_octstring(19);
829 var octetstring si5_diff := f_rnd_octstring(19);
830 RSL.send(ts_RSL_SACCH_FILL(RSL_SYSTEM_INFO_5, si5));
831
832 f_l1_tune(L1CTL);
833 RSL.clear;
834
835 log("Activating channel, expecting standard SI5");
836 /* activate the logical channel */
837 f_est_dchan();
838 /* check that the specified SI5 value is actually sent */
839 f_sacch_present(si5);
840
841 /* set channel-specific different SI5 */
842 log("Setting channel specific SACCH INFO, expecting it");
843 RSL.send(ts_RSL_SACCH_INF_MOD(g_chan_nr, RSL_SYSTEM_INFO_5, si5_diff))
844 /* check that the specified lchan-specific value is now used */
845 f_sacch_present(si5_diff);
846
847 /* deactivate the channel and re-activate it, this should result in default SI5 */
848 log("De-activating and re-activating channel, expecting standard SI5");
849 f_rsl_chan_deact();
850 f_rsl_chan_act(valueof(ts_RSL_ChanMode_SIGN));
851 /* Verify that the TRX-wide default SACCH filling is present again */
852 f_sacch_present(si5);
853
854 /* release the channel */
855 RSL.clear;
856 f_rsl_chan_deact();
857 f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
858}
859testcase TC_sacch_info_mod() runs on test_CT {
860 var ConnHdlr vc_conn;
861 var ConnHdlrPars pars;
862 f_init();
863 for (var integer i := 0; i < sizeof(g_AllChannels); i := i+1) {
864 pars := valueof(t_Pars(g_AllChannels[i], ts_RSL_ChanMode_SIGN));
865 log(testcasename(), ": Starting for ", g_AllChannels[i]);
866 vc_conn := f_start_handler(refers(f_TC_sacch_info_mod), pars);
867 vc_conn.done;
868 }
869 /* TODO: do the above in parallel, rather than sequentially? */
870 f_shutdown();
871}
872
Harald Welte075d84c2018-03-12 13:07:24 +0100873/* Test SACCH scheduling of multiple different SI message types */
874private function f_TC_sacch_multi(charstring id) runs on ConnHdlr {
875 var octetstring si5 := f_rnd_octstring(19);
876 var octetstring si5bis := f_rnd_octstring(19);
877 var octetstring si5ter := f_rnd_octstring(19);
878 var octetstring si6 := f_rnd_octstring(19);
879
880 RSL.send(ts_RSL_SACCH_FILL(RSL_SYSTEM_INFO_5, si5));
881 RSL.send(ts_RSL_SACCH_FILL(RSL_SYSTEM_INFO_5bis, si5bis));
882 RSL.send(ts_RSL_SACCH_FILL(RSL_SYSTEM_INFO_5ter, si5ter));
883 RSL.send(ts_RSL_SACCH_FILL(RSL_SYSTEM_INFO_6, si6));
884
885 f_l1_tune(L1CTL);
886 RSL.clear;
887
888 /* activate the logical channel */
889 f_est_dchan();
890 L1CTL.clear;
891
892 /* check that SACCH actually are received as expected */
893 f_sacch_present(si5);
894 f_sacch_present(si5bis);
895 f_sacch_present(si5ter);
896 f_sacch_present(si6);
897
898 /* release the channel */
899 f_rsl_chan_deact();
900 f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
901}
902testcase TC_sacch_multi() runs on test_CT {
903 var ConnHdlr vc_conn;
904 var ConnHdlrPars pars;
905 f_init();
906 for (var integer i := 0; i < sizeof(g_AllChannels); i := i+1) {
907 pars := valueof(t_Pars(g_AllChannels[i], ts_RSL_ChanMode_SIGN));
908 log(testcasename(), ": Starting for ", g_AllChannels[i]);
909 vc_conn := f_start_handler(refers(f_TC_sacch_multi), pars);
910 vc_conn.done;
911 }
912 /* TODO: do the above in parallel, rather than sequentially? */
913 f_shutdown();
914}
915
Harald Welte55700662018-03-12 13:15:43 +0100916/* Test if SACH information is modified as expected */
917private function f_TC_sacch_multi_chg(charstring id) runs on ConnHdlr {
918 var octetstring si5 := f_rnd_octstring(19);
919 var octetstring si6 := f_rnd_octstring(19);
920
921 /* First, configure both SI5 and SI6 to be transmitted */
922 RSL.send(ts_RSL_SACCH_FILL(RSL_SYSTEM_INFO_5, si5));
923 RSL.send(ts_RSL_SACCH_FILL(RSL_SYSTEM_INFO_6, si6));
924
925 f_l1_tune(L1CTL);
926 RSL.clear;
927
928 /* activate the logical channel */
929 f_est_dchan();
930 L1CTL.clear;
931
932 /* check that SACCH actually are received as expected */
933 f_sacch_present(si5);
934 f_sacch_present(si6);
935
936 /* disable SI6 */
937 RSL.send(ts_RSL_SACCH_FILL(RSL_SYSTEM_INFO_6, ''O));
938
939 /* check that SI5 is still transmitted */
940 f_sacch_present(si5);
941 /* check if SI6 is now gone */
942 f_sacch_missing(si6);
943
944 /* release the channel */
945 f_rsl_chan_deact();
946 f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
947}
948testcase TC_sacch_multi_chg() runs on test_CT {
949 var ConnHdlr vc_conn;
950 var ConnHdlrPars pars;
951 f_init();
952 for (var integer i := 0; i < sizeof(g_AllChannels); i := i+1) {
953 pars := valueof(t_Pars(g_AllChannels[i], ts_RSL_ChanMode_SIGN));
954 log(testcasename(), ": Starting for ", g_AllChannels[i]);
955 vc_conn := f_start_handler(refers(f_TC_sacch_multi_chg), pars);
956 vc_conn.done;
957 }
958 /* TODO: do the above in parallel, rather than sequentially? */
959 f_shutdown();
960}
961
Harald Welte075d84c2018-03-12 13:07:24 +0100962/* TODO: Test for SACCH information present in RSL CHAN ACT (overrides FILLING) */
963/* TODO: Test for SACCH transmission rules in the context of special CHAN ACT (HO) */
Harald Welte629cc6b2018-03-11 17:19:05 +0100964
965
966/***********************************************************************
Harald Welte93640c62018-02-25 16:59:33 +0100967 * RACH Handling
968 ***********************************************************************/
969
Harald Welte8c24c2b2018-02-26 08:31:31 +0100970/* like L1SAP_IS_PACKET_RACH */
971private function ra_is_ps(OCT1 ra) return boolean {
Harald Welte56c05802018-02-28 21:39:35 +0100972 if ((ra and4b 'F0'O == '70'O) and (ra and4b '0F'O != '0F'O)) {
Harald Welte8c24c2b2018-02-26 08:31:31 +0100973 return true;
974 }
975 return false;
976}
977
978/* generate a random RACH for circuit-switched */
979private function f_rnd_ra_cs() return OCT1 {
980 var OCT1 ra;
981 do {
982 ra := f_rnd_octstring(1);
983 } while (ra_is_ps(ra));
984 return ra;
985}
986
Harald Welte883340c2018-02-28 18:59:29 +0100987/* generate a random RACH for packet-switched */
988private function f_rnd_ra_ps() return OCT1 {
989 var OCT1 ra;
990 do {
991 ra := f_rnd_octstring(1);
992 } while (not ra_is_ps(ra));
993 return ra;
994}
995
Harald Welte8c24c2b2018-02-26 08:31:31 +0100996/* Send 1000 RACH requests and check their RA+FN on the RSL side */
997testcase TC_rach_content() runs on test_CT {
998 f_init(testcasename());
999 f_init_l1ctl();
Harald Welte68e495b2018-02-25 00:05:57 +01001000 f_l1_tune(L1CTL);
Harald Welte70767382018-02-21 12:16:40 +01001001
Harald Welte8c24c2b2018-02-26 08:31:31 +01001002 var GsmFrameNumber fn_last := 0;
1003 for (var integer i := 0; i < 1000; i := i+1) {
1004 var OCT1 ra := f_rnd_ra_cs();
1005 var GsmFrameNumber fn := f_L1CTL_RACH(L1CTL, oct2int(ra));
1006 if (fn == fn_last) {
1007 setverdict(fail, "Two RACH in same FN?!?");
Daniel Willmann17ddd852018-07-05 17:33:20 +02001008 mtc.stop;
Harald Welte8c24c2b2018-02-26 08:31:31 +01001009 }
1010 fn_last := fn;
1011
1012 timer T := 5.0;
Harald Welte56c05802018-02-28 21:39:35 +01001013 T.start;
Harald Welte8c24c2b2018-02-26 08:31:31 +01001014 alt {
1015 [] RSL_CCHAN.receive(tr_RSL_UD(tr_RSL_CHAN_RQD(ra, fn, ?))) {
1016 T.stop;
1017 }
1018 [] RSL_CCHAN.receive(tr_RSL_UD(tr_RSL_CHAN_RQD(?, ?, ?))) {
1019 setverdict(fail, "Unexpected CHAN RQD");
Daniel Willmann17ddd852018-07-05 17:33:20 +02001020 mtc.stop;
Harald Welte8c24c2b2018-02-26 08:31:31 +01001021 }
1022 [] RSL_CCHAN.receive { repeat; }
1023 [] T.timeout {
1024 setverdict(fail, "Timeout waiting for CHAN RQD");
Daniel Willmann17ddd852018-07-05 17:33:20 +02001025 mtc.stop;
Harald Welte8c24c2b2018-02-26 08:31:31 +01001026 }
1027 }
1028 }
1029 setverdict(pass);
Harald Welte294b0a22018-03-10 23:26:48 +01001030 f_shutdown();
Harald Welte70767382018-02-21 12:16:40 +01001031}
Harald Welte8c24c2b2018-02-26 08:31:31 +01001032
1033/* Send 1000 RACH Requests (flood ~ 89/s) and count if count(Abis) == count(Um) */
1034testcase TC_rach_count() runs on test_CT {
Harald Welte294b0a22018-03-10 23:26:48 +01001035 f_init();
Harald Welte8c24c2b2018-02-26 08:31:31 +01001036 f_init_l1ctl();
Harald Welte294b0a22018-03-10 23:26:48 +01001037 f_sleep(1.0);
Harald Welte8c24c2b2018-02-26 08:31:31 +01001038 f_l1_tune(L1CTL);
1039
1040 var GsmFrameNumber fn_last := 0;
1041 for (var integer i := 0; i < 1000; i := i+1) {
1042 var OCT1 ra := f_rnd_ra_cs();
1043 var GsmFrameNumber fn := f_L1CTL_RACH(L1CTL, oct2int(ra));
1044 if (fn == fn_last) {
1045 setverdict(fail, "Two RACH in same FN?!?");
Daniel Willmann17ddd852018-07-05 17:33:20 +02001046 mtc.stop;
Harald Welte8c24c2b2018-02-26 08:31:31 +01001047 }
1048 fn_last := fn;
1049 }
1050 var integer rsl_chrqd := 0;
1051 timer T := 3.0;
Harald Welte56c05802018-02-28 21:39:35 +01001052 T.start;
Harald Welte8c24c2b2018-02-26 08:31:31 +01001053 alt {
1054 [] RSL_CCHAN.receive(tr_RSL_UD(tr_RSL_CHAN_RQD(?,?))) {
1055 rsl_chrqd := rsl_chrqd + 1;
Harald Weltec3a3f452018-02-26 17:37:47 +01001056 f_timer_safe_restart(T);
Harald Welte8c24c2b2018-02-26 08:31:31 +01001057 repeat;
1058 }
1059 [] RSL_CCHAN.receive { repeat; }
1060 [] T.timeout { }
1061 }
1062 if (rsl_chrqd == 1000) {
1063 setverdict(pass);
1064 } else {
1065 setverdict(fail, "Received only ", rsl_chrqd, " out of 1000 RACH");
1066 }
Harald Welte294b0a22018-03-10 23:26:48 +01001067 f_shutdown();
Harald Welte70767382018-02-21 12:16:40 +01001068}
1069
Harald Welte54a2a2d2018-02-26 09:14:05 +01001070private function f_main_trxc_connect() runs on test_CT {
1071 map(self:BB_TRXC, system:BB_TRXC);
1072 var Result res;
Harald Welted3a88a62018-03-01 16:04:52 +01001073 res := TRXC_CodecPort_CtrlFunct.f_IPL4_connect(BB_TRXC, mp_bb_trxc_ip, mp_bb_trxc_port,
1074 "", -1, -1, {udp:={}}, {});
Harald Welte9220f632018-05-23 20:27:02 +02001075 if (not ispresent(res.connId)) {
1076 setverdict(fail, "Could not connect to trx-control interface of trxcon, check your configuration");
Daniel Willmann17ddd852018-07-05 17:33:20 +02001077 mtc.stop;
Harald Welte9220f632018-05-23 20:27:02 +02001078 }
Harald Welte54a2a2d2018-02-26 09:14:05 +01001079 g_bb_trxc_conn_id := res.connId;
1080}
1081
1082private function f_rach_toffs(int16_t toffs256, boolean expect_pass) runs on test_CT {
Harald Weltef8df4cb2018-03-10 15:15:08 +01001083 var TrxcMessage ret;
Harald Welte54a2a2d2018-02-26 09:14:05 +01001084 /* tell fake_trx to use a given timing offset for all bursts */
Harald Weltef8df4cb2018-03-10 15:15:08 +01001085 ret := f_TRXC_transceive(BB_TRXC, g_bb_trxc_conn_id, valueof(ts_TRXC_FAKE_TIMING(toffs256)));
Harald Welte54a2a2d2018-02-26 09:14:05 +01001086 f_sleep(0.5);
1087
1088 /* Transmit RACH request + wait for confirmation */
1089 var OCT1 ra := f_rnd_ra_cs();
1090 var GsmFrameNumber fn := f_L1CTL_RACH(L1CTL, oct2int(ra));
1091
1092 /* Check for expected result */
1093 timer T := 1.5;
1094 T.start;
1095 alt {
1096 [expect_pass] RSL_CCHAN.receive(tr_RSL_UD(tr_RSL_CHAN_RQD(ra, fn))) {
1097 setverdict(pass);
1098 }
1099 [not expect_pass] RSL_CCHAN.receive(tr_RSL_UD(tr_RSL_CHAN_RQD(ra, fn))) {
Harald Welteb3e30942018-03-02 10:33:42 +01001100 setverdict(fail, "RACH passed but was expected to be dropped: ", toffs256);
Daniel Willmann17ddd852018-07-05 17:33:20 +02001101 mtc.stop;
Harald Welte54a2a2d2018-02-26 09:14:05 +01001102 }
1103 [] RSL_CCHAN.receive { repeat; }
1104 [not expect_pass] T.timeout {
1105 setverdict(pass);
1106 }
1107 [expect_pass] T.timeout {
1108 setverdict(fail, "Timeout waiting for CHAN RQD");
Daniel Willmann17ddd852018-07-05 17:33:20 +02001109 mtc.stop;
Harald Welte54a2a2d2018-02-26 09:14:05 +01001110 }
1111 }
1112}
1113
1114/* Test if dropping of RACH Based on NM_ATT_MAX_TA works */
1115testcase TC_rach_max_ta() runs on test_CT {
1116 f_init(testcasename());
1117 f_init_l1ctl();
1118 f_l1_tune(L1CTL);
Harald Welte54a2a2d2018-02-26 09:14:05 +01001119 f_sleep(1.0);
1120
1121 /* default max-ta is 63 (full range of GSM timing advance */
1122
Vadim Yanitskiyc81d6e42018-03-05 22:39:01 +07001123 /* We allow early arrival up to 2 symbols */
1124 f_rach_toffs(-1*256, true);
1125 f_rach_toffs(-2*256, true);
Harald Welte54a2a2d2018-02-26 09:14:05 +01001126 f_rach_toffs(-10*256, false);
1127
1128 /* 0 / 32 / 63 bits is legal / permitted */
1129 f_rach_toffs(0, true);
1130 f_rach_toffs(32*256, true);
1131 f_rach_toffs(63*256, true);
1132
1133 /* more than 63 bits is not legal / permitted */
1134 f_rach_toffs(64*256, false);
1135 f_rach_toffs(127*256, false);
Harald Welte294b0a22018-03-10 23:26:48 +01001136 f_shutdown();
Harald Welte54a2a2d2018-02-26 09:14:05 +01001137}
Harald Welte8c24c2b2018-02-26 08:31:31 +01001138
Harald Welte93640c62018-02-25 16:59:33 +01001139/***********************************************************************
1140 * Measurement Processing / Reporting
1141 ***********************************************************************/
1142
Harald Welte70767382018-02-21 12:16:40 +01001143template LapdmAddressField ts_LapdmAddr(LapdmSapi sapi, boolean c_r) := {
1144 spare := '0'B,
1145 lpd := 0,
1146 sapi := sapi,
1147 c_r := c_r,
1148 ea := true
1149}
1150
Harald Welted879bd92018-03-12 15:01:23 +01001151template LapdmFrameAB ts_LAPDm_AB(LapdmSapi sapi, boolean c_r, boolean p, octetstring pl) := {
Harald Welte70767382018-02-21 12:16:40 +01001152 addr := ts_LapdmAddr(sapi, c_r),
Harald Welted879bd92018-03-12 15:01:23 +01001153 ctrl := ts_LapdmCtrlUI(p),
Harald Welte70767382018-02-21 12:16:40 +01001154 len := 0, /* overwritten */
1155 m := false,
1156 el := 1,
1157 payload := pl
1158}
1159
1160/* handle incoming downlink SACCH and respond with uplink SACCH (meas res) */
1161altstep as_l1_sacch() runs on ConnHdlr {
1162 var L1ctlDlMessage l1_dl;
Harald Weltef8df4cb2018-03-10 15:15:08 +01001163 [] L1CTL.receive(tr_L1CTL_DATA_IND(g_chan_nr, tr_RslLinkID_SACCH(?))) -> value l1_dl {
Harald Welte70767382018-02-21 12:16:40 +01001164 log("SACCH received: ", l1_dl.payload.data_ind.payload);
1165 var GsmRrL3Message meas_rep := valueof(ts_MEAS_REP(true, 23, 23, 0, 0, omit));
Harald Welted879bd92018-03-12 15:01:23 +01001166 var LapdmFrameAB lb := valueof(ts_LAPDm_AB(0, false, false, enc_GsmRrL3Message(meas_rep)));
Harald Welte70767382018-02-21 12:16:40 +01001167 log("LAPDm: ", lb);
Pau Espin Pedroled359cb2018-09-28 16:08:24 +02001168
1169 var L1ctlDataReq data_req := {
1170 l1header := valueof(ts_SacchL1Header(g_pars.l1_pars.ms_power_level, false, g_pars.l1_pars.ms_actual_ta)),
1171 l2_payload := f_pad_oct(enc_LapdmFrameAB(lb), 21, '2B'O)
1172 }
1173 log("Sending Measurement Report: ", data_req);
1174 L1CTL.send(ts_L1CTL_DATA_REQ_SACCH(g_chan_nr, ts_RslLinkID_SACCH(0), data_req));
Harald Welte70767382018-02-21 12:16:40 +01001175 repeat;
1176 }
1177}
1178
1179altstep as_l1_dcch() runs on ConnHdlr {
1180 var L1ctlDlMessage l1_dl;
Harald Weltef8df4cb2018-03-10 15:15:08 +01001181 [] L1CTL.receive(tr_L1CTL_DATA_IND(g_chan_nr, tr_RslLinkID_DCCH(?))) -> value l1_dl {
Harald Welte70767382018-02-21 12:16:40 +01001182 log("DCCH received: ", l1_dl.payload.data_ind.payload);
1183 var octetstring pl := '010301'O;
Vadim Yanitskiy31e7c672018-07-27 02:23:16 +07001184 L1CTL.send(ts_L1CTL_DATA_REQ(g_chan_nr, ts_RslLinkID_DCCH(0),
1185 f_pad_oct(pl, 23, '2B'O)));
Harald Welte70767382018-02-21 12:16:40 +01001186 repeat;
1187 }
1188}
1189
1190type record MeasElem {
1191 uint6_t rxlev,
1192 uint3_t rxqual
1193}
1194
1195type record MeasElemFS {
1196 MeasElem full,
1197 MeasElem sub
1198}
1199
1200type record ConnL1Pars {
1201 boolean dtx_enabled,
Harald Welte685d5982018-02-27 20:42:05 +01001202 boolean toa256_enabled,
Harald Welte70767382018-02-21 12:16:40 +01001203 MeasElemFS meas_ul,
1204 int16_t timing_offset_256syms,
1205 uint5_t bs_power_level,
1206 uint5_t ms_power_level,
1207 uint8_t ms_actual_ta
1208}
1209
1210/* Convert tiing offset from 1/256th symbol to RSL Timing Offset */
1211private function toffs256s_to_rsl(int16_t toffs256s) return uint8_t {
1212 return 63 + (toffs256s/256);
1213}
1214
Harald Welted5684392018-03-10 18:22:04 +01001215private function f_max(integer a, integer b) return integer {
1216 if (a > b) {
1217 return a;
1218 } else {
1219 return b;
1220 }
1221}
1222
1223private function f_min(integer a, integer b) return integer {
1224 if (a < b) {
1225 return a;
1226 } else {
1227 return b;
1228 }
1229}
1230
1231/* compute negative tolerance val-tolerance, ensure >= min */
1232private function f_tolerance_neg(integer val, integer min, integer tolerance) return integer {
1233 val := val - tolerance;
1234 return f_max(val, min);
1235}
1236
1237/* compute positive tolerance val+tolerance, ensure <= max */
1238private function f_tolerance_pos(integer val, integer max, integer tolerance) return integer {
1239 val := val + tolerance;
1240 return f_min(val, max);
1241}
1242
1243/* return a template of (val-tolerance .. val+tolerance) ensuring it is within (min .. max) */
1244private function f_tolerance(integer val, integer min, integer max, integer tolerance)
1245return template integer {
1246 var template integer ret;
1247 ret := (f_tolerance_neg(val, min, tolerance) .. f_tolerance_pos(val, max, tolerance));
1248 return ret;
1249}
1250
1251
Harald Welte70767382018-02-21 12:16:40 +01001252/* build a template for matching measurement results against */
1253private function f_build_meas_res_tmpl() runs on ConnHdlr return template RSL_Message {
1254 var ConnL1Pars l1p := g_pars.l1_pars;
1255 var template RSL_IE_UplinkMeas ul_meas := {
1256 len := 3,
1257 rfu := '0'B,
1258 dtx_d := l1p.dtx_enabled,
Harald Welted5684392018-03-10 18:22:04 +01001259 rxlev_f_u := f_tolerance(l1p.meas_ul.full.rxlev, 0, 63, mp_tolerance_rxlev),
Harald Welte70767382018-02-21 12:16:40 +01001260 reserved1 := '00'B,
Harald Welted5684392018-03-10 18:22:04 +01001261 rxlev_s_u := f_tolerance(l1p.meas_ul.sub.rxlev, 0, 63, mp_tolerance_rxlev),
Harald Welte70767382018-02-21 12:16:40 +01001262 reserved2 := '00'B,
Harald Welted5684392018-03-10 18:22:04 +01001263 rxq_f_u := f_tolerance(l1p.meas_ul.full.rxqual, 0, 7, mp_tolerance_rxqual),
1264 rxq_s_u := f_tolerance(l1p.meas_ul.sub.rxqual, 0, 7, mp_tolerance_rxqual),
Harald Welte70767382018-02-21 12:16:40 +01001265 supp_meas_info := omit
1266 };
Harald Welte685d5982018-02-27 20:42:05 +01001267 if (l1p.toa256_enabled) {
Harald Welte15de8ba2018-06-29 08:51:42 +02001268 ul_meas.len := (3+8);
1269 ul_meas.supp_meas_info := {
Pau Espin Pedrol121724c2018-09-28 15:58:12 +02001270 toa256_mean := f_tolerance(l1p.timing_offset_256syms, -63*256, 192*256, mp_tolerance_timing_offset_256syms),
Harald Welte15de8ba2018-06-29 08:51:42 +02001271 toa256_min := ?,
1272 toa256_max := ?,
1273 toa256_std_dev := ?
1274 }
Harald Welte685d5982018-02-27 20:42:05 +01001275 }
Harald Welte70767382018-02-21 12:16:40 +01001276 /* HACK HACK HACK FIXME HACK HACK HACK see https://osmocom.org/issues/2988 */
1277 ul_meas.rxlev_f_u := ?;
1278 ul_meas.rxlev_s_u := ?;
1279 ul_meas.rxq_f_u := ?;
1280 ul_meas.rxq_s_u := ?;
1281 var template RSL_IE_BS_Power bs_power := {
1282 reserved := 0,
1283 epc := false,
1284 fpc := false,
1285 power_level := l1p.bs_power_level
1286 };
1287 var template RSL_IE_L1Info l1_info := {
1288 ms_power_lvl := l1p.ms_power_level,
1289 fpc := false,
1290 reserved := 0,
Pau Espin Pedrol121724c2018-09-28 15:58:12 +02001291 actual_ta := f_tolerance(l1p.ms_actual_ta, 0, 63, mp_tolerance_timing_offset_256syms/256)
Harald Welte70767382018-02-21 12:16:40 +01001292 };
1293 var uint8_t offs := toffs256s_to_rsl(l1p.timing_offset_256syms);
Pau Espin Pedrol121724c2018-09-28 15:58:12 +02001294 var template uint8_t t_toffs := f_tolerance(offs, 0, 255, mp_tolerance_timing_offset_256syms/256);
Harald Welte70767382018-02-21 12:16:40 +01001295 return tr_RSL_MEAS_RES_OSMO(g_chan_nr, g_next_meas_res_nr, ul_meas, bs_power, l1_info,
1296 ?, t_toffs);
1297}
1298
1299/* verify we regularly receive measurement reports with incrementing numbers */
Vadim Yanitskiy41baf002018-10-04 17:44:50 +07001300altstep as_meas_res(boolean verify_meas := true) runs on ConnHdlr {
Harald Welte70767382018-02-21 12:16:40 +01001301 var RSL_Message rsl;
Vadim Yanitskiy41baf002018-10-04 17:44:50 +07001302 [not verify_meas] RSL.receive(tr_RSL_MEAS_RES(?)) { repeat; }
Harald Welte70767382018-02-21 12:16:40 +01001303 [] RSL.receive(f_build_meas_res_tmpl()) -> value rsl {
1304 /* increment counter of next to-be-expected meas rep */
1305 g_next_meas_res_nr := (g_next_meas_res_nr + 1) mod 256;
1306 /* Re-start the timer expecting the next MEAS RES */
Harald Weltec3a3f452018-02-26 17:37:47 +01001307 f_timer_safe_restart(g_Tmeas_exp);
Harald Welte70767382018-02-21 12:16:40 +01001308 repeat;
1309 }
1310 [] RSL.receive(tr_RSL_MEAS_RES(g_chan_nr, g_next_meas_res_nr)) -> value rsl {
Harald Weltefa45e9e2018-03-10 18:59:03 +01001311 /* increment counter of next to-be-expected meas rep */
1312 g_next_meas_res_nr := (g_next_meas_res_nr + 1) mod 256;
1313 if (g_first_meas_res) {
1314 g_first_meas_res := false;
1315 repeat;
1316 } else {
1317 setverdict(fail, "Received unspecific MEAS RES ", rsl);
Daniel Willmann17ddd852018-07-05 17:33:20 +02001318 mtc.stop;
Harald Weltefa45e9e2018-03-10 18:59:03 +01001319 }
Harald Welte70767382018-02-21 12:16:40 +01001320 }
1321 [] RSL.receive(tr_RSL_MEAS_RES(?)) -> value rsl {
1322 setverdict(fail, "Received unexpected MEAS RES ", rsl);
Daniel Willmann17ddd852018-07-05 17:33:20 +02001323 mtc.stop;
Harald Welte70767382018-02-21 12:16:40 +01001324 }
Pau Espin Pedrol425b62f2018-07-06 16:11:43 +02001325 [g_Tmeas_exp.running] g_Tmeas_exp.timeout {
Harald Welte70767382018-02-21 12:16:40 +01001326 setverdict(fail, "Didn't receive expected measurement result")
Daniel Willmann17ddd852018-07-05 17:33:20 +02001327 mtc.stop;
Harald Welte70767382018-02-21 12:16:40 +01001328 }
1329}
1330
Harald Weltee613f962018-04-18 22:38:16 +02001331private function f_alg_id_to_l1ctl(RSL_AlgId rsl_alg_id) return uint8_t {
1332 select (rsl_alg_id) {
1333 case (RSL_ALG_ID_A5_0) { return 0; }
1334 case (RSL_ALG_ID_A5_1) { return 1; }
1335 case (RSL_ALG_ID_A5_2) { return 2; }
1336 case (RSL_ALG_ID_A5_3) { return 3; }
1337 case (RSL_ALG_ID_A5_4) { return 4; }
1338 case (RSL_ALG_ID_A5_5) { return 5; }
1339 case (RSL_ALG_ID_A5_6) { return 6; }
1340 case (RSL_ALG_ID_A5_7) { return 7; }
1341 case else {
1342 setverdict(fail, "Unknwon Algorithm ID");
Daniel Willmann17ddd852018-07-05 17:33:20 +02001343 mtc.stop;
Harald Weltee613f962018-04-18 22:38:16 +02001344 }
1345 }
1346}
1347
1348private function f_alg_id_to_l3(RSL_AlgId rsl_alg_id) return BIT3 {
1349 select (rsl_alg_id) {
1350 case (RSL_ALG_ID_A5_1) { return '000'B; }
1351 case (RSL_ALG_ID_A5_2) { return '001'B; }
1352 case (RSL_ALG_ID_A5_3) { return '010'B; }
1353 case (RSL_ALG_ID_A5_4) { return '011'B; }
1354 case (RSL_ALG_ID_A5_5) { return '100'B; }
1355 case (RSL_ALG_ID_A5_6) { return '101'B; }
1356 case (RSL_ALG_ID_A5_7) { return '110'B; }
1357 case else {
1358 setverdict(fail, "Unknwon Algorithm ID");
Daniel Willmann17ddd852018-07-05 17:33:20 +02001359 mtc.stop;
Harald Weltee613f962018-04-18 22:38:16 +02001360 }
1361 }
1362}
1363
1364
Harald Welte70767382018-02-21 12:16:40 +01001365/* Establish dedicated channel: L1CTL + RSL side */
Harald Weltee613f962018-04-18 22:38:16 +02001366private function f_est_dchan(boolean encr_enable := false) runs on ConnHdlr {
Harald Welte70767382018-02-21 12:16:40 +01001367 var GsmFrameNumber fn;
1368 var ImmediateAssignment imm_ass;
1369 var integer ra := 23;
1370
Pau Espin Pedrol99a7aca2018-09-28 16:10:32 +02001371 f_L1CTL_PARAM(L1CTL, g_pars.l1_pars.ms_actual_ta, g_pars.l1_pars.ms_power_level);
Harald Welte70767382018-02-21 12:16:40 +01001372 fn := f_L1CTL_RACH(L1CTL, ra);
1373 /* This arrives on CCHAN, so we cannot test for receiving CHAN RQDhere */
1374 //RSL.receive(tr_RSL_CHAN_RQD(int2oct(23,1)));
1375
1376 /* Activate channel on BTS side */
Harald Weltee613f962018-04-18 22:38:16 +02001377 f_rsl_chan_act(g_pars.chan_mode, encr_enable);
Harald Welte70767382018-02-21 12:16:40 +01001378
1379 /* Send IMM.ASS via CCHAN */
1380 var ChannelDescription ch_desc := {
1381 chan_nr := g_pars.chan_nr,
1382 tsc := 7,
1383 h := false,
1384 arfcn := mp_trx0_arfcn,
1385 maio_hsn := omit
1386 };
1387 var MobileAllocation ma := {
1388 len := 0,
1389 ma := ''B
1390 };
1391 var GsmRrMessage rr_msg := valueof(ts_IMM_ASS(ra, fn, 0, ch_desc, ma));
1392 RSL.send(ts_RSL_IMM_ASSIGN(enc_GsmRrMessage(rr_msg)));
1393
1394 /* receive IMM.ASS on MS side */
1395 var ImmediateAssignment ia_um;
1396 ia_um := f_L1CTL_WAIT_IMM_ASS(L1CTL, ra, fn);
1397 /* enable dedicated mode */
1398 f_L1CTL_DM_EST_REQ_IA(L1CTL, ia_um);
Harald Weltee613f962018-04-18 22:38:16 +02001399 /* enable encryption, if requested */
1400 if (encr_enable) {
1401 var uint8_t alg_id := f_alg_id_to_l1ctl(g_pars.encr.alg_id);
1402 f_L1CTL_CRYPTO_REQ(L1CTL, g_pars.chan_nr, alg_id, g_pars.encr.key);
1403 }
Harald Weltefa45e9e2018-03-10 18:59:03 +01001404
1405 g_first_meas_res := true;
Harald Welte70767382018-02-21 12:16:40 +01001406}
1407
1408/* establish DChan, verify existance + contents of measurement reports */
1409function f_TC_meas_res_periodic(charstring id) runs on ConnHdlr {
Harald Welte68e495b2018-02-25 00:05:57 +01001410 f_l1_tune(L1CTL);
Harald Welte70767382018-02-21 12:16:40 +01001411 RSL.clear;
1412
Pau Espin Pedrol121724c2018-09-28 15:58:12 +02001413 g_pars.l1_pars.meas_ul.full.rxlev := dbm2rxlev(-100);
Harald Welte5398d5e2018-03-10 19:00:24 +01001414 g_pars.l1_pars.meas_ul.sub.rxlev := g_pars.l1_pars.meas_ul.full.rxlev;
Pau Espin Pedrol121724c2018-09-28 15:58:12 +02001415 if (mp_bb_trxc_port != -1) {
1416 f_trxc_fake_rssi(100);
1417 f_trx_fake_toffs256(g_pars.l1_pars.timing_offset_256syms);
1418 }
Harald Welte70767382018-02-21 12:16:40 +01001419
1420 f_est_dchan();
1421
1422 /* run for a number of seconds, send SACCH + FACCH from MS side and verify
1423 * RSL measurement reports on Abis side */
1424 timer T := 8.0;
1425 T.start;
1426 alt {
1427 [] as_l1_sacch();
1428 [] as_meas_res();
1429 [] as_l1_dcch();
1430 [] L1CTL.receive { repeat; }
1431 [g_Tmeas_exp.running] T.timeout {
Daniel Willmann17ddd852018-07-05 17:33:20 +02001432 /* as_meas_res() would have done setverdict(fail) / mtc.stop in case
Harald Welte70767382018-02-21 12:16:40 +01001433 * of any earlier errors, so if we reach this timeout, we're good */
1434 setverdict(pass);
1435 }
1436 [] T.timeout {
1437 setverdict(fail, "No MEAS RES received at all");
Daniel Willmann17ddd852018-07-05 17:33:20 +02001438 mtc.stop;
Harald Welte70767382018-02-21 12:16:40 +01001439 }
1440 }
1441 f_rsl_chan_deact();
Harald Welte3dc20462018-03-10 23:03:38 +01001442 f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
Harald Welte70767382018-02-21 12:16:40 +01001443}
Harald Welte0472ab42018-03-12 15:02:26 +01001444
Harald Welte70767382018-02-21 12:16:40 +01001445testcase TC_meas_res_sign_tchf() runs on test_CT {
1446 var ConnHdlr vc_conn;
1447 var ConnHdlrPars pars;
1448 f_init(testcasename());
1449 for (var integer tn := 1; tn <= 4; tn := tn+1) {
1450 pars := valueof(t_Pars(t_RslChanNr_Bm(tn), ts_RSL_ChanMode_SIGN));
1451 vc_conn := f_start_handler(refers(f_TC_meas_res_periodic), pars);
1452 vc_conn.done;
1453 }
Harald Welte294b0a22018-03-10 23:26:48 +01001454 f_shutdown();
Harald Welte70767382018-02-21 12:16:40 +01001455}
1456testcase TC_meas_res_sign_tchh() runs on test_CT {
1457 var ConnHdlr vc_conn;
1458 var ConnHdlrPars pars;
1459 f_init(testcasename());
1460 for (var integer ss := 0; ss <= 1; ss := ss+1) {
1461 pars := valueof(t_Pars(t_RslChanNr_Lm(5, ss), ts_RSL_ChanMode_SIGN));
1462 vc_conn := f_start_handler(refers(f_TC_meas_res_periodic), pars);
1463 vc_conn.done;
1464 }
Harald Welte294b0a22018-03-10 23:26:48 +01001465 f_shutdown();
Harald Welte70767382018-02-21 12:16:40 +01001466}
1467testcase TC_meas_res_sign_sdcch4() runs on test_CT {
1468 var ConnHdlr vc_conn;
1469 var ConnHdlrPars pars;
1470 f_init(testcasename());
1471 for (var integer ss := 0; ss <= 3; ss := ss+1) {
1472 pars := valueof(t_Pars(t_RslChanNr_SDCCH4(0, ss), ts_RSL_ChanMode_SIGN));
1473 vc_conn := f_start_handler(refers(f_TC_meas_res_periodic), pars);
1474 vc_conn.done;
1475 }
Harald Welte294b0a22018-03-10 23:26:48 +01001476 f_shutdown();
Harald Welte70767382018-02-21 12:16:40 +01001477}
1478testcase TC_meas_res_sign_sdcch8() runs on test_CT {
1479 var ConnHdlr vc_conn;
1480 var ConnHdlrPars pars;
1481 f_init(testcasename());
1482 for (var integer ss := 0; ss <= 7; ss := ss+1) {
1483 pars := valueof(t_Pars(t_RslChanNr_SDCCH8(6, ss), ts_RSL_ChanMode_SIGN));
1484 vc_conn := f_start_handler(refers(f_TC_meas_res_periodic), pars);
1485 vc_conn.done;
1486 }
Harald Welte294b0a22018-03-10 23:26:48 +01001487 f_shutdown();
Harald Welte70767382018-02-21 12:16:40 +01001488}
Harald Welte685d5982018-02-27 20:42:05 +01001489testcase TC_meas_res_sign_tchh_toa256() runs on test_CT {
1490 var ConnHdlr vc_conn;
1491 var ConnHdlrPars pars;
1492 f_init(testcasename());
1493 f_vty_config(BTSVTY, "bts 0", "supp-meas-info toa256");
1494 for (var integer ss := 0; ss <= 1; ss := ss+1) {
1495 pars := valueof(t_Pars(t_RslChanNr_Lm(5, ss), ts_RSL_ChanMode_SIGN));
1496 pars.l1_pars.toa256_enabled := true;
1497 vc_conn := f_start_handler(refers(f_TC_meas_res_periodic), pars);
1498 vc_conn.done;
1499 }
Harald Welte294b0a22018-03-10 23:26:48 +01001500 f_shutdown();
Harald Welte685d5982018-02-27 20:42:05 +01001501}
1502
Harald Welte70767382018-02-21 12:16:40 +01001503
Harald Welte0472ab42018-03-12 15:02:26 +01001504/* 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 +01001505private function f_TC_conn_fail_crit(charstring id) runs on ConnHdlr {
Harald Welte68e495b2018-02-25 00:05:57 +01001506 f_l1_tune(L1CTL);
Harald Welte70767382018-02-21 12:16:40 +01001507 RSL.clear;
1508
1509 f_est_dchan();
1510 f_sleep(2.0);
Harald Weltef8df4cb2018-03-10 15:15:08 +01001511 L1CTL.send(ts_L1CTL_DM_REL_REQ(g_chan_nr));
Harald Welte70767382018-02-21 12:16:40 +01001512
1513 timer T := 40.0;
1514 T.start;
1515 alt {
1516 [] RSL.receive(tr_RSL_CONN_FAIL_IND(g_chan_nr, ?)) {
1517 setverdict(pass)
1518 }
1519 [] RSL.receive { repeat };
1520 [] T.timeout {
1521 setverdict(fail, "No CONN FAIL IND received");
Daniel Willmann17ddd852018-07-05 17:33:20 +02001522 mtc.stop;
Harald Welte70767382018-02-21 12:16:40 +01001523 }
1524 }
1525 f_rsl_chan_deact();
1526}
1527testcase TC_conn_fail_crit() runs on test_CT {
1528 var ConnHdlr vc_conn;
1529 var ConnHdlrPars pars;
1530 f_init(testcasename());
1531 pars := valueof(t_Pars(t_RslChanNr_SDCCH8(6, 3), ts_RSL_ChanMode_SIGN));
1532 pars.t_guard := 60.0;
1533 vc_conn := f_start_handler(refers(f_TC_conn_fail_crit), pars);
1534 vc_conn.done;
1535}
1536
Harald Welte93640c62018-02-25 16:59:33 +01001537/***********************************************************************
1538 * Paging
1539 ***********************************************************************/
1540
Harald Welte68e495b2018-02-25 00:05:57 +01001541function tmsi_is_dummy(TMSIP_TMSI_V tmsi) return boolean {
1542 if (tmsi == 'FFFFFFFF'O) {
1543 return true;
1544 } else {
1545 return false;
1546 }
1547}
Harald Welte70767382018-02-21 12:16:40 +01001548
Philipp Maier82cb0b12018-08-31 14:41:39 +02001549type record allowedFn { integer frame_nr }
1550template allowedFn bs_ag_blks_res_0 := { frame_nr := (6, 12, 16, 22, 26, 32, 36, 42, 46) }
1551template allowedFn bs_ag_blks_res_1 := { frame_nr := (12, 16, 22, 26, 32, 36, 42, 46) }
1552template allowedFn bs_ag_blks_res_2 := { frame_nr := (16, 22, 26, 32, 36, 42, 46) }
1553template allowedFn bs_ag_blks_res_3 := { frame_nr := (22, 26, 32, 36, 42, 46) }
1554template allowedFn bs_ag_blks_res_4 := { frame_nr := (26, 32, 36, 42, 46) }
1555template allowedFn bs_ag_blks_res_5 := { frame_nr := (32, 36, 42, 46) }
1556template allowedFn bs_ag_blks_res_6 := { frame_nr := (36, 42, 46) }
1557template allowedFn bs_ag_blks_res_7 := { frame_nr := (42, 46) }
1558function check_pch_fn(integer frame_nr, integer bs_ag_blks_res) runs on test_CT
1559{
1560 var integer frame_nr_51;
1561 frame_nr_51 := frame_nr mod 51
1562
1563 var allowedFn fn_check;
1564 fn_check.frame_nr := frame_nr_51;
1565
1566 if (bs_ag_blks_res < 0 or bs_ag_blks_res > 7) {
1567 setverdict(fail, "bs_ag_blks_res out of valid range (0..7)");
1568 mtc.stop;
1569 return;
1570 }
1571
1572 if (bs_ag_blks_res == 0 and match(fn_check, bs_ag_blks_res_0)) {
1573 return;
1574 }
1575 if (bs_ag_blks_res == 1 and match(fn_check, bs_ag_blks_res_1)) {
1576 return;
1577 }
1578 if (bs_ag_blks_res == 2 and match(fn_check, bs_ag_blks_res_2)) {
1579 return;
1580 }
1581 if (bs_ag_blks_res == 3 and match(fn_check, bs_ag_blks_res_3)) {
1582 return;
1583 }
1584 if (bs_ag_blks_res == 4 and match(fn_check, bs_ag_blks_res_4)) {
1585 return;
1586 }
1587 if (bs_ag_blks_res == 5 and match(fn_check, bs_ag_blks_res_5)) {
1588 return;
1589 }
1590 if (bs_ag_blks_res == 6 and match(fn_check, bs_ag_blks_res_6)) {
1591 return;
1592 }
1593 if (bs_ag_blks_res == 7 and match(fn_check, bs_ag_blks_res_7)) {
1594 return;
1595 }
1596
1597 setverdict(fail, "received paging on AGCH");
1598 mtc.stop;
1599 return;
1600}
1601
1602altstep as_l1_count_paging(inout integer num_paging_rcv_msgs, inout integer num_paging_rcv_ids, PagingTestCfg cfg)
Harald Welte68e495b2018-02-25 00:05:57 +01001603runs on test_CT {
1604 var L1ctlDlMessage dl;
Harald Weltef8df4cb2018-03-10 15:15:08 +01001605 [] L1CTL.receive(tr_L1CTL_DATA_IND(t_RslChanNr_PCH_AGCH(0), ?, c_DummyUI)) {
Harald Welte68e495b2018-02-25 00:05:57 +01001606 repeat;
1607 }
Harald Weltef8df4cb2018-03-10 15:15:08 +01001608 [] L1CTL.receive(tr_L1CTL_DATA_IND(t_RslChanNr_PCH_AGCH(0))) -> value dl {
Harald Welte68e495b2018-02-25 00:05:57 +01001609 var octetstring without_plen :=
1610 substr(dl.payload.data_ind.payload, 1, lengthof(dl.payload.data_ind.payload)-1);
1611 var PDU_ML3_NW_MS rr := dec_PDU_ML3_NW_MS(without_plen);
Philipp Maier82cb0b12018-08-31 14:41:39 +02001612
1613 check_pch_fn(dl.dl_info.frame_nr, cfg.bs_ag_blks_res);
1614
Harald Welte68e495b2018-02-25 00:05:57 +01001615 if (match(rr, tr_PAGING_REQ1)) {
1616 num_paging_rcv_msgs := num_paging_rcv_msgs + 1;
1617 num_paging_rcv_ids := num_paging_rcv_ids + 1;
1618 if (isvalue(rr.msgs.rrm.pagingReq_Type1.mobileIdentity2)) {
1619 num_paging_rcv_ids := num_paging_rcv_ids + 1;
1620 }
1621 } else if (match(rr, tr_PAGING_REQ2)) {
1622 num_paging_rcv_msgs := num_paging_rcv_msgs + 1;
1623 if (not tmsi_is_dummy(rr.msgs.rrm.pagingReq_Type2.mobileIdentity1)) {
1624 num_paging_rcv_ids := num_paging_rcv_ids + 1;
1625 }
1626 if (not tmsi_is_dummy(rr.msgs.rrm.pagingReq_Type2.mobileIdentity2)) {
1627 num_paging_rcv_ids := num_paging_rcv_ids + 1;
1628 }
1629 if (isvalue(rr.msgs.rrm.pagingReq_Type2.mobileIdentity3)) {
1630 num_paging_rcv_ids := num_paging_rcv_ids + 1;
1631 }
1632 } else if (match(rr, tr_PAGING_REQ3)) {
1633 num_paging_rcv_msgs := num_paging_rcv_msgs + 1;
1634 if (not tmsi_is_dummy(rr.msgs.rrm.pagingReq_Type3.mobileIdentity1)) {
1635 num_paging_rcv_ids := num_paging_rcv_ids + 1;
1636 }
1637 if (not tmsi_is_dummy(rr.msgs.rrm.pagingReq_Type3.mobileIdentity2)) {
1638 num_paging_rcv_ids := num_paging_rcv_ids + 1;
1639 }
1640 if (not tmsi_is_dummy(rr.msgs.rrm.pagingReq_Type3.mobileIdentity3)) {
1641 num_paging_rcv_ids := num_paging_rcv_ids + 1;
1642 }
1643 if (not tmsi_is_dummy(rr.msgs.rrm.pagingReq_Type3.mobileIdentity4)) {
1644 num_paging_rcv_ids := num_paging_rcv_ids + 1;
1645 }
1646 }
1647 repeat;
1648 }
1649}
1650
1651type record PagingTestCfg {
1652 boolean combined_ccch,
1653 integer bs_ag_blks_res,
1654 float load_factor,
1655 boolean exp_load_ind,
1656 boolean exp_overload,
1657 boolean use_tmsi
1658}
1659
1660type record PagingTestState {
1661 integer num_paging_sent,
1662 integer num_paging_rcv_msgs,
1663 integer num_paging_rcv_ids,
1664 integer num_overload
1665}
1666
1667/* receive + ignore RSL RF RES IND */
1668altstep as_rsl_res_ind() runs on test_CT {
1669 [] RSL_CCHAN.receive(tr_RSL_UD(tr_RSL_RF_RES_IND)) {
1670 repeat;
1671 }
1672}
1673
1674/* Helper function for paging related testing */
1675private function f_TC_paging(PagingTestCfg cfg) runs on test_CT return PagingTestState {
1676 f_init(testcasename());
1677 f_init_l1ctl();
1678 f_l1_tune(L1CTL);
1679
1680 var PagingTestState st := {
1681 num_paging_sent := 0,
1682 num_paging_rcv_msgs := 0,
1683 num_paging_rcv_ids := 0,
1684 num_overload := 0
1685 };
1686
1687 var float max_pch_blocks_per_sec := f_pch_block_rate_est(cfg.combined_ccch, cfg.bs_ag_blks_res);
1688 var float max_pch_imsi_per_sec;
1689 if (cfg.use_tmsi) {
1690 max_pch_imsi_per_sec := max_pch_blocks_per_sec * 4.0; /* Type 3 */
1691 } else {
1692 max_pch_imsi_per_sec := max_pch_blocks_per_sec * 2.0; /* Type 1 */
1693 }
1694 var float pch_blocks_per_sec := max_pch_imsi_per_sec * cfg.load_factor;
1695 var float interval := 1.0 / pch_blocks_per_sec;
Pau Espin Pedrol9c3ff4e2018-09-26 18:30:16 +02001696 var float time_total := 20.0;
1697 var integer pkt_total := float2int(time_total * pch_blocks_per_sec);
1698 log("pch_blocks_total=", pkt_total," pch_blocks_per_sec=", pch_blocks_per_sec, " interval=", interval);
Harald Welte68e495b2018-02-25 00:05:57 +01001699
Pau Espin Pedrol9c3ff4e2018-09-26 18:30:16 +02001700 timer T_total := 300.0; /* big value (far bigger than time_total), used to count elapsed time */
1701 T_total.start;
Harald Welte68e495b2018-02-25 00:05:57 +01001702
Pau Espin Pedrol9c3ff4e2018-09-26 18:30:16 +02001703 timer T_itv := 0.0;
1704 T_itv.start;
1705 while (st.num_paging_sent < pkt_total) {
Harald Welte68e495b2018-02-25 00:05:57 +01001706 alt {
1707 /* check for presence of CCCH LOAD IND (paging load) */
1708 [cfg.exp_overload] RSL_CCHAN.receive(tr_RSL_UD(tr_RSL_PAGING_LOAD_IND(0))) {
1709 st.num_overload := st.num_overload + 1;
1710 repeat;
1711 }
1712 [not cfg.exp_overload] RSL_CCHAN.receive(tr_RSL_UD(tr_RSL_PAGING_LOAD_IND(0))) {
1713 setverdict(fail, "Unexpected PCH Overload");
Daniel Willmann17ddd852018-07-05 17:33:20 +02001714 mtc.stop;
Harald Welte68e495b2018-02-25 00:05:57 +01001715 }
1716 [cfg.exp_load_ind] RSL_CCHAN.receive(tr_RSL_UD(tr_RSL_PAGING_LOAD_IND)) {
1717 log("Rx LOAD_IND");
1718 /* FIXME: analyze/verify interval + contents */
1719 repeat;
1720 }
1721 /* check if paging requests arrive on Um side */
Philipp Maier82cb0b12018-08-31 14:41:39 +02001722 [] as_l1_count_paging(st.num_paging_rcv_msgs, st.num_paging_rcv_ids, cfg);
Harald Welte68e495b2018-02-25 00:05:57 +01001723 [] L1CTL.receive { repeat; }
Pau Espin Pedrol9c3ff4e2018-09-26 18:30:16 +02001724 [] T_itv.timeout {
1725 /* Send paging cmds based on elapsed time */
1726 var integer new_sent := f_min(pkt_total, float2int(T_total.read * pch_blocks_per_sec) + 1);
1727 while (st.num_paging_sent < new_sent) {
1728 /* build mobile Identity */
1729 var MobileL3_CommonIE_Types.MobileIdentityLV mi;
1730 if (cfg.use_tmsi) {
1731 mi := valueof(ts_MI_TMSI_LV(f_rnd_octstring(4)));
1732 } else {
1733 mi := valueof(ts_MI_IMSI_LV(f_gen_imsi(st.num_paging_sent)));
1734 }
1735 var octetstring mi_enc_lv := enc_MobileIdentityLV(mi);
1736 var octetstring mi_enc := substr(mi_enc_lv, 1, lengthof(mi_enc_lv)-1);
1737
1738 /* Send RSL PAGING COMMAND */
1739 RSL_CCHAN.send(ts_RSL_UD(ts_RSL_PAGING_CMD(mi_enc, st.num_paging_sent mod 4)));
1740
1741 st.num_paging_sent := st.num_paging_sent + 1;
1742 }
1743 if (st.num_paging_sent < pkt_total) {
1744 /* Wait for interval to next PAGING COMMAND */
1745 var float time_now := T_total.read;
1746 var float next_sched := int2float(st.num_paging_sent)*interval;
1747 if (next_sched > time_now) {
1748 T_itv.start(next_sched - time_now);
1749 } else {
1750 T_itv.start(0.0);
1751 }
1752 } else {
1753 /* We are done, no need to keep counting */
1754 T_total.stop;
1755 }
1756 }
1757 [] T_total.timeout { }
Harald Welte68e495b2018-02-25 00:05:57 +01001758 [] as_rsl_res_ind();
1759 }
1760 }
1761
1762 /* wait for max 18s for paging queue to drain (size: 200, ~ 13 per s -> 15s) */
1763 timer T_wait := 18.0;
1764 T_wait.start;
1765 alt {
Philipp Maier82cb0b12018-08-31 14:41:39 +02001766 [] as_l1_count_paging(st.num_paging_rcv_msgs, st.num_paging_rcv_ids, cfg);
Harald Welte68e495b2018-02-25 00:05:57 +01001767 [] L1CTL.receive { repeat; }
1768 /* 65535 == empty paging queue, we can terminate*/
1769 [] RSL_CCHAN.receive(tr_RSL_UD(tr_RSL_PAGING_LOAD_IND(65535))) { }
1770 [] RSL_CCHAN.receive(tr_RSL_UD(tr_RSL_PAGING_LOAD_IND)) { repeat; }
1771 [] T_wait.timeout {
1772 setverdict(fail, "Waiting for empty paging queue");
Daniel Willmann17ddd852018-07-05 17:33:20 +02001773 mtc.stop;
Harald Welte68e495b2018-02-25 00:05:57 +01001774 }
1775 [] as_rsl_res_ind();
1776 }
1777
1778 log("num_paging_sent=", st.num_paging_sent, " rcvd_msgs=", st.num_paging_rcv_msgs,
1779 " rcvd_ids=", st.num_paging_rcv_ids);
1780 return st;
1781}
1782
1783/* Create ~ 80% paging load (IMSI only) sustained for about 20s, verifying that
1784 * - the number of Mobile Identities on Um PCH match the number of pages on RSL
1785 * - that CCCH LOAD IND (PCH) are being generated
1786 * - that CCCH LOAD IND (PCH) [no load] is received after paging flood is over */
1787testcase TC_paging_imsi_80percent() runs on test_CT {
Philipp Maierd65d0562018-08-30 16:25:47 +02001788 var SystemInformation si3 := valueof(ts_SI3_default);
Harald Welte68e495b2018-02-25 00:05:57 +01001789 var PagingTestCfg cfg := {
1790 combined_ccch := true,
Philipp Maierd65d0562018-08-30 16:25:47 +02001791 bs_ag_blks_res := si3.payload.si3.ctrl_chan_desc.bs_ag_blks_res,
Harald Welte68e495b2018-02-25 00:05:57 +01001792 load_factor := 0.8,
1793 exp_load_ind := true,
1794 exp_overload := false,
1795 use_tmsi := false
1796 };
1797 var PagingTestState st := f_TC_paging(cfg);
1798 if (st.num_paging_sent != st.num_paging_rcv_ids) {
1799 setverdict(fail, "Expected ", st.num_paging_sent, " pagings but have ",
1800 st.num_paging_rcv_ids);
1801 } else {
1802 setverdict(pass);
1803 }
Daniel Willmanna59afab2018-07-05 16:16:32 +02001804 f_shutdown();
Harald Welte68e495b2018-02-25 00:05:57 +01001805}
1806
1807/* Create ~ 80% paging load (TMSI only) sustained for about 20s, verifying that
1808 * - the number of Mobile Identities on Um PCH match the number of pages on RSL
1809 * - that CCCH LOAD IND (PCH) are being generated
1810 * - that CCCH LOAD IND (PCH) [no load] is received after paging flood is over */
1811testcase TC_paging_tmsi_80percent() runs on test_CT {
Philipp Maierd65d0562018-08-30 16:25:47 +02001812 var SystemInformation si3 := valueof(ts_SI3_default);
Harald Welte68e495b2018-02-25 00:05:57 +01001813 var PagingTestCfg cfg := {
1814 combined_ccch := true,
Philipp Maierd65d0562018-08-30 16:25:47 +02001815 bs_ag_blks_res := si3.payload.si3.ctrl_chan_desc.bs_ag_blks_res,
Harald Welte68e495b2018-02-25 00:05:57 +01001816 load_factor := 0.8,
1817 exp_load_ind := true,
1818 exp_overload := false,
1819 use_tmsi := true
1820 };
1821 var PagingTestState st := f_TC_paging(cfg);
1822 if (st.num_paging_sent != st.num_paging_rcv_ids) {
1823 setverdict(fail, "Expected ", st.num_paging_sent, " pagings but have ",
1824 st.num_paging_rcv_ids);
1825 } else {
1826 setverdict(pass);
1827 }
Daniel Willmanna59afab2018-07-05 16:16:32 +02001828 f_shutdown();
Harald Welte68e495b2018-02-25 00:05:57 +01001829}
1830
1831/* Create ~ 200% paging load (IMSI only) sustained for about 20s, verifying that
1832 * - the number of Mobile Identities on Um PCH are ~ 82% of the number of pages on RSL
1833 * - that CCCH LOAD IND (PCH) are being generated and reach 0 at some point
1834 * - that CCCH LOAD IND (PCH) [no load] is received after paging flood is over */
1835testcase TC_paging_imsi_200percent() runs on test_CT {
Philipp Maierd65d0562018-08-30 16:25:47 +02001836 var SystemInformation si3 := valueof(ts_SI3_default);
Harald Welte68e495b2018-02-25 00:05:57 +01001837 var PagingTestCfg cfg := {
1838 combined_ccch := true,
Philipp Maierd65d0562018-08-30 16:25:47 +02001839 bs_ag_blks_res := si3.payload.si3.ctrl_chan_desc.bs_ag_blks_res,
Harald Welte68e495b2018-02-25 00:05:57 +01001840 load_factor := 2.0,
1841 exp_load_ind := true,
1842 exp_overload := true,
1843 use_tmsi := false
1844 };
1845 var PagingTestState st := f_TC_paging(cfg);
1846 /* We expect about 80-85% to pass, given that we can fill the paging buffer of 200
1847 * slots and will fully drain that buffer before returning */
Pau Espin Pedrol9c3ff4e2018-09-26 18:30:16 +02001848 var template integer tpl := (st.num_paging_sent*78/100 .. st.num_paging_sent *85/100);
Harald Welte68e495b2018-02-25 00:05:57 +01001849 if (not match(st.num_paging_rcv_ids, tpl)) {
1850 setverdict(fail, "Expected ", tpl, " pagings but have ", st.num_paging_rcv_ids);
1851 } else {
1852 setverdict(pass);
1853 }
Daniel Willmanna59afab2018-07-05 16:16:32 +02001854 f_shutdown();
Harald Welte68e495b2018-02-25 00:05:57 +01001855}
1856
1857/* Create ~ 200% paging load (TMSI only) sustained for about 20s, verifying that
1858 * - the number of Mobile Identities on Um PCH are ~ 82% of the number of pages on RSL
1859 * - that CCCH LOAD IND (PCH) are being generated and reach 0 at some point
1860 * - that CCCH LOAD IND (PCH) [no load] is received after paging flood is over */
1861testcase TC_paging_tmsi_200percent() runs on test_CT {
Philipp Maierd65d0562018-08-30 16:25:47 +02001862 var SystemInformation si3 := valueof(ts_SI3_default);
Harald Welte68e495b2018-02-25 00:05:57 +01001863 var PagingTestCfg cfg := {
1864 combined_ccch := true,
Philipp Maierd65d0562018-08-30 16:25:47 +02001865 bs_ag_blks_res := si3.payload.si3.ctrl_chan_desc.bs_ag_blks_res,
Harald Welte68e495b2018-02-25 00:05:57 +01001866 load_factor := 2.0,
1867 exp_load_ind := true,
1868 exp_overload := true,
1869 use_tmsi := true
1870 };
1871 var PagingTestState st := f_TC_paging(cfg);
1872 /* We expect about 70% to pass, given that we can fill the paging buffer of 200
1873 * slots and will fully drain that buffer before returning */
Pau Espin Pedrol9c3ff4e2018-09-26 18:30:16 +02001874 var template integer tpl := (st.num_paging_sent*64/100 .. st.num_paging_sent *72/100);
Harald Welte68e495b2018-02-25 00:05:57 +01001875 if (not match(st.num_paging_rcv_ids, tpl)) {
1876 setverdict(fail, "Expected ", tpl, " pagings but have ", st.num_paging_rcv_ids);
1877 } else {
1878 setverdict(pass);
1879 }
Daniel Willmanna59afab2018-07-05 16:16:32 +02001880 f_shutdown();
Harald Welte68e495b2018-02-25 00:05:57 +01001881}
1882
1883
Harald Welte93640c62018-02-25 16:59:33 +01001884/***********************************************************************
1885 * Immediate Assignment / AGCH
1886 ***********************************************************************/
Harald Weltee8d750e2018-06-10 21:41:35 +02001887const MobileAllocation c_MA_null := {
1888 len := 0,
1889 ma := ''B
1890}
Harald Welte93640c62018-02-25 16:59:33 +01001891
Harald Weltee8d750e2018-06-10 21:41:35 +02001892template (value) ChannelDescription ts_ChanDesc(template (value) RslChannelNr chan_nr, uint3_t tsc := 7,
1893 uint12_t arfcn := 871) := {
1894 chan_nr := chan_nr,
1895 tsc := tsc,
1896 h := false,
1897 arfcn := arfcn,
1898 maio_hsn := omit
1899}
1900
1901private function f_fmt_ia_stats(integer num_tx, integer num_rx, integer num_del) return charstring {
1902 return int2str(num_tx) & " sent, "
1903 & int2str(num_rx) & " received, "
1904 & int2str(num_del) & " deleted";
1905}
1906
1907private function f_TC_imm_ass(integer num_total, float sleep_s, float exp_pass) runs on test_CT {
1908 var L1ctlDlMessage l1_dl;
1909 timer T := 10.0;
1910 var integer num_tx := 0;
1911 var integer num_rx := 0;
1912 var integer num_del := 0;
1913 var charstring res_str;
1914 var float rx_ratio;
1915
Harald Welte68e495b2018-02-25 00:05:57 +01001916 f_init(testcasename());
Harald Weltee8d750e2018-06-10 21:41:35 +02001917 f_init_l1ctl();
1918 f_l1_tune(L1CTL);
1919
1920 for (var integer i := 0; i < num_total; i := i+1) {
1921 var ChannelDescription ch_desc := valueof(ts_ChanDesc(valueof(t_RslChanNr_SDCCH4(0, 0))));
1922 var GsmRrMessage ia := valueof(ts_IMM_ASS(42, i, 5, ch_desc, c_MA_null));
1923 var octetstring ia_enc := enc_GsmRrMessage(ia);
Harald Welte68e495b2018-02-25 00:05:57 +01001924 RSL_CCHAN.send(ts_RSL_UD(ts_RSL_IMM_ASSIGN(ia_enc, 0)));
Harald Weltee8d750e2018-06-10 21:41:35 +02001925 num_tx := num_tx+1;
1926 f_sleep(sleep_s);
Harald Welte68e495b2018-02-25 00:05:57 +01001927 }
1928 /* FIXME: check if imm.ass arrive on Um side */
Harald Weltee8d750e2018-06-10 21:41:35 +02001929 T.start;
1930 alt {
1931 [] RSL_CCHAN.receive(tr_RSL_UD(tr_RSL_DELETE_IND(?, 0))) {
1932 num_del := num_del+1;
1933 repeat;
1934 }
1935 [] RSL_CCHAN.receive {
1936 repeat;
1937 }
1938 [] L1CTL.receive(tr_L1CTL_DATA_IND(t_RslChanNr_PCH_AGCH(0), ?)) -> value l1_dl {
1939 /* somehow dec_SystemInformation will try to decode even non-RR as SI */
1940 var GsmRrMessage rr := dec_GsmRrMessage(l1_dl.payload.data_ind.payload);
1941 if (not match(rr, tr_IMM_ASS(42, ?, 5, ?, ?))) {
1942 /* FIXME: Why are we seeing paging requests on PCH/AGCH? */
1943 //setverdict(fail, "Unexpected IMM-ASS values on AGCH: ", rr);
Daniel Willmann17ddd852018-07-05 17:33:20 +02001944 //mtc.stop;
Harald Weltee8d750e2018-06-10 21:41:35 +02001945 } else {
1946 num_rx := num_rx+1;
1947 }
1948 repeat;
1949 }
1950 [] L1CTL.receive { repeat; }
1951 [] T.timeout { }
1952 }
1953 res_str := f_fmt_ia_stats(num_tx, num_rx, num_del);
1954 log("AGCH test: " & res_str);
1955 if (num_rx + num_del != num_tx) {
1956 setverdict(fail, "RX + DEL != TX ?!?: " & res_str);
Daniel Willmann17ddd852018-07-05 17:33:20 +02001957 mtc.stop
Harald Weltee8d750e2018-06-10 21:41:35 +02001958 }
1959 rx_ratio := int2float(num_rx) / int2float(num_tx);
1960 if (rx_ratio < exp_pass*0.8 or rx_ratio > exp_pass*1.2) {
1961 setverdict(fail, "RX ratio ("&float2str(rx_ratio)&") far from expected ("&float2str(exp_pass)&") " & res_str);
1962 } else {
1963 setverdict(pass);
1964 }
Daniel Willmann17ddd852018-07-05 17:33:20 +02001965 f_shutdown();
Harald Welte68e495b2018-02-25 00:05:57 +01001966}
1967
Harald Weltee8d750e2018-06-10 21:41:35 +02001968/* send a long burst of 1000 IMM.ASS with 20ms spacing (50 per s); expect 75% of them to be deleted */
1969testcase TC_imm_ass_1000_20ms() runs on test_CT {
1970 f_TC_imm_ass(1000, 0.02, 0.25);
1971}
1972
1973/* send a short burst of 200 IMM.ASS without any spacing; expect 95% of them to be deleted */
1974testcase TC_imm_ass_200_0ms() runs on test_CT {
1975 f_TC_imm_ass(200, 0.0, 0.05);
1976}
1977
1978/* send 150 IMM.ASS at rate of 13/s; expect none of them to be deleted */
1979testcase TC_imm_ass_200_76ms() runs on test_CT {
1980 f_TC_imm_ass(150, 0.076, 1.00);
1981}
1982
1983
1984
Harald Welte48494ca2018-02-25 16:59:50 +01001985/***********************************************************************
1986 * BCCH
1987 ***********************************************************************/
1988
1989/* tuple of Frame Number + decoded SI */
1990type record SystemInformationFn {
1991 GsmFrameNumber frame_number,
1992 SystemInformation si
1993}
1994
1995/* an arbitrary-length vector of decoded SI + gsmtap header */
1996type record of SystemInformationFn SystemInformationVector;
1997
1998/* an array of SI-vectors indexed by TC value */
1999type SystemInformationVector SystemInformationVectorPerTc[8];
2000
2001/* determine if a given SI vector contains given SI type at least once */
2002function f_si_vecslot_contains(SystemInformationVector arr, RrMessageType key, boolean bcch_ext := false) return boolean {
2003 for (var integer i:= 0; i< sizeof(arr); i := i + 1) {
2004 var integer fn_mod51 := arr[i].frame_number mod 51;
2005 if (not bcch_ext and fn_mod51 == 2 or
2006 bcch_ext and fn_mod51 == 6) {
2007 if (arr[i].si.header.message_type == key) {
2008 return true;
2009 }
2010 }
2011 }
2012 return false;
2013}
2014
2015/* ensure a given TC slot of the SI vector contains given SI type at least once at TC */
2016function f_ensure_si_vec_contains(SystemInformationVectorPerTc arr, integer tc, RrMessageType key, boolean ext_bcch := false) {
2017 if (not f_si_vecslot_contains(arr[tc], key, ext_bcch)) {
2018 setverdict(fail, "No ", key, " in TC=", tc, "!");
Daniel Willmann17ddd852018-07-05 17:33:20 +02002019 mtc.stop;
Harald Welte48494ca2018-02-25 16:59:50 +01002020 }
2021}
2022
2023/* check if a given SI vector contains given SI type at least once on any TC */
2024function f_si_vec_contains(SystemInformationVectorPerTc arr, RrMessageType key) return boolean {
2025 for (var integer tc:= 0; tc < sizeof(arr); tc := tc + 1) {
2026 if (f_si_vecslot_contains(arr[tc], key) or
2027 f_si_vecslot_contains(arr[tc], key, true)) {
2028 return true;
2029 }
2030 }
2031 return false;
2032}
2033
2034/* determine if a given SI vector contains given SI type at least N of M times */
2035function f_si_vecslot_contains_n_of_m(SystemInformationVector arr, RrMessageType key, boolean bcch_ext := false, integer n := 1, integer m := 4) return boolean {
2036 var integer count := 0;
2037 if (sizeof(arr) < m) {
2038 setverdict(fail, "Error: Insufficient SI in array");
Daniel Willmann17ddd852018-07-05 17:33:20 +02002039 mtc.stop;
Harald Welte48494ca2018-02-25 16:59:50 +01002040 }
2041 for (var integer i:= 0; i < m; i := i + 1) {
2042 var integer fn_mod51 := arr[i].frame_number mod 51;
2043 if (not bcch_ext and fn_mod51 == 2 or
2044 bcch_ext and fn_mod51 == 6) {
2045 if (arr[i].si.header.message_type == key) {
2046 count := count + 1;
2047 }
2048 }
2049 }
2050 if (count >= n) {
2051 return true;
2052 } else {
2053 return false;
2054 }
2055}
2056
2057/* ensure a given TC slot of the SI vector contains given SI type at least N out of M times at TC */
2058function f_ensure_si_vec_contains_n_of_m(SystemInformationVectorPerTc arr, integer tc, RrMessageType key, boolean ext_bcch := false, integer n, integer m) {
2059 if (not f_si_vecslot_contains_n_of_m(arr[tc], key, ext_bcch, n, m)) {
2060 setverdict(fail, "Not ", n, "/", m, " of ", key, " in TC=", tc, "!");
Daniel Willmann17ddd852018-07-05 17:33:20 +02002061 mtc.stop;
Harald Welte48494ca2018-02-25 16:59:50 +01002062 }
2063}
2064
2065/* determine if a given SI vector contains given SI type at least once */
2066function f_si_vecslot_contains_only(SystemInformationVector arr, RrMessageType key, boolean bcch_ext := false) return boolean {
2067 for (var integer i:= 0; i< sizeof(arr); i := i + 1) {
2068 var integer fn_mod51 := arr[i].frame_number mod 51;
2069 if (not bcch_ext and fn_mod51 == 2 or
2070 bcch_ext and fn_mod51 == 6) {
2071 if (arr[i].si.header.message_type != key) {
2072 return false;
2073 }
2074 }
2075 }
2076 return true;
2077}
2078
2079/* ensure a given TC slot of the SI vector contains only given SI type */
2080function f_ensure_si_vec_contains_only(SystemInformationVectorPerTc arr, integer tc, RrMessageType key, boolean ext_bcch := false) {
2081 if (not f_si_vecslot_contains_only(arr[tc], key, ext_bcch)) {
2082 setverdict(fail, "Not all ", key, " in TC=", tc, "!");
Daniel Willmann17ddd852018-07-05 17:33:20 +02002083 mtc.stop;
Harald Welte48494ca2018-02-25 16:59:50 +01002084 }
2085}
2086
2087/* SI configuration of cell, against which we validate actual SI messages */
2088type set SystemInformationConfig {
2089 boolean bcch_extended,
2090 boolean si1_present,
2091 boolean si2bis_present,
2092 boolean si2ter_present,
2093 boolean si2quater_present,
2094 boolean si7_present,
2095 boolean si8_present,
2096 boolean si9_present,
2097 boolean si13_present,
2098 boolean si13alt_present,
2099 boolean si15_present,
2100 boolean si16_present,
2101 boolean si17_present,
2102 boolean si2n_present,
2103 boolean si21_present,
2104 boolean si22_present
2105}
2106
2107/* validate the SI scheduling according to TS 45.002 version 14.1.0 Release 14, Section 6.3.1.3 */
2108function f_validate_si_scheduling(SystemInformationConfig cfg, SystemInformationVectorPerTc si_per_tc) {
2109 var integer i;
2110 for (i := 0; i < sizeof(si_per_tc); i := i + 1) {
2111 if (sizeof(si_per_tc[i]) == 0) {
Harald Welte544565a2018-03-02 10:34:08 +01002112 setverdict(fail, "No SI messages for TC=", i);
Daniel Willmann17ddd852018-07-05 17:33:20 +02002113 mtc.stop;
Harald Welte48494ca2018-02-25 16:59:50 +01002114 }
2115 }
2116 if (cfg.si1_present) {
2117 /* ii) System Information Type 1 needs to be sent if frequency hopping is in use or
2118 * when the NCH is present in a cell. If the MS finds another message on BCCH Norm
2119 * when TC = 0, it can assume that System Information Type 1 is not in use. */
2120 f_ensure_si_vec_contains(si_per_tc, 0, SYSTEM_INFORMATION_TYPE_1);
2121 /* make sure *ALL* contain SI1 */
2122 f_ensure_si_vec_contains_only(si_per_tc, 0, SYSTEM_INFORMATION_TYPE_1);
2123 }
2124 f_ensure_si_vec_contains(si_per_tc, 1, SYSTEM_INFORMATION_TYPE_2);
2125 /* iii) A SI 2 message will be sent at least every time TC = 1 */
2126 f_ensure_si_vec_contains(si_per_tc, 2, SYSTEM_INFORMATION_TYPE_3);
2127 f_ensure_si_vec_contains(si_per_tc, 6, SYSTEM_INFORMATION_TYPE_3);
2128 f_ensure_si_vec_contains(si_per_tc, 3, SYSTEM_INFORMATION_TYPE_4);
2129 f_ensure_si_vec_contains(si_per_tc, 7, SYSTEM_INFORMATION_TYPE_4);
2130
2131 /* iii) System information type 2 bis or 2 ter messages are sent if needed, as determined by the
2132 * system operator. If only one of them is needed, it is sent when TC = 5. If both are
2133 * needed, 2bis is sent when TC = 5 and 2ter is sent at least once within any of 4
2134 * consecutive occurrences of TC = 4. */
2135 if (cfg.si2bis_present and not cfg.si2ter_present) {
2136 f_ensure_si_vec_contains(si_per_tc, 5, SYSTEM_INFORMATION_TYPE_2bis);
2137 } else if (cfg.si2ter_present and not cfg.si2bis_present) {
2138 f_ensure_si_vec_contains(si_per_tc, 5, SYSTEM_INFORMATION_TYPE_2ter);
2139 } else if (cfg.si2ter_present and cfg.si2bis_present) {
2140 f_ensure_si_vec_contains(si_per_tc, 5, SYSTEM_INFORMATION_TYPE_2bis);
2141 f_ensure_si_vec_contains_n_of_m(si_per_tc, 4, SYSTEM_INFORMATION_TYPE_2ter, false, 1, 4);
2142 }
2143
2144 if (cfg.si7_present or cfg.si8_present) {
2145 /* vi) Use of System Information type 7 and 8 is not always necessary. It is necessary
2146 * if System Information type 4 does not contain all information needed for cell
2147 * selection and reselection. */
2148 if (not cfg.bcch_extended) {
2149 testcase.stop("Error: SI7/SI8 require BCCH Extd.");
2150 }
2151 if (cfg.si7_present) {
2152 f_ensure_si_vec_contains(si_per_tc, 7, SYSTEM_INFORMATION_TYPE_7, true);
2153 }
2154 if (cfg.si8_present) {
2155 f_ensure_si_vec_contains(si_per_tc, 3, SYSTEM_INFORMATION_TYPE_8, true);
2156 }
2157 }
2158
2159 if (cfg.si2quater_present) {
2160 /* iii) System information type 2 quater is sent if needed, as determined by the system
2161 * operator. If sent on BCCH Norm, it shall be sent when TC = 5 if neither of 2bis
2162 * and 2ter are used, otherwise it shall be sent at least once within any of 4
2163 * consecutive occurrences of TC = 4. If sent on BCCH Ext, it is sent at least once
2164 * within any of 4 consecutive occurrences of TC = 5. */
2165 if (not (cfg.bcch_extended)) {
2166 if (not (cfg.si2bis_present or cfg.si2ter_present)) {
2167 f_ensure_si_vec_contains(si_per_tc, 5, SYSTEM_INFORMATION_TYPE_2quater);
2168 } else {
2169 f_ensure_si_vec_contains_n_of_m(si_per_tc, 4, SYSTEM_INFORMATION_TYPE_2quater, false, 1, 4);
2170 }
2171 } else {
2172 f_ensure_si_vec_contains_n_of_m(si_per_tc, 5, SYSTEM_INFORMATION_TYPE_2quater, true, 1, 4);
2173 }
2174 }
2175 if (cfg.si9_present) {
2176 /* vi) System Information type 9 is sent in those blocks with TC = 4 which are specified
2177 * in system information type 3 as defined in 3GPP TS 44.018. */
2178 f_ensure_si_vec_contains(si_per_tc, 4, SYSTEM_INFORMATION_TYPE_9); // FIXME SI3
2179 }
2180 if (cfg.si13_present) {
2181 /* vii) System Information type 13 is only related to the GPRS service. System Information
2182 * Type 13 need only be sent if GPRS support is indicated in one or more of System
2183 * Information Type 3 or 4 or 7 or 8 messages. These messages also indicate if the
2184 * message is sent on the BCCH Norm or if the message is transmitted on the BCCH Ext.
2185 * In the case that the message is sent on the BCCH Norm, it is sent at least once
2186 * within any of 4 consecutive occurrences of TC=4. */
2187 if (not cfg.bcch_extended) {
2188 log("not-bccch-extended");
2189 f_ensure_si_vec_contains_n_of_m(si_per_tc, 4, SYSTEM_INFORMATION_TYPE_13, false, 1, 4);
2190 } else {
2191 log("bccch-extended");
2192 f_ensure_si_vec_contains(si_per_tc, 0, SYSTEM_INFORMATION_TYPE_13, true);
2193 }
2194 if (f_si_vec_contains(si_per_tc, SYSTEM_INFORMATION_TYPE_13alt)) {
2195 setverdict(fail, "Cannot have SI13alt and SI13");
Daniel Willmann17ddd852018-07-05 17:33:20 +02002196 mtc.stop;
Harald Welte48494ca2018-02-25 16:59:50 +01002197 }
2198 }
2199 if (cfg.si16_present or cfg.si17_present) {
2200 /* viii) System Information type 16 and 17 are only related to the SoLSA service. They
2201 * should not be sent in a cell where network sharing is used (see rule xv). */
2202 if (cfg.si22_present) {
2203 testcase.stop("Error: Cannot have SI16/SI17 and SI22!");
2204 }
2205 if (f_si_vec_contains(si_per_tc, SYSTEM_INFORMATION_TYPE_22)) {
2206 setverdict(fail, "Cannot have SI16/SI17 and SI22!");
Daniel Willmann17ddd852018-07-05 17:33:20 +02002207 mtc.stop;
Harald Welte48494ca2018-02-25 16:59:50 +01002208 }
2209 if (not cfg.bcch_extended) {
2210 testcase.stop("Error: SI16/SI17 requires BCCH Extd!");
2211 }
2212 if (cfg.si16_present) {
2213 f_ensure_si_vec_contains(si_per_tc, 6, SYSTEM_INFORMATION_TYPE_16, true);
2214 }
2215 if (cfg.si17_present) {
2216 f_ensure_si_vec_contains(si_per_tc, 2, SYSTEM_INFORMATION_TYPE_17, true);
2217 }
2218 }
2219
2220 /* ix) System Information type 18 and 20 are sent in order to transmit non-GSM
2221 * broadcast information. The frequency with which they are sent is determined by the
2222 * system operator. System Information type 9 identifies the scheduling of System
2223 * Information type 18 and 20 messages. */
2224
2225 /* x) System Information Type 19 is sent if COMPACT neighbours exist. If System
2226 * Information Type 19 is present, then its scheduling shall be indicated in System
2227 * Information Type 9. */
2228
2229 if (cfg.si15_present) {
2230 /* xi) System Information Type 15 is broadcast if dynamic ARFCN mapping is used in the
2231 * PLMN. If sent on BCCH Norm, it is sent at least once within any of 4 consecutive
2232 * occurrences of TC = 4. If sent on BCCH Ext, it is sent at least once within any of
2233 * 4 consecutive occurrences of TC = 1. */
2234 if (not cfg.bcch_extended) {
2235 f_ensure_si_vec_contains_n_of_m(si_per_tc, 4, SYSTEM_INFORMATION_TYPE_15, false, 1, 4);
2236 } else {
2237 f_ensure_si_vec_contains_n_of_m(si_per_tc, 1, SYSTEM_INFORMATION_TYPE_15, true, 1, 4);
2238 }
2239 }
2240 if (cfg.si13alt_present) {
2241 /* xii) System Information type 13 alt is only related to the GERAN Iu mode. System
2242 * Information Type 13 alt need only be sent if GERAN Iu mode support is indicated in
2243 * one or more of System Information Type 3 or 4 or 7 or 8 messages and SI 13 is not
2244 * broadcast. These messages also indicate if the message is sent on the BCCH Norm or
2245 * if the message is transmitted on the BCCH Ext. In the case that the message is sent
2246 * on the BCCH Norm, it is sent at least once within any of 4 consecutive occurrences
2247 * of TC = 4. */
2248 if (cfg.si13_present) {
2249 testcase.stop("Error: Cannot have SI13alt and SI13");
2250 }
2251 if (f_si_vec_contains(si_per_tc, SYSTEM_INFORMATION_TYPE_13)) {
2252 setverdict(fail, "Cannot have SI13alt and SI13");
Daniel Willmann17ddd852018-07-05 17:33:20 +02002253 mtc.stop;
Harald Welte48494ca2018-02-25 16:59:50 +01002254 }
2255 if (not cfg.bcch_extended) {
2256 f_ensure_si_vec_contains_n_of_m(si_per_tc, 4, SYSTEM_INFORMATION_TYPE_13alt, false, 1, 4);
2257 } else {
2258 f_ensure_si_vec_contains(si_per_tc, 0, SYSTEM_INFORMATION_TYPE_13alt, true);
2259 }
2260 }
2261 if (cfg.si2n_present) {
2262 /* xiii) System Information Type 2n is optionally sent on BCCH Norm or BCCH Ext if needed,
2263 * as determined by the system operator. In the case that the message is sent on the
2264 * BCCH Norm, it is sent at least once within any of 4 consecutive occurrences of TC =
2265 * 4. If the message is sent on BCCH Ext, it is sent at least once within any of 2
2266 * consecutive occurrences of TC = 4. */
2267 if (not cfg.bcch_extended) {
2268 f_ensure_si_vec_contains_n_of_m(si_per_tc, 4, SYSTEM_INFORMATION_TYPE_2n, false, 1, 4);
2269 } else {
2270 f_ensure_si_vec_contains_n_of_m(si_per_tc, 4, SYSTEM_INFORMATION_TYPE_2n, true, 2, 4);
2271 }
2272 }
2273 if (cfg.si21_present) {
2274 /* xiv) System Information Type 21 is optionally sent on BCCH Norm or BCCH Ext, as
2275 * determined by the system operator. If Extended Access Barring is in use in the cell
2276 * then this message is sent at least once within any of 4 consecutive occurrences of
2277 * TC = 4 regardless if it is sent on BCCH Norm or BCCH Ext. If BCCH Ext is used in a
2278 * cell then this message shall only be sent on BCCH Ext. */
2279 if (not cfg.bcch_extended) {
2280 f_ensure_si_vec_contains_n_of_m(si_per_tc, 4, SYSTEM_INFORMATION_TYPE_21, false, 1, 4);
2281 } else {
2282 f_ensure_si_vec_contains_n_of_m(si_per_tc, 4, SYSTEM_INFORMATION_TYPE_21, true, 1, 4);
2283 if (f_si_vecslot_contains(si_per_tc[4], SYSTEM_INFORMATION_TYPE_21)) {
2284 setverdict(fail, "Cannot have SI21 on BCCH Norm if BCCH Extd enabled!");
Daniel Willmann17ddd852018-07-05 17:33:20 +02002285 mtc.stop;
Harald Welte48494ca2018-02-25 16:59:50 +01002286 }
2287 }
2288 }
2289 if (cfg.si22_present) {
2290 /* xv) System Information Type 22 is sent if network sharing is in use in the cell. It
2291 * should not be sent in a cell where SoLSA is used (see rule viii). System
2292 * Information Type 22 instances shall be sent on BCCH Ext within any occurrence of TC
2293 * =2 and TC=6. */
2294 if (cfg.si16_present or cfg.si17_present) {
2295 testcase.stop("Error: Cannot have SI16/SI17 and SI22!");
2296 }
2297 if (f_si_vec_contains(si_per_tc, SYSTEM_INFORMATION_TYPE_16) or
2298 f_si_vec_contains(si_per_tc, SYSTEM_INFORMATION_TYPE_17)) {
2299 setverdict(fail, "Cannot have SI16/SI17 and SI22!");
Daniel Willmann17ddd852018-07-05 17:33:20 +02002300 mtc.stop;
Harald Welte48494ca2018-02-25 16:59:50 +01002301 }
2302 if (not cfg.bcch_extended) {
2303 testcase.stop("Error: SI22 requires BCCH Extd!");
2304 } else {
2305 f_ensure_si_vec_contains_only(si_per_tc, 2, SYSTEM_INFORMATION_TYPE_22, true);
2306 f_ensure_si_vec_contains_only(si_per_tc, 6, SYSTEM_INFORMATION_TYPE_22, true);
2307 }
2308 }
2309}
2310
2311/* sample Systme Information for specified duration via L1CTL */
2312function f_l1_sample_si(L1CTL_PT pt, float duration := 8.0) return SystemInformationVectorPerTc {
2313 timer T := duration;
2314 var SystemInformationVectorPerTc si_per_tc;
2315 var L1ctlDlMessage l1_dl;
2316
2317 /* initialize all per-TC vectors empty */
2318 for (var integer i:= 0; i < sizeof(si_per_tc); i := i+1) {
2319 si_per_tc[i] := {};
2320 }
2321
2322 /* flush all previous L1 queued msgs */
2323 pt.clear;
2324
2325 T.start;
2326 alt {
Harald Weltef8df4cb2018-03-10 15:15:08 +01002327 [] pt.receive(tr_L1CTL_DATA_IND(t_RslChanNr_BCCH(0), ?)) -> value l1_dl {
Harald Welte48494ca2018-02-25 16:59:50 +01002328 /* somehow dec_SystemInformation will try to decode even non-RR as SI */
2329 if (not (l1_dl.payload.data_ind.payload[1] == '06'O)) {
2330 log("Ignoring non-RR SI ", l1_dl);
2331 repeat;
2332 }
2333 var SystemInformationFn sig := {
2334 frame_number := l1_dl.dl_info.frame_nr,
2335 si := dec_SystemInformation(l1_dl.payload.data_ind.payload)
2336 }
2337 var integer tc := f_gsm_compute_tc(sig.frame_number);
2338 log("SI received at TC=", tc, ": ", sig.si);
2339 /* append to the per-TC bucket */
2340 si_per_tc[tc] := si_per_tc[tc] & { sig };
2341 repeat;
2342 }
2343 [] pt.receive { repeat; }
2344 [] T.timeout { }
2345 }
2346
2347 for (var integer i:= 0; i < sizeof(si_per_tc); i := i+1) {
2348 log(testcasename(), ": TC=", i, " has #of SI=", sizeof(si_per_tc[i]));
2349 }
2350 log("si_per_tc=", si_per_tc);
2351 return si_per_tc;
2352}
2353
2354/* helper function: Set given SI via RSL + validate scheduling.
2355 * CALLER MUST MAKE SURE TO CHANGE GLOBAL si_cfg! */
2356function f_TC_si_sched() runs on test_CT {
2357 var SystemInformationVectorPerTc si_per_tc;
2358 f_init_l1ctl();
2359 f_l1_tune(L1CTL);
2360
2361 /* Sample + Validate Scheduling */
2362 si_per_tc := f_l1_sample_si(L1CTL);
2363 f_validate_si_scheduling(si_cfg, si_per_tc);
2364
2365 setverdict(pass);
2366}
2367
2368testcase TC_si_sched_default() runs on test_CT {
2369 f_init();
Harald Welte0cae4552018-03-09 22:20:26 +01002370 /* 2+3+4 are mandatory and set in f_init() */
2371 f_TC_si_sched();
Harald Welte294b0a22018-03-10 23:26:48 +01002372 f_shutdown();
Harald Welte0cae4552018-03-09 22:20:26 +01002373}
2374
2375testcase TC_si_sched_1() runs on test_CT {
2376 f_init();
2377 si_cfg.si1_present := true;
2378 f_rsl_bcch_fill_raw(RSL_SYSTEM_INFO_1, '5506198fb38000000000000000000000000000e504002b'O);
Harald Welte48494ca2018-02-25 16:59:50 +01002379 f_TC_si_sched();
Harald Welte294b0a22018-03-10 23:26:48 +01002380 f_shutdown();
Harald Welte48494ca2018-02-25 16:59:50 +01002381}
2382
2383testcase TC_si_sched_2bis() runs on test_CT {
2384 f_init();
2385 si_cfg.si2bis_present := true;
2386 f_rsl_bcch_fill_raw(RSL_SYSTEM_INFO_2bis, '550602bfe809b3ff00000000000000000000007900002b'O);
2387 f_TC_si_sched();
Harald Welte294b0a22018-03-10 23:26:48 +01002388 f_shutdown();
Harald Welte48494ca2018-02-25 16:59:50 +01002389}
2390
2391testcase TC_si_sched_2ter() runs on test_CT {
2392 f_init();
2393 si_cfg.si2ter_present := true;
2394 f_rsl_bcch_fill_raw(RSL_SYSTEM_INFO_2ter, '010603bf66b0aa0a00000002000000000000002b2b2b2b'O);
2395 f_TC_si_sched();
Harald Welte294b0a22018-03-10 23:26:48 +01002396 f_shutdown();
Harald Welte48494ca2018-02-25 16:59:50 +01002397}
2398
2399testcase TC_si_sched_2ter_2bis() runs on test_CT {
2400 f_init();
2401 si_cfg.si2bis_present := true;
2402 f_rsl_bcch_fill_raw(RSL_SYSTEM_INFO_2bis, '550602bfe809b3ff00000000000000000000007900002b'O);
2403 si_cfg.si2ter_present := true;
2404 f_rsl_bcch_fill_raw(RSL_SYSTEM_INFO_2ter, '010603bf66b0aa0a00000002000000000000002b2b2b2b'O);
2405 f_TC_si_sched();
Harald Welte294b0a22018-03-10 23:26:48 +01002406 f_shutdown();
Harald Welte48494ca2018-02-25 16:59:50 +01002407}
2408
2409testcase TC_si_sched_2quater() runs on test_CT {
2410 f_init();
2411 si_cfg.si2quater_present := true;
2412 f_rsl_bcch_fill_raw(RSL_SYSTEM_INFO_2quater, '050607a8a0364aa698d72ff424feee0506d5e7fff02043'O);
2413 f_TC_si_sched();
Harald Welte294b0a22018-03-10 23:26:48 +01002414 f_shutdown();
Harald Welte48494ca2018-02-25 16:59:50 +01002415}
2416
2417testcase TC_si_sched_13() runs on test_CT {
2418 f_init();
2419 si_cfg.si13_present := true;
Harald Welte5618c2a2018-04-15 16:24:46 +02002420 f_rsl_bcch_fill_raw(RSL_SYSTEM_INFO_13, '0106009000185a6fc9e08410ab2b2b2b2b2b2b2b2b2b2b'O);
Harald Welte48494ca2018-02-25 16:59:50 +01002421 f_TC_si_sched();
Harald Welte294b0a22018-03-10 23:26:48 +01002422 f_shutdown();
Harald Welte48494ca2018-02-25 16:59:50 +01002423}
2424
2425testcase TC_si_sched_13_2bis_2ter_2quater() runs on test_CT {
2426 f_init();
2427 si_cfg.si2bis_present := true;
2428 f_rsl_bcch_fill_raw(RSL_SYSTEM_INFO_2bis, '550602bfe809b3ff00000000000000000000007900002b'O);
2429 si_cfg.si2ter_present := true;
2430 f_rsl_bcch_fill_raw(RSL_SYSTEM_INFO_2ter, '010603bf66b0aa0a00000002000000000000002b2b2b2b'O);
2431 si_cfg.si2quater_present := true;
2432 f_rsl_bcch_fill_raw(RSL_SYSTEM_INFO_2quater, '050607a8a0364aa698d72ff424feee0506d5e7fff02043'O);
2433 si_cfg.si13_present := true;
Harald Welte5618c2a2018-04-15 16:24:46 +02002434 f_rsl_bcch_fill_raw(RSL_SYSTEM_INFO_13, '0106009000185a6fc9e08410ab2b2b2b2b2b2b2b2b2b2b'O);
Harald Welte48494ca2018-02-25 16:59:50 +01002435 f_TC_si_sched();
Harald Welte294b0a22018-03-10 23:26:48 +01002436 f_shutdown();
Harald Welte48494ca2018-02-25 16:59:50 +01002437}
2438
2439
Harald Welte68e495b2018-02-25 00:05:57 +01002440testcase TC_bcch_info() runs on test_CT {
2441 f_init(testcasename());
2442 /* FIXME: enable / disable individual BCCH info */
2443 //ts_RSL_BCCH_INFO(si_type, info);
2444 /* expect no ERROR REPORT after either of them *
2445 /* negative test: ensure ERROR REPORT on unsupported types */
Harald Welte294b0a22018-03-10 23:26:48 +01002446 f_shutdown();
Harald Welte68e495b2018-02-25 00:05:57 +01002447}
2448
Harald Welte93640c62018-02-25 16:59:33 +01002449/***********************************************************************
2450 * Low-Level Protocol Errors / ERROR REPORT
2451 ***********************************************************************/
2452
Harald Welte01d982c2018-02-25 01:31:40 +01002453private function f_exp_err_rep(template RSL_Cause cause) runs on test_CT {
2454 timer T := 5.0;
2455 T.start;
2456 alt {
2457 [] RSL_CCHAN.receive(tr_RSL_UD(tr_RSL_ERROR_REPORT(cause))) {
2458 setverdict(pass);
2459 }
2460 [] RSL_CCHAN.receive(tr_RSL_UD(tr_RSL_ERROR_REPORT(?))) {
2461 setverdict(fail, "Wrong cause in RSL ERR REP");
Daniel Willmann17ddd852018-07-05 17:33:20 +02002462 mtc.stop;
Harald Welte01d982c2018-02-25 01:31:40 +01002463 }
2464 [] RSL_CCHAN.receive {
2465 repeat;
2466 }
2467 [] T.timeout {
2468 setverdict(fail, "Timeout waiting for RSL ERR REP");
Daniel Willmann17ddd852018-07-05 17:33:20 +02002469 mtc.stop;
Harald Welte01d982c2018-02-25 01:31:40 +01002470 }
2471 }
2472}
2473
2474/* Provoke a protocol error (message too short) and match on ERROR REPORT */
2475testcase TC_rsl_protocol_error() runs on test_CT {
2476 f_init(testcasename());
2477 var RSL_Message rsl := valueof(ts_RSL_BCCH_INFO(RSL_SYSTEM_INFO_1, ''O));
2478 rsl.ies := omit;
2479 RSL_CCHAN.send(ts_RSL_UD(rsl));
2480
2481 f_exp_err_rep(RSL_ERR_PROTO);
2482}
2483
2484/* Provoke a mandatory IE error and match on ERROR REPORT */
2485testcase TC_rsl_mand_ie_error() runs on test_CT {
2486 f_init(testcasename());
2487
2488 var RSL_Message rsl := valueof(ts_RSL_BCCH_INFO(RSL_SYSTEM_INFO_1, ''O));
2489 rsl.ies := { rsl.ies[0] };
2490 RSL_CCHAN.send(ts_RSL_UD(rsl));
2491
2492 f_exp_err_rep(RSL_ERR_MAND_IE_ERROR);
2493}
2494
2495/* Provoke an IE content error and match on ERROR REPORT */
2496testcase TC_rsl_ie_content_error() runs on test_CT {
2497 f_init(testcasename());
2498 var RSL_Message rsl := valueof(ts_RSL_BCCH_INFO(RSL_SYSTEM_INFO_1, ''O));
2499 rsl.ies[1].body.sysinfo_type := RSL_SYSTEM_INFO_5;
2500 RSL_CCHAN.send(ts_RSL_UD(rsl));
2501
2502 f_exp_err_rep(RSL_ERR_IE_CONTENT);
2503}
2504
Harald Welte93640c62018-02-25 16:59:33 +01002505/***********************************************************************
2506 * IPA CRCX/MDCX/DLCS media stream handling
2507 ***********************************************************************/
2508
Harald Weltea871a382018-02-25 02:03:14 +01002509/* Send IPA DLCX to inactive lchan */
2510function f_TC_ipa_dlcx_not_active(charstring id) runs on ConnHdlr {
Harald Welte1eba3742018-02-25 12:48:14 +01002511 f_rsl_transceive(ts_RSL_IPA_DLCX(g_chan_nr, 0), tr_RSL_IPA_DLCX_ACK(g_chan_nr, ?, ?),
2512 "IPA DLCX ACK");
Harald Weltea871a382018-02-25 02:03:14 +01002513}
2514testcase TC_ipa_dlcx_not_active() runs on test_CT {
2515 var ConnHdlrPars pars := valueof(t_Pars(t_RslChanNr_Bm(1), ts_RSL_ChanMode_SIGN));
2516 f_init(testcasename());
2517 var ConnHdlr vc_conn := f_start_handler(refers(f_TC_ipa_dlcx_not_active), pars);
2518 vc_conn.done;
2519}
Harald Welte68e495b2018-02-25 00:05:57 +01002520
Harald Weltea3f1df92018-02-25 12:49:55 +01002521/* Send IPA CRCX twice to inactive lchan */
2522function f_TC_ipa_crcx_twice_not_active(charstring id) runs on ConnHdlr {
2523 f_rsl_transceive(ts_RSL_IPA_CRCX(g_chan_nr), tr_RSL_IPA_CRCX_ACK(g_chan_nr, ?, ?, ?),
2524 "IPA CRCX ACK");
2525 f_rsl_transceive(ts_RSL_IPA_CRCX(g_chan_nr), tr_RSL_IPA_CRCX_NACK(g_chan_nr, RSL_ERR_RES_UNAVAIL),
2526 "IPA CRCX NACK");
2527}
2528testcase TC_ipa_crcx_twice_not_active() runs on test_CT {
2529 var ConnHdlrPars pars := valueof(t_Pars(t_RslChanNr_Bm(1), ts_RSL_ChanMode_SIGN));
2530 f_init(testcasename());
2531 var ConnHdlr vc_conn := f_start_handler(refers(f_TC_ipa_crcx_twice_not_active), pars);
2532 vc_conn.done;
2533}
2534
2535/* Regular sequence of CRCX/MDCX/DLCX */
2536function f_TC_ipa_crcx_mdcx_dlcx_not_active(charstring id) runs on ConnHdlr {
2537 f_rsl_transceive(ts_RSL_IPA_CRCX(g_chan_nr), tr_RSL_IPA_CRCX_ACK(g_chan_nr, ?, ?, ?),
2538 "IPA CRCX ACK");
2539 var uint32_t remote_ip := f_rnd_int(c_UINT32_MAX);
2540 var uint16_t remote_port := f_rnd_int(c_UINT16_MAX);
2541 var uint7_t rtp_pt2 := f_rnd_int(127);
2542 var uint16_t fake_conn_id := 23; /* we're too lazy to read it out from the CRCX ACK above */
2543 f_rsl_transceive(ts_RSL_IPA_MDCX(g_chan_nr, fake_conn_id, remote_ip, remote_port, rtp_pt2),
2544 tr_RSL_IPA_MDCX_ACK(g_chan_nr, ?, ?, ?, rtp_pt2),
2545 "IPA MDCX ACK");
2546 f_rsl_transceive(ts_RSL_IPA_DLCX(g_chan_nr, fake_conn_id), tr_RSL_IPA_DLCX_ACK(g_chan_nr, ?, ?),
2547 "IPA DLCX ACK");
2548}
2549testcase TC_ipa_crcx_mdcx_dlcx_not_active() runs on test_CT {
2550 var ConnHdlrPars pars := valueof(t_Pars(t_RslChanNr_Bm(1), ts_RSL_ChanMode_SIGN));
2551 f_init(testcasename());
2552 var ConnHdlr vc_conn := f_start_handler(refers(f_TC_ipa_crcx_mdcx_dlcx_not_active), pars);
2553 vc_conn.done;
2554}
2555
Harald Welte3ae11da2018-02-25 13:36:06 +01002556/* Sequence of CRCX, 2x MDCX, DLCX */
2557function f_TC_ipa_crcx_mdcx_mdcx_dlcx_not_active(charstring id) runs on ConnHdlr {
2558 f_rsl_transceive(ts_RSL_IPA_CRCX(g_chan_nr), tr_RSL_IPA_CRCX_ACK(g_chan_nr, ?, ?, ?),
2559 "IPA CRCX ACK");
2560 var uint32_t remote_ip := f_rnd_int(c_UINT32_MAX);
2561 var uint16_t remote_port := f_rnd_int(c_UINT16_MAX);
2562 var uint7_t rtp_pt2 := f_rnd_int(127);
2563 var uint16_t fake_conn_id := 23; /* we're too lazy to read it out from the CRCX ACK above */
2564 f_rsl_transceive(ts_RSL_IPA_MDCX(g_chan_nr, fake_conn_id, remote_ip, remote_port, rtp_pt2),
2565 tr_RSL_IPA_MDCX_ACK(g_chan_nr, ?, ?, ?, rtp_pt2),
2566 "IPA MDCX ACK");
2567 /* Second MDCX */
2568 remote_ip := f_rnd_int(c_UINT32_MAX);
2569 remote_port := f_rnd_int(c_UINT16_MAX);
2570 f_rsl_transceive(ts_RSL_IPA_MDCX(g_chan_nr, fake_conn_id, remote_ip, remote_port, rtp_pt2),
2571 tr_RSL_IPA_MDCX_ACK(g_chan_nr, ?, ?, ?, rtp_pt2),
2572 "IPA MDCX ACK");
2573 f_rsl_transceive(ts_RSL_IPA_DLCX(g_chan_nr, fake_conn_id), tr_RSL_IPA_DLCX_ACK(g_chan_nr, ?, ?),
2574 "IPA DLCX ACK");
2575}
2576testcase TC_ipa_crcx_mdcx_mdcx_dlcx_not_active() runs on test_CT {
2577 var ConnHdlrPars pars := valueof(t_Pars(t_RslChanNr_Bm(1), ts_RSL_ChanMode_SIGN));
2578 f_init(testcasename());
2579 var ConnHdlr vc_conn := f_start_handler(refers(f_TC_ipa_crcx_mdcx_mdcx_dlcx_not_active), pars);
2580 vc_conn.done;
2581}
2582
Harald Welte9912eb52018-02-25 13:30:15 +01002583/* IPA CRCX on SDCCH/4 and SDCCH/8 (doesn't make sense) */
2584function f_TC_ipa_crcx_sdcch_not_active(charstring id) runs on ConnHdlr {
2585 f_rsl_transceive(ts_RSL_IPA_CRCX(g_chan_nr), tr_RSL_IPA_CRCX_NACK(g_chan_nr, ?),
2586 "IPA CRCX NACK");
2587}
2588testcase TC_ipa_crcx_sdcch_not_active() runs on test_CT {
2589 var ConnHdlrPars pars;
2590 var ConnHdlr vc_conn;
2591 f_init(testcasename());
2592
2593 pars := valueof(t_Pars(t_RslChanNr_SDCCH4(0,1), ts_RSL_ChanMode_SIGN));
2594 vc_conn := f_start_handler(refers(f_TC_ipa_crcx_sdcch_not_active), pars);
2595 vc_conn.done;
2596
2597 pars := valueof(t_Pars(t_RslChanNr_SDCCH8(6,5), ts_RSL_ChanMode_SIGN));
2598 vc_conn := f_start_handler(refers(f_TC_ipa_crcx_sdcch_not_active), pars);
2599 vc_conn.done;
2600}
2601
Harald Weltea3f1df92018-02-25 12:49:55 +01002602
Harald Welte883340c2018-02-28 18:59:29 +01002603/***********************************************************************
2604 * PCU Socket related tests
2605 ***********************************************************************/
2606
2607private function f_TC_pcu_act_req(uint8_t bts_nr, uint8_t trx_nr, uint8_t ts_nr, boolean exp_success)
2608runs on test_CT {
2609 timer T := 3.0;
2610
2611 /* we don't expect any RTS.req before PDCH are active */
2612 T.start;
2613 alt {
2614 [] PCU.receive(t_SD_PCUIF(g_pcu_conn_id, tr_PCUIF_RTS_REQ(bts_nr))) {
2615 setverdict(fail, "PCU RTS.req before PDCH active?");
Daniel Willmann17ddd852018-07-05 17:33:20 +02002616 mtc.stop;
Harald Welte883340c2018-02-28 18:59:29 +01002617 }
2618 [] PCU.receive { repeat; }
2619 [] T.timeout { }
2620 }
2621
2622 /* Send PDCH activate request for known PDCH timeslot */
2623 PCU.send(t_SD_PCUIF(g_pcu_conn_id, ts_PCUIF_ACT_REQ(bts_nr, trx_nr, ts_nr)));
2624
2625 /* we now expect RTS.req for this timeslot (only) */
2626 T.start;
2627 alt {
2628 [exp_success] PCU.receive(t_SD_PCUIF(g_pcu_conn_id, tr_PCUIF_RTS_REQ(bts_nr, trx_nr, ts_nr))) {
2629 setverdict(pass);
2630 }
2631 [not exp_success] PCU.receive(t_SD_PCUIF(g_pcu_conn_id,
2632 tr_PCUIF_RTS_REQ(bts_nr, trx_nr, ts_nr))) {
2633 setverdict(fail, "Unexpected RTS.req for supposedly failing activation");
Daniel Willmann17ddd852018-07-05 17:33:20 +02002634 mtc.stop;
Harald Welte883340c2018-02-28 18:59:29 +01002635 }
2636 [] PCU.receive(t_SD_PCUIF(g_pcu_conn_id, tr_PCUIF_RTS_REQ)) {
2637 setverdict(fail, "RTS.req for wrong TRX/TS");
Daniel Willmann17ddd852018-07-05 17:33:20 +02002638 mtc.stop;
Harald Welte883340c2018-02-28 18:59:29 +01002639 }
2640 [] PCU.receive { repeat; }
2641 [exp_success] T.timeout {
2642 setverdict(fail, "Timeout waiting for PCU RTS.req");
Daniel Willmann17ddd852018-07-05 17:33:20 +02002643 mtc.stop;
Harald Welte883340c2018-02-28 18:59:29 +01002644 }
2645 [not exp_success] T.timeout {
2646 setverdict(pass);
2647 }
2648 }
2649}
2650
2651private function f_TC_pcu_deact_req(uint8_t bts_nr, uint8_t trx_nr, uint8_t ts_nr)
2652runs on test_CT {
2653 timer T := 3.0;
2654
2655 /* Send PDCH activate request for known PDCH timeslot */
2656 PCU.send(t_SD_PCUIF(g_pcu_conn_id, ts_PCUIF_DEACT_REQ(bts_nr, trx_nr, ts_nr)));
2657
2658 PCU.clear;
2659 /* we now expect no RTS.req for this timeslot */
2660 T.start;
2661 alt {
2662 [] PCU.receive(t_SD_PCUIF(g_pcu_conn_id, tr_PCUIF_RTS_REQ(bts_nr, trx_nr, ts_nr))) {
2663 setverdict(fail, "Received unexpected PCU RTS.req");
Daniel Willmann17ddd852018-07-05 17:33:20 +02002664 mtc.stop;
Harald Welte883340c2018-02-28 18:59:29 +01002665 }
2666 [] PCU.receive { repeat; }
2667 [] T.timeout {
2668 setverdict(pass);
2669 }
2670 }
2671}
2672
2673/* PDCH activation via PCU socket; check for presence of RTS.req */
2674testcase TC_pcu_act_req() runs on test_CT {
2675 f_init();
2676 f_TC_pcu_act_req(0, 0, 7, true);
2677}
2678
2679/* PDCH activation via PCU socket on non-PDCU timeslot */
2680testcase TC_pcu_act_req_wrong_ts() runs on test_CT {
2681 f_init();
2682 f_TC_pcu_act_req(0, 0, 1, false);
2683}
2684
2685/* PDCH activation via PCU socket on wrong BTS */
2686testcase TC_pcu_act_req_wrong_bts() runs on test_CT {
2687 f_init();
2688 f_TC_pcu_act_req(23, 0, 7, false);
2689}
2690
2691/* PDCH activation via PCU socket on wrong TRX */
2692testcase TC_pcu_act_req_wrong_trx() runs on test_CT {
2693 f_init();
2694 f_TC_pcu_act_req(0, 23, 7, false);
2695}
2696
2697/* PDCH deactivation via PCU socket; check for absence of RTS.req */
2698testcase TC_pcu_deact_req() runs on test_CT {
2699 f_init();
2700 /* Activate PDCH */
2701 f_TC_pcu_act_req(0, 0, 7, true);
2702 f_sleep(1.0);
2703 /* and De-Activate again */
2704 f_TC_pcu_deact_req(0, 0, 7);
2705}
2706
2707/* Attempt to deactivate a PDCH on a non-PDCH timeslot */
2708testcase TC_pcu_deact_req_wrong_ts() runs on test_CT {
2709 f_init();
2710 f_TC_pcu_deact_req(0, 0, 1);
2711}
2712
2713/* Test the PCU->BTS Version and BTS->PCU SI13 handshake */
2714testcase TC_pcu_ver_si13() runs on test_CT {
2715 const octetstring si13 := '00010203040506070909'O;
2716 var PCUIF_send_data sd;
2717 timer T:= 3.0;
2718 f_init();
2719
2720 /* Set SI13 via RSL */
2721 f_rsl_bcch_fill_raw(RSL_SYSTEM_INFO_13, si13);
2722 PCU.send(t_SD_PCUIF(g_pcu_conn_id, ts_PCUIF_TXT_IND(0, PCU_VERSION, "BTS_Test v23")));
2723 T.start;
2724 alt {
2725 [] PCU.receive(t_SD_PCUIF(g_pcu_conn_id, tr_PCUIF_DATA_IND(0, 0, 0, ?, PCU_IF_SAPI_BCCH))) -> value sd {
2726 if (substr(sd.data.u.data_ind.data, 0, lengthof(si13)) == si13) {
2727 setverdict(pass);
2728 } else {
2729 repeat;
2730 }
2731 }
2732 [] PCU.receive { repeat; }
2733 [] T.timeout {
2734 setverdict(fail, "Timeout waiting for SI13");
Daniel Willmann17ddd852018-07-05 17:33:20 +02002735 mtc.stop;
Harald Welte883340c2018-02-28 18:59:29 +01002736 }
2737 }
2738}
2739
2740private const octetstring c_PCU_DATA := '000102030405060708090a0b0c0d0e0f10111213141516'O;
2741
2742/* helper function to send a PCU DATA.req */
2743private function f_pcu_data_req(uint8_t bts_nr, uint8_t trx_nr, uint8_t ts_nr,
2744 uint8_t block_nr, uint32_t fn, PCUIF_Sapi sapi, octetstring data)
2745runs on test_CT
2746{
2747 PCU.send(t_SD_PCUIF(g_pcu_conn_id,
2748 ts_PCUIF_DATA_REQ(bts_nr, trx_nr, ts_nr, block_nr, fn, sapi, data)));
2749}
2750
2751/* helper function to wait for RTS.ind for given SAPI on given BTS/TRX/TS and then send */
2752private function f_pcu_wait_rts_and_data_req(uint8_t bts_nr, uint8_t trx_nr, uint8_t ts_nr,
2753 PCUIF_Sapi sapi, octetstring data)
2754runs on test_CT
2755{
2756 var PCUIF_send_data sd;
2757
2758 timer T := 3.0;
2759 T.start;
2760 alt {
2761 [] PCU.receive(t_SD_PCUIF(g_pcu_conn_id,
2762 tr_PCUIF_RTS_REQ(bts_nr, trx_nr, ts_nr, sapi))) -> value sd {
2763 f_pcu_data_req(bts_nr, trx_nr, ts_nr, sd.data.u.rts_req.block_nr,
2764 sd.data.u.rts_req.fn, sapi, data);
2765 }
2766 [] PCU.receive { repeat; }
2767 [] T.timeout {
2768 setverdict(fail, "Timeout waiting for RTS.ind");
Daniel Willmann17ddd852018-07-05 17:33:20 +02002769 mtc.stop;
Harald Welte883340c2018-02-28 18:59:29 +01002770 }
2771 }
2772}
2773
2774/* Send DATA.req on invalid BTS */
2775testcase TC_pcu_data_req_wrong_bts() runs on test_CT {
2776 f_init();
2777 f_TC_pcu_act_req(0, 0, 7, true);
2778 f_pcu_data_req(23, 0, 7, 0, 0, PCU_IF_SAPI_PDTCH, c_PCU_DATA);
2779 /* FIXME: how to check this wasn't actually sent and didn't crash BTS? */
2780 f_sleep(10.0);
2781}
2782
2783/* Send DATA.req on invalid TRX */
2784testcase TC_pcu_data_req_wrong_trx() runs on test_CT {
2785 f_init();
2786 f_TC_pcu_act_req(0, 0, 7, true);
2787 f_pcu_data_req(0, 100, 7, 0, 0, PCU_IF_SAPI_PDTCH, c_PCU_DATA);
2788 /* FIXME: how to check this wasn't actually sent and didn't crash BTS? */
2789 f_sleep(10.0);
2790}
2791
2792/* Send DATA.req on invalid timeslot */
2793testcase TC_pcu_data_req_wrong_ts() runs on test_CT {
2794 f_init();
2795 f_TC_pcu_act_req(0, 0, 7, true);
2796 f_pcu_data_req(0, 0, 70, 0, 0, PCU_IF_SAPI_PDTCH, c_PCU_DATA);
2797 /* FIXME: how to check this wasn't actually sent and didn't crash BTS? */
2798 f_sleep(10.0);
2799}
2800
2801/* Send DATA.req on timeslot that hasn't been activated */
2802testcase TC_pcu_data_req_ts_inactive() runs on test_CT {
2803 f_init();
2804 f_pcu_data_req(0, 0, 7, 0, 0, PCU_IF_SAPI_PDTCH, c_PCU_DATA);
2805 /* FIXME: how to check this wasn't actually sent and didn't crash BTS? */
2806 f_sleep(2.0);
2807}
2808
2809testcase TC_pcu_data_req_pdtch() runs on test_CT {
2810 f_init();
2811 f_TC_pcu_act_req(0, 0, 7, true);
2812 f_pcu_wait_rts_and_data_req(0, 0, 7, PCU_IF_SAPI_PDTCH, c_PCU_DATA);
2813 /* FIXME: how to check this was actually sent */
2814 f_sleep(2.0);
2815}
2816
2817testcase TC_pcu_data_req_ptcch() runs on test_CT {
2818 f_init();
2819 f_TC_pcu_act_req(0, 0, 7, true);
2820 f_pcu_wait_rts_and_data_req(0, 0, 7, PCU_IF_SAPI_PTCCH, c_PCU_DATA);
2821 /* FIXME: how to check this was actually sent */
2822 f_sleep(2.0);
2823}
2824
2825/* Send AGCH from PCU; check it appears on Um side */
2826testcase TC_pcu_data_req_agch() runs on test_CT {
2827 timer T := 3.0;
2828 f_init();
2829 f_init_l1ctl();
2830 f_l1_tune(L1CTL);
2831
2832 f_TC_pcu_act_req(0, 0, 7, true);
2833 f_pcu_data_req(0, 0, 7, 0, 0, PCU_IF_SAPI_AGCH, c_PCU_DATA);
2834
2835 T.start;
2836 alt {
Harald Weltef8df4cb2018-03-10 15:15:08 +01002837 [] L1CTL.receive(tr_L1CTL_DATA_IND(t_RslChanNr_PCH_AGCH(0), ?, c_PCU_DATA)) {
Harald Welte883340c2018-02-28 18:59:29 +01002838 setverdict(pass);
2839 }
2840 [] L1CTL.receive { repeat; }
2841 [] T.timeout {
2842 setverdict(fail, "Timeout waiting for PCU-originated AGCH block on Um");
Daniel Willmann17ddd852018-07-05 17:33:20 +02002843 mtc.stop;
Harald Welte883340c2018-02-28 18:59:29 +01002844 }
2845 }
2846}
2847
2848/* Send IMM.ASS from PCU for PCH; check it appears on Um side */
2849testcase TC_pcu_data_req_imm_ass_pch() runs on test_CT {
2850 var octetstring imm_ass := f_rnd_octstring(23);
2851 f_init();
2852 f_init_l1ctl();
2853 f_l1_tune(L1CTL);
2854
2855 /* append 3 last imsi digits so BTS can compute pagng group */
2856 var uint32_t fn := f_PCUIF_tx_imm_ass_pch(PCU, g_pcu_conn_id, imm_ass, '123459987'H);
2857
2858 timer T := 0.5;
2859 T.start;
2860 alt {
Harald Weltef8df4cb2018-03-10 15:15:08 +01002861 [] L1CTL.receive(tr_L1CTL_DATA_IND(t_RslChanNr_PCH_AGCH(0), ?, imm_ass)) {
Harald Welte883340c2018-02-28 18:59:29 +01002862 /* TODO: verify paging group */
2863 setverdict(pass);
2864 }
2865 [] L1CTL.receive { repeat; }
2866 [] T.timeout {
2867 setverdict(fail, "Timeout waiting for PCU-originated AGCH block on Um");
Daniel Willmann17ddd852018-07-05 17:33:20 +02002868 mtc.stop;
Harald Welte883340c2018-02-28 18:59:29 +01002869 }
2870 }
2871}
2872
2873/* Send RACH from Um side, expect it to show up on PCU socket */
2874testcase TC_pcu_rach_content() runs on test_CT {
2875 f_init();
2876 f_init_l1ctl();
2877 f_l1_tune(L1CTL);
2878
2879 var GsmFrameNumber fn_last := 0;
2880 for (var integer i := 0; i < 1000; i := i+1) {
2881 var OCT1 ra := f_rnd_ra_ps();
2882 var GsmFrameNumber fn := f_L1CTL_RACH(L1CTL, oct2int(ra));
2883 if (fn == fn_last) {
2884 setverdict(fail, "Two RACH in same FN?!?");
Daniel Willmann17ddd852018-07-05 17:33:20 +02002885 mtc.stop;
Harald Welte883340c2018-02-28 18:59:29 +01002886 }
2887 fn_last := fn;
2888
2889 timer T := 2.0;
2890 T.start;
2891 alt {
2892 [] PCU.receive(t_SD_PCUIF(g_pcu_conn_id, tr_PCUIF_RACH_IND(0, oct2int(ra), 0, ?, fn))) {
2893 T.stop;
2894 }
2895 [] PCU.receive(t_SD_PCUIF(g_pcu_conn_id, tr_PCUIF_RACH_IND)) {
2896 setverdict(fail, "Unexpected RACH IND");
Daniel Willmann17ddd852018-07-05 17:33:20 +02002897 mtc.stop;
Harald Welte883340c2018-02-28 18:59:29 +01002898 }
2899 [] PCU.receive { repeat; }
2900 [] T.timeout {
2901 setverdict(fail, "Timeout waiting for RACH IND");
Daniel Willmann17ddd852018-07-05 17:33:20 +02002902 mtc.stop;
Harald Welte883340c2018-02-28 18:59:29 +01002903 }
2904 }
2905 }
2906 setverdict(pass);
2907}
2908
2909private function f_pad_oct(octetstring str, integer len, OCT1 pad) return octetstring {
2910 var integer strlen := lengthof(str);
2911 for (var integer i := 0; i < len-strlen; i := i+1) {
2912 str := str & pad;
2913 }
2914 return str;
2915}
2916
2917/* Send PAGING via RSL, expect it to shw up on PCU socket */
2918testcase TC_pcu_paging_from_rsl() runs on test_CT {
2919 f_init();
2920
2921 for (var integer i := 0; i < 100; i := i+1) {
2922 var MobileL3_CommonIE_Types.MobileIdentityLV mi;
2923 timer T := 3.0;
2924 if (i < 50) {
2925 mi := valueof(ts_MI_TMSI_LV(f_rnd_octstring(4)));
2926 } else {
2927 mi := valueof(ts_MI_IMSI_LV(f_gen_imsi(i)));
2928 }
2929 var octetstring mi_enc_lv := enc_MobileIdentityLV(mi);
2930 var octetstring mi_enc := substr(mi_enc_lv, 1, lengthof(mi_enc_lv)-1);
2931 var octetstring t_mi_lv := f_pad_oct(mi_enc_lv, 9, '00'O);
2932
2933 /* Send RSL PAGING COMMAND */
2934 RSL_CCHAN.send(ts_RSL_UD(ts_RSL_PAGING_CMD(mi_enc, i mod 4)));
2935 T.start;
2936 alt {
2937 [] PCU.receive(t_SD_PCUIF(g_pcu_conn_id, tr_PCUIF_PAG_REQ(0, t_mi_lv))) {
2938 }
2939 [] PCU.receive(t_SD_PCUIF(g_pcu_conn_id, tr_PCUIF_PAG_REQ)) {
2940 setverdict(fail, "Unexpected PAGING REQ");
Daniel Willmann17ddd852018-07-05 17:33:20 +02002941 mtc.stop;
Harald Welte883340c2018-02-28 18:59:29 +01002942 }
2943 [] PCU.receive { repeat; }
2944 [] T.timeout {
2945 setverdict(fail, "Timeout waiting for PAGING REQ");
Daniel Willmann17ddd852018-07-05 17:33:20 +02002946 mtc.stop;
Harald Welte883340c2018-02-28 18:59:29 +01002947 }
2948 }
2949 }
2950 setverdict(pass);
2951}
2952
Harald Welte3d04ae62018-04-04 20:29:05 +02002953/***********************************************************************
Harald Welte9bbbfb52018-04-05 09:33:19 +02002954 * Osmocom Style Dynamic Timeslot Support
Harald Welte3d04ae62018-04-04 20:29:05 +02002955 ***********************************************************************/
2956
2957private function f_dyn_osmo_pdch_act(integer pcu_conn_id, integer bts_nr, integer trx_nr)
2958runs on ConnHdlr {
2959 var PCUIF_send_data sd;
2960 /* Expect BTS to immediately acknowledge activation as PDCH */
2961 PCU.clear;
2962 f_rsl_chan_act(g_pars.chan_mode);
2963 /* expect INFO_IND on PCU interface listing TS as PDCH */
2964 alt {
2965 [] PCU.receive(t_SD_PCUIF(pcu_conn_id, tr_PCUIF_INFO_IND(bts_nr, ?))) -> value sd {
2966 if (substr(sd.data.u.info_ind.trx[trx_nr].pdch_mask, g_chan_nr.tn, 1) != '1'B) {
2967 setverdict(fail, "PCUIF_INFO_IND PDCH_MASK not '1' after PDCH ACT");
Daniel Willmann17ddd852018-07-05 17:33:20 +02002968 mtc.stop;
Harald Welte3d04ae62018-04-04 20:29:05 +02002969 }
2970 }
2971 [] PCU.receive { repeat; }
2972 }
2973 /* try to activate this PDCH from the PCU point of view */
2974 PCU.send(t_SD_PCUIF(pcu_conn_id, ts_PCUIF_ACT_REQ(bts_nr, trx_nr, g_chan_nr.tn)));
2975 /* FIXME: is there a response? */
2976}
2977
2978private function f_dyn_osmo_pdch_deact(integer pcu_conn_id, integer bts_nr, integer trx_nr)
2979runs on ConnHdlr {
2980 var PCUIF_send_data sd;
2981 /* Send RSL CHAN REL (deactivate) */
2982 PCU.clear;
2983 RSL.send(ts_RSL_RF_CHAN_REL(g_chan_nr));
2984 /* expect BTS to ask PCU to deactivate the channel */
2985 alt {
2986 [] PCU.receive(t_SD_PCUIF(pcu_conn_id, tr_PCUIF_INFO_IND(bts_nr, ?))) -> value sd {
2987 if (substr(sd.data.u.info_ind.trx[trx_nr].pdch_mask, g_chan_nr.tn, 1) != '0'B) {
2988 setverdict(fail, "PCUIF_INFO_IND PDCH_MASK not '0' after PDCH DEACT");
Daniel Willmann17ddd852018-07-05 17:33:20 +02002989 mtc.stop;
Harald Welte3d04ae62018-04-04 20:29:05 +02002990 }
2991 }
2992 [] PCU.receive { repeat; }
2993 }
2994 /* Emulate PCU asking BTS to deactivate PDCH */
2995 PCU.send(t_SD_PCUIF(pcu_conn_id, ts_PCUIF_DEACT_REQ(bts_nr, trx_nr, g_chan_nr.tn)));
2996 alt {
2997 [] RSL.receive(tr_RSL_RF_CHAN_REL_ACK(g_chan_nr)) {
2998 setverdict(pass);
2999 }
3000 [] RSL.receive { repeat; }
3001 }
3002}
3003
3004/* Activate Osmocom-style dynamic PDCH from BSC side */
3005function f_TC_dyn_osmo_pdch_act_deact(charstring id) runs on ConnHdlr {
3006 var PCUIF_Message first_info;
3007 var integer ts_nr := g_chan_nr.tn;
3008 var integer trx_nr := 0;
3009 var integer bts_nr := 0;
3010 var integer pcu_conn_id := -1;
3011
3012 f_init_pcu(PCU, id, pcu_conn_id, first_info);
3013
3014 f_dyn_osmo_pdch_act(pcu_conn_id, bts_nr, trx_nr);
3015 f_sleep(3.0);
3016 f_dyn_osmo_pdch_deact(pcu_conn_id, bts_nr, trx_nr);
3017 setverdict(pass);
3018}
3019testcase TC_dyn_osmo_pdch_act_deact() runs on test_CT {
3020 var ConnHdlrPars pars;
3021 var ConnHdlr vc_conn;
3022 f_init(testcasename());
3023
3024 pars := valueof(t_Pars(t_RslChanNr_PDCH(4), ts_RSL_ChanMode_SIGN));
3025 vc_conn := f_start_handler(refers(f_TC_dyn_osmo_pdch_act_deact), pars, true);
3026 vc_conn.done;
3027}
3028
3029/* send a RF CHAN REL for PDCH on an osmocom dynamci PDCH that's already inactive */
3030function f_TC_dyn_osmo_pdch_unsol_deact(charstring id) runs on ConnHdlr {
3031 var PCUIF_Message first_info;
Harald Welte3d04ae62018-04-04 20:29:05 +02003032 var integer pcu_conn_id := -1;
3033
3034 f_init_pcu(PCU, id, pcu_conn_id, first_info);
3035
Neels Hofmeyr9c50ca52018-05-08 20:37:54 +02003036 RSL.send(ts_RSL_RF_CHAN_REL(g_chan_nr));
3037 /* since the lchan is already released, we don't expect any PCU changes, just a rel ack. */
3038 RSL.receive(tr_RSL_RF_CHAN_REL_ACK(g_chan_nr));
Harald Welte3d04ae62018-04-04 20:29:05 +02003039 setverdict(pass);
3040}
3041testcase TC_dyn_osmo_pdch_unsol_deact() runs on test_CT {
3042 var ConnHdlrPars pars;
3043 var ConnHdlr vc_conn;
3044 f_init(testcasename());
3045
3046 pars := valueof(t_Pars(t_RslChanNr_PDCH(4), ts_RSL_ChanMode_SIGN));
3047 vc_conn := f_start_handler(refers(f_TC_dyn_osmo_pdch_unsol_deact), pars, true);
3048 vc_conn.done;
3049}
3050
3051/* try to RSL CHAN ACT a PDCH on an osmocom-style PDCH that's already active */
3052function f_TC_dyn_osmo_pdch_double_act(charstring id) runs on ConnHdlr {
3053 var PCUIF_Message first_info;
3054 var integer ts_nr := g_chan_nr.tn;
3055 var integer trx_nr := 0;
3056 var integer bts_nr := 0;
3057 var integer pcu_conn_id := -1;
3058
3059 f_init_pcu(PCU, id, pcu_conn_id, first_info);
3060
3061 f_dyn_osmo_pdch_act(pcu_conn_id, bts_nr, trx_nr);
Neels Hofmeyrdf936a22018-05-08 22:07:57 +02003062 /* Send a second Chan Activ and expect it to be NACKed */
3063 f_rsl_transceive(ts_RSL_CHAN_ACT(g_chan_nr, g_pars.chan_mode), tr_RSL_CHAN_ACT_NACK(g_chan_nr),
3064 "RSL CHAN ACT NACK");
Harald Welte3d04ae62018-04-04 20:29:05 +02003065 setverdict(pass);
3066}
3067testcase TC_dyn_osmo_pdch_double_act() runs on test_CT {
3068 var ConnHdlrPars pars;
3069 var ConnHdlr vc_conn;
3070 f_init(testcasename());
3071
3072 pars := valueof(t_Pars(t_RslChanNr_PDCH(4), ts_RSL_ChanMode_SIGN));
3073 vc_conn := f_start_handler(refers(f_TC_dyn_osmo_pdch_double_act), pars, true);
3074 vc_conn.done;
3075}
3076
3077/* try to RSL CHAN ACT a TCH/F on an osmocom-style PDCH */
3078function f_TC_dyn_osmo_pdch_tchf_act(charstring id) runs on ConnHdlr {
3079 var PCUIF_Message first_info;
3080 var integer ts_nr := g_chan_nr.tn;
3081 var integer trx_nr := 0;
3082 var integer bts_nr := 0;
3083 var integer pcu_conn_id := -1;
3084 var RslChannelNr chan_nr := valueof(t_RslChanNr_Bm(g_chan_nr.tn));
3085
3086 /* register for the TCH/F channel number */
3087 f_rslem_register(0, chan_nr);
3088
3089 f_init_pcu(PCU, id, pcu_conn_id, first_info);
3090
3091 f_rsl_transceive(ts_RSL_CHAN_ACT(chan_nr, g_pars.chan_mode), tr_RSL_CHAN_ACT_ACK(chan_nr),
3092 "RSL CHAN ACT");
3093 setverdict(pass);
3094}
3095testcase TC_dyn_osmo_pdch_tchf_act() runs on test_CT {
3096 var ConnHdlrPars pars;
3097 var ConnHdlr vc_conn;
3098 f_init(testcasename());
3099
3100 pars := valueof(t_Pars(t_RslChanNr_PDCH(4), ts_RSL_ChanMode_SIGN));
3101 vc_conn := f_start_handler(refers(f_TC_dyn_osmo_pdch_tchf_act), pars, true);
3102 vc_conn.done;
3103}
3104
3105/* try to RSL CHAN ACT the TCH/H on an osmocom-style PDCH */
3106function f_TC_dyn_osmo_pdch_tchh_act(charstring id) runs on ConnHdlr {
3107 var PCUIF_Message first_info;
3108 var integer ts_nr := g_chan_nr.tn;
3109 var integer trx_nr := 0;
3110 var integer bts_nr := 0;
3111 var integer pcu_conn_id := -1;
3112 var RslChannelNr chan_nr[2] := { valueof(t_RslChanNr_Lm(g_chan_nr.tn, 0)),
3113 valueof(t_RslChanNr_Lm(g_chan_nr.tn, 1)) };
3114
3115 /* register for the TCH/H channel numbers */
3116 f_rslem_register(0, chan_nr[0]);
3117 f_rslem_register(0, chan_nr[1]);
3118
3119 f_init_pcu(PCU, id, pcu_conn_id, first_info);
3120
3121 f_rsl_transceive(ts_RSL_CHAN_ACT(chan_nr[1], g_pars.chan_mode),
3122 tr_RSL_CHAN_ACT_ACK(chan_nr[1]), "RSL CHAN ACT [1]");
3123 f_rsl_transceive(ts_RSL_CHAN_ACT(chan_nr[0], g_pars.chan_mode),
3124 tr_RSL_CHAN_ACT_ACK(chan_nr[0]), "RSL CHAN ACT [0]");
3125 setverdict(pass);
3126}
3127testcase TC_dyn_osmo_pdch_tchh_act() runs on test_CT {
3128 var ConnHdlrPars pars;
3129 var ConnHdlr vc_conn;
3130 f_init(testcasename());
3131
3132 pars := valueof(t_Pars(t_RslChanNr_PDCH(4), ts_RSL_ChanMode_SIGN));
3133 vc_conn := f_start_handler(refers(f_TC_dyn_osmo_pdch_tchh_act), pars, true);
3134 vc_conn.done;
3135}
3136
Harald Welte9bbbfb52018-04-05 09:33:19 +02003137/***********************************************************************
3138 * IPA Style Dynamic Timeslot Support
3139 ***********************************************************************/
3140
3141private function f_dyn_ipa_pdch_act(integer pcu_conn_id, integer bts_nr, integer trx_nr)
3142runs on ConnHdlr {
3143 var PCUIF_send_data sd;
3144 /* Expect BTS to immediately acknowledge activation as PDCH */
3145 PCU.clear;
3146 RSL.send(ts_RSL_IPA_PDCH_ACT(g_chan_nr));
3147 /* expect INFO_IND on PCU interface listing TS as PDCH */
3148 alt {
3149 [] PCU.receive(t_SD_PCUIF(pcu_conn_id, tr_PCUIF_INFO_IND(bts_nr, ?))) -> value sd {
3150 if (substr(sd.data.u.info_ind.trx[trx_nr].pdch_mask, g_chan_nr.tn, 1) != '1'B) {
3151 setverdict(fail, "PCUIF_INFO_IND PDCH_MASK not '1' after PDCH ACT");
Daniel Willmann17ddd852018-07-05 17:33:20 +02003152 mtc.stop;
Harald Welte9bbbfb52018-04-05 09:33:19 +02003153 }
3154 }
3155 [] PCU.receive { repeat; }
3156 }
3157 /* try to activate this PDCH from the PCU point of view */
3158 PCU.send(t_SD_PCUIF(pcu_conn_id, ts_PCUIF_ACT_REQ(bts_nr, trx_nr, g_chan_nr.tn)));
3159 /* FIXME: is there a response? */
3160
3161 RSL.receive(tr_RSL_IPA_PDCH_ACT_ACK(g_chan_nr, ?));
3162}
3163
3164private function f_dyn_ipa_pdch_deact(integer pcu_conn_id, integer bts_nr, integer trx_nr)
3165runs on ConnHdlr {
3166 var PCUIF_send_data sd;
3167 /* Send RSL CHAN REL (deactivate) */
3168 RSL.send(ts_RSL_IPA_PDCH_DEACT(g_chan_nr));
3169 PCU.clear;
3170 /* expect BTS to ask PCU to deactivate the channel */
3171 alt {
3172 [] PCU.receive(t_SD_PCUIF(pcu_conn_id, tr_PCUIF_INFO_IND(bts_nr, ?))) -> value sd {
3173 if (substr(sd.data.u.info_ind.trx[trx_nr].pdch_mask, g_chan_nr.tn, 1) != '0'B) {
3174 setverdict(fail, "PCUIF_INFO_IND PDCH_MASK not '0' after PDCH DEACT");
Daniel Willmann17ddd852018-07-05 17:33:20 +02003175 mtc.stop;
Harald Welte9bbbfb52018-04-05 09:33:19 +02003176 }
3177 }
3178 [] PCU.receive { repeat; }
3179 }
3180 /* Emulate PCU asking BTS to deactivate PDCH */
3181 PCU.send(t_SD_PCUIF(pcu_conn_id, ts_PCUIF_DEACT_REQ(bts_nr, trx_nr, g_chan_nr.tn)));
3182 alt {
3183 [] RSL.receive(tr_RSL_IPA_PDCH_DEACT_ACK(g_chan_nr)) {
3184 setverdict(pass);
3185 }
3186 [] RSL.receive { repeat; }
3187 }
3188}
3189
3190/* Activate and de-activate an IPA-style dynamic TCH/F + PDCH */
3191function f_TC_dyn_ipa_pdch_act_deact(charstring id) runs on ConnHdlr {
3192 var PCUIF_Message first_info;
3193 var integer ts_nr := g_chan_nr.tn;
3194 var integer trx_nr := 0;
3195 var integer bts_nr := 0;
3196 var integer pcu_conn_id := -1;
3197
3198 f_init_pcu(PCU, id, pcu_conn_id, first_info);
3199
3200 f_dyn_ipa_pdch_act(pcu_conn_id, bts_nr, trx_nr);
3201 f_sleep(3.0);
3202 f_dyn_ipa_pdch_deact(pcu_conn_id, bts_nr, trx_nr);
3203
3204 setverdict(pass);
3205
3206}
3207testcase TC_dyn_ipa_pdch_act_deact() runs on test_CT {
3208 var ConnHdlrPars pars;
3209 var ConnHdlr vc_conn;
3210 f_init();
3211
3212 pars := valueof(t_Pars(t_RslChanNr_Bm(3), ts_RSL_ChanMode_SIGN));
3213 vc_conn := f_start_handler(refers(f_TC_dyn_ipa_pdch_act_deact), pars, true);
3214 vc_conn.done;
3215}
3216
3217/* try to RSL CHAN ACT a TCH/F on an IPA-style PDCH */
3218function f_TC_dyn_ipa_pdch_tchf_act(charstring id) runs on ConnHdlr {
3219 var PCUIF_Message first_info;
3220 var integer ts_nr := g_chan_nr.tn;
3221 var integer trx_nr := 0;
3222 var integer bts_nr := 0;
3223 var integer pcu_conn_id := -1;
3224
3225 f_init_pcu(PCU, id, pcu_conn_id, first_info);
3226
3227 f_rsl_transceive(ts_RSL_CHAN_ACT(g_chan_nr, g_pars.chan_mode), tr_RSL_CHAN_ACT_ACK(g_chan_nr),
3228 "RSL CHAN ACT");
3229 f_rsl_transceive(ts_RSL_RF_CHAN_REL(g_chan_nr), tr_RSL_RF_CHAN_REL_ACK(g_chan_nr),
3230 "RF CHAN REL", true);
3231 setverdict(pass);
3232}
3233testcase TC_dyn_ipa_pdch_tchf_act() runs on test_CT {
3234 var ConnHdlrPars pars;
3235 var ConnHdlr vc_conn;
3236 f_init(testcasename());
3237
3238 pars := valueof(t_Pars(t_RslChanNr_Bm(3), ts_RSL_ChanMode_SIGN));
3239 vc_conn := f_start_handler(refers(f_TC_dyn_ipa_pdch_tchf_act), pars, true);
3240 vc_conn.done;
3241}
3242
3243/* Activate IPA style dyn PDCH as TCH/F and then illegally try to activate it as PDCH, too */
3244function f_TC_dyn_ipa_pdch_tchf_act_pdch_act_nack(charstring id) runs on ConnHdlr {
3245 var PCUIF_Message first_info;
3246 var integer ts_nr := g_chan_nr.tn;
3247 var integer trx_nr := 0;
3248 var integer bts_nr := 0;
3249 var integer pcu_conn_id := -1;
3250
3251 f_init_pcu(PCU, id, pcu_conn_id, first_info);
3252
3253 f_rsl_transceive(ts_RSL_CHAN_ACT(g_chan_nr, g_pars.chan_mode), tr_RSL_CHAN_ACT_ACK(g_chan_nr),
3254 "RSL CHAN ACT");
3255
3256 RSL.send(ts_RSL_IPA_PDCH_ACT(g_chan_nr));
3257 alt {
3258 [] RSL.receive(tr_RSL_IPA_PDCH_ACT_NACK(g_chan_nr, ?));
3259 [] RSL.receive(tr_RSL_IPA_PDCH_ACT_ACK(g_chan_nr, ?)) {
3260 setverdict(fail, "Unexpected PDCH ACT ACK");
Daniel Willmann17ddd852018-07-05 17:33:20 +02003261 mtc.stop;
Harald Welte9bbbfb52018-04-05 09:33:19 +02003262 }
3263 [] RSL.receive { repeat; }
3264 }
3265
3266 f_rsl_transceive(ts_RSL_RF_CHAN_REL(g_chan_nr), tr_RSL_RF_CHAN_REL_ACK(g_chan_nr),
3267 "RF CHAN REL", true);
3268 setverdict(pass);
3269}
3270testcase TC_dyn_ipa_pdch_tchf_act_pdch_act_nack() runs on test_CT {
3271 var ConnHdlrPars pars;
3272 var ConnHdlr vc_conn;
3273 f_init(testcasename());
3274
3275 pars := valueof(t_Pars(t_RslChanNr_Bm(3), ts_RSL_ChanMode_SIGN));
3276 vc_conn := f_start_handler(refers(f_TC_dyn_ipa_pdch_tchf_act_pdch_act_nack), pars, true);
3277 vc_conn.done;
3278}
3279
3280/* try to RSL CHAN ACT a TCH/F on an IPA-style PDCH that's already in PDCH mode; expect NACK */
3281function f_TC_dyn_ipa_pdch_act_tchf_act_nack(charstring id) runs on ConnHdlr {
3282 var PCUIF_Message first_info;
3283 var integer ts_nr := g_chan_nr.tn;
3284 var integer trx_nr := 0;
3285 var integer bts_nr := 0;
3286 var integer pcu_conn_id := -1;
3287
3288 /* register for the TCH/F channel number */
3289 f_rslem_register(0, g_chan_nr);
3290
3291 f_init_pcu(PCU, id, pcu_conn_id, first_info);
3292
3293 f_dyn_ipa_pdch_act(pcu_conn_id, bts_nr, trx_nr);
3294
3295 f_rsl_transceive(ts_RSL_CHAN_ACT(g_chan_nr, g_pars.chan_mode), tr_RSL_CHAN_ACT_NACK(g_chan_nr),
3296 "RSL CHAN ACT");
3297
3298 f_dyn_ipa_pdch_deact(pcu_conn_id, bts_nr, trx_nr);
3299
3300 setverdict(pass);
3301}
3302testcase TC_dyn_ipa_pdch_act_tchf_act_nack() runs on test_CT {
3303 var ConnHdlrPars pars;
3304 var ConnHdlr vc_conn;
3305 f_init(testcasename());
3306
3307 pars := valueof(t_Pars(t_RslChanNr_Bm(3), ts_RSL_ChanMode_SIGN));
3308 vc_conn := f_start_handler(refers(f_TC_dyn_ipa_pdch_act_tchf_act_nack), pars, true);
3309 vc_conn.done;
3310}
3311
3312
Harald Welte0472ab42018-03-12 15:02:26 +01003313/***********************************************************************
3314 * LAPDm / RLL related
3315 ***********************************************************************/
3316
3317private function f_tx_lapdm(template (value) LapdmFrame l,
3318 template (value) RslLinkId link_id) runs on ConnHdlr {
3319 var octetstring l2 := enc_LapdmFrame(valueof(l));
3320 if (valueof(link_id.c) == SACCH) {
3321 /* prepend dummy L1 header */
Pau Espin Pedrola0fb42a2018-10-10 15:56:39 +02003322 var L1ctlDataReq l1hl2 := {
3323 l1header := valueof(ts_SacchL1Header(g_pars.l1_pars.ms_power_level, false, g_pars.l1_pars.ms_actual_ta)),
3324 l2_payload := f_pad_oct(l2, 21, '2B'O)
3325 }
3326 L1CTL.send(ts_L1CTL_DATA_REQ_SACCH(g_chan_nr, link_id, l1hl2));
3327 } else {
3328 /* If required, pad L2 frame with constant 0x2b filling */
3329 l2 := f_pad_oct(l2, 23, '2B'O);
3330
3331 log("encoding ", l, " to ", l2);
3332 L1CTL.send(ts_L1CTL_DATA_REQ(g_chan_nr, link_id, l2));
Harald Welte0472ab42018-03-12 15:02:26 +01003333 }
Harald Welte0472ab42018-03-12 15:02:26 +01003334}
3335
3336type record RllTestCase {
3337 uint3_t sapi,
3338 RslLinkId link_id,
3339 octetstring l3,
3340 boolean exp
3341}
3342type record of RllTestCase RllTestCases;
3343template RllTestCase t_EITC(uint3_t sapi, RslLinkId id, octetstring l3, boolean exp) := {
3344 sapi := sapi,
3345 link_id := id,
3346 l3 := l3,
3347 exp := exp
3348}
3349
3350/* execute the same callback function with a set of different parameters (tcs) on a
3351 * variety of logical channels */
3352private function f_rll_testmatrix(RllTestCases tcs, void_fn fn) runs on test_CT {
3353 var ConnHdlrPars pars;
3354 var ConnHdlr vc_conn;
3355 f_init(testcasename());
3356
3357 /* test on each of the channels we have */
3358 for (var integer i := 0; i < sizeof(g_AllChanTypes); i := i+1) {
3359 pars := valueof(t_Pars(g_AllChanTypes[i], ts_RSL_ChanMode_SIGN));
3360
3361 /* test each of the test cases on the current channel */
3362 for (var integer j := 0; j < sizeof(tcs); j := j+1) {
3363 pars.spec.rll := tcs[j];
3364 log(testcasename(), ": XXX Starting ", tcs[j] , " on ", g_AllChanTypes[i]);
3365 vc_conn := f_start_handler(fn, pars);
3366 vc_conn.done;
3367 }
3368 }
3369
3370 f_shutdown();
3371}
3372
3373/* test if SABM on Um triggers EST IND (TS 48.058 3.1) */
3374private function f_TC_rll_est_ind(charstring id) runs on ConnHdlr {
3375 var RllTestCase tc := g_pars.spec.rll;
3376 timer T := 3.0;
3377
3378 f_l1_tune(L1CTL);
3379 RSL.clear;
3380
3381 /* activate the logical channel */
3382 f_est_dchan();
3383 L1CTL.clear;
3384
3385 f_tx_lapdm(ts_LAPDm_SABM(tc.sapi, cr_MO_CMD, true, tc.l3), tc.link_id);
3386 T.start;
3387 alt {
3388 [tc.l3 != ''O] RSL.receive(tr_RSL_EST_IND(g_chan_nr, tc.link_id, tc.l3)) {
3389 if (tc.exp) {
3390 setverdict(pass);
3391 } else {
3392 setverdict(fail, "Unexpected EST IND with L3 in ", tc);
Daniel Willmann17ddd852018-07-05 17:33:20 +02003393 mtc.stop;
Harald Welte0472ab42018-03-12 15:02:26 +01003394 }
3395 }
3396 [tc.l3 == ''O] RSL.receive(tr_RSL_EST_IND_NOL3(g_chan_nr, tc.link_id)) {
3397 if (tc.exp) {
3398 setverdict(pass);
3399 } else {
3400 setverdict(fail, "Unexpected EST IND without L3 in ", tc);
Daniel Willmann17ddd852018-07-05 17:33:20 +02003401 mtc.stop;
Harald Welte0472ab42018-03-12 15:02:26 +01003402 }
3403 }
Vadim Yanitskiy35677872018-10-04 17:30:21 +07003404 /* We also expect to receive the measurements */
3405 [] as_meas_res(verify_meas := false);
Harald Welte0472ab42018-03-12 15:02:26 +01003406 [tc.exp] T.timeout {
3407 setverdict(fail, "Timeout waiting for EST IND");
Daniel Willmann17ddd852018-07-05 17:33:20 +02003408 mtc.stop;
Harald Welte0472ab42018-03-12 15:02:26 +01003409 }
3410 [not tc.exp] T.timeout {
3411 setverdict(pass);
3412 }
3413 }
3414
3415 f_rsl_chan_deact();
3416 f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
3417 f_rslem_unregister(0, g_chan_nr);
3418}
3419testcase TC_rll_est_ind() runs on test_CT {
3420 var RllTestCases tcs := {
Harald Welte7aacbbf2018-05-09 16:56:41 +02003421 /* SAPI0 establishment (contention resolution) */
Harald Welte0472ab42018-03-12 15:02:26 +01003422 valueof(t_EITC(0, valueof(ts_RslLinkID_DCCH(0)), '01020304'O, true)),
Harald Welte7aacbbf2018-05-09 16:56:41 +02003423 /* normal SAPI0 establishment */
3424 valueof(t_EITC(0, valueof(ts_RslLinkID_DCCH(0)), ''O, true)),
Harald Welte0472ab42018-03-12 15:02:26 +01003425 /* SAPI 3 doesn't support contention resolution */
3426 valueof(t_EITC(3, valueof(ts_RslLinkID_DCCH(3)), '01020304'O, false)),
3427 valueof(t_EITC(3, valueof(ts_RslLinkID_SACCH(3)), '01020304'O, false)),
3428 /* normal SAPI3 establishment on main DCCH */
3429 valueof(t_EITC(3, valueof(ts_RslLinkID_DCCH(3)), ''O, true)),
3430 /* normal SAPI3 establishment on SACCH */
3431 valueof(t_EITC(3, valueof(ts_RslLinkID_SACCH(3)), ''O, true))
3432 };
3433 f_rll_testmatrix(tcs, refers(f_TC_rll_est_ind));
3434}
3435
3436/* test if RLL EST REQ trigeres SABM on Um; UA on Um triggers EST CONF (TS 48.058 3.2) */
3437private function f_TC_rll_est_req(charstring id) runs on ConnHdlr {
3438 var RllTestCase tc := g_pars.spec.rll;
3439 var L1ctlDlMessage dl;
3440 timer T := 3.0;
3441
3442 f_l1_tune(L1CTL);
3443 RSL.clear;
3444
3445 /* activate the logical channel */
3446 f_est_dchan();
3447 L1CTL.clear;
3448
3449 /* Send a RSL EST REQ for SAPI3 on main DCCH */
3450 RSL.send(ts_RSL_EST_REQ(g_chan_nr, tc.link_id));
3451 T.start;
3452 alt {
3453 [] L1CTL.receive(tr_L1CTL_DATA_IND(g_chan_nr, ?)) -> value dl {
3454 var LapdmFrame lapdm;
3455 var octetstring l2 := dl.payload.data_ind.payload;
3456 if (dl.dl_info.link_id.c == SACCH) {
3457 /* remove L1 header */
3458 l2 := substr(l2, 2, lengthof(l2)-2);
3459 }
3460 lapdm.ab := dec_LapdmFrameAB(l2);
3461 if (match(lapdm, tr_LAPDm_SABM(tc.sapi, cr_MT_CMD, true, ''O))) {
3462 setverdict(pass);
3463 } else {
3464 repeat;
3465 }
3466 }
3467 [] L1CTL.receive { repeat; }
3468 [] T.timeout {
3469 setverdict(fail, "Timeout waiting for SABM");
Daniel Willmann17ddd852018-07-05 17:33:20 +02003470 mtc.stop;
Harald Welte0472ab42018-03-12 15:02:26 +01003471 }
3472 }
3473
3474 f_rsl_chan_deact();
3475 f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
3476 f_rslem_unregister(0, g_chan_nr);
3477}
3478testcase TC_rll_est_req_DCCH_3() runs on test_CT {
3479 var RllTestCases tcs := {
3480 /* normal SAPI3 establishment on main DCCH */
3481 valueof(t_EITC(3, valueof(ts_RslLinkID_DCCH(3)), ''O, true))//,
3482 };
3483 f_rll_testmatrix(tcs, refers(f_TC_rll_est_req));
3484}
3485testcase TC_rll_est_req_ACCH_3() runs on test_CT {
3486 var RllTestCases tcs := {
3487 /* normal SAPI3 establishment on SACCH */
3488 valueof(t_EITC(3, valueof(ts_RslLinkID_SACCH(3)), ''O, true))
3489 }
3490 f_rll_testmatrix(tcs, refers(f_TC_rll_est_req));
3491}
3492
3493/* altstep to receive a LAPDm frame matching the given template */
3494private altstep as_l1_exp_lapdm(template LapdmFrame exp) runs on ConnHdlr {
3495 var L1ctlDlMessage dl;
3496 [] L1CTL.receive(tr_L1CTL_DATA_IND(g_chan_nr, ?)) -> value dl {
3497 var LapdmFrame lapdm;
3498 var octetstring l2 := dl.payload.data_ind.payload;
3499 if (dl.dl_info.link_id.c == SACCH) {
3500 /* remove L1 header */
3501 l2 := substr(l2, 2, lengthof(l2)-2);
3502 }
3503 if (ischosen(exp.ab)) {
3504 lapdm.ab := dec_LapdmFrameAB(l2);
3505 } else if (ischosen(exp.b4)) {
3506 lapdm.b4 := dec_LapdmFrameB4(l2);
3507 } else if (ischosen(exp.bbis)) {
3508 lapdm.bbis := dec_LapdmFrameBbis(l2);
3509 }
3510 log("Rx LAPDm ", lapdm);
3511 if (match(lapdm, exp)) {
3512 setverdict(pass);
3513 } else {
3514 repeat;
3515 }
3516 }
3517 [] L1CTL.receive { repeat; }
3518}
3519private function f_l1_exp_lapdm(template LapdmFrame exp, float t := 3.0) runs on ConnHdlr {
3520 timer T := t;
3521 T.start;
3522 alt {
3523 [] T.timeout {
3524 setverdict(fail, "Timeout waiting for LAPDm ", exp);
Daniel Willmann17ddd852018-07-05 17:33:20 +02003525 mtc.stop;
Harald Welte0472ab42018-03-12 15:02:26 +01003526 }
3527 [] as_l1_exp_lapdm(exp);
3528 }
3529}
3530
3531/* establish one Radio Link Layer via SABM -> UA. Use l3 for contention resolution */
3532private function f_est_rll_mo(uint3_t sapi, RslLinkId link_id, octetstring l3) runs on ConnHdlr {
3533 /* send SABM from MS -> BTS */
3534 f_tx_lapdm(ts_LAPDm_SABM(sapi, cr_MO_CMD, true, l3), link_id);
3535 /* expect RLL EST IND on Abis */
3536 alt {
3537 [l3 != ''O] RSL.receive(tr_RSL_EST_IND(g_chan_nr, link_id, l3));
3538 [l3 == ''O] RSL.receive(tr_RSL_EST_IND_NOL3(g_chan_nr, link_id));
3539 [] RSL.receive(tr_RSL_ERROR_IND(g_chan_nr, link_id, ?)) {
3540 setverdict(fail, "Failing due to RSL_ERROR_IND");
Daniel Willmann17ddd852018-07-05 17:33:20 +02003541 mtc.stop;
Harald Welte0472ab42018-03-12 15:02:26 +01003542 }
3543 [] RSL.receive { repeat; }
3544 }
3545 /* expect UA from BTS -> MS */
3546 f_l1_exp_lapdm(tr_LAPDm_UA(sapi, cr_MT_RSP, true, l3));
3547}
3548
3549/* test if DISC on Um triggers RLL REL IND (TS 48.058 3.3) */
3550private function f_TC_rll_rel_ind(charstring id) runs on ConnHdlr {
3551 var RllTestCase tc := g_pars.spec.rll;
3552
3553 f_l1_tune(L1CTL);
3554 RSL.clear;
3555
3556 /* activate the logical channel */
3557 f_est_dchan();
3558 L1CTL.clear;
3559
3560 /* first establish the link-layer */
3561 f_est_rll_mo(tc.sapi, tc.link_id, tc.l3);
3562
3563 /* then send the DISC */
3564 f_tx_lapdm(ts_LAPDm_DISC(tc.sapi, cr_MO_CMD, true), tc.link_id);
3565 /* ... and expect the REL IND on the RSL side */
3566 alt {
3567 [] RSL.receive(tr_RSL_REL_IND(g_chan_nr, tc.link_id)) {
3568 setverdict(pass);
3569 }
Vadim Yanitskiy35677872018-10-04 17:30:21 +07003570 /* We also expect to receive the measurements */
3571 [] as_meas_res(verify_meas := false);
Harald Welte0472ab42018-03-12 15:02:26 +01003572 }
3573
3574 /* release the channel */
3575 f_rsl_chan_deact();
3576 f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
3577 f_rslem_unregister(0, g_chan_nr);
3578}
3579testcase TC_rll_rel_ind_DCCH_0() runs on test_CT {
3580 var RllTestCases tcs := {
3581 valueof(t_EITC(0, valueof(ts_RslLinkID_DCCH(0)), '01020304'O, true))
3582 };
3583 f_rll_testmatrix(tcs, refers(f_TC_rll_rel_ind));
3584}
3585
3586testcase TC_rll_rel_ind_ACCH_0() runs on test_CT {
3587 var RllTestCases tcs := {
3588 valueof(t_EITC(0, valueof(ts_RslLinkID_SACCH(0)), ''O, true))
3589 };
3590 f_rll_testmatrix(tcs, refers(f_TC_rll_rel_ind));
3591}
3592testcase TC_rll_rel_ind_DCCH_3() runs on test_CT {
3593 var RllTestCases tcs := {
3594 valueof(t_EITC(3, valueof(ts_RslLinkID_DCCH(3)), ''O, true))
3595 };
3596 f_rll_testmatrix(tcs, refers(f_TC_rll_rel_ind));
3597}
3598testcase TC_rll_rel_ind_ACCH_3() runs on test_CT {
3599 var RllTestCases tcs := {
3600 valueof(t_EITC(3, valueof(ts_RslLinkID_SACCH(3)), ''O, true))
3601 };
3602 f_rll_testmatrix(tcs, refers(f_TC_rll_rel_ind));
3603}
3604
3605/* test if RLL REL REQ triggers DISC on Um; UA/DM triggers RLL REL CONF (TS 48.058 3.4) */
3606private function f_TC_rll_rel_req(charstring id) runs on ConnHdlr {
3607 var RllTestCase tc := g_pars.spec.rll;
3608 f_l1_tune(L1CTL);
3609 RSL.clear;
3610
3611 /* activate the logical channel */
3612 f_est_dchan();
3613 L1CTL.clear;
3614
3615 /* first establish the link-layer */
3616 f_est_rll_mo(tc.sapi, tc.link_id, tc.l3);
3617
3618 /* then send the REL REQ via RSL */
3619 RSL.send(ts_RSL_REL_REQ(g_chan_nr, tc.link_id, RSL_REL_MODE_NORMAL));
3620 /* ... and expect the DISC on the Um side */
3621 alt {
Harald Weltebc6199f2018-05-10 19:38:18 +02003622 [] as_l1_exp_lapdm(tr_LAPDm_DISC(tc.sapi, cr_MT_CMD, true)) {
Harald Welte0472ab42018-03-12 15:02:26 +01003623 /* FIXME: send a UA in resposne to the DISC */
3624 }
3625 }
3626
3627 /* release the channel */
3628 f_rsl_chan_deact();
3629 f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
3630 f_rslem_unregister(0, g_chan_nr);
3631}
3632testcase TC_rll_rel_req() runs on test_CT {
3633 var RllTestCases tcs := {
3634 valueof(t_EITC(0, valueof(ts_RslLinkID_DCCH(0)), '01020304'O, true)),
3635 valueof(t_EITC(0, valueof(ts_RslLinkID_SACCH(0)), ''O, true)),
3636 valueof(t_EITC(3, valueof(ts_RslLinkID_DCCH(3)), ''O, true)),
3637 valueof(t_EITC(3, valueof(ts_RslLinkID_SACCH(3)), ''O, true))
3638 };
3639 f_rll_testmatrix(tcs, refers(f_TC_rll_rel_req));
3640}
3641
3642/* test if RLL DATA REQ triggers I-frames on Um (TS 48.058 3.5) */
3643testcase TC_rll_data_req() runs on test_CT {
3644}
3645
3646/* test if I-frames on Um trigger RLL DATA IND (TS 48.058 3.6) */
3647testcase TC_rll_data_ind() runs on test_CT {
3648}
3649
3650/* test if RLL UNIT DATA REQ triggers UI-frame on Um (TS 48.058 3.7) */
3651private function f_TC_rll_ud_req(charstring id) runs on ConnHdlr {
3652 var RllTestCase tc := g_pars.spec.rll;
3653
3654 f_l1_tune(L1CTL);
3655 RSL.clear;
3656
3657 f_est_dchan();
3658 L1CTL.clear;
3659
3660 /* Send UNITDATA REQ on RSL side */
3661 RSL.send(ts_RSL_UNITDATA_REQ(g_chan_nr, tc.link_id, tc.l3));
3662 /* Expect it to arrive on the other side */
3663 if (tc.link_id.c == SACCH) {
Harald Weltee613f962018-04-18 22:38:16 +02003664 f_l1_exp_lapdm(tr_LAPDm_B4_UI(tc.sapi, cr_MT_CMD, tc.l3));
Harald Welte0472ab42018-03-12 15:02:26 +01003665 } else {
Harald Weltee613f962018-04-18 22:38:16 +02003666 f_l1_exp_lapdm(tr_LAPDm_UI(tc.sapi, cr_MT_CMD, tc.l3));
Harald Welte0472ab42018-03-12 15:02:26 +01003667 }
3668
3669 /* release the channel */
3670 f_rsl_chan_deact();
3671 f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
3672 f_rslem_unregister(0, g_chan_nr);
3673}
3674testcase TC_rll_unit_data_req_DCCH() runs on test_CT {
3675 var octetstring l3 := f_rnd_octstring(15);
3676 var RllTestCases tcs := {
3677 valueof(t_EITC(0, valueof(ts_RslLinkID_DCCH(0)), l3, true)),
3678 valueof(t_EITC(3, valueof(ts_RslLinkID_DCCH(3)), l3, true))
3679 };
3680 f_rll_testmatrix(tcs, refers(f_TC_rll_ud_req));
3681}
3682testcase TC_rll_unit_data_req_ACCH() runs on test_CT {
3683 var octetstring l3 := f_rnd_octstring(19);
3684 var RllTestCases tcs := {
3685 valueof(t_EITC(0, valueof(ts_RslLinkID_SACCH(0)), l3, true)),
3686 valueof(t_EITC(3, valueof(ts_RslLinkID_SACCH(3)), l3, true))
3687 };
3688 f_rll_testmatrix(tcs, refers(f_TC_rll_ud_req));
3689}
3690
3691/* test if UI-frames on Um trigger RLL UNIT DATA IND (TS 48.058 3.8) */
3692private function f_TC_rll_ud_ind(charstring id) runs on ConnHdlr {
3693 var RllTestCase tc := g_pars.spec.rll;
3694
3695 f_l1_tune(L1CTL);
3696 RSL.clear;
3697
3698 f_est_dchan();
3699 L1CTL.clear;
3700
3701 /* Send LAPDm UI frame. There is no B4 format in uplink! */
Harald Weltee613f962018-04-18 22:38:16 +02003702 f_tx_lapdm(ts_LAPDm_UI(tc.sapi, cr_MO_CMD, tc.l3), tc.link_id);
Harald Welte0472ab42018-03-12 15:02:26 +01003703 /* Expdct RLL UNITDATA IND on RSL side */
3704 alt {
3705 [] RSL.receive(tr_RSL_UNITDATA_IND(g_chan_nr, tc.link_id, tc.l3)) {
3706 setverdict(pass);
3707 }
3708 [] RSL.receive { repeat; }
3709 }
3710
3711 /* release the channel */
3712 f_rsl_chan_deact();
3713 f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
3714 f_rslem_unregister(0, g_chan_nr);
3715}
3716testcase TC_rll_unit_data_ind_DCCH() runs on test_CT {
Stefan Sperlingc4181912018-07-25 17:03:08 +02003717 var octetstring l3 := f_rnd_octstring(20);
Harald Welte0472ab42018-03-12 15:02:26 +01003718 var RllTestCases tcs := {
3719 valueof(t_EITC(0, valueof(ts_RslLinkID_DCCH(0)), l3, true)),
3720 valueof(t_EITC(3, valueof(ts_RslLinkID_DCCH(3)), l3, true))
3721 };
3722 f_rll_testmatrix(tcs, refers(f_TC_rll_ud_ind));
3723}
3724testcase TC_rll_unit_data_ind_ACCH() runs on test_CT {
3725 var octetstring l3 := f_rnd_octstring(18);
3726 var RllTestCases tcs := {
3727 valueof(t_EITC(0, valueof(ts_RslLinkID_SACCH(0)), l3, true)),
3728 valueof(t_EITC(3, valueof(ts_RslLinkID_SACCH(3)), l3, true))
3729 };
3730 f_rll_testmatrix(tcs, refers(f_TC_rll_ud_ind));
3731}
3732
Harald Weltee613f962018-04-18 22:38:16 +02003733/***********************************************************************
3734 * Encryption Related
3735 ***********************************************************************/
3736
3737/* send UNITDATA_REQ from BTS to MS and expect it to arrive */
3738function f_unitdata_mt(RslLinkId link_id, octetstring l3) runs on ConnHdlr {
3739 RSL.send(ts_RSL_UNITDATA_REQ(g_chan_nr, link_id, l3));
3740 if (link_id.c == SACCH) {
3741 f_l1_exp_lapdm(tr_LAPDm_B4_UI(link_id.sapi, cr_MT_CMD, l3));
3742 } else {
3743 f_l1_exp_lapdm(tr_LAPDm_UI(link_id.sapi, cr_MT_CMD, l3));
3744 }
3745}
3746
Vadim Yanitskiyad131c82018-10-04 06:18:59 +07003747/* Expect (or not expect) other kinds of messages */
3748private altstep as_rsl_any_ind(boolean exp_any) runs on ConnHdlr {
3749 [exp_any] RSL.receive { repeat; }
3750 [not exp_any] RSL.receive {
3751 setverdict(fail, "Unexpected RSL message!");
3752 mtc.stop;
3753 }
3754}
3755
Harald Weltee613f962018-04-18 22:38:16 +02003756/* Send UI frame from MS and expect it to arrive as RLL UNITDATA IND on Abis */
Vadim Yanitskiy8d8f91c2018-10-04 06:19:45 +07003757private function f_unitdata_mo(
Vadim Yanitskiy98e03152018-10-03 18:06:06 +07003758 RslLinkId link_id,
3759 octetstring l3,
3760 boolean exp_sacch := true, /* Should tolerate SACCH messages? */
Vadim Yanitskiyb9920502018-10-03 18:29:51 +07003761 boolean exp_any := false /* Should tolerate any other RSL messages? */
Vadim Yanitskiy98e03152018-10-03 18:06:06 +07003762) runs on ConnHdlr {
Harald Weltee613f962018-04-18 22:38:16 +02003763 timer T := 3.0;
3764 f_tx_lapdm(ts_LAPDm_UI(link_id.sapi, cr_MO_CMD, l3), link_id);
3765 T.start;
3766 /* Expect RLL UNITDATA IND on RSL side */
3767 alt {
3768 [] RSL.receive(tr_RSL_UNITDATA_IND(g_chan_nr, link_id, l3)) {
3769 setverdict(pass);
3770 }
Vadim Yanitskiye0b91a72018-10-04 15:44:40 +07003771 [exp_sacch] as_meas_res(verify_meas := false);
Vadim Yanitskiyad131c82018-10-04 06:18:59 +07003772 [] as_rsl_any_ind(exp_any);
Harald Weltee613f962018-04-18 22:38:16 +02003773 [] T.timeout {
3774 setverdict(fail, "Timeout waiting for UNIT_DATA_IND");
Daniel Willmann17ddd852018-07-05 17:33:20 +02003775 mtc.stop;
Harald Weltee613f962018-04-18 22:38:16 +02003776 }
Harald Weltee613f962018-04-18 22:38:16 +02003777 }
3778}
3779
Vadim Yanitskiy4d78a702018-10-03 03:59:34 +07003780/* Send I-frame from MS and expect it to arrive as RLL DATA IND on Abis */
3781private function f_data_mo(
3782 RslLinkId link_id,
3783 boolean p, uint3_t nr, uint3_t ns,
3784 octetstring l3,
3785 boolean exp_sacch := true, /* Should tolerate SACCH messages? */
Vadim Yanitskiyb9920502018-10-03 18:29:51 +07003786 boolean exp_any := false /* Should tolerate any other RSL messages? */
Vadim Yanitskiy4d78a702018-10-03 03:59:34 +07003787) runs on ConnHdlr {
3788 timer T := 3.0;
3789 f_tx_lapdm(ts_LAPDm_I(link_id.sapi, cr_MO_CMD, p, nr, ns, l3), link_id);
3790 T.start;
3791 /* Expect RLL DATA IND on RSL side */
3792 alt {
3793 [] RSL.receive(tr_RSL_DATA_IND(g_chan_nr, link_id, l3)) {
3794 setverdict(pass);
3795 }
Vadim Yanitskiye0b91a72018-10-04 15:44:40 +07003796 [exp_sacch] as_meas_res(verify_meas := false);
Vadim Yanitskiy4d78a702018-10-03 03:59:34 +07003797 [] as_rsl_any_ind(exp_any);
3798 [] T.timeout {
3799 setverdict(fail, "Timeout waiting for DATA_IND");
3800 mtc.stop;
3801 }
3802 }
3803}
3804
Harald Weltee613f962018-04-18 22:38:16 +02003805/* Test channel activation with A5/n right from the beginning (like in assignment + hand-over) */
3806function f_TC_chan_act_encr(charstring id) runs on ConnHdlr {
3807 f_l1_tune(L1CTL);
3808 f_est_dchan(true);
3809
3810 /* now we actually need to transmit some data both ways to check if the encryption works */
3811 var L1ctlDlMessage dl;
3812
Stefan Sperling603d98e2018-07-25 16:47:28 +02003813 var octetstring l3 := f_rnd_octstring(20);
Harald Weltee613f962018-04-18 22:38:16 +02003814 var RslLinkId link_id := valueof(ts_RslLinkID_DCCH(0));
3815
3816 /* send UNITDATA_REQ from BTS to MS and expect it to arrive */
3817 f_unitdata_mt(link_id, l3);
3818
3819 /* Send UI frame from MS and expect it to arrive as RLL UNITDATA IND on Abis */
3820 f_unitdata_mo(link_id, l3);
3821
3822 /* release the channel */
3823 f_rsl_chan_deact();
3824 f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
3825 f_rslem_unregister(0, g_chan_nr);
3826}
3827testcase TC_chan_act_a51() runs on test_CT {
3828 var ConnHdlrPars pars := valueof(t_Pars(t_RslChanNr_Bm(1), ts_RSL_ChanMode_SIGN));
3829 pars.encr := valueof(ts_RSL_IE_EncrInfo(RSL_ALG_ID_A5_1, f_rnd_octstring(8)));
3830 f_testmatrix_each_chan(pars, refers(f_TC_chan_act_encr));
3831}
3832testcase TC_chan_act_a52() runs on test_CT {
3833 var ConnHdlrPars pars := valueof(t_Pars(t_RslChanNr_Bm(1), ts_RSL_ChanMode_SIGN));
3834 pars.encr := valueof(ts_RSL_IE_EncrInfo(RSL_ALG_ID_A5_2, f_rnd_octstring(8)));
3835 f_testmatrix_each_chan(pars, refers(f_TC_chan_act_encr));
3836}
3837testcase TC_chan_act_a53() runs on test_CT {
3838 var ConnHdlrPars pars := valueof(t_Pars(t_RslChanNr_Bm(1), ts_RSL_ChanMode_SIGN));
3839 pars.encr := valueof(ts_RSL_IE_EncrInfo(RSL_ALG_ID_A5_3, f_rnd_octstring(8)));
3840 f_testmatrix_each_chan(pars, refers(f_TC_chan_act_encr));
3841}
3842
3843
3844/* Test unencrypted channel activation followed by explicit ENCR CMD later */
3845function f_TC_encr_cmd(charstring id) runs on ConnHdlr {
3846 /* L3 payload doesn't matter, as it is passed transparently */
3847 var BIT3 l3_alg_id := f_alg_id_to_l3(g_pars.encr.alg_id);
3848 var octetstring l3 := enc_PDU_ML3_NW_MS(valueof(ts_RRM_CiphModeCmd(l3_alg_id)));
3849 var RslLinkId link_id := valueof(ts_RslLinkID_DCCH(0));
3850
3851 f_l1_tune(L1CTL);
3852
3853 /* first establish a dedicated channel in the clear */
3854 f_est_dchan(false);
3855
3856 /* Establish ABM */
3857 f_est_rll_mo(link_id.sapi, link_id, '23420815'O);
3858
3859 /* then send the RSL ENCR CMD with an actual RR CIPH MOD CMD inside */
3860 RSL.send(ts_RSL_ENCR_CMD(g_chan_nr, link_id, g_pars.encr.alg_id, g_pars.encr.key, l3));
3861 /* expect the L3 to arrive still unencrypted on the MS side */
3862 f_l1_exp_lapdm(tr_LAPDm_I(link_id.sapi, cr_MT_CMD, ?, ?, ?, l3));
3863
3864 /* configure L1 to apply ciphering */
3865 var uint8_t alg_id := f_alg_id_to_l1ctl(g_pars.encr.alg_id);
3866 f_L1CTL_CRYPTO_REQ(L1CTL, g_pars.chan_nr, alg_id, g_pars.encr.key);
3867
Vadim Yanitskiy4d78a702018-10-03 03:59:34 +07003868 /* send first ciphered I-frame in response and expect it on RSL */
3869 f_data_mo(link_id, true, 1, 0, '0a0b0c0d'O, exp_sacch := true);
Harald Weltee613f962018-04-18 22:38:16 +02003870
3871 /* now the BTS code should have detected the first properly encrypted uplink I-frame,
3872 * and hence enable encryption also on the downlink */
3873
3874 /* expect bi-directional communication work in encrypted mode */
3875 f_unitdata_mo(link_id, f_rnd_octstring(15));
3876 f_unitdata_mt(link_id, f_rnd_octstring(15));
3877
3878 /* release the channel */
3879 f_rsl_chan_deact();
3880 f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
3881 f_rslem_unregister(0, g_chan_nr);
3882}
3883testcase TC_encr_cmd_a51() runs on test_CT {
3884 var ConnHdlrPars pars := valueof(t_Pars(t_RslChanNr_Bm(1), ts_RSL_ChanMode_SIGN));
3885 pars.encr := valueof(ts_RSL_IE_EncrInfo(RSL_ALG_ID_A5_1, f_rnd_octstring(8)));
3886 f_testmatrix_each_chan(pars, refers(f_TC_encr_cmd));
3887}
3888testcase TC_encr_cmd_a52() runs on test_CT {
3889 var ConnHdlrPars pars := valueof(t_Pars(t_RslChanNr_Bm(1), ts_RSL_ChanMode_SIGN));
3890 pars.encr := valueof(ts_RSL_IE_EncrInfo(RSL_ALG_ID_A5_2, f_rnd_octstring(8)));
3891 f_testmatrix_each_chan(pars, refers(f_TC_encr_cmd));
3892}
3893testcase TC_encr_cmd_a53() runs on test_CT {
3894 var ConnHdlrPars pars := valueof(t_Pars(t_RslChanNr_Bm(1), ts_RSL_ChanMode_SIGN));
3895 pars.encr := valueof(ts_RSL_IE_EncrInfo(RSL_ALG_ID_A5_3, f_rnd_octstring(8)));
3896 f_testmatrix_each_chan(pars, refers(f_TC_encr_cmd));
3897}
3898
3899private function f_assert_lapdm(octetstring enc, template LapdmFrame exp_match, charstring name := "") {
3900 var LapdmFrame lf;
3901 var octetstring reenc;
3902
3903 /* decode the LAPDm frame */
3904 if (ischosen(exp_match.ab)) {
3905 lf.ab := dec_LapdmFrameAB(enc);
3906 } else {
3907 setverdict(fail, "unsupported frame type");
Daniel Willmann17ddd852018-07-05 17:33:20 +02003908 mtc.stop;
Harald Weltee613f962018-04-18 22:38:16 +02003909 }
3910
3911 /* check if decoder result matches expectation */
3912 if (not match(lf, exp_match)) {
3913 setverdict(fail, name, ": decoded LAPDm doesn't match");
Daniel Willmann17ddd852018-07-05 17:33:20 +02003914 mtc.stop;
Harald Weltee613f962018-04-18 22:38:16 +02003915 } else {
3916 log(name, ": matched");
3917 setverdict(pass);
3918 }
3919
3920 /* test if re-encoded frame equals original input */
3921 reenc := enc_LapdmFrame(lf);
3922 if (enc != reenc) {
3923 setverdict(fail, name, ": re-encoded LAPDm frame doesn't match");
Daniel Willmann17ddd852018-07-05 17:33:20 +02003924 mtc.stop;
Harald Weltee613f962018-04-18 22:38:16 +02003925 } else {
3926 setverdict(pass);
3927 }
3928}
3929
3930testcase TC_lapdm_selftest() runs on test_CT {
3931 f_assert_lapdm('030301'O, tr_LAPDm_UI(0, true, ''O), "ui_s0_empty");
3932 f_assert_lapdm('0F0301'O, tr_LAPDm_UI(3, true, ''O), "ui_s3_empty");
3933 f_assert_lapdm('013F01'O, tr_LAPDm_SABM(0, false, true, ''O), "sabm_s0_empty");
3934 f_assert_lapdm('013F1123420815'O, tr_LAPDm_SABM(0, false, true, '23420815'O), "sabm_s0_l3");
3935 f_assert_lapdm('03E101'O, tr_LAPDm_RR(0, true, false, 7), "rr_s0_7");
3936 f_assert_lapdm('03000d063505'O, tr_LAPDm_I(0, true, false, 0, 0, '063505'O), "I/0/0");
3937 f_assert_lapdm('03e00d063505'O, tr_LAPDm_I(0, true, false, 7, 0, '063505'O), "I/7/0");
3938}
3939
Stefan Sperling4880be42018-08-07 18:12:59 +02003940/***********************************************************************
3941 * DTX Related (see GSM 05.08, section 8.3)
3942 ***********************************************************************/
3943
3944/* XXX These functions must be kept in sync with g_AllChannels defined on test_CT. */
3945function f_g_chan_is_tchf() runs on ConnHdlr return boolean {
3946 return (g_chan_nr == valueof(ts_RslChanNr_Bm(1)) or
3947 g_chan_nr == valueof(ts_RslChanNr_Bm(2)) or
3948 g_chan_nr == valueof(ts_RslChanNr_Bm(3)) or
3949 g_chan_nr == valueof(ts_RslChanNr_Bm(4)));
3950}
3951function f_g_chan_is_tchh() runs on ConnHdlr return boolean {
3952 return (g_chan_nr == valueof(ts_RslChanNr_Lm(5,0)) or
3953 g_chan_nr == valueof(ts_RslChanNr_Lm(5,1)));
3954}
3955function f_g_chan_is_sdcch4() runs on ConnHdlr return boolean {
3956 return (g_chan_nr == valueof(ts_RslChanNr_SDCCH4(0,0)) or
3957 g_chan_nr == valueof(ts_RslChanNr_SDCCH4(0,1)) or
3958 g_chan_nr == valueof(ts_RslChanNr_SDCCH4(0,2)) or
3959 g_chan_nr == valueof(ts_RslChanNr_SDCCH4(0,3)));
3960}
3961function f_g_chan_is_sdcch8() runs on ConnHdlr return boolean {
3962 return (g_chan_nr == valueof(ts_RslChanNr_SDCCH8(6,0)) or
3963 g_chan_nr == valueof(ts_RslChanNr_SDCCH8(6,1)) or
3964 g_chan_nr == valueof(ts_RslChanNr_SDCCH8(6,2)) or
3965 g_chan_nr == valueof(ts_RslChanNr_SDCCH8(6,3)) or
3966 g_chan_nr == valueof(ts_RslChanNr_SDCCH8(6,4)) or
3967 g_chan_nr == valueof(ts_RslChanNr_SDCCH8(6,5)) or
3968 g_chan_nr == valueof(ts_RslChanNr_SDCCH8(6,6)) or
3969 g_chan_nr == valueof(ts_RslChanNr_SDCCH8(6,7)));
3970}
3971
3972function f_test_l2_fill_frames(boolean dtxd) runs on ConnHdlr {
3973 var L1ctlDlMessage dl;
3974 var octetstring l2_fill_frame := '0303012B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B'O;
3975 var octetstring l2_fill_frame_sacch := substr(l2_fill_frame, 0, lengthof(l2_fill_frame) - 2);
3976 var GsmFrameNumber first_fn;
3977 var boolean is_first_frame := true;
Stefan Sperling91d4c9d2018-08-09 20:03:08 +02003978 var integer nfill_frames_sacch := 0;
3979 var integer nfill_frames_nonsacch := 0;
3980 var integer expected_fill_frames := 10000; /* initial value causes test failure if not overridden */
Stefan Sperling4880be42018-08-07 18:12:59 +02003981 /* Frames numbers (mod 104) for which a fill frame is expected on TCHF if DTX is enabled. */
3982 var Integers required_tdma_frames_dtx_tchf := { 52, 53, 54, 55, 56, 57, 58, 59 };
Stefan Sperling91d4c9d2018-08-09 20:03:08 +02003983 const integer frame_dtx_tchf_mod := 104;
3984 /* Frame numbers (mod 104) for which a fill frame is expected at the L1SAP level,
3985 * which operates in terms of blocks rather than frames. */
3986 var Integers required_tdma_blocks_dtx_tchf := { 52, 56 };
3987 const integer block_dtx_tchf_mod := 26;
Stefan Sperling4880be42018-08-07 18:12:59 +02003988 timer T := 5.0;
3989
3990 f_l1_tune(L1CTL);
3991 RSL.clear;
3992 L1CTL.clear;
3993
3994 /* activate TCHF signalling channel */
3995 f_est_dchan(false);
3996
3997 T.start;
3998 alt {
3999 [] L1CTL.receive(tr_L1CTL_DATA_IND(g_chan_nr, ?)) -> value dl {
4000 var GsmFrameNumber fn := dl.dl_info.frame_nr;
4001 var octetstring l2 := dl.payload.data_ind.payload;
4002
4003 if (is_first_frame) {
4004 is_first_frame := false;
4005 first_fn := dl.dl_info.frame_nr;
4006 }
4007
4008 if (dl.dl_info.link_id.c == SACCH) {
4009 l2 := substr(l2, 2, lengthof(l2) - 2); /* remove L1 header */
4010 if (not match(l2_fill_frame_sacch, l2)) {
4011 repeat;
4012 }
4013 } else if (not match(l2_fill_frame, l2)) {
4014 repeat;
4015 }
4016
4017 if (dtxd) {
4018 if (not f_g_chan_is_tchf()) {
4019 T.stop;
4020 f_rsl_chan_deact();
4021 f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
4022 setverdict(fail, "Received fill frame on non-TCH/F channel; DTX is only allowed on TCH/F!");
4023 }
Stefan Sperling91d4c9d2018-08-09 20:03:08 +02004024 if (fn > first_fn + frame_dtx_tchf_mod) {
Stefan Sperling4880be42018-08-07 18:12:59 +02004025 T.stop;
4026 f_rsl_chan_deact();
4027 f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
Stefan Sperling91d4c9d2018-08-09 20:03:08 +02004028
4029 /* With DTX enabled we can expect at least 3 fill frames for every 104 frames.
4030 * 2 SACCH, 1 TCH/F */
4031 expected_fill_frames := 3;
4032
4033 if (nfill_frames_sacch + nfill_frames_nonsacch < expected_fill_frames) {
4034 log("received only ", nfill_frames_sacch, "+", nfill_frames_nonsacch,
4035 " (SACCH+other) out of ", expected_fill_frames, " expected fill frames");
4036 setverdict(fail, "Not enough fill frames received");
Stefan Sperling4880be42018-08-07 18:12:59 +02004037 } else {
4038 setverdict(pass);
4039 }
Stefan Sperling91d4c9d2018-08-09 20:03:08 +02004040 } else {
4041 if (dl.dl_info.link_id.c == SACCH) {
4042 nfill_frames_sacch := nfill_frames_sacch + 1;
Stefan Sperling4880be42018-08-07 18:12:59 +02004043 repeat;
4044 }
Stefan Sperling91d4c9d2018-08-09 20:03:08 +02004045 /* On DTX TCH/F channels, fill frames occur only for specific frame numbers mod 104.
4046 * Furthermore, the L1SAP layer gives us frame numbers for the start of a block so
4047 * we should only see the subset of frames numbers which correspond to a block boundary.
4048 * TCH/F blocks are defined to start at 0,4,8,13,17,21 (modulo 26) */
4049 for (var integer i := 0; i < lengthof(required_tdma_blocks_dtx_tchf); i := i + 1) {
4050 if (fn mod frame_dtx_tchf_mod == required_tdma_blocks_dtx_tchf[i]) {
4051 nfill_frames_nonsacch := nfill_frames_nonsacch + 1;
4052 repeat;
4053 }
4054 }
4055 log("Received DTX TCH fill frame with bad frame number: ", fn,
4056 " (mod ", frame_dtx_tchf_mod, ": ", fn mod frame_dtx_tchf_mod, ")",
4057 " (mod ", block_dtx_tchf_mod, ": ", fn mod block_dtx_tchf_mod, ")");
4058 f_rsl_chan_deact();
4059 f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
4060 setverdict(fail, "Unexpected L2 fill frame received on Um");
Stefan Sperling4880be42018-08-07 18:12:59 +02004061 }
Stefan Sperling4880be42018-08-07 18:12:59 +02004062 } else {
Stefan Sperling91d4c9d2018-08-09 20:03:08 +02004063 if (dl.dl_info.link_id.c == SACCH) {
4064 nfill_frames_sacch := nfill_frames_sacch + 1;
4065 } else {
4066 nfill_frames_nonsacch := nfill_frames_nonsacch + 1;
4067 }
4068 if (fn > first_fn + frame_dtx_tchf_mod) {
Stefan Sperling4880be42018-08-07 18:12:59 +02004069 T.stop;
4070 if (f_g_chan_is_tchf()) {
4071 /* Without DTX we can expect 25 fill frames for every 104 frames.
4072 * (24 FACCH + 1 SACCH filling) */
4073 expected_fill_frames := 25;
4074 } else if (f_g_chan_is_tchh()) {
4075 /* We can expect 2 fill frames for every 104 frames. */
4076 expected_fill_frames := 2;
4077 } else if (f_g_chan_is_sdcch4() or f_g_chan_is_sdcch8()) {
4078 /* We can expect 5 fill frames for every 104 frames. */
4079 expected_fill_frames := 5;
4080 } else {
4081 f_rsl_chan_deact();
4082 f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
4083 setverdict(fail, "Unknown channel type");
4084 }
4085
4086 f_rsl_chan_deact();
4087 f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
Stefan Sperling91d4c9d2018-08-09 20:03:08 +02004088
4089 if (nfill_frames_sacch + nfill_frames_nonsacch >= expected_fill_frames) {
Stefan Sperling4880be42018-08-07 18:12:59 +02004090 setverdict(pass);
4091 } else {
Stefan Sperling91d4c9d2018-08-09 20:03:08 +02004092 log("received only ", nfill_frames_sacch, "+", nfill_frames_nonsacch,
4093 " (SACCH+other) out of ", expected_fill_frames, " expected fill frames");
Stefan Sperling4880be42018-08-07 18:12:59 +02004094 setverdict(fail, "Not enough fill frames received");
4095 }
4096 } else {
4097 repeat;
4098 }
4099 }
4100 }
4101 [] L1CTL.receive { repeat; }
4102 [] T.timeout {
4103 f_rsl_chan_deact();
4104 f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
4105 setverdict(fail, "Timeout waiting for L2 fill frames on Um");
4106 mtc.stop;
4107 }
4108 }
4109}
4110
4111function f_TC_tch_sign_l2_fill_frame(charstring id) runs on ConnHdlr {
4112 f_test_l2_fill_frames(false);
4113}
4114
4115function f_TC_tch_sign_l2_fill_frame_dtxd(charstring id) runs on ConnHdlr {
4116 f_test_l2_fill_frames(true);
4117}
4118
4119function f_tch_sign_l2_fill_frame(boolean dtxd) runs on test_CT {
4120 var ConnHdlr vc_conn;
4121 var ConnHdlrPars pars;
4122 pars.t_guard := 60.0;
4123 f_init(testcasename());
4124 for (var integer i := 0; i < sizeof(g_AllChannels); i := i + 1) {
4125 pars := valueof(t_Pars(g_AllChannels[i], ts_RSL_ChanMode_SIGN(dtxd)));
4126 if (dtxd) {
4127 if (i >= 4) { /* DTX is only allowed on TCH/F */
4128 break;
4129 }
4130 vc_conn := f_start_handler(refers(f_TC_tch_sign_l2_fill_frame_dtxd), pars);
4131 } else {
4132 vc_conn := f_start_handler(refers(f_TC_tch_sign_l2_fill_frame), pars);
4133 }
4134 vc_conn.done;
4135 }
4136}
4137
4138/* Verify that L2 fill frames are sent on TCH in signaling mode if
4139 * there is nothing to transmit while DTX is disabled on downlink. */
4140testcase TC_tch_sign_l2_fill_frame() runs on test_CT {
4141 f_tch_sign_l2_fill_frame(false);
4142}
4143
4144/* Verify that particular L2 fill frames are sent on TCH in signaling mode if
4145 * there is nothing to transmit while DTX is enabled on downlink. */
4146testcase TC_tch_sign_l2_fill_frame_dtxd() runs on test_CT {
4147 f_tch_sign_l2_fill_frame(true);
4148}
Harald Welte0472ab42018-03-12 15:02:26 +01004149
Stefan Sperling0ec1c262018-10-15 15:12:52 +02004150testcase TC_chopped_ipa_ping() runs on test_CT {
4151 IPA_Testing.f_run_TC_chopped_ipa_ping(mp_rsl_ip, mp_rsl_port, LISTEN_FOR_CLIENT);
4152}
4153
Harald Welte0472ab42018-03-12 15:02:26 +01004154/* test generation of RLL ERR IND based on Um errors (TS 48.058 3.9) */
4155/* protocol error as per 44.006 */
4156/* link layer failure (repetition of I-frame N200 times without ACK */
4157/* repetition of SABM or DISC N200 times without ACK */
4158/* receptiom of SABM in multi-frame established state */
4159
4160
4161
4162
Harald Welte883340c2018-02-28 18:59:29 +01004163
Harald Welte68e495b2018-02-25 00:05:57 +01004164/* TODO Areas:
4165
4166* channel activation
4167** with BS_Power / MS_Power, bypassing power control loop
4168** on primary vs. secondary TRX
Harald Welte68e495b2018-02-25 00:05:57 +01004169** with timing advance from initial activation on
4170* mode modify
4171** encryption
4172** multirate
4173* check DEACTIVATE SACCH
Harald Welte68e495b2018-02-25 00:05:57 +01004174** unsupported algorithm
4175* handover detection
4176* MS Power Control
4177* BS Power Control
4178* Physical Context
Harald Welte43c54642018-09-15 17:47:04 +03004179* CCCH Load Indication for RACH
Harald Welte68e495b2018-02-25 00:05:57 +01004180* SMS Broadcast Req / Cmd / CBCH LOad Ind
4181* RF resource ind
Harald Welte68e495b2018-02-25 00:05:57 +01004182* error handling
Harald Welte43c54642018-09-15 17:47:04 +03004183** discriminator error
Harald Welte68e495b2018-02-25 00:05:57 +01004184** type error
4185** sequence error
4186** IE duplicated?
Harald Welte883340c2018-02-28 18:59:29 +01004187* PCU interface
4188** TIME_IND from BTS->PCU
4189** DATA_IND from BTS->PCU
4190** verification of PCU-originated DATA_REQ arrival on Um/MS side
Harald Welte68e495b2018-02-25 00:05:57 +01004191
4192*/
Harald Welte70767382018-02-21 12:16:40 +01004193
4194control {
4195 execute( TC_chan_act_stress() );
4196 execute( TC_chan_act_react() );
4197 execute( TC_chan_deact_not_active() );
4198 execute( TC_chan_act_wrong_nr() );
Harald Welte629cc6b2018-03-11 17:19:05 +01004199 execute( TC_deact_sacch() );
Harald Welteea17b912018-03-11 22:29:31 +01004200 execute( TC_sacch_filling() );
4201 execute( TC_sacch_info_mod() );
Harald Welte075d84c2018-03-12 13:07:24 +01004202 execute( TC_sacch_multi() );
Harald Welte55700662018-03-12 13:15:43 +01004203 execute( TC_sacch_multi_chg() );
Harald Welte8c24c2b2018-02-26 08:31:31 +01004204 execute( TC_rach_content() );
4205 execute( TC_rach_count() );
Harald Welte54a2a2d2018-02-26 09:14:05 +01004206 execute( TC_rach_max_ta() );
Harald Welte70767382018-02-21 12:16:40 +01004207 execute( TC_meas_res_sign_tchf() );
4208 execute( TC_meas_res_sign_tchh() );
4209 execute( TC_meas_res_sign_sdcch4() );
4210 execute( TC_meas_res_sign_sdcch8() );
Harald Welte685d5982018-02-27 20:42:05 +01004211 execute( TC_meas_res_sign_tchh_toa256() );
Harald Welte70767382018-02-21 12:16:40 +01004212 execute( TC_conn_fail_crit() );
Harald Welte68e495b2018-02-25 00:05:57 +01004213 execute( TC_paging_imsi_80percent() );
4214 execute( TC_paging_tmsi_80percent() );
4215 execute( TC_paging_imsi_200percent() );
4216 execute( TC_paging_tmsi_200percent() );
Harald Welte01d982c2018-02-25 01:31:40 +01004217 execute( TC_rsl_protocol_error() );
4218 execute( TC_rsl_mand_ie_error() );
4219 execute( TC_rsl_ie_content_error() );
Harald Welte48494ca2018-02-25 16:59:50 +01004220 execute( TC_si_sched_default() );
Harald Welte0cae4552018-03-09 22:20:26 +01004221 execute( TC_si_sched_1() );
Harald Welte48494ca2018-02-25 16:59:50 +01004222 execute( TC_si_sched_2bis() );
4223 execute( TC_si_sched_2ter() );
4224 execute( TC_si_sched_2ter_2bis() );
4225 execute( TC_si_sched_2quater() );
4226 execute( TC_si_sched_13() );
4227 execute( TC_si_sched_13_2bis_2ter_2quater() );
Harald Weltea871a382018-02-25 02:03:14 +01004228 execute( TC_ipa_dlcx_not_active() );
Harald Weltea3f1df92018-02-25 12:49:55 +01004229 execute( TC_ipa_crcx_twice_not_active() );
4230 execute( TC_ipa_crcx_mdcx_dlcx_not_active() );
Harald Welte3ae11da2018-02-25 13:36:06 +01004231 execute( TC_ipa_crcx_mdcx_mdcx_dlcx_not_active() );
Harald Welte9912eb52018-02-25 13:30:15 +01004232 execute( TC_ipa_crcx_sdcch_not_active() );
Harald Welte883340c2018-02-28 18:59:29 +01004233
4234 execute( TC_pcu_act_req() );
4235 execute( TC_pcu_act_req_wrong_ts() );
4236 execute( TC_pcu_act_req_wrong_bts() );
4237 execute( TC_pcu_act_req_wrong_trx() );
4238 execute( TC_pcu_deact_req() );
4239 execute( TC_pcu_deact_req_wrong_ts() );
4240 execute( TC_pcu_ver_si13() );
4241 execute( TC_pcu_data_req_wrong_bts() );
4242 execute( TC_pcu_data_req_wrong_trx() );
4243 execute( TC_pcu_data_req_wrong_ts() );
4244 execute( TC_pcu_data_req_ts_inactive() );
4245 execute( TC_pcu_data_req_pdtch() );
4246 execute( TC_pcu_data_req_ptcch() );
4247 execute( TC_pcu_data_req_agch() );
4248 execute( TC_pcu_data_req_imm_ass_pch() );
4249 execute( TC_pcu_rach_content() );
4250 execute( TC_pcu_paging_from_rsl() );
Harald Welte3d04ae62018-04-04 20:29:05 +02004251
4252 execute( TC_dyn_osmo_pdch_act_deact() );
4253 execute( TC_dyn_osmo_pdch_unsol_deact() );
4254 execute( TC_dyn_osmo_pdch_double_act() );
4255 execute( TC_dyn_osmo_pdch_tchf_act() );
4256 execute( TC_dyn_osmo_pdch_tchh_act() );
Harald Welte9bbbfb52018-04-05 09:33:19 +02004257 execute( TC_dyn_ipa_pdch_act_deact() );
4258 execute( TC_dyn_ipa_pdch_tchf_act() );
4259 execute( TC_dyn_ipa_pdch_tchf_act_pdch_act_nack() );
4260 execute( TC_dyn_ipa_pdch_act_tchf_act_nack() );
Harald Welte0472ab42018-03-12 15:02:26 +01004261
4262 execute( TC_rll_est_ind() );
4263 execute( TC_rll_est_req_DCCH_3() );
4264 execute( TC_rll_est_req_ACCH_3() );
4265 execute( TC_rll_rel_ind_DCCH_0() );
4266 execute( TC_rll_rel_ind_DCCH_3() );
4267 execute( TC_rll_rel_ind_ACCH_0() );
4268 execute( TC_rll_rel_ind_ACCH_3() );
4269 execute( TC_rll_rel_req() );
4270 execute( TC_rll_unit_data_req_DCCH() );
4271 execute( TC_rll_unit_data_req_ACCH() );
4272 execute( TC_rll_unit_data_ind_DCCH() );
4273 execute( TC_rll_unit_data_ind_ACCH() );
Harald Weltee613f962018-04-18 22:38:16 +02004274
4275 execute( TC_chan_act_a51() );
4276 execute( TC_chan_act_a52() );
4277 execute( TC_chan_act_a53() );
4278 execute( TC_encr_cmd_a51() );
4279 execute( TC_encr_cmd_a52() );
4280 execute( TC_encr_cmd_a53() );
4281
4282 execute( TC_lapdm_selftest() );
Stefan Sperling4880be42018-08-07 18:12:59 +02004283
4284 execute( TC_tch_sign_l2_fill_frame() );
4285 execute( TC_tch_sign_l2_fill_frame_dtxd() );
Stefan Sperling0ec1c262018-10-15 15:12:52 +02004286
4287 execute( TC_chopped_ipa_ping() );
Harald Welte70767382018-02-21 12:16:40 +01004288}
4289
4290
4291}