blob: 92e80940df900dfcf3c84625fe8771fb0bbb4eb2 [file] [log] [blame]
Harald Welte505cf9b2018-09-15 17:47:23 +03001module BTS_Tests_SMSCB {
2
3/* Integration Tests for OsmoBTS
4 * (C) 2019 by Harald Welte <laforge@gnumonks.org>
5 * All rights reserved.
6 *
7 * Released under the terms of GNU General Public License, Version 2 or
8 * (at your option) any later version.
9 *
Harald Welte34b5a952019-05-27 11:54:11 +020010 * SPDX-License-Identifier: GPL-2.0-or-later
11 *
Harald Welte505cf9b2018-09-15 17:47:23 +030012 * This test suite tests the SMSCB (Cell Broadcast) related functionality of
13 * OsmoBTS by attaching to the A-bis RSL and Um interface and emulating both
14 * BSC and MS.
15 */
16
17import from Misc_Helpers all;
18import from General_Types all;
19import from Osmocom_Types all;
20import from GSM_Types all;
21import from L1CTL_PortType all;
22import from L1CTL_Types all;
23import from LAPDm_Types all;
Harald Welte4a129f82019-05-21 16:35:22 +020024import from IPA_Emulation all;
Harald Welte908ce542019-09-04 23:05:40 +020025import from GSM_RR_Types all;
Vadim Yanitskiya9a198d2020-03-28 05:11:26 +070026import from L3_Templates all;
Harald Welte505cf9b2018-09-15 17:47:23 +030027
28import from RSL_Types all;
29
Harald Welte11b734c2019-09-05 14:17:54 +020030import from PCUIF_Types all;
31import from PCUIF_CodecPort all;
32
Harald Welte505cf9b2018-09-15 17:47:23 +030033import from Osmocom_VTY_Functions all;
34
35import from BTS_Tests all;
36
37/***********************************************************************
38 * Cell Broadcast related tests
39 ***********************************************************************/
40
Harald Weltea3ff6702019-05-20 20:03:50 +020041/* Test parameters for one channel (e.g. Basic, Extended) */
42type record CbchTestParsChan {
43 /* list of "normal" (sent-once) SMSCB messages */
44 CbchTestMsgs msgs,
45 /* default message, if any */
46 CbchTestMsg default_msg optional
47}
48
49private template (value) CbchTestParsChan
50t_CbchPC(template (value) CbchTestMsgs msgs, template (omit) CbchTestMsg def := omit) := {
51 msgs := msgs,
52 default_msg := def
53}
54
55/* CBCH test parameters for most of our tests */
Harald Welte505cf9b2018-09-15 17:47:23 +030056type record CbchTestPars {
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +070057 /* Should we execute on SDCCH4 or SDCCH8? */
58 RslChannelNr chan_nr,
Harald Weltea3ff6702019-05-20 20:03:50 +020059 /* Parameters for BASIC CBCH */
60 CbchTestParsChan basic,
61 /* Parameters for EXTENDED CBCH */
62 CbchTestParsChan extended optional
Harald Welte505cf9b2018-09-15 17:47:23 +030063};
64
65type record CbchTestMsg {
66 /* config / input data */
67 RSL_CbCommand rsl_cb_cmd,
68 uint2_t last_block, /* 0..3 */
69 octetstring payload,
70 /* computed / result data */
71 CbchBlocks blocks optional
72};
73type record of CbchTestMsg CbchTestMsgs;
74
75/* a single 22byte block within a CbchTestMsg */
76type record CbchBlock {
77 uint4_t seq_nr, /* as per TS 04.12 */
78 boolean is_last,
79 OCT22 payload,
80 boolean seen_once
81};
82type record of CbchBlock CbchBlocks;
83
84/* compute the expected blocks for given test parameters */
85private function f_cbch_compute_exp_blocks(inout CbchTestPars pars) {
Harald Weltea3ff6702019-05-20 20:03:50 +020086 f_cbch_compute_exp_blocks_chan(pars.basic);
87 if (ispresent(pars.extended)) {
88 f_cbch_compute_exp_blocks_chan(pars.extended);
89 }
90}
91private function f_cbch_compute_exp_blocks_chan(inout CbchTestParsChan pars_chan) {
Harald Welte505cf9b2018-09-15 17:47:23 +030092 var integer i;
Harald Weltea3ff6702019-05-20 20:03:50 +020093 for (i := 0; i < lengthof(pars_chan.msgs); i := i+1) {
94 pars_chan.msgs[i].blocks := f_comp_blocks(pars_chan.msgs[i]);
95 }
96 if (ispresent(pars_chan.default_msg)) {
97 pars_chan.default_msg.blocks := f_comp_blocks(pars_chan.default_msg);
Harald Welte505cf9b2018-09-15 17:47:23 +030098 }
99}
100private function f_comp_blocks(in CbchTestMsg msg) return CbchBlocks {
101 var CbchBlocks blocks := {};
102 var integer i;
103
104 for (i := 0; i <= msg.last_block; i := i+1) {
105 var CbchBlock block := {
106 seq_nr := i,
107 is_last := false,
108 payload := substr(msg.payload, 22*i, 22),
109 seen_once := false
110 };
111 if (msg.rsl_cb_cmd == RSL_CB_CMD_SCHEDULE and i == 0) {
112 block.seq_nr := 8;
113 }
114 if (i == msg.last_block) {
115 block.is_last := true;
116 }
117 blocks := blocks & {block};
118 }
119
120 return blocks;
121};
122
123/* TS 48.058 Section 9.3.41 */
124private function f_cbch_block_nr2rsl(uint2_t nr) return uint2_t {
125 select (nr) {
126 case (0) { return 1; }
127 case (1) { return 2; }
128 case (2) { return 3; }
129 case (3) { return 0; }
130 }
131 setverdict(fail, "Invalid block number");
132 mtc.stop;
133}
134
Harald Welte88e5dff2019-05-20 15:14:46 +0200135private function f_cbch_fn2tb(uint32_t fn) return integer
136{
137 return (fn/51) mod 8; /* TS 05.02 Section 6.5.4 */
138}
139
Harald Welte505cf9b2018-09-15 17:47:23 +0300140/* Verify the CBCH TB scheduling rules of TS 05.02 Section 6.5.4 */
141private function f_cbch_fn_verify(uint32_t fn, CBCH_Block cb)
142{
Harald Welte88e5dff2019-05-20 15:14:46 +0200143 var integer tb := f_cbch_fn2tb(fn);
Harald Welte505cf9b2018-09-15 17:47:23 +0300144 if (cb.block_type.seq_nr == 15 /* null */) {
145 /* always permitted */
146 return;
147 } else if (cb.block_type.seq_nr == 8 /* schedule */) {
148 if (tb != 0) {
149 setverdict(fail, "Schedule block at TB=", tb);
150 }
151 } else if (cb.block_type.seq_nr < 4) {
152 if (cb.block_type.seq_nr != tb and cb.block_type.seq_nr+4 != tb) {
153 setverdict(fail, "Normal block at wrong TB=", tb, ": ", cb);
154 }
155 }
156}
157
Harald Weltedf4d0f02019-05-20 16:04:11 +0200158private function f_rsl_smscb_default_null() runs on test_CT
159{
160 var RSL_IE_CbCommandType cmd_type :=
161 valueof(ts_RSL_IE_CbCmdType(RSL_CB_CMD_DEFAULT, 1, true));
Vadim Yanitskiy493abe72020-05-25 22:03:48 +0700162 RSL_CCHAN.send(ts_ASP_RSL_UD(ts_RSL_SMSCB_CMD(cmd_type, ''O)));
Harald Weltedf4d0f02019-05-20 16:04:11 +0200163}
164
Harald Weltea3ff6702019-05-20 20:03:50 +0200165template RSL_IE t_RSL_IE_SMSCB_EXT := t_RSL_IE(RSL_IE_SMSCB_CHAN_INDICATOR, {smscb_chan_ind := 1});
166
167private function f_smscb_setup_rsl_chan(inout CbchTestParsChan pars_chan, boolean extd := false)
168runs on test_CT {
Harald Welte88e5dff2019-05-20 15:14:46 +0200169 var integer i;
Harald Weltea3ff6702019-05-20 20:03:50 +0200170 var CbchTestMsg msg;
171 var uint2_t rsl_last_block;
172 var RSL_IE_CbCommandType cmd_type;
173 var RSL_Message rsl;
174
175 /* send SMSCB[s] via RSL */
176 for (i := 0; i < lengthof(pars_chan.msgs); i := i+1) {
177 msg := pars_chan.msgs[i];
178 rsl_last_block := f_cbch_block_nr2rsl(msg.last_block);
179 cmd_type := valueof(ts_RSL_IE_CbCmdType(msg.rsl_cb_cmd, rsl_last_block));
180 rsl := valueof(ts_RSL_SMSCB_CMD(cmd_type, msg.payload));
181 if (extd) {
182 rsl.ies := rsl.ies & { valueof(t_RSL_IE_SMSCB_EXT) };
183 }
Vadim Yanitskiy493abe72020-05-25 22:03:48 +0700184 RSL_CCHAN.send(ts_ASP_RSL_UD(rsl));
Harald Weltea3ff6702019-05-20 20:03:50 +0200185 }
186 if (ispresent(pars_chan.default_msg)) {
187 msg := pars_chan.default_msg;
188 rsl_last_block := f_cbch_block_nr2rsl(msg.last_block);
189 cmd_type := valueof(ts_RSL_IE_CbCmdType(msg.rsl_cb_cmd, rsl_last_block, false));
190 rsl := valueof(ts_RSL_SMSCB_CMD(cmd_type, msg.payload));
191 if (extd) {
192 rsl.ies := rsl.ies & { valueof(t_RSL_IE_SMSCB_EXT) };
193 }
Vadim Yanitskiy493abe72020-05-25 22:03:48 +0700194 RSL_CCHAN.send(ts_ASP_RSL_UD(rsl));
Harald Weltea3ff6702019-05-20 20:03:50 +0200195 }
196}
Harald Welte505cf9b2018-09-15 17:47:23 +0300197
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700198private function f_vty_cbch_setup(in RslChannelNr chan_nr) runs on test_CT {
Harald Welte505cf9b2018-09-15 17:47:23 +0300199
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700200 if (match(chan_nr, t_RslChanNr_CBCH4(0))) {
201 f_vty_config2(BSCVTY, { "network", "bts 0", "trx 0", "timeslot 0"},
Harald Welte505cf9b2018-09-15 17:47:23 +0300202 "phys_chan_config CCCH+SDCCH4+CBCH");
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700203 /* (Re)configure timeslots 1..3 as TCH/F */
204 for (var integer tn := 1; tn <= 3; tn := tn + 1) {
205 f_vty_config2(BSCVTY, { "network", "bts 0", "trx 0",
206 "timeslot " & int2str(tn) },
207 "phys_chan_config TCH/F");
208 }
209 } else if (match(chan_nr, t_RslChanNr_CBCH8(?))) {
210 f_vty_config2(BSCVTY, { "network", "bts 0", "trx 0", "timeslot 0"},
Harald Welte505cf9b2018-09-15 17:47:23 +0300211 "phys_chan_config CCCH+SDCCH4");
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700212 f_vty_config2(BSCVTY, { "network", "bts 0", "trx 0",
213 "timeslot " & int2str(chan_nr.tn) },
Harald Welte505cf9b2018-09-15 17:47:23 +0300214 "phys_chan_config SDCCH8+CBCH");
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700215
216 /* (Re)configure timeslots 1..3 (excluding the given one) as TCH/F */
217 for (var integer tn := 1; tn <= 3; tn := tn + 1) {
218 if (tn == chan_nr.tn)
219 { continue; }
220 f_vty_config2(BSCVTY, { "network", "bts 0", "trx 0",
221 "timeslot " & int2str(tn) },
222 "phys_chan_config TCH/F");
223 }
Harald Welte505cf9b2018-09-15 17:47:23 +0300224 }
225 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
226 f_sleep(2.0);
Harald Welte4a129f82019-05-21 16:35:22 +0200227}
228private function f_smscb_setup(inout CbchTestPars pars) runs on test_CT {
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700229 /* Make sure we've got either SDCCH4+CBCH or SDCCH8+CBCH.
230 * SDCCH4+CBCH can only be allocated on TS0, SDCCH8+CBCH on TS0..3.
231 * On C0 the first timeslot shall always transmit BCCH, thus TS1..3.*/
232 if (not match(pars.chan_nr, (t_RslChanNr_CBCH4(0), t_RslChanNr_CBCH8(1),
233 t_RslChanNr_CBCH8(2), t_RslChanNr_CBCH8(3)))) {
234 setverdict(inconc, "Unhandled channel number: ", pars.chan_nr);
235 mtc.stop;
236 }
Harald Welte4a129f82019-05-21 16:35:22 +0200237
238 f_cbch_compute_exp_blocks(pars);
239
240 f_init_vty_bsc();
241 /* ensure that a CBCH is present in channel combination */
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700242 f_vty_cbch_setup(pars.chan_nr);
Harald Welte10474062019-05-30 16:48:17 +0200243 f_init();
Harald Welte505cf9b2018-09-15 17:47:23 +0300244
245 f_init_l1ctl();
Vadim Yanitskiyf1c95c82020-07-31 06:43:57 +0700246
247 /* Tune L1 to the given CBCH timeslot (SDCCH4+CBCH or SDCCH8+CBCH) */
248 if (match(pars.chan_nr, t_RslChanNr_CBCH4(0))) {
249 f_l1_tune(L1CTL, ccch_mode := CCCH_MODE_COMBINED_CBCH);
250 } else {
251 f_l1_tune(L1CTL, ccch_mode := CCCH_MODE_COMBINED);
252 /* TODO: also handle frequency hopping parameters */
253 L1CTL.send(ts_L1CTL_DM_EST_REQ_H0(pars.chan_nr,
254 7 /* TODO: mp_tsc */,
255 mp_trx0_arfcn));
256 }
Harald Welte505cf9b2018-09-15 17:47:23 +0300257
258 /* send SMSCB[s] via RSL */
Harald Weltea3ff6702019-05-20 20:03:50 +0200259 f_smscb_setup_rsl_chan(pars.basic, false);
260 if (ispresent(pars.extended)) {
261 f_smscb_setup_rsl_chan(pars.extended, true);
Harald Welte505cf9b2018-09-15 17:47:23 +0300262 }
Harald Welte88e5dff2019-05-20 15:14:46 +0200263}
264
Harald Weltea3ff6702019-05-20 20:03:50 +0200265/* construct a receive/match template for given block_nr in given msg */
266private function f_get_block_template(CbchTestMsg msg, integer block_nr) return template CBCH_Block {
267 var template CBCH_Block tr;
268 if (block_nr < lengthof(msg.blocks)) {
269 var CbchBlock b := msg.blocks[block_nr];
270 tr := tr_CBCH_Block(b.seq_nr, b.is_last, b.payload);
271 } else {
272 tr := tr_CBCH_Block(15, ?, ?);
273 }
274 return tr;
275}
276
277/* the heart of the CBCH test case matching engine for one channel (basic, extended) */
278private function f_cbch_match(inout CbchTestParsChan pars_chan, CBCH_Block cb, integer tb)
279{
280 var integer block_nr := tb mod 4;
281 var integer i;
282
283 if (not match(cb, tr_CBCH_Block)) {
284 setverdict(fail, "Illegal CBCH Block received: ", cb);
285 } else {
286 var boolean matched := false;
287 /* check if it's any of our expected blocks */
288 for (i := 0; i < lengthof(pars_chan.msgs); i := i+1) {
289 if (block_nr < lengthof(pars_chan.msgs[i].blocks)) {
290 if (match(cb, f_get_block_template(pars_chan.msgs[i], block_nr))) {
291 log("Found block_nr ", block_nr, " of msg ", i);
292 if (not pars_chan.msgs[i].blocks[block_nr].seen_once) {
293 pars_chan.msgs[i].blocks[block_nr].seen_once := true;
294 setverdict(pass);
295 } else {
296 setverdict(fail, "Received SMSCB twice! ", cb);
297 }
298 matched := true;
299 break;
300 }
301 }
302 }
303 if (not matched) {
304 var template CBCH_Block tr;
305 if (ispresent(pars_chan.default_msg)) {
306 /* it must be a block of the default message */
307 tr := f_get_block_template(pars_chan.default_msg, block_nr);
308 } else {
309 /* it must be a NULL block */
310 tr := tr_CBCH_Block(15, ?, ?);
311 }
312 if (not match(cb, tr)) {
313 setverdict(fail, "Received unexpected CBCH block: ", cb);
314 } else {
315 log("Found block_nr ", block_nr, " of DEFAULT/NULL");
316 if (ispresent(pars_chan.default_msg) and
317 block_nr < lengthof(pars_chan.default_msg.blocks)) {
318 pars_chan.default_msg.blocks[block_nr].seen_once := true;
319 }
320 }
321 }
322 }
323}
324
325/* Report/Evaluate the per-channel CBCH test results */
326private function f_cbch_report(CbchTestParsChan pars_chan, charstring id)
327{
328 var integer i, j;
329
330 /* verify that each block of each message has been seen once */
331 for (i := 0; i < lengthof(pars_chan.msgs); i := i+1) {
332 for (j := 0; j < lengthof(pars_chan.msgs[i].blocks); j := j+1) {
333 var CbchBlock b := pars_chan.msgs[i].blocks[j];
334 if (not b.seen_once) {
335 setverdict(fail, "Timeout waiting for ", id, " CBCH block ",
336 j, " of msg ", i);
337 }
338 }
339 }
340 if (ispresent(pars_chan.default_msg)) {
341 /* verify that each block of default message has been seen at least once */
342 for (j := 0; j < lengthof(pars_chan.default_msg.blocks); j := j+1) {
343 var CbchBlock b := pars_chan.default_msg.blocks[j];
344 if (not b.seen_once) {
345 setverdict(fail, "Timeout waiting for at leaset one instance of ",
346 "CBCH block ", j, " of DEFAULT msg");
347 }
348 }
349 }
350}
351
Harald Welte88e5dff2019-05-20 15:14:46 +0200352/* shared function doing the heavy lifting for most CBCH tests */
353private function f_TC_smscb(CbchTestPars pars) runs on test_CT {
354 var L1ctlDlMessage dl;
Harald Weltea3ff6702019-05-20 20:03:50 +0200355 var integer msg_count;
356 timer T;
357
358 msg_count := lengthof(pars.basic.msgs);
359 if (ispresent(pars.basic.default_msg)) {
360 msg_count := msg_count + 1;
361 }
362 if (ispresent(pars.extended)) {
363 msg_count := msg_count + lengthof(pars.extended.msgs);
364 if (ispresent(pars.extended.default_msg)) {
365 msg_count := msg_count + 1;
366 }
367 }
Harald Welte88e5dff2019-05-20 15:14:46 +0200368
369 f_smscb_setup(pars);
370
Harald Weltea3ff6702019-05-20 20:03:50 +0200371 /* dynamically adjust timeout based on number of messages */
372 T.start(5.0 + 3.0 * int2float(msg_count));
Harald Welte505cf9b2018-09-15 17:47:23 +0300373 /* Expect this to show up exactly once on the basic CBCH (four blocks) */
374 alt {
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700375 [] L1CTL.receive(tr_L1CTL_DATA_IND(pars.chan_nr)) -> value dl {
Harald Weltea3ff6702019-05-20 20:03:50 +0200376 var integer tb := f_cbch_fn2tb(dl.dl_info.frame_nr);
Harald Welte505cf9b2018-09-15 17:47:23 +0300377 var CBCH_Block cb := dec_CBCH_Block(dl.payload.data_ind.payload);
Harald Weltea3ff6702019-05-20 20:03:50 +0200378 log("Tb=", tb, ", CBCH: ", dl, ", block: ", cb);
379
Harald Welte505cf9b2018-09-15 17:47:23 +0300380 /* detect the proper CBCH messages; check frame number */
381 f_cbch_fn_verify(dl.dl_info.frame_nr, cb);
Harald Weltea3ff6702019-05-20 20:03:50 +0200382
383 if (tb < 4) {
384 f_cbch_match(pars.basic, cb, tb);
Harald Welte505cf9b2018-09-15 17:47:23 +0300385 } else {
Harald Weltea3ff6702019-05-20 20:03:50 +0200386 if (not ispresent(pars.extended)) {
387 /* no parameters for ext. BCCH given: ignore */
388 repeat;
Harald Welte505cf9b2018-09-15 17:47:23 +0300389 }
Harald Weltea3ff6702019-05-20 20:03:50 +0200390 f_cbch_match(pars.extended, cb, tb);
Harald Welte505cf9b2018-09-15 17:47:23 +0300391 }
Harald Weltea3ff6702019-05-20 20:03:50 +0200392 repeat;
Harald Welte505cf9b2018-09-15 17:47:23 +0300393 }
394 [] L1CTL.receive { repeat; }
395 [] T.timeout {
Harald Weltea3ff6702019-05-20 20:03:50 +0200396 f_cbch_report(pars.basic, "Basic");
397 if (ispresent(pars.extended)) {
398 f_cbch_report(pars.extended, "Extended");
Harald Welte505cf9b2018-09-15 17:47:23 +0300399 }
400 }
401 }
402
Harald Welte88e5dff2019-05-20 15:14:46 +0200403 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, pass);
404}
405
406private function f_TC_smscb_default_only(CbchTestPars pars) runs on test_CT {
407 var L1ctlDlMessage dl;
408 timer T := 5.0;
409
410 f_smscb_setup(pars);
411
412 /* ensure whatever initial NULL messages have all been drained */
413 f_sleep(5.0);
414 L1CTL.clear;
415
416 T.start;
417 alt {
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700418 [] L1CTL.receive(tr_L1CTL_DATA_IND(pars.chan_nr)) -> value dl {
Harald Welte88e5dff2019-05-20 15:14:46 +0200419 var integer tb := f_cbch_fn2tb(dl.dl_info.frame_nr);
420 log("CBCH: ", dl);
421 var CBCH_Block cb := dec_CBCH_Block(dl.payload.data_ind.payload);
422 /* detect the proper CBCH messages; check frame number */
423 f_cbch_fn_verify(dl.dl_info.frame_nr, cb);
424 if (tb >= 4) {
425 /* skip extended CBCH for now */
426 repeat;
427 }
428 if (not match(cb, tr_CBCH_Block)) {
429 setverdict(fail, "Illegal CBCH Block received: ", cb);
430 } else {
431 var uint4_t rx_seq_nr := cb.block_type.seq_nr;
432 var template CBCH_Block tr;
Harald Weltea3ff6702019-05-20 20:03:50 +0200433 if (rx_seq_nr < lengthof(pars.basic.msgs[0].blocks)) {
434 var CbchBlock b := pars.basic.msgs[0].blocks[rx_seq_nr];
Harald Welte88e5dff2019-05-20 15:14:46 +0200435 tr := tr_CBCH_Block(b.seq_nr, b.is_last, b.payload);
436 } else {
437 tr := tr_CBCH_Block(15, ?, ?);
438 }
439 if (match(cb, tr)) {
440 setverdict(pass); /* FIXME: check that all blocks are received? */
441 repeat;
442 } else {
443 setverdict(fail, "Unexpected CBCH block ", cb, ", expected ", tr);
444 }
445 }
446 }
447 [] L1CTL.receive { repeat; }
448 [] T.timeout {}
449 }
450
Harald Welte88e5dff2019-05-20 15:14:46 +0200451 /* don't shut down; some tests still want to continue */
Harald Welte505cf9b2018-09-15 17:47:23 +0300452}
453
454private const CbchTestMsgs msgs_1m_1b_norm := {
455 { RSL_CB_CMD_NORMAL, 0, '001000320f1141660c344dd3cba09a0c000000000000'O, omit }
456}
457
458private const CbchTestMsgs msgs_1m_2b_norm := {
459 { RSL_CB_CMD_NORMAL, 1, '001000320f1141660c344dd3cba09a0c000000000000'O &
460 '000102030405060708090a0b0c0d0e0f101213141516'O,
461 omit }
462}
463
464private const CbchTestMsgs msgs_1m_3b_norm := {
465 { RSL_CB_CMD_NORMAL, 2, '001000320f1141660c344dd3cba09a0c000000000000'O &
466 '000102030405060708090a0b0c0d0e0f101213141516'O &
467 '101112131415161718191a1b1c1d1e1f202223242526'O,
468 omit }
469}
470
471private const CbchTestMsgs msgs_1m_4b_norm := {
472 { RSL_CB_CMD_NORMAL, 3, '001000320f1141660c344dd3cba09a0c000000000000'O &
473 '000102030405060708090a0b0c0d0e0f101213141516'O &
474 '101112131415161718191a1b1c1d1e1f202223242526'O &
475 '202122232425262728292a2b2c2d2e2f303233343536'O,
476 omit }
477}
478
479private const CbchTestMsgs msgs_1m_4b_sched := {
480 { RSL_CB_CMD_SCHEDULE, 3, '001000320f1141660c344dd3cba09a0c000000000000'O &
481 '000102030405060708090a0b0c0d0e0f101213141516'O &
482 '101112131415161718191a1b1c1d1e1f202223242526'O &
483 '202122232425262728292a2b2c2d2e2f303233343536'O,
484 omit }
485}
486
Harald Weltee0026c32019-05-20 00:27:30 +0200487private const CbchTestMsgs msgs_3m_4b_norm := {
488 { RSL_CB_CMD_NORMAL, 3, '001000320f1141660c344dd3cba09a0c000000000000'O &
489 '000102030405060708090a0b0c0d0e0f101213141516'O &
490 '101112131415161718191a1b1c1d1e1f202223242526'O &
491 '201122232425262728292a2b2c2d2e2f303233343536'O,
492 omit },
493 { RSL_CB_CMD_NORMAL, 3, '002000320f1141660c344dd3cba09a0c000000000000'O &
494 '002102030405060708090a0b0c0d0e0f101213141516'O &
495 '102112131415161718191a1b1c1d1e1f202223242526'O &
496 '202122232425262728292a2b2c2d2e2f303233343536'O,
497 omit },
498 { RSL_CB_CMD_NORMAL, 3, '003000320f1141660c344dd3cba09a0c000000000000'O &
499 '003102030405060708090a0b0c0d0e0f101213141516'O &
500 '103112131415161718191a1b1c1d1e1f202223242526'O &
501 '203122232425262728292a2b2c2d2e2f303233343536'O,
502 omit }
503}
504
Harald Welte88e5dff2019-05-20 15:14:46 +0200505private const CbchTestMsgs msgs_1m_3b_default := {
506 { RSL_CB_CMD_DEFAULT, 2, '001000320f1141660c344dd3cba09a0c000000000000'O &
507 '000102030405060708090a0b0c0d0e0f101213141516'O &
508 '101112131415161718191a1b1c1d1e1f202223242526'O,
509 omit }
510}
Harald Weltea3ff6702019-05-20 20:03:50 +0200511private const CbchTestMsg msg_default := {
512 RSL_CB_CMD_DEFAULT, 0, '010203040506070708090a0b0c0d0e0f101112131415'O,
513 omit
514}
Harald Welte88e5dff2019-05-20 15:14:46 +0200515
Harald Welte505cf9b2018-09-15 17:47:23 +0300516/* transmit single-block SMSCB COMMAND */
517testcase TC_sms_cb_cmd_sdcch4_1block() runs on test_CT {
518 var CbchTestPars pars := {
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700519 chan_nr := valueof(ts_RslChanNr_CBCH4(0)),
Harald Weltea3ff6702019-05-20 20:03:50 +0200520 basic := valueof(t_CbchPC(msgs_1m_1b_norm)),
521 extended := omit
Harald Welte505cf9b2018-09-15 17:47:23 +0300522 };
523 f_TC_smscb(pars);
524}
525testcase TC_sms_cb_cmd_sdcch8_1block() runs on test_CT {
526 var CbchTestPars pars := {
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700527 chan_nr := valueof(ts_RslChanNr_CBCH8(2)),
Harald Weltea3ff6702019-05-20 20:03:50 +0200528 basic := valueof(t_CbchPC(msgs_1m_1b_norm)),
529 extended := omit
Harald Welte505cf9b2018-09-15 17:47:23 +0300530 };
531 f_TC_smscb(pars);
532}
533
534/* transmit dual-block SMSCB COMMAND */
535testcase TC_sms_cb_cmd_sdcch4_2block() runs on test_CT {
536 var CbchTestPars pars := {
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700537 chan_nr := valueof(ts_RslChanNr_CBCH4(0)),
Harald Weltea3ff6702019-05-20 20:03:50 +0200538 basic := valueof(t_CbchPC(msgs_1m_2b_norm)),
539 extended := omit
Harald Welte505cf9b2018-09-15 17:47:23 +0300540 };
541 f_TC_smscb(pars);
542}
543testcase TC_sms_cb_cmd_sdcch8_2block() runs on test_CT {
544 var CbchTestPars pars := {
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700545 chan_nr := valueof(ts_RslChanNr_CBCH8(2)),
Harald Weltea3ff6702019-05-20 20:03:50 +0200546 basic := valueof(t_CbchPC(msgs_1m_2b_norm)),
547 extended := omit
Harald Welte505cf9b2018-09-15 17:47:23 +0300548 };
549 f_TC_smscb(pars);
550}
551
552/* transmit triple-block SMSCB COMMAND */
553testcase TC_sms_cb_cmd_sdcch4_3block() runs on test_CT {
554 var CbchTestPars pars := {
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700555 chan_nr := valueof(ts_RslChanNr_CBCH4(0)),
Harald Weltea3ff6702019-05-20 20:03:50 +0200556 basic := valueof(t_CbchPC(msgs_1m_3b_norm)),
557 extended := omit
Harald Welte505cf9b2018-09-15 17:47:23 +0300558 };
559 f_TC_smscb(pars);
560}
561testcase TC_sms_cb_cmd_sdcch8_3block() runs on test_CT {
562 var CbchTestPars pars := {
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700563 chan_nr := valueof(ts_RslChanNr_CBCH8(2)),
Harald Weltea3ff6702019-05-20 20:03:50 +0200564 basic := valueof(t_CbchPC(msgs_1m_3b_norm)),
565 extended := omit
Harald Welte505cf9b2018-09-15 17:47:23 +0300566 };
567 f_TC_smscb(pars);
568}
569
570/* transmit quad-block SMSCB COMMAND */
571testcase TC_sms_cb_cmd_sdcch4_4block() runs on test_CT {
572 var CbchTestPars pars := {
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700573 chan_nr := valueof(ts_RslChanNr_CBCH4(0)),
Harald Weltea3ff6702019-05-20 20:03:50 +0200574 basic := valueof(t_CbchPC(msgs_1m_4b_norm)),
575 extended := omit
Harald Welte505cf9b2018-09-15 17:47:23 +0300576 };
577 f_TC_smscb(pars);
578}
579testcase TC_sms_cb_cmd_sdcch8_4block() runs on test_CT {
580 var CbchTestPars pars := {
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700581 chan_nr := valueof(ts_RslChanNr_CBCH8(2)),
Harald Weltea3ff6702019-05-20 20:03:50 +0200582 basic := valueof(t_CbchPC(msgs_1m_4b_norm)),
583 extended := omit
Harald Welte505cf9b2018-09-15 17:47:23 +0300584 };
585 f_TC_smscb(pars);
586}
587
Harald Weltee0026c32019-05-20 00:27:30 +0200588/* transmit multiple commands of each 4 blocks */
589testcase TC_sms_cb_cmd_sdcch4_multi() runs on test_CT {
590 var CbchTestPars pars := {
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700591 chan_nr := valueof(ts_RslChanNr_CBCH4(0)),
Harald Weltea3ff6702019-05-20 20:03:50 +0200592 basic := valueof(t_CbchPC(msgs_3m_4b_norm)),
593 extended := omit
Harald Weltee0026c32019-05-20 00:27:30 +0200594 };
595 f_TC_smscb(pars);
596}
597testcase TC_sms_cb_cmd_sdcch8_multi() runs on test_CT {
598 var CbchTestPars pars := {
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700599 chan_nr := valueof(ts_RslChanNr_CBCH8(2)),
Harald Weltea3ff6702019-05-20 20:03:50 +0200600 basic := valueof(t_CbchPC(msgs_3m_4b_norm)),
601 extended := omit
Harald Weltee0026c32019-05-20 00:27:30 +0200602 };
603 f_TC_smscb(pars);
604}
605
Harald Welte60bd92b2019-05-20 21:42:21 +0200606/* transmit multiple commands of each 4 blocks on CBCH EXTD */
607testcase TC_sms_cb_cmd_sdcch4_extd_multi() runs on test_CT {
608 var CbchTestPars pars := {
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700609 chan_nr := valueof(ts_RslChanNr_CBCH4(0)),
Harald Welte60bd92b2019-05-20 21:42:21 +0200610 basic := valueof(t_CbchPC({})),
611 extended := valueof(t_CbchPC(msgs_3m_4b_norm))
612 };
613 f_TC_smscb(pars);
614}
615testcase TC_sms_cb_cmd_sdcch8_extd_multi() runs on test_CT {
616 var CbchTestPars pars := {
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700617 chan_nr := valueof(ts_RslChanNr_CBCH8(2)),
Harald Welte60bd92b2019-05-20 21:42:21 +0200618 basic := valueof(t_CbchPC({})),
619 extended := valueof(t_CbchPC(msgs_3m_4b_norm))
620 };
621 f_TC_smscb(pars);
622}
623
Harald Welte505cf9b2018-09-15 17:47:23 +0300624/* transmit SMSCB COMMAND with SCHEDULE payload */
625testcase TC_sms_cb_cmd_sdcch4_schedule() runs on test_CT {
626 var CbchTestPars pars := {
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700627 chan_nr := valueof(ts_RslChanNr_CBCH4(0)),
Harald Weltea3ff6702019-05-20 20:03:50 +0200628 basic := valueof(t_CbchPC(msgs_1m_4b_sched)),
629 extended := omit
Harald Welte505cf9b2018-09-15 17:47:23 +0300630 };
631 f_TC_smscb(pars);
632}
633testcase TC_sms_cb_cmd_sdcch8_schedule() runs on test_CT {
634 var CbchTestPars pars := {
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700635 chan_nr := valueof(ts_RslChanNr_CBCH8(2)),
Harald Weltea3ff6702019-05-20 20:03:50 +0200636 basic := valueof(t_CbchPC(msgs_1m_4b_sched)),
637 extended := omit
Harald Welte505cf9b2018-09-15 17:47:23 +0300638 };
639 f_TC_smscb(pars);
640}
641
Harald Welte88e5dff2019-05-20 15:14:46 +0200642/* set a DEFAULT message; verify it gets transmitted all the time */
643testcase TC_sms_cb_cmd_sdcch4_default_only() runs on test_CT {
644 var CbchTestPars pars := {
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700645 chan_nr := valueof(ts_RslChanNr_CBCH4(0)),
Harald Weltea3ff6702019-05-20 20:03:50 +0200646 basic := valueof(t_CbchPC(msgs_1m_3b_default)),
647 extended := omit
Harald Welte88e5dff2019-05-20 15:14:46 +0200648 };
649 f_TC_smscb_default_only(pars);
650 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, pass);
651}
652testcase TC_sms_cb_cmd_sdcch8_default_only() runs on test_CT {
653 var CbchTestPars pars := {
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700654 chan_nr := valueof(ts_RslChanNr_CBCH4(0)),
Harald Weltea3ff6702019-05-20 20:03:50 +0200655 basic := valueof(t_CbchPC(msgs_1m_3b_default)),
656 extended := omit
Harald Welte88e5dff2019-05-20 15:14:46 +0200657 };
658 f_TC_smscb_default_only(pars);
659 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, pass);
660}
661
Harald Welted522ca02019-05-20 20:06:12 +0200662testcase TC_sms_cb_cmd_sdcch4_default_and_normal() runs on test_CT {
663 var CbchTestPars pars := {
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700664 chan_nr := valueof(ts_RslChanNr_CBCH4(0)),
Harald Welted522ca02019-05-20 20:06:12 +0200665 basic := valueof(t_CbchPC(msgs_1m_3b_norm, msg_default)),
666 extended := omit
667 };
668 f_TC_smscb(pars);
669}
670testcase TC_sms_cb_cmd_sdcch8_default_and_normal() runs on test_CT {
671 var CbchTestPars pars := {
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700672 chan_nr := valueof(ts_RslChanNr_CBCH8(2)),
Harald Welted522ca02019-05-20 20:06:12 +0200673 basic := valueof(t_CbchPC(msgs_1m_3b_norm, msg_default)),
674 extended := omit
675 };
676 f_TC_smscb(pars);
677}
678
Harald Weltedf4d0f02019-05-20 16:04:11 +0200679/* first set a DEFAULT message, then disable it again */
680testcase TC_sms_cb_cmd_sdcch4_default_then_null() runs on test_CT {
681 var CbchTestPars pars := {
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700682 chan_nr := valueof(ts_RslChanNr_CBCH4(0)),
Harald Weltea3ff6702019-05-20 20:03:50 +0200683 basic := valueof(t_CbchPC(msgs_1m_3b_default)),
684 extended := omit
Harald Weltedf4d0f02019-05-20 16:04:11 +0200685 };
Harald Welte6b86b342019-05-27 17:14:36 +0200686 var template RslChannelNr t_chan_nr := t_RslChanNr_CBCH4(0);
Harald Weltedf4d0f02019-05-20 16:04:11 +0200687 var L1ctlDlMessage dl;
688 timer T := 5.0;
689
690 f_TC_smscb_default_only(pars);
691
692 /* disable DEFAULT message; switch back to NULL */
693 f_rsl_smscb_default_null();
694
695 /* ensure whatever initial non-NULL messages have all been drained */
696 f_sleep(5.0);
697 L1CTL.clear;
698
699 T.start;
700 alt {
Harald Welte6b86b342019-05-27 17:14:36 +0200701 [] L1CTL.receive(tr_L1CTL_DATA_IND(t_chan_nr)) -> value dl {
Harald Weltedf4d0f02019-05-20 16:04:11 +0200702 log("CBCH: ", dl);
703 var CBCH_Block cb := dec_CBCH_Block(dl.payload.data_ind.payload);
704 /* detect the proper CBCH messages; check frame number */
705 f_cbch_fn_verify(dl.dl_info.frame_nr, cb);
706 if (not match(cb, tr_CBCH_Block)) {
707 setverdict(fail, "Illegal CBCH Block received: ", cb);
708 } else {
709 if (not match(cb, tr_CBCH_Block(15, ?, ?))) {
710 setverdict(fail, "Unexpected non-NULL CBCH block received");
711 }
712 repeat;
713 }
714 }
715 [] L1CTL.receive { repeat; }
716 [] T.timeout {
717 setverdict(pass);
718 }
719 }
720
721 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, pass);
722}
723
Harald Welte4a129f82019-05-21 16:35:22 +0200724/* Verify there are no CBCH load indications if no CBCH is present */
725testcase TC_cbch_load_idle_no_cbch() runs on test_CT {
726 var ASP_RSL_Unitdata rx_ud;
727 timer T := 10.0;
728
Harald Welte10474062019-05-30 16:48:17 +0200729 f_init();
Harald Welte4a129f82019-05-21 16:35:22 +0200730 f_init_vty_bsc();
731
732 T.start;
733 alt {
Vadim Yanitskiy493abe72020-05-25 22:03:48 +0700734 [] RSL_CCHAN.receive(tr_ASP_RSL_UD(tr_RSL_CBCH_LOAD_IND_BASIC)) -> value rx_ud {
Harald Welte4a129f82019-05-21 16:35:22 +0200735 setverdict(fail, "Received unexpected CBCH LOAD IND: ", rx_ud);
736 }
Vadim Yanitskiy493abe72020-05-25 22:03:48 +0700737 [] RSL_CCHAN.receive(tr_ASP_RSL_UD(tr_RSL_CBCH_LOAD_IND_EXTD)) -> value rx_ud {
Harald Welte4a129f82019-05-21 16:35:22 +0200738 setverdict(fail, "Received unexpected CBCH LOAD IND: ", rx_ud);
739 }
740 [] RSL_CCHAN.receive { repeat; }
741 [] T.timeout {
742 setverdict(pass);
743 }
744 }
745 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
746}
747
748/* Verify the CBCH load indications of an idle cell (without CBCH load) */
749function f_TC_cbc_load_idle() runs on test_CT {
750 template integer tr_slot_count := (2 .. 15);
751 const integer min_load_ind := 4;
752 var integer basic_count := 0;
753 var integer extd_count := 0;
754 var ASP_RSL_Unitdata rx_ud;
755 timer T := 10.0;
756
Harald Welte10474062019-05-30 16:48:17 +0200757 f_init();
Harald Welte4a129f82019-05-21 16:35:22 +0200758
759 RSL_CCHAN.clear;
760 T.start;
761 alt {
Vadim Yanitskiy493abe72020-05-25 22:03:48 +0700762 [] RSL_CCHAN.receive(tr_ASP_RSL_UD(tr_RSL_CBCH_LOAD_IND_BASIC(false, tr_slot_count))) {
Harald Welte4a129f82019-05-21 16:35:22 +0200763 basic_count := basic_count + 1;
764 repeat;
765 }
Vadim Yanitskiy493abe72020-05-25 22:03:48 +0700766 [] RSL_CCHAN.receive(tr_ASP_RSL_UD(tr_RSL_CBCH_LOAD_IND_EXTD(false, tr_slot_count))) -> value rx_ud {
Harald Welte4a129f82019-05-21 16:35:22 +0200767 extd_count := extd_count + 1;
768 repeat;
769 }
Vadim Yanitskiy493abe72020-05-25 22:03:48 +0700770 [] RSL_CCHAN.receive(tr_ASP_RSL_UD(tr_RSL_CBCH_LOAD_IND_BASIC)) -> value rx_ud {
Harald Welte4a129f82019-05-21 16:35:22 +0200771 setverdict(fail, "Received unexpected CBCH LOAD IND: ", rx_ud);
772 }
Vadim Yanitskiy493abe72020-05-25 22:03:48 +0700773 [] RSL_CCHAN.receive(tr_ASP_RSL_UD(tr_RSL_CBCH_LOAD_IND_EXTD)) -> value rx_ud {
Harald Welte4a129f82019-05-21 16:35:22 +0200774 setverdict(fail, "Received unexpected CBCH LOAD IND: ", rx_ud);
775 }
776 [] RSL_CCHAN.receive { repeat; }
777 [] T.timeout {
778 if ((basic_count >= min_load_ind) and (extd_count >= min_load_ind)) {
779 setverdict(pass);
780 } else {
781 setverdict(fail, "Insufficient number of CBCH LOAD IND: ",
782 "BASIC=", basic_count, " EXTD=", extd_count);
783 }
784 }
785 }
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700786
Harald Welte4a129f82019-05-21 16:35:22 +0200787 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
788}
789testcase TC_cbc_sdcch4_load_idle() runs on test_CT {
790 f_init_vty_bsc();
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700791 f_vty_cbch_setup(valueof(ts_RslChanNr_CBCH4(0)));
Harald Welte4a129f82019-05-21 16:35:22 +0200792 f_TC_cbc_load_idle();
793}
794testcase TC_cbc_sdcch8_load_idle() runs on test_CT {
795 f_init_vty_bsc();
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700796 f_vty_cbch_setup(valueof(ts_RslChanNr_CBCH8(2)));
Harald Welte4a129f82019-05-21 16:35:22 +0200797 f_TC_cbc_load_idle();
798}
799
800/* Verify CBCH overload indications are sent when sending too many SMS CB CMD */
801function f_TC_cbc_load_overload(CbchTestPars pars) runs on test_CT {
802 template integer tr_slot_count_basic := (11 .. 13);
803 template integer tr_slot_count_extd := (2 .. 15);
804 const integer min_load_ind := 4;
805 var integer basic_count := 0;
806 var integer extd_count := 0;
807 var ASP_RSL_Unitdata rx_ud;
808 timer T_total := 10.0;
809 timer T_retransmit := 0.2;
810 timer T_initial_guard := 2.0;
811 var integer i;
812
Harald Welte10474062019-05-30 16:48:17 +0200813 f_init();
Harald Welte4a129f82019-05-21 16:35:22 +0200814
815 /* send tons of SMSCB Command */
816 for (i := 0; i < 30; i := i+1) {
817 f_smscb_setup_rsl_chan(pars.basic);
818 }
819
820 /* keep sending SMSCB Commands for another two seconds */
821 T_initial_guard.start;
822 T_retransmit.start;
823 alt {
824 [] T_retransmit.timeout {
825 f_smscb_setup_rsl_chan(pars.basic);
826 T_retransmit.start;
827 repeat;
828 }
829 [] T_initial_guard.timeout { }
830 }
831 /* clear any pending messages (where load may not have peaked yet) */
832 RSL_CCHAN.clear;
833
834 /* keep sending SMSCB Commands while verifying LOAD INDICATIONS */
835 T_total.start;
836 T_retransmit.start;
837 alt {
Vadim Yanitskiy493abe72020-05-25 22:03:48 +0700838 [] RSL_CCHAN.receive(tr_ASP_RSL_UD(tr_RSL_CBCH_LOAD_IND_BASIC(true, tr_slot_count_basic))) {
Harald Welte4a129f82019-05-21 16:35:22 +0200839 basic_count := basic_count + 1;
840 repeat;
841 }
Vadim Yanitskiy493abe72020-05-25 22:03:48 +0700842 [] RSL_CCHAN.receive(tr_ASP_RSL_UD(tr_RSL_CBCH_LOAD_IND_EXTD(false, tr_slot_count_extd))) {
Harald Welte4a129f82019-05-21 16:35:22 +0200843 extd_count := extd_count + 1;
844 repeat;
845 }
Vadim Yanitskiy493abe72020-05-25 22:03:48 +0700846 [] RSL_CCHAN.receive(tr_ASP_RSL_UD(tr_RSL_CBCH_LOAD_IND_BASIC)) -> value rx_ud {
Harald Welte4a129f82019-05-21 16:35:22 +0200847 setverdict(fail, "Received unexpected CBCH LOAD IND: ", rx_ud);
848 }
Vadim Yanitskiy493abe72020-05-25 22:03:48 +0700849 [] RSL_CCHAN.receive(tr_ASP_RSL_UD(tr_RSL_CBCH_LOAD_IND_EXTD)) -> value rx_ud {
Harald Welte4a129f82019-05-21 16:35:22 +0200850 setverdict(fail, "Received unexpected CBCH LOAD IND: ", rx_ud);
851 }
852 [] RSL_CCHAN.receive { repeat; }
853 [] T_retransmit.timeout {
854 f_smscb_setup_rsl_chan(pars.basic);
855 T_retransmit.start;
856 repeat;
857 }
858 [] T_total.timeout {
859 if ((basic_count >= min_load_ind) and (extd_count >= min_load_ind)) {
860 setverdict(pass);
861 } else {
862 setverdict(fail, "Insufficient number of CBCH LOAD IND: ",
863 "BASIC=", basic_count, " EXTD=", extd_count);
864 }
865 }
866 }
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700867
Harald Welte4a129f82019-05-21 16:35:22 +0200868 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
869}
870testcase TC_cbc_sdcch4_load_overload() runs on test_CT {
871 var CbchTestPars pars := {
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700872 chan_nr := valueof(ts_RslChanNr_CBCH4(0)),
Harald Welte4a129f82019-05-21 16:35:22 +0200873 basic := valueof(t_CbchPC(msgs_1m_3b_norm)),
874 extended := omit
875 };
876
877 f_init_vty_bsc();
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700878 f_vty_cbch_setup(pars.chan_nr);
Harald Welte4a129f82019-05-21 16:35:22 +0200879 f_TC_cbc_load_overload(pars);
880}
881testcase TC_cbc_sdcch8_load_overload() runs on test_CT {
882 var CbchTestPars pars := {
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700883 chan_nr := valueof(ts_RslChanNr_CBCH4(2)),
Harald Welte4a129f82019-05-21 16:35:22 +0200884 basic := valueof(t_CbchPC(msgs_1m_3b_norm)),
885 extended := omit
886 };
887
888 f_init_vty_bsc();
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700889 f_vty_cbch_setup(pars.chan_nr);
Harald Welte4a129f82019-05-21 16:35:22 +0200890 f_TC_cbc_load_overload(pars);
891}
Harald Weltedf4d0f02019-05-20 16:04:11 +0200892
Harald Welte88e5dff2019-05-20 15:14:46 +0200893
Harald Welte908ce542019-09-04 23:05:40 +0200894private template GsmRrMessage tr_PagingType1 := {
895 header := t_RrHeader(PAGING_REQUEST_TYPE_1, ?),
896 payload :=?
897};
898
Harald Welte908ce542019-09-04 23:05:40 +0200899/* we expect four blocks of 14 bytes, let's fill them with content easily distinguishable */
900const octetstring c_etws_seg0 := '000102030405060708090a0b0c0d'O;
901const octetstring c_etws_seg1 := '101112131415161718191a1b1c1d'O;
902const octetstring c_etws_seg2 := '202122232425262728292a2b2c2d'O;
903const octetstring c_etws_seg3 := '303132333435363738393a3b3c3d'O;
904const octetstring c_etws := c_etws_seg0 & c_etws_seg1 & c_etws_seg2 & c_etws_seg3;
905
906/* Ensure only Paging Type 1 with segmented ETWS Primary Notification are sent after RSL_OSMO_ETWS_CMD */
907testcase TC_etws_p1ro() runs on test_CT {
908 var template RslChannelNr t_chan_nr := ts_RslChanNr_PCH_AGCH(0);
909 /* decoding the actual entire P1 rest octets by manually generated code is
910 * too much effort; instead simply do a binary compare to this constant */
911 const bitstring c_P1RO_hdr := '00101011101'B;
912 var integer seg_received[4] := { 0, 0, 0, 0 };
913 var L1ctlDlMessage dl;
914 timer T := 10.0;
915
916 f_init();
917 f_init_l1ctl();
918 f_l1_tune(L1CTL, ccch_mode := CCCH_MODE_COMBINED_CBCH);
919
Vadim Yanitskiy493abe72020-05-25 22:03:48 +0700920 RSL_CCHAN.send(ts_ASP_RSL_UD(ts_RSL_OSMO_ETWS_CMD(c_etws)));
Harald Welte908ce542019-09-04 23:05:40 +0200921 /* wait for a bit until old non-ETWS Paging messages are gone */
922 f_sleep(1.0);
923 L1CTL.clear;
924 T.start;
925 alt {
926 [] L1CTL.receive(tr_L1CTL_DATA_IND(t_chan_nr)) -> value dl {
927 var GsmRrMessage l3 := dec_GsmRrMessage(dl.payload.data_ind.payload);
928 select (l3) {
Vadim Yanitskiya9a198d2020-03-28 05:11:26 +0700929 case (tr_PAG_REQ1(tr_MI_LV(t_MI_NoIdentity()))) {
Harald Welte908ce542019-09-04 23:05:40 +0200930 var octetstring p1ro := l3.payload.pag_req_1.rest_octets;
931 var bitstring midamble := oct2bit(substr(p1ro, 0, 3));
932 var octetstring segment := substr(p1ro, 3, lengthof(p1ro)-3);
933 var BIT1 not_first := substr(midamble, 11, 1);
934 var integer seg_nr := bit2int(substr(midamble, 12, 4));
935 var boolean err := false;
936 if (substr(midamble, 0, 11) != c_P1RO_hdr) {
937 setverdict(fail, "Received unexpected P1 RO header ", midamble);
938 }
939 if (not_first == '1'B) {
940 select (seg_nr) {
941 case (2) {
942 if (segment != c_etws_seg1) {
943 err := true
944 } else {
945 seg_received[1] := seg_received[1] + 1;
946 }}
947 case (3) {
948 if (segment != c_etws_seg2) {
949 err := true
950 } else {
951 seg_received[2] := seg_received[2] + 1;
952 }}
953 case (4) {
954 if (segment != c_etws_seg3) {
955 err := true
956 } else {
957 seg_received[3] := seg_received[3] + 1;
958 }}
959 case else { setverdict(fail, "Unknown segment Nr ", seg_nr); }
960 }
961 if (err) {
962 setverdict(fail, "Unexpected segment ", seg_nr, ": ", segment);
963 }
964 } else {
965 if (seg_nr != 4) {
966 setverdict(fail, "Invalid number of segments ", seg_nr);
967 err := true;
968 }
969 if (segment != c_etws_seg0) {
970 setverdict(fail, "Invalid first segment ", segment);
971 err := true;
972 }
973 if (not err) {
974 seg_received[0] := seg_received[0] + 1;
975 }
976 }
977 }
978 case (tr_PagingType1) {
979 setverdict(fail, "Received unexpected PAGING TYPE 1: ", l3);
980 }
981 }
982 repeat;
983 }
984 [] L1CTL.receive { repeat; }
985 [] T.timeout {
986 setverdict(pass);
987 }
988 }
989 log("Quantity of received ETWS PN segments: ", seg_received);
990 var integer i;
991 for (i := 0; i < 4; i := i+1) {
992 if (seg_received[i] < 15) {
993 setverdict(fail, "Segment ", i, " not received often enough");
994 }
995 }
996}
997
998/* Ensure only Paging Type 1 without ETWS Primary Notification are sent after disabling them */
999testcase TC_etws_p1ro_end() runs on test_CT {
1000 var template RslChannelNr t_chan_nr := ts_RslChanNr_PCH_AGCH(0);
1001 /* we expect four blocks of 14 bytes, let's fill them with content easily
1002 * distinguishable */
1003 /* decoding the actual entire P1 rest octets by manually generated code is
1004 * too much effort; instead simply do a binary compare to this constant */
1005 const bitstring c_P1RO_hdr := '00101011101'B;
1006 var L1ctlDlMessage dl;
1007 timer T := 10.0;
1008
1009 f_init();
1010 f_init_l1ctl();
1011 f_l1_tune(L1CTL, ccch_mode := CCCH_MODE_COMBINED_CBCH);
1012
Vadim Yanitskiy493abe72020-05-25 22:03:48 +07001013 RSL_CCHAN.send(ts_ASP_RSL_UD(ts_RSL_OSMO_ETWS_CMD(c_etws)));
Harald Welte908ce542019-09-04 23:05:40 +02001014 /* wait for a bit until old non-ETWS Paging messages are gone */
1015 f_sleep(3.0);
1016 /* disable the ETWS PN again */
Vadim Yanitskiy493abe72020-05-25 22:03:48 +07001017 RSL_CCHAN.send(ts_ASP_RSL_UD(ts_RSL_OSMO_ETWS_CMD(''O)));
Harald Welte908ce542019-09-04 23:05:40 +02001018 f_sleep(2.0);
1019 T.start;
1020 L1CTL.clear;
1021 alt {
1022 [] L1CTL.receive(tr_L1CTL_DATA_IND(t_chan_nr)) -> value dl {
1023 var GsmRrMessage l3 := dec_GsmRrMessage(dl.payload.data_ind.payload);
1024 select (l3) {
Vadim Yanitskiya9a198d2020-03-28 05:11:26 +07001025 case (tr_PAG_REQ1(tr_MI_LV(t_MI_NoIdentity()))) { repeat; }
Harald Welte908ce542019-09-04 23:05:40 +02001026 case (tr_PagingType1) {
1027 setverdict(fail, "Received non-empty PT1 after disabling ETWS PN: ", l3);
1028 }
1029 }
1030 repeat;
1031 }
1032 [] L1CTL.receive { repeat; }
1033 [] T.timeout {
1034 setverdict(pass);
1035 }
1036 }
1037}
1038
Harald Welte11b734c2019-09-05 14:17:54 +02001039/* Ensure ETWS Primary Notification is passed from RSL to PCU interface */
1040testcase TC_etws_pcu() runs on test_CT {
1041 timer T := 10.0;
1042
1043 f_init();
1044 f_init_l1ctl();
1045 f_l1_tune(L1CTL, ccch_mode := CCCH_MODE_COMBINED_CBCH);
1046
Vadim Yanitskiy493abe72020-05-25 22:03:48 +07001047 RSL_CCHAN.send(ts_ASP_RSL_UD(ts_RSL_OSMO_ETWS_CMD(c_etws)));
Harald Welte11b734c2019-09-05 14:17:54 +02001048
1049 T.start;
1050 alt {
1051 [] PCU.receive(t_SD_PCUIF(g_pcu_conn_id, tr_PCUIF_APP_INFO_REQ(0, 0, c_etws))) {
1052 setverdict(pass);
1053 }
1054 [] PCU.receive(t_SD_PCUIF(g_pcu_conn_id, tr_PCUIF_APP_INFO_REQ(?, ?, ?))) {
1055 setverdict(fail, "PCU socket received invalid APP INFO");
1056 }
1057 [] PCU.receive { repeat; }
1058 [] T.timeout {
1059 setverdict(fail, "PCU socket timeout receiving APP INFO (ETWS)");
1060 }
1061 }
1062}
1063
1064
Harald Welte908ce542019-09-04 23:05:40 +02001065
Harald Welte505cf9b2018-09-15 17:47:23 +03001066/* SMSCB TODO:
1067 * multiple SMS BC CMD at the same time: Ensure all of them are sent exactly once
1068 * extended CBCH vs. normal CBCH
1069 *
1070 */
1071
1072control {
Harald Welte4a129f82019-05-21 16:35:22 +02001073 execute( TC_cbch_load_idle_no_cbch() );
1074
Harald Welte505cf9b2018-09-15 17:47:23 +03001075 execute( TC_sms_cb_cmd_sdcch4_1block() );
1076 execute( TC_sms_cb_cmd_sdcch4_2block() );
1077 execute( TC_sms_cb_cmd_sdcch4_3block() );
1078 execute( TC_sms_cb_cmd_sdcch4_4block() );
Harald Weltee0026c32019-05-20 00:27:30 +02001079 execute( TC_sms_cb_cmd_sdcch4_multi() );
Harald Welte505cf9b2018-09-15 17:47:23 +03001080 execute( TC_sms_cb_cmd_sdcch4_schedule() );
Harald Welte88e5dff2019-05-20 15:14:46 +02001081 execute( TC_sms_cb_cmd_sdcch4_default_only() );
Harald Welted522ca02019-05-20 20:06:12 +02001082 execute( TC_sms_cb_cmd_sdcch4_default_and_normal() );
Harald Weltedf4d0f02019-05-20 16:04:11 +02001083 execute( TC_sms_cb_cmd_sdcch4_default_then_null() );
Harald Welte4a129f82019-05-21 16:35:22 +02001084 execute( TC_cbc_sdcch4_load_idle() );
1085 execute( TC_cbc_sdcch4_load_overload() );
1086
Harald Welte505cf9b2018-09-15 17:47:23 +03001087 if (false) { /* FIXME: SDCCH/8 support broken, needs trxcon + L1CTL work */
1088 execute( TC_sms_cb_cmd_sdcch8_1block() );
1089 execute( TC_sms_cb_cmd_sdcch8_2block() );
1090 execute( TC_sms_cb_cmd_sdcch8_3block() );
1091 execute( TC_sms_cb_cmd_sdcch8_4block() );
Harald Weltee0026c32019-05-20 00:27:30 +02001092 execute( TC_sms_cb_cmd_sdcch8_multi() );
Harald Welte505cf9b2018-09-15 17:47:23 +03001093 execute( TC_sms_cb_cmd_sdcch8_schedule() );
Harald Welte88e5dff2019-05-20 15:14:46 +02001094 execute( TC_sms_cb_cmd_sdcch8_default_only() );
Harald Welted522ca02019-05-20 20:06:12 +02001095 execute( TC_sms_cb_cmd_sdcch8_default_and_normal() );
Harald Welte4a129f82019-05-21 16:35:22 +02001096 execute( TC_cbc_sdcch8_load_idle() );
1097 execute( TC_cbc_sdcch8_load_overload() );
Harald Welte505cf9b2018-09-15 17:47:23 +03001098 }
Harald Welte908ce542019-09-04 23:05:40 +02001099
1100 execute( TC_etws_p1ro() );
1101 execute( TC_etws_p1ro_end() );
Harald Welte11b734c2019-09-05 14:17:54 +02001102 execute( TC_etws_pcu() );
Harald Welte505cf9b2018-09-15 17:47:23 +03001103}
1104
1105
1106}