blob: ed37428d161185b07e9dae7df997fc151281ab37 [file] [log] [blame]
Harald Welte70767382018-02-21 12:16:40 +01001module BTS_Tests {
2
3import from General_Types all;
4import from GSM_Types all;
5import from GSM_RR_Types all;
6import from Osmocom_Types all;
7import from GSM_Types all;
8import from GSM_RR_Types all;
9import from L1CTL_PortType all;
10import from L1CTL_Types all;
11import from LAPDm_Types all;
12import from Osmocom_CTRL_Adapter all;
13
14import from RSL_Types all;
Harald Welte7484fc42018-02-24 14:09:45 +010015import from IPA_Types all;
Harald Welte70767382018-02-21 12:16:40 +010016import from IPA_Emulation all;
17import from RSL_Emulation all;
18
19import from IPL4asp_Types all;
20import from TRXC_Types all;
21import from TRXC_CodecPort all;
22import from TRXC_CodecPort_CtrlFunct all;
23
Harald Welte7484fc42018-02-24 14:09:45 +010024import from MobileL3_CommonIE_Types all;
Harald Welte68e495b2018-02-25 00:05:57 +010025import from MobileL3_RRM_Types all;
26import from MobileL3_Types all;
27import from L3_Templates all;
Harald Welte7484fc42018-02-24 14:09:45 +010028
Harald Welte70767382018-02-21 12:16:40 +010029/* The tests assume a BTS with the following timeslot configuration:
30 * TS0 : Combined CCCH + SDCCH/4
31 * TS1 .. TS 4: TCH/F
32 * TS5 : TCH/H
33 * TS6 : SDCCH/8
34 * TS7 : PDCH
35 */
36
37modulepar {
38 charstring mp_rsl_ip := "127.0.0.2";
39 integer mp_rsl_port := 3003;
40 integer mp_trx0_arfcn := 871;
41 integer mp_bb_trxc_port := 5704;
42}
43
44type component test_CT extends CTRL_Adapter_CT {
Harald Welte68e495b2018-02-25 00:05:57 +010045 /* IPA Emulation component underneath RSL */
Harald Welte70767382018-02-21 12:16:40 +010046 var IPA_Emulation_CT vc_IPA;
Harald Welte68e495b2018-02-25 00:05:57 +010047 /* RSL Emulation component (for ConnHdlr tests) */
Harald Welte70767382018-02-21 12:16:40 +010048 var RSL_Emulation_CT vc_RSL;
Harald Welte68e495b2018-02-25 00:05:57 +010049 /* Direct RSL_CCHAN_PT */
Harald Welte70767382018-02-21 12:16:40 +010050 port RSL_CCHAN_PT RSL_CCHAN;
Harald Welte68e495b2018-02-25 00:05:57 +010051
52 /* L1CTL port (for classic tests) */
53 port L1CTL_PT L1CTL;
Harald Welte70767382018-02-21 12:16:40 +010054}
55
56/* an individual call / channel */
57type component ConnHdlr extends RSL_DchanHdlr {
58 port L1CTL_PT L1CTL;
59
60 port TRXC_CODEC_PT BB_TRXC;
61 var integer g_bb_trxc_conn_id;
62
63 timer g_Tguard;
64 timer g_Tmeas_exp := 2.0; /* >= 103 SACCH multiframe ~ 500ms */
65
66 var ConnHdlrPars g_pars;
67 var uint8_t g_next_meas_res_nr := 0;
68}
69
70function f_init_rsl(charstring id) runs on test_CT {
71 vc_IPA := IPA_Emulation_CT.create(id & "-RSL-IPA");
72 vc_RSL := RSL_Emulation_CT.create(id & "-RSL");
73
74 map(vc_IPA:IPA_PORT, system:IPA_CODEC_PT);
75 connect(vc_IPA:IPA_RSL_PORT, vc_RSL:IPA_PT);
76 connect(self:RSL_CCHAN, vc_RSL:CCHAN_PT);
77
78 vc_IPA.start(IPA_Emulation.main_server(mp_rsl_ip, mp_rsl_port));
79 vc_RSL.start(RSL_Emulation.main(false));
80}
81
82type record ConnHdlrPars {
83 RslChannelNr chan_nr,
84 RSL_IE_ChannelMode chan_mode,
85 float t_guard,
86 ConnL1Pars l1_pars
87}
88
Harald Welte7484fc42018-02-24 14:09:45 +010089/* Default SYSTEM INFORMATION 3 */
90template (value) GsmRrMessage ts_SI3_default := {
91 header := t_RrHeader(SYSTEM_INFORMATION_TYPE_3, 0),
92 payload := {
93 si3 := {
94 cell_id := 23,
95 lai := {
96 mcc_mnc := '262F42'H,
97 lac := 42
98 },
99 ctrl_chan_desc := {
100 msc_r99 := true,
101 att := true,
102 bs_ag_blks_res := 1,
103 ccch_conf := CCHAN_DESC_1CCCH_COMBINED,
104 si22_ind := false,
105 cbq3 := CBQ3_IU_MODE_NOT_SUPPORTED,
106 spare := '00'B,
107 bs_pa_mfrms := 0, /* 2 multiframes */
108 t3212 := 1 /* 6 minutes */
109 },
110 cell_opts := {
111 dn_ind := false,
112 pwrc := false,
113 dtx := MS_MAY_USE_UL_DTX,
114 radio_link_tout_div4 := 4/4
115 },
116 cell_sel_pars := {
117 cell_resel_hyst_2dB := 0,
118 ms_txpwr_max_cch := 0,
119 acs := '0'B,
120 neci := true,
121 rxlev_access_min := 0
122 },
123 rach_ctrl_pars := {
124 max_retrans := RACH_MAX_RETRANS_1,
125 tx_integer := '0000'B, /* 3 slots */
126 cell_bar_access := false,
127 re_not_allowed := true,
128 acc := '1111111111111111'B
129 },
130 rest_octets := ''O
131 }
132 }
133}
Harald Welte70767382018-02-21 12:16:40 +0100134
135/* global init function */
Harald Welte68e495b2018-02-25 00:05:57 +0100136function f_init(charstring id := "BTS-Test") runs on test_CT {
Harald Welte70767382018-02-21 12:16:40 +0100137 f_init_rsl(id);
138 RSL_CCHAN.receive(ASP_IPA_Event:{up_down := ASP_IPA_EVENT_UP});
Harald Welte7484fc42018-02-24 14:09:45 +0100139
140 /* Send SI3 to the BTS, it is needed for various computations */
141 var GsmRrMessage si3 := valueof(ts_SI3_default);
142 log("Sending SI3 ", si3);
143 var octetstring si3_enc := enc_GsmRrMessage(si3);
144 RSL_CCHAN.send(ts_RSL_UD(ts_RSL_BCCH_INFO(RSL_SYSTEM_INFO_3, si3_enc)));
Harald Welte70767382018-02-21 12:16:40 +0100145}
146
Harald Welte68e495b2018-02-25 00:05:57 +0100147/* Attach L1CTL to master test_CT (classic tests, non-handler mode) */
148function f_init_l1ctl() runs on test_CT {
149 map(self:L1CTL, system:L1CTL);
150 f_connect_reset(L1CTL);
151}
152
Harald Welte70767382018-02-21 12:16:40 +0100153type function void_fn(charstring id) runs on ConnHdlr;
154
155/* create a new test component */
156function f_start_handler(void_fn fn, ConnHdlrPars pars)
157runs on test_CT return ConnHdlr {
158 var charstring id := testcasename();
159 var ConnHdlr vc_conn;
160
161 vc_conn := ConnHdlr.create(id);
162 /* connect to RSL Emulation main component */
163 connect(vc_conn:RSL, vc_RSL:CLIENT_PT);
164 connect(vc_conn:RSL_PROC, vc_RSL:RSL_PROC);
165
166 vc_conn.start(f_handler_init(fn, id, pars));
167 return vc_conn;
168}
169
Harald Welte7484fc42018-02-24 14:09:45 +0100170template ASP_RSL_Unitdata ts_RSL_UD(template RSL_Message rsl, IpaStreamId sid := IPAC_PROTO_RSL_TRX0) := {
171 streamId := sid,
172 rsl := rsl
173}
174
175template ASP_RSL_Unitdata tr_RSL_UD(template RSL_Message rsl,
176 template IpaStreamId sid := IPAC_PROTO_RSL_TRX0) := {
177 streamId := sid,
178 rsl := rsl
179}
180
Harald Welte70767382018-02-21 12:16:40 +0100181private altstep as_Tguard() runs on ConnHdlr {
182 [] g_Tguard.timeout {
183 setverdict(fail, "Tguard timeout");
184 self.stop;
185 }
186}
187
Harald Welte68e495b2018-02-25 00:05:57 +0100188private function f_l1_tune(L1CTL_PT L1CTL) {
Harald Welte70767382018-02-21 12:16:40 +0100189 f_L1CTL_FBSB(L1CTL, { false, mp_trx0_arfcn }, CCCH_MODE_COMBINED);
190}
191
192private function f_trxc_connect() runs on ConnHdlr {
193 map(self:BB_TRXC, system:BB_TRXC);
194 var Result res;
195 res := TRXC_CodecPort_CtrlFunct.f_IPL4_connect(BB_TRXC, "127.0.0.1", mp_bb_trxc_port,
196 "127.0.0.1", 0, -1, {udp:={}}, {});
197 g_bb_trxc_conn_id := res.connId;
198}
199
200private function f_trxc_fake_rssi(uint8_t rssi) runs on ConnHdlr {
201 BB_TRXC.send(ts_TRXC_Send(g_bb_trxc_conn_id, ts_TRXC_FAKE_RSSI(rssi)));
202}
203
204private function f_trx_fake_toffs256(int16_t toffs256) runs on ConnHdlr {
205 BB_TRXC.send(ts_TRXC_Send(g_bb_trxc_conn_id, ts_TRXC_FAKE_TIMING(toffs256)));
206}
207
208/* first function started in ConnHdlr component */
209private function f_handler_init(void_fn fn, charstring id, ConnHdlrPars pars)
210runs on ConnHdlr {
211 g_pars := pars;
212 g_chan_nr := pars.chan_nr;
213
214 map(self:L1CTL, system:L1CTL);
215 f_connect_reset(L1CTL);
216
217 f_trxc_connect();
218
219 g_Tguard.start(pars.t_guard);
220 activate(as_Tguard());
221
222 f_rslem_register(0, pars.chan_nr);
223
224 /* call the user-supplied test case function */
225 fn.apply(id);
226}
227
228
229function f_rsl_chan_act(RSL_IE_ChannelMode mode) runs on ConnHdlr {
230 RSL.send(ts_RSL_CHAN_ACT(g_chan_nr, mode));
231 alt {
232 [] RSL.receive(tr_RSL_CHAN_ACT_ACK(g_chan_nr)) {
233 g_Tmeas_exp.start;
234 }
235 [] RSL.receive(tr_RSL_CHAN_ACT_NACK(g_chan_nr)) {
236 setverdict(fail, "Unexpected RF CHAN ACT NACK");
237 }
238 }
239}
240
241function f_rsl_chan_deact() runs on ConnHdlr {
242 timer T := 3.0;
243 RSL.send(ts_RSL_RF_CHAN_REL(g_chan_nr));
244 T.start;
245 alt {
246 [] RSL.receive(tr_RSL_RF_CHAN_REL_ACK(g_chan_nr)) {
247 g_Tmeas_exp.stop;
248 }
249 [] T.timeout {
250 setverdict(fail, "Timeout waiting for RF CHAN REL ACK");
251 }
252 }
253}
254
255
256private template ConnHdlrPars t_Pars(template RslChannelNr chan_nr,
257 template RSL_IE_ChannelMode chan_mode,
258 float t_guard := 20.0) := {
259 chan_nr := valueof(chan_nr),
260 chan_mode := valueof(chan_mode),
261 t_guard := t_guard,
262 l1_pars := {
263 dtx_enabled := false,
264 meas_ul := {
265 full := {
266 rxlev := dbm2rxlev(-53),
267 rxqual := 0
268 },
269 sub := {
270 rxlev := dbm2rxlev(-53),
271 rxqual := 0
272 }
273 },
274 timing_offset_256syms := 0,
275 bs_power_level := 0,
276 ms_power_level := 0,
277 ms_actual_ta := 0
278 }
279}
280
281/* Stress test: Do 500 channel activations/deactivations in rapid succession */
282function f_TC_chan_act_stress(charstring id) runs on ConnHdlr {
283 for (var integer i := 0; i < 500; i := i+1) {
284 f_rsl_chan_act(g_pars.chan_mode);
285 f_rsl_chan_deact();
286 }
287 setverdict(pass);
288}
289testcase TC_chan_act_stress() runs on test_CT {
290 var ConnHdlr vc_conn;
291 var ConnHdlrPars pars := valueof(t_Pars(t_RslChanNr_Bm(1), ts_RSL_ChanMode_SIGN));
292 f_init(testcasename());
293 vc_conn := f_start_handler(refers(f_TC_chan_act_stress), pars);
294 vc_conn.done;
295}
296
297/* Test if re-activation of an already active channel fails as expected */
298function f_TC_chan_act_react(charstring id) runs on ConnHdlr {
299 f_rsl_chan_act(g_pars.chan_mode);
300 /* attempt to activate the same lchan again -> expect reject */
301 RSL.send(ts_RSL_CHAN_ACT(g_chan_nr, g_pars.chan_mode));
302 alt {
303 [] RSL.receive(tr_RSL_CHAN_ACT_ACK(g_chan_nr)) {
304 setverdict(fail, "Unexpected CHAN ACT ACK on double activation");
305 }
306 [] RSL.receive(tr_RSL_CHAN_ACT_NACK(g_chan_nr)) {
307 setverdict(pass);
308 }
309 }
310 f_rsl_chan_deact();
311}
312testcase TC_chan_act_react() runs on test_CT {
313 var ConnHdlr vc_conn;
314 var ConnHdlrPars pars := valueof(t_Pars(t_RslChanNr_Bm(1), ts_RSL_ChanMode_SIGN));
315 f_init(testcasename());
316 vc_conn := f_start_handler(refers(f_TC_chan_act_react), pars);
317 vc_conn.done;
318}
319
320/* Attempt to de-activate a channel that's not active */
321function f_TC_chan_deact_not_active(charstring id) runs on ConnHdlr {
322 timer T := 3.0;
323 RSL.send(ts_RSL_RF_CHAN_REL(g_chan_nr));
324 T.start;
325 alt {
326 [] RSL.receive(tr_RSL_RF_CHAN_REL_ACK(g_chan_nr)) {
327 setverdict(pass);
328 }
329 [] T.timeout {
330 setverdict(fail, "Timeout expecting RF_CHAN_REL_ACK");
331 }
332 }
333}
334testcase TC_chan_deact_not_active() runs on test_CT {
335 var ConnHdlrPars pars := valueof(t_Pars(t_RslChanNr_Bm(1), ts_RSL_ChanMode_SIGN));
336 f_init(testcasename());
337 var ConnHdlr vc_conn := f_start_handler(refers(f_TC_chan_deact_not_active), pars);
338 vc_conn.done;
339}
340
341/* attempt to activate channel with wrong RSL Channel Nr IE; expect NACK */
342function f_TC_chan_act_wrong_nr(charstring id) runs on ConnHdlr {
343 RSL.send(ts_RSL_CHAN_ACT(g_chan_nr, g_pars.chan_mode));
344 alt {
345 [] RSL.receive(tr_RSL_CHAN_ACT_ACK(g_chan_nr)) {
346 setverdict(fail, "Unexpected CHAN ACT ACK");
347 }
348 [] RSL.receive(tr_RSL_CHAN_ACT_NACK(g_chan_nr)) {
349 setverdict(pass);
350 }
351 }
352}
353private type record WrongChanNrCase {
354 RslChannelNr chan_nr,
355 charstring description
356}
357private type record of WrongChanNrCase WrongChanNrCases;
358private template WrongChanNrCase t_WCN(template RslChannelNr chan_nr, charstring desc) := {
359 chan_nr := chan_nr,
360 description := desc
361}
362
363testcase TC_chan_act_wrong_nr() runs on test_CT {
364 var ConnHdlr vc_conn;
365 var ConnHdlrPars pars;
366
367 f_init(testcasename());
368
369 var WrongChanNrCases wrong := {
370 valueof(t_WCN(t_RslChanNr_RACH(0), "RACH is not a dedicated channel")),
371 valueof(t_WCN(t_RslChanNr_RACH(1), "RACH doesn't exist on timeslot")),
372 valueof(t_WCN(t_RslChanNr_BCCH(0), "BCCH is not a dedicated channel")),
373 valueof(t_WCN(t_RslChanNr_PCH_AGCH(0), "PCH/AGCH is not a dedicated channel")),
374 valueof(t_WCN(t_RslChanNr_Bm(0), "TS0 cannot be TCH/F")),
375 valueof(t_WCN(t_RslChanNr_Lm(0, 0), "TS0 cannot be TCH/H")),
376 valueof(t_WCN(t_RslChanNr_Lm(0, 1), "TS0 cannot be TCH/H")),
377 valueof(t_WCN(t_RslChanNr_PDCH(0), "TS0 cannot be PDCH")),
378 valueof(t_WCN(t_RslChanNr_SDCCH8(0, 0), "TS0 cannot be SDCCH/8")),
379 valueof(t_WCN(t_RslChanNr_SDCCH8(0, 7), "TS0 cannot be SDCCH/8")),
380 valueof(t_WCN(t_RslChanNr_SDCCH4(7, 0), "TS7 cannot be SDCCH/4")),
381 valueof(t_WCN(t_RslChanNr_SDCCH4(7, 3), "TS7 cannot be SDCCH/4")),
382 valueof(t_WCN(t_RslChanNr_Lm(1, 0), "TS1 cannot be TCH/H"))
383 };
384
385 for (var integer i := 0; i < sizeof(wrong); i := i+1) {
386 pars := valueof(t_Pars(wrong[i].chan_nr, ts_RSL_ChanMode_SIGN));
387 vc_conn := f_start_handler(refers(f_TC_chan_act_wrong_nr), pars);
388 vc_conn.done;
389 }
390}
391
392function f_TC_chan_req(charstring id) runs on ConnHdlr {
Harald Welte68e495b2018-02-25 00:05:57 +0100393 f_l1_tune(L1CTL);
Harald Welte70767382018-02-21 12:16:40 +0100394
395 RSL.clear;
396 //L1.send(DCCH_establish_req:{ra := 23});
397 /* This arrives on CCHAN, so we cannot test here */
398 //RSL.receive(tr_RSL_CHAN_RQD(int2oct(23,1)));
399}
400testcase TC_chan_req() runs on test_CT {
401 var ConnHdlr vc_conn;
402 var ConnHdlrPars pars := valueof(t_Pars(t_RslChanNr_Bm(1), ts_RSL_ChanMode_SIGN));
403 f_init(testcasename());
404 vc_conn := f_start_handler(refers(f_TC_chan_req), pars);
405 vc_conn.done;
406}
407
408template LapdmAddressField ts_LapdmAddr(LapdmSapi sapi, boolean c_r) := {
409 spare := '0'B,
410 lpd := 0,
411 sapi := sapi,
412 c_r := c_r,
413 ea := true
414}
415
416template LapdmFrameB ts_LAPDm_B(LapdmSapi sapi, boolean c_r, boolean p, octetstring pl) := {
417 addr := ts_LapdmAddr(sapi, c_r),
418 ctrl := t_LapdmCtrlUI(p),
419 len := 0, /* overwritten */
420 m := false,
421 el := 1,
422 payload := pl
423}
424
425/* handle incoming downlink SACCH and respond with uplink SACCH (meas res) */
426altstep as_l1_sacch() runs on ConnHdlr {
427 var L1ctlDlMessage l1_dl;
428 [] L1CTL.receive(t_L1CTL_DATA_IND(g_chan_nr, tr_RslLinkID_SACCH(?))) -> value l1_dl {
429 log("SACCH received: ", l1_dl.payload.data_ind.payload);
430 var GsmRrL3Message meas_rep := valueof(ts_MEAS_REP(true, 23, 23, 0, 0, omit));
431 var LapdmFrameB lb := valueof(ts_LAPDm_B(0, false, false, enc_GsmRrL3Message(meas_rep)));
432 log("LAPDm: ", lb);
433 var octetstring pl := '0000'O & enc_LapdmFrameB(lb);
434 L1CTL.send(t_L1CTL_DATA_REQ(g_chan_nr, ts_RslLinkID_SACCH(0), pl));
435 repeat;
436 }
437}
438
439altstep as_l1_dcch() runs on ConnHdlr {
440 var L1ctlDlMessage l1_dl;
441 [] L1CTL.receive(t_L1CTL_DATA_IND(g_chan_nr, tr_RslLinkID_DCCH(?))) -> value l1_dl {
442 log("DCCH received: ", l1_dl.payload.data_ind.payload);
443 var octetstring pl := '010301'O;
444 L1CTL.send(t_L1CTL_DATA_REQ(g_chan_nr, ts_RslLinkID_DCCH(0), pl));
445 repeat;
446 }
447}
448
449type record MeasElem {
450 uint6_t rxlev,
451 uint3_t rxqual
452}
453
454type record MeasElemFS {
455 MeasElem full,
456 MeasElem sub
457}
458
459type record ConnL1Pars {
460 boolean dtx_enabled,
461 MeasElemFS meas_ul,
462 int16_t timing_offset_256syms,
463 uint5_t bs_power_level,
464 uint5_t ms_power_level,
465 uint8_t ms_actual_ta
466}
467
468/* Convert tiing offset from 1/256th symbol to RSL Timing Offset */
469private function toffs256s_to_rsl(int16_t toffs256s) return uint8_t {
470 return 63 + (toffs256s/256);
471}
472
473/* build a template for matching measurement results against */
474private function f_build_meas_res_tmpl() runs on ConnHdlr return template RSL_Message {
475 var ConnL1Pars l1p := g_pars.l1_pars;
476 var template RSL_IE_UplinkMeas ul_meas := {
477 len := 3,
478 rfu := '0'B,
479 dtx_d := l1p.dtx_enabled,
480 rxlev_f_u := l1p.meas_ul.full.rxlev,
481 reserved1 := '00'B,
482 rxlev_s_u := l1p.meas_ul.sub.rxlev,
483 reserved2 := '00'B,
484 rxq_f_u := l1p.meas_ul.full.rxqual,
485 rxq_s_u := l1p.meas_ul.sub.rxqual,
486 supp_meas_info := omit
487 };
488 /* HACK HACK HACK FIXME HACK HACK HACK see https://osmocom.org/issues/2988 */
489 ul_meas.rxlev_f_u := ?;
490 ul_meas.rxlev_s_u := ?;
491 ul_meas.rxq_f_u := ?;
492 ul_meas.rxq_s_u := ?;
493 var template RSL_IE_BS_Power bs_power := {
494 reserved := 0,
495 epc := false,
496 fpc := false,
497 power_level := l1p.bs_power_level
498 };
499 var template RSL_IE_L1Info l1_info := {
500 ms_power_lvl := l1p.ms_power_level,
501 fpc := false,
502 reserved := 0,
503 actual_ta := l1p.ms_actual_ta
504 };
505 var uint8_t offs := toffs256s_to_rsl(l1p.timing_offset_256syms);
506 var template uint8_t t_toffs := (offs-1 .. offs+1); /* some tolerance */
507 return tr_RSL_MEAS_RES_OSMO(g_chan_nr, g_next_meas_res_nr, ul_meas, bs_power, l1_info,
508 ?, t_toffs);
509}
510
511/* verify we regularly receive measurement reports with incrementing numbers */
512altstep as_meas_res() runs on ConnHdlr {
513 var RSL_Message rsl;
514 [] RSL.receive(f_build_meas_res_tmpl()) -> value rsl {
515 /* increment counter of next to-be-expected meas rep */
516 g_next_meas_res_nr := (g_next_meas_res_nr + 1) mod 256;
517 /* Re-start the timer expecting the next MEAS RES */
518 g_Tmeas_exp.start;
519 repeat;
520 }
521 [] RSL.receive(tr_RSL_MEAS_RES(g_chan_nr, g_next_meas_res_nr)) -> value rsl {
522 setverdict(fail, "Received unspecific MEAS RES ", rsl);
523 self.stop;
524 }
525 [] RSL.receive(tr_RSL_MEAS_RES(?)) -> value rsl {
526 setverdict(fail, "Received unexpected MEAS RES ", rsl);
527 self.stop;
528 }
529 [] g_Tmeas_exp.timeout {
530 setverdict(fail, "Didn't receive expected measurement result")
531 self.stop;
532 }
533}
534
535/* Establish dedicated channel: L1CTL + RSL side */
536private function f_est_dchan() runs on ConnHdlr {
537 var GsmFrameNumber fn;
538 var ImmediateAssignment imm_ass;
539 var integer ra := 23;
540
541 fn := f_L1CTL_RACH(L1CTL, ra);
542 /* This arrives on CCHAN, so we cannot test for receiving CHAN RQDhere */
543 //RSL.receive(tr_RSL_CHAN_RQD(int2oct(23,1)));
544
545 /* Activate channel on BTS side */
546 f_rsl_chan_act(g_pars.chan_mode);
547
548 /* Send IMM.ASS via CCHAN */
549 var ChannelDescription ch_desc := {
550 chan_nr := g_pars.chan_nr,
551 tsc := 7,
552 h := false,
553 arfcn := mp_trx0_arfcn,
554 maio_hsn := omit
555 };
556 var MobileAllocation ma := {
557 len := 0,
558 ma := ''B
559 };
560 var GsmRrMessage rr_msg := valueof(ts_IMM_ASS(ra, fn, 0, ch_desc, ma));
561 RSL.send(ts_RSL_IMM_ASSIGN(enc_GsmRrMessage(rr_msg)));
562
563 /* receive IMM.ASS on MS side */
564 var ImmediateAssignment ia_um;
565 ia_um := f_L1CTL_WAIT_IMM_ASS(L1CTL, ra, fn);
566 /* enable dedicated mode */
567 f_L1CTL_DM_EST_REQ_IA(L1CTL, ia_um);
568}
569
570/* establish DChan, verify existance + contents of measurement reports */
571function f_TC_meas_res_periodic(charstring id) runs on ConnHdlr {
Harald Welte68e495b2018-02-25 00:05:57 +0100572 f_l1_tune(L1CTL);
Harald Welte70767382018-02-21 12:16:40 +0100573 RSL.clear;
574
575 g_pars.l1_pars.meas_ul.full.rxlev := dbm2rxlev(-100);
576 g_pars.l1_pars.meas_ul.sub.rxlev := g_pars.l1_pars.meas_ul.full.rxlev;
577 f_trxc_fake_rssi(100);
578
579 g_pars.l1_pars.timing_offset_256syms := 512; /* 2 symbols */
580 f_trx_fake_toffs256(g_pars.l1_pars.timing_offset_256syms);
581
582 f_est_dchan();
583
584 /* run for a number of seconds, send SACCH + FACCH from MS side and verify
585 * RSL measurement reports on Abis side */
586 timer T := 8.0;
587 T.start;
588 alt {
589 [] as_l1_sacch();
590 [] as_meas_res();
591 [] as_l1_dcch();
592 [] L1CTL.receive { repeat; }
593 [g_Tmeas_exp.running] T.timeout {
594 /* as_meas_res() would have done setverdict(fail) / self.stop in case
595 * of any earlier errors, so if we reach this timeout, we're good */
596 setverdict(pass);
597 }
598 [] T.timeout {
599 setverdict(fail, "No MEAS RES received at all");
600 }
601 }
602 f_rsl_chan_deact();
603}
604testcase TC_meas_res_sign_tchf() runs on test_CT {
605 var ConnHdlr vc_conn;
606 var ConnHdlrPars pars;
607 f_init(testcasename());
608 for (var integer tn := 1; tn <= 4; tn := tn+1) {
609 pars := valueof(t_Pars(t_RslChanNr_Bm(tn), ts_RSL_ChanMode_SIGN));
610 vc_conn := f_start_handler(refers(f_TC_meas_res_periodic), pars);
611 vc_conn.done;
612 }
613}
614testcase TC_meas_res_sign_tchh() runs on test_CT {
615 var ConnHdlr vc_conn;
616 var ConnHdlrPars pars;
617 f_init(testcasename());
618 for (var integer ss := 0; ss <= 1; ss := ss+1) {
619 pars := valueof(t_Pars(t_RslChanNr_Lm(5, ss), ts_RSL_ChanMode_SIGN));
620 vc_conn := f_start_handler(refers(f_TC_meas_res_periodic), pars);
621 vc_conn.done;
622 }
623}
624testcase TC_meas_res_sign_sdcch4() runs on test_CT {
625 var ConnHdlr vc_conn;
626 var ConnHdlrPars pars;
627 f_init(testcasename());
628 for (var integer ss := 0; ss <= 3; ss := ss+1) {
629 pars := valueof(t_Pars(t_RslChanNr_SDCCH4(0, ss), ts_RSL_ChanMode_SIGN));
630 vc_conn := f_start_handler(refers(f_TC_meas_res_periodic), pars);
631 vc_conn.done;
632 }
633}
634testcase TC_meas_res_sign_sdcch8() runs on test_CT {
635 var ConnHdlr vc_conn;
636 var ConnHdlrPars pars;
637 f_init(testcasename());
638 for (var integer ss := 0; ss <= 7; ss := ss+1) {
639 pars := valueof(t_Pars(t_RslChanNr_SDCCH8(6, ss), ts_RSL_ChanMode_SIGN));
640 vc_conn := f_start_handler(refers(f_TC_meas_res_periodic), pars);
641 vc_conn.done;
642 }
643}
644
645/* Test if a channel without valid uplink bursts generates RSL CONN FAIL IND */
646private function f_TC_conn_fail_crit(charstring id) runs on ConnHdlr {
Harald Welte68e495b2018-02-25 00:05:57 +0100647 f_l1_tune(L1CTL);
Harald Welte70767382018-02-21 12:16:40 +0100648 RSL.clear;
649
650 f_est_dchan();
651 f_sleep(2.0);
652 L1CTL.send(t_L1CTL_DM_REL_REQ(g_chan_nr));
653
654 timer T := 40.0;
655 T.start;
656 alt {
657 [] RSL.receive(tr_RSL_CONN_FAIL_IND(g_chan_nr, ?)) {
658 setverdict(pass)
659 }
660 [] RSL.receive { repeat };
661 [] T.timeout {
662 setverdict(fail, "No CONN FAIL IND received");
663 }
664 }
665 f_rsl_chan_deact();
666}
667testcase TC_conn_fail_crit() runs on test_CT {
668 var ConnHdlr vc_conn;
669 var ConnHdlrPars pars;
670 f_init(testcasename());
671 pars := valueof(t_Pars(t_RslChanNr_SDCCH8(6, 3), ts_RSL_ChanMode_SIGN));
672 pars.t_guard := 60.0;
673 vc_conn := f_start_handler(refers(f_TC_conn_fail_crit), pars);
674 vc_conn.done;
675}
676
Harald Welte68e495b2018-02-25 00:05:57 +0100677function tmsi_is_dummy(TMSIP_TMSI_V tmsi) return boolean {
678 if (tmsi == 'FFFFFFFF'O) {
679 return true;
680 } else {
681 return false;
682 }
683}
Harald Welte70767382018-02-21 12:16:40 +0100684
685
Harald Welte68e495b2018-02-25 00:05:57 +0100686altstep as_l1_count_paging(inout integer num_paging_rcv_msgs, inout integer num_paging_rcv_ids)
687runs on test_CT {
688 var L1ctlDlMessage dl;
689 [] L1CTL.receive(t_L1CTL_DATA_IND(t_RslChanNr_PCH_AGCH(0), ?, c_DummyUI)) {
690 repeat;
691 }
692 [] L1CTL.receive(t_L1CTL_DATA_IND(t_RslChanNr_PCH_AGCH(0))) -> value dl {
693 var octetstring without_plen :=
694 substr(dl.payload.data_ind.payload, 1, lengthof(dl.payload.data_ind.payload)-1);
695 var PDU_ML3_NW_MS rr := dec_PDU_ML3_NW_MS(without_plen);
696 if (match(rr, tr_PAGING_REQ1)) {
697 num_paging_rcv_msgs := num_paging_rcv_msgs + 1;
698 num_paging_rcv_ids := num_paging_rcv_ids + 1;
699 if (isvalue(rr.msgs.rrm.pagingReq_Type1.mobileIdentity2)) {
700 num_paging_rcv_ids := num_paging_rcv_ids + 1;
701 }
702 } else if (match(rr, tr_PAGING_REQ2)) {
703 num_paging_rcv_msgs := num_paging_rcv_msgs + 1;
704 if (not tmsi_is_dummy(rr.msgs.rrm.pagingReq_Type2.mobileIdentity1)) {
705 num_paging_rcv_ids := num_paging_rcv_ids + 1;
706 }
707 if (not tmsi_is_dummy(rr.msgs.rrm.pagingReq_Type2.mobileIdentity2)) {
708 num_paging_rcv_ids := num_paging_rcv_ids + 1;
709 }
710 if (isvalue(rr.msgs.rrm.pagingReq_Type2.mobileIdentity3)) {
711 num_paging_rcv_ids := num_paging_rcv_ids + 1;
712 }
713 } else if (match(rr, tr_PAGING_REQ3)) {
714 num_paging_rcv_msgs := num_paging_rcv_msgs + 1;
715 if (not tmsi_is_dummy(rr.msgs.rrm.pagingReq_Type3.mobileIdentity1)) {
716 num_paging_rcv_ids := num_paging_rcv_ids + 1;
717 }
718 if (not tmsi_is_dummy(rr.msgs.rrm.pagingReq_Type3.mobileIdentity2)) {
719 num_paging_rcv_ids := num_paging_rcv_ids + 1;
720 }
721 if (not tmsi_is_dummy(rr.msgs.rrm.pagingReq_Type3.mobileIdentity3)) {
722 num_paging_rcv_ids := num_paging_rcv_ids + 1;
723 }
724 if (not tmsi_is_dummy(rr.msgs.rrm.pagingReq_Type3.mobileIdentity4)) {
725 num_paging_rcv_ids := num_paging_rcv_ids + 1;
726 }
727 }
728 repeat;
729 }
730}
731
732type record PagingTestCfg {
733 boolean combined_ccch,
734 integer bs_ag_blks_res,
735 float load_factor,
736 boolean exp_load_ind,
737 boolean exp_overload,
738 boolean use_tmsi
739}
740
741type record PagingTestState {
742 integer num_paging_sent,
743 integer num_paging_rcv_msgs,
744 integer num_paging_rcv_ids,
745 integer num_overload
746}
747
748/* receive + ignore RSL RF RES IND */
749altstep as_rsl_res_ind() runs on test_CT {
750 [] RSL_CCHAN.receive(tr_RSL_UD(tr_RSL_RF_RES_IND)) {
751 repeat;
752 }
753}
754
755/* Helper function for paging related testing */
756private function f_TC_paging(PagingTestCfg cfg) runs on test_CT return PagingTestState {
757 f_init(testcasename());
758 f_init_l1ctl();
759 f_l1_tune(L1CTL);
760
761 var PagingTestState st := {
762 num_paging_sent := 0,
763 num_paging_rcv_msgs := 0,
764 num_paging_rcv_ids := 0,
765 num_overload := 0
766 };
767
768 var float max_pch_blocks_per_sec := f_pch_block_rate_est(cfg.combined_ccch, cfg.bs_ag_blks_res);
769 var float max_pch_imsi_per_sec;
770 if (cfg.use_tmsi) {
771 max_pch_imsi_per_sec := max_pch_blocks_per_sec * 4.0; /* Type 3 */
772 } else {
773 max_pch_imsi_per_sec := max_pch_blocks_per_sec * 2.0; /* Type 1 */
774 }
775 var float pch_blocks_per_sec := max_pch_imsi_per_sec * cfg.load_factor;
776 var float interval := 1.0 / pch_blocks_per_sec;
777 log("pch_blocks_per_sec=", pch_blocks_per_sec, " interval=", interval);
778
779 for (var integer i := 0; i < float2int(20.0/interval); i := i+1) {
780 /* build mobile Identity */
781 var MobileL3_CommonIE_Types.MobileIdentityLV mi;
782 if (cfg.use_tmsi) {
783 mi := valueof(ts_MI_TMSI_LV(f_rnd_octstring(4)));
784 } else {
785 mi := valueof(ts_MI_IMSI_LV(f_gen_imsi(i)));
786 }
787 var octetstring mi_enc_lv := enc_MobileIdentityLV(mi);
788 var octetstring mi_enc := substr(mi_enc_lv, 1, lengthof(mi_enc_lv)-1);
789
790 /* Send RSL PAGING COMMAND */
791 RSL_CCHAN.send(ts_RSL_UD(ts_RSL_PAGING_CMD(mi_enc, i mod 4)));
792 st.num_paging_sent := st.num_paging_sent + 1;
793
794 /* Wait for interval to next PAGING COMMAND */
795 timer T_itv := interval;
796 T_itv.start;
797 alt {
798 /* check for presence of CCCH LOAD IND (paging load) */
799 [cfg.exp_overload] RSL_CCHAN.receive(tr_RSL_UD(tr_RSL_PAGING_LOAD_IND(0))) {
800 st.num_overload := st.num_overload + 1;
801 repeat;
802 }
803 [not cfg.exp_overload] RSL_CCHAN.receive(tr_RSL_UD(tr_RSL_PAGING_LOAD_IND(0))) {
804 setverdict(fail, "Unexpected PCH Overload");
805 }
806 [cfg.exp_load_ind] RSL_CCHAN.receive(tr_RSL_UD(tr_RSL_PAGING_LOAD_IND)) {
807 log("Rx LOAD_IND");
808 /* FIXME: analyze/verify interval + contents */
809 repeat;
810 }
811 /* check if paging requests arrive on Um side */
812 [] as_l1_count_paging(st.num_paging_rcv_msgs, st.num_paging_rcv_ids);
813 [] L1CTL.receive { repeat; }
814 [] T_itv.timeout { }
815 [] as_rsl_res_ind();
816 }
817 }
818
819 /* wait for max 18s for paging queue to drain (size: 200, ~ 13 per s -> 15s) */
820 timer T_wait := 18.0;
821 T_wait.start;
822 alt {
823 [] as_l1_count_paging(st.num_paging_rcv_msgs, st.num_paging_rcv_ids);
824 [] L1CTL.receive { repeat; }
825 /* 65535 == empty paging queue, we can terminate*/
826 [] RSL_CCHAN.receive(tr_RSL_UD(tr_RSL_PAGING_LOAD_IND(65535))) { }
827 [] RSL_CCHAN.receive(tr_RSL_UD(tr_RSL_PAGING_LOAD_IND)) { repeat; }
828 [] T_wait.timeout {
829 setverdict(fail, "Waiting for empty paging queue");
830 }
831 [] as_rsl_res_ind();
832 }
833
834 log("num_paging_sent=", st.num_paging_sent, " rcvd_msgs=", st.num_paging_rcv_msgs,
835 " rcvd_ids=", st.num_paging_rcv_ids);
836 return st;
837}
838
839/* Create ~ 80% paging load (IMSI only) sustained for about 20s, verifying that
840 * - the number of Mobile Identities on Um PCH match the number of pages on RSL
841 * - that CCCH LOAD IND (PCH) are being generated
842 * - that CCCH LOAD IND (PCH) [no load] is received after paging flood is over */
843testcase TC_paging_imsi_80percent() runs on test_CT {
844 var PagingTestCfg cfg := {
845 combined_ccch := true,
846 bs_ag_blks_res := 1,
847 load_factor := 0.8,
848 exp_load_ind := true,
849 exp_overload := false,
850 use_tmsi := false
851 };
852 var PagingTestState st := f_TC_paging(cfg);
853 if (st.num_paging_sent != st.num_paging_rcv_ids) {
854 setverdict(fail, "Expected ", st.num_paging_sent, " pagings but have ",
855 st.num_paging_rcv_ids);
856 } else {
857 setverdict(pass);
858 }
859}
860
861/* Create ~ 80% paging load (TMSI only) sustained for about 20s, verifying that
862 * - the number of Mobile Identities on Um PCH match the number of pages on RSL
863 * - that CCCH LOAD IND (PCH) are being generated
864 * - that CCCH LOAD IND (PCH) [no load] is received after paging flood is over */
865testcase TC_paging_tmsi_80percent() runs on test_CT {
866 var PagingTestCfg cfg := {
867 combined_ccch := true,
868 bs_ag_blks_res := 1,
869 load_factor := 0.8,
870 exp_load_ind := true,
871 exp_overload := false,
872 use_tmsi := true
873 };
874 var PagingTestState st := f_TC_paging(cfg);
875 if (st.num_paging_sent != st.num_paging_rcv_ids) {
876 setverdict(fail, "Expected ", st.num_paging_sent, " pagings but have ",
877 st.num_paging_rcv_ids);
878 } else {
879 setverdict(pass);
880 }
881}
882
883/* Create ~ 200% paging load (IMSI only) sustained for about 20s, verifying that
884 * - the number of Mobile Identities on Um PCH are ~ 82% of the number of pages on RSL
885 * - that CCCH LOAD IND (PCH) are being generated and reach 0 at some point
886 * - that CCCH LOAD IND (PCH) [no load] is received after paging flood is over */
887testcase TC_paging_imsi_200percent() runs on test_CT {
888 var PagingTestCfg cfg := {
889 combined_ccch := true,
890 bs_ag_blks_res := 1,
891 load_factor := 2.0,
892 exp_load_ind := true,
893 exp_overload := true,
894 use_tmsi := false
895 };
896 var PagingTestState st := f_TC_paging(cfg);
897 /* We expect about 80-85% to pass, given that we can fill the paging buffer of 200
898 * slots and will fully drain that buffer before returning */
899 var template integer tpl := (st.num_paging_sent*80/100 .. st.num_paging_sent *85/100);
900 if (not match(st.num_paging_rcv_ids, tpl)) {
901 setverdict(fail, "Expected ", tpl, " pagings but have ", st.num_paging_rcv_ids);
902 } else {
903 setverdict(pass);
904 }
905}
906
907/* Create ~ 200% paging load (TMSI only) sustained for about 20s, verifying that
908 * - the number of Mobile Identities on Um PCH are ~ 82% of the number of pages on RSL
909 * - that CCCH LOAD IND (PCH) are being generated and reach 0 at some point
910 * - that CCCH LOAD IND (PCH) [no load] is received after paging flood is over */
911testcase TC_paging_tmsi_200percent() runs on test_CT {
912 var PagingTestCfg cfg := {
913 combined_ccch := true,
914 bs_ag_blks_res := 1,
915 load_factor := 2.0,
916 exp_load_ind := true,
917 exp_overload := true,
918 use_tmsi := true
919 };
920 var PagingTestState st := f_TC_paging(cfg);
921 /* We expect about 70% to pass, given that we can fill the paging buffer of 200
922 * slots and will fully drain that buffer before returning */
923 var template integer tpl := (st.num_paging_sent*68/100 .. st.num_paging_sent *72/100);
924 if (not match(st.num_paging_rcv_ids, tpl)) {
925 setverdict(fail, "Expected ", tpl, " pagings but have ", st.num_paging_rcv_ids);
926 } else {
927 setverdict(pass);
928 }
929}
930
931
932testcase TC_imm_ass() runs on test_CT {
933 f_init(testcasename());
934 for (var integer i := 0; i < 1000; i := i+1) {
935 var octetstring ia_enc := f_rnd_octstring(8);
936 RSL_CCHAN.send(ts_RSL_UD(ts_RSL_IMM_ASSIGN(ia_enc, 0)));
937 f_sleep(0.02);
938 }
939 /* FIXME: check if imm.ass arrive on Um side */
940 /* FIXME: check for DELETE INDICATION */
941 f_sleep(100.0);
942}
943
944testcase TC_bcch_info() runs on test_CT {
945 f_init(testcasename());
946 /* FIXME: enable / disable individual BCCH info */
947 //ts_RSL_BCCH_INFO(si_type, info);
948 /* expect no ERROR REPORT after either of them *
949 /* negative test: ensure ERROR REPORT on unsupported types */
950}
951
Harald Welte01d982c2018-02-25 01:31:40 +0100952private function f_exp_err_rep(template RSL_Cause cause) runs on test_CT {
953 timer T := 5.0;
954 T.start;
955 alt {
956 [] RSL_CCHAN.receive(tr_RSL_UD(tr_RSL_ERROR_REPORT(cause))) {
957 setverdict(pass);
958 }
959 [] RSL_CCHAN.receive(tr_RSL_UD(tr_RSL_ERROR_REPORT(?))) {
960 setverdict(fail, "Wrong cause in RSL ERR REP");
961 }
962 [] RSL_CCHAN.receive {
963 repeat;
964 }
965 [] T.timeout {
966 setverdict(fail, "Timeout waiting for RSL ERR REP");
967 }
968 }
969}
970
971/* Provoke a protocol error (message too short) and match on ERROR REPORT */
972testcase TC_rsl_protocol_error() runs on test_CT {
973 f_init(testcasename());
974 var RSL_Message rsl := valueof(ts_RSL_BCCH_INFO(RSL_SYSTEM_INFO_1, ''O));
975 rsl.ies := omit;
976 RSL_CCHAN.send(ts_RSL_UD(rsl));
977
978 f_exp_err_rep(RSL_ERR_PROTO);
979}
980
981/* Provoke a mandatory IE error and match on ERROR REPORT */
982testcase TC_rsl_mand_ie_error() runs on test_CT {
983 f_init(testcasename());
984
985 var RSL_Message rsl := valueof(ts_RSL_BCCH_INFO(RSL_SYSTEM_INFO_1, ''O));
986 rsl.ies := { rsl.ies[0] };
987 RSL_CCHAN.send(ts_RSL_UD(rsl));
988
989 f_exp_err_rep(RSL_ERR_MAND_IE_ERROR);
990}
991
992/* Provoke an IE content error and match on ERROR REPORT */
993testcase TC_rsl_ie_content_error() runs on test_CT {
994 f_init(testcasename());
995 var RSL_Message rsl := valueof(ts_RSL_BCCH_INFO(RSL_SYSTEM_INFO_1, ''O));
996 rsl.ies[1].body.sysinfo_type := RSL_SYSTEM_INFO_5;
997 RSL_CCHAN.send(ts_RSL_UD(rsl));
998
999 f_exp_err_rep(RSL_ERR_IE_CONTENT);
1000}
1001
Harald Welte68e495b2018-02-25 00:05:57 +01001002
1003/* TODO Areas:
1004
1005* channel activation
1006** with BS_Power / MS_Power, bypassing power control loop
1007** on primary vs. secondary TRX
1008** with encryption from initial activation on
1009** with timing advance from initial activation on
1010* mode modify
1011** encryption
1012** multirate
1013* check DEACTIVATE SACCH
1014* encryption command / intricate logic about tx-only/tx+rx/...
1015** unsupported algorithm
1016* handover detection
1017* MS Power Control
1018* BS Power Control
1019* Physical Context
1020* SACCH info modify
1021* BCCH INFO (SI Broadcasting)
1022* CCCH Load Indication for PCH and RACH
1023* Delete Indication on AGCH overflow
1024* SMS Broadcast Req / Cmd / CBCH LOad Ind
1025* RF resource ind
1026* IPA/speech related commands
1027* error handling
1028* discriminator error
1029** type error
1030** sequence error
1031** IE duplicated?
Harald Welte68e495b2018-02-25 00:05:57 +01001032
1033*/
Harald Welte70767382018-02-21 12:16:40 +01001034
1035control {
1036 execute( TC_chan_act_stress() );
1037 execute( TC_chan_act_react() );
1038 execute( TC_chan_deact_not_active() );
1039 execute( TC_chan_act_wrong_nr() );
1040 execute( TC_chan_req() );
1041 execute( TC_meas_res_sign_tchf() );
1042 execute( TC_meas_res_sign_tchh() );
1043 execute( TC_meas_res_sign_sdcch4() );
1044 execute( TC_meas_res_sign_sdcch8() );
1045 execute( TC_conn_fail_crit() );
Harald Welte68e495b2018-02-25 00:05:57 +01001046 execute( TC_paging_imsi_80percent() );
1047 execute( TC_paging_tmsi_80percent() );
1048 execute( TC_paging_imsi_200percent() );
1049 execute( TC_paging_tmsi_200percent() );
Harald Welte01d982c2018-02-25 01:31:40 +01001050 execute( TC_rsl_protocol_error() );
1051 execute( TC_rsl_mand_ie_error() );
1052 execute( TC_rsl_ie_content_error() );
Harald Welte70767382018-02-21 12:16:40 +01001053}
1054
1055
1056}