blob: 292205a7f630e186974b6f0007acf38ab9e5cc9d [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;
Harald Welte505cf9b2018-09-15 17:47:23 +030026
27import from RSL_Types all;
28
Harald Welte11b734c2019-09-05 14:17:54 +020029import from PCUIF_Types all;
30import from PCUIF_CodecPort all;
31
Harald Welte505cf9b2018-09-15 17:47:23 +030032import from Osmocom_VTY_Functions all;
33
34import from BTS_Tests all;
35
36/***********************************************************************
37 * Cell Broadcast related tests
38 ***********************************************************************/
39
Harald Weltea3ff6702019-05-20 20:03:50 +020040/* Test parameters for one channel (e.g. Basic, Extended) */
41type record CbchTestParsChan {
42 /* list of "normal" (sent-once) SMSCB messages */
43 CbchTestMsgs msgs,
44 /* default message, if any */
45 CbchTestMsg default_msg optional
46}
47
48private template (value) CbchTestParsChan
49t_CbchPC(template (value) CbchTestMsgs msgs, template (omit) CbchTestMsg def := omit) := {
50 msgs := msgs,
51 default_msg := def
52}
53
54/* CBCH test parameters for most of our tests */
Harald Welte505cf9b2018-09-15 17:47:23 +030055type record CbchTestPars {
Harald Weltea3ff6702019-05-20 20:03:50 +020056 /* should we execute on SDCCH4 (true) or SDCCH8 (false) ? */
Harald Welte505cf9b2018-09-15 17:47:23 +030057 boolean use_sdcch4,
Harald Weltea3ff6702019-05-20 20:03:50 +020058 /* Parameters for BASIC CBCH */
59 CbchTestParsChan basic,
60 /* Parameters for EXTENDED CBCH */
61 CbchTestParsChan extended optional
Harald Welte505cf9b2018-09-15 17:47:23 +030062};
63
64type record CbchTestMsg {
65 /* config / input data */
66 RSL_CbCommand rsl_cb_cmd,
67 uint2_t last_block, /* 0..3 */
68 octetstring payload,
69 /* computed / result data */
70 CbchBlocks blocks optional
71};
72type record of CbchTestMsg CbchTestMsgs;
73
74/* a single 22byte block within a CbchTestMsg */
75type record CbchBlock {
76 uint4_t seq_nr, /* as per TS 04.12 */
77 boolean is_last,
78 OCT22 payload,
79 boolean seen_once
80};
81type record of CbchBlock CbchBlocks;
82
83/* compute the expected blocks for given test parameters */
84private function f_cbch_compute_exp_blocks(inout CbchTestPars pars) {
Harald Weltea3ff6702019-05-20 20:03:50 +020085 f_cbch_compute_exp_blocks_chan(pars.basic);
86 if (ispresent(pars.extended)) {
87 f_cbch_compute_exp_blocks_chan(pars.extended);
88 }
89}
90private function f_cbch_compute_exp_blocks_chan(inout CbchTestParsChan pars_chan) {
Harald Welte505cf9b2018-09-15 17:47:23 +030091 var integer i;
Harald Weltea3ff6702019-05-20 20:03:50 +020092 for (i := 0; i < lengthof(pars_chan.msgs); i := i+1) {
93 pars_chan.msgs[i].blocks := f_comp_blocks(pars_chan.msgs[i]);
94 }
95 if (ispresent(pars_chan.default_msg)) {
96 pars_chan.default_msg.blocks := f_comp_blocks(pars_chan.default_msg);
Harald Welte505cf9b2018-09-15 17:47:23 +030097 }
98}
99private function f_comp_blocks(in CbchTestMsg msg) return CbchBlocks {
100 var CbchBlocks blocks := {};
101 var integer i;
102
103 for (i := 0; i <= msg.last_block; i := i+1) {
104 var CbchBlock block := {
105 seq_nr := i,
106 is_last := false,
107 payload := substr(msg.payload, 22*i, 22),
108 seen_once := false
109 };
110 if (msg.rsl_cb_cmd == RSL_CB_CMD_SCHEDULE and i == 0) {
111 block.seq_nr := 8;
112 }
113 if (i == msg.last_block) {
114 block.is_last := true;
115 }
116 blocks := blocks & {block};
117 }
118
119 return blocks;
120};
121
122/* TS 48.058 Section 9.3.41 */
123private function f_cbch_block_nr2rsl(uint2_t nr) return uint2_t {
124 select (nr) {
125 case (0) { return 1; }
126 case (1) { return 2; }
127 case (2) { return 3; }
128 case (3) { return 0; }
129 }
130 setverdict(fail, "Invalid block number");
131 mtc.stop;
132}
133
Harald Welte88e5dff2019-05-20 15:14:46 +0200134private function f_cbch_fn2tb(uint32_t fn) return integer
135{
136 return (fn/51) mod 8; /* TS 05.02 Section 6.5.4 */
137}
138
Harald Welte505cf9b2018-09-15 17:47:23 +0300139/* Verify the CBCH TB scheduling rules of TS 05.02 Section 6.5.4 */
140private function f_cbch_fn_verify(uint32_t fn, CBCH_Block cb)
141{
Harald Welte88e5dff2019-05-20 15:14:46 +0200142 var integer tb := f_cbch_fn2tb(fn);
Harald Welte505cf9b2018-09-15 17:47:23 +0300143 if (cb.block_type.seq_nr == 15 /* null */) {
144 /* always permitted */
145 return;
146 } else if (cb.block_type.seq_nr == 8 /* schedule */) {
147 if (tb != 0) {
148 setverdict(fail, "Schedule block at TB=", tb);
149 }
150 } else if (cb.block_type.seq_nr < 4) {
151 if (cb.block_type.seq_nr != tb and cb.block_type.seq_nr+4 != tb) {
152 setverdict(fail, "Normal block at wrong TB=", tb, ": ", cb);
153 }
154 }
155}
156
Harald Weltedf4d0f02019-05-20 16:04:11 +0200157private function f_rsl_smscb_default_null() runs on test_CT
158{
159 var RSL_IE_CbCommandType cmd_type :=
160 valueof(ts_RSL_IE_CbCmdType(RSL_CB_CMD_DEFAULT, 1, true));
161 RSL_CCHAN.send(ts_RSL_UD(ts_RSL_SMSCB_CMD(cmd_type, ''O)));
162}
163
Harald Weltea3ff6702019-05-20 20:03:50 +0200164template RSL_IE t_RSL_IE_SMSCB_EXT := t_RSL_IE(RSL_IE_SMSCB_CHAN_INDICATOR, {smscb_chan_ind := 1});
165
166private function f_smscb_setup_rsl_chan(inout CbchTestParsChan pars_chan, boolean extd := false)
167runs on test_CT {
Harald Welte88e5dff2019-05-20 15:14:46 +0200168 var integer i;
Harald Weltea3ff6702019-05-20 20:03:50 +0200169 var CbchTestMsg msg;
170 var uint2_t rsl_last_block;
171 var RSL_IE_CbCommandType cmd_type;
172 var RSL_Message rsl;
173
174 /* send SMSCB[s] via RSL */
175 for (i := 0; i < lengthof(pars_chan.msgs); i := i+1) {
176 msg := pars_chan.msgs[i];
177 rsl_last_block := f_cbch_block_nr2rsl(msg.last_block);
178 cmd_type := valueof(ts_RSL_IE_CbCmdType(msg.rsl_cb_cmd, rsl_last_block));
179 rsl := valueof(ts_RSL_SMSCB_CMD(cmd_type, msg.payload));
180 if (extd) {
181 rsl.ies := rsl.ies & { valueof(t_RSL_IE_SMSCB_EXT) };
182 }
183 RSL_CCHAN.send(ts_RSL_UD(rsl));
184 }
185 if (ispresent(pars_chan.default_msg)) {
186 msg := pars_chan.default_msg;
187 rsl_last_block := f_cbch_block_nr2rsl(msg.last_block);
188 cmd_type := valueof(ts_RSL_IE_CbCmdType(msg.rsl_cb_cmd, rsl_last_block, false));
189 rsl := valueof(ts_RSL_SMSCB_CMD(cmd_type, msg.payload));
190 if (extd) {
191 rsl.ies := rsl.ies & { valueof(t_RSL_IE_SMSCB_EXT) };
192 }
193 RSL_CCHAN.send(ts_RSL_UD(rsl));
194 }
195}
Harald Welte505cf9b2018-09-15 17:47:23 +0300196
Harald Welte4a129f82019-05-21 16:35:22 +0200197private function f_vty_cbch_setup(boolean use_sdcch4 := true) runs on test_CT {
Harald Welte505cf9b2018-09-15 17:47:23 +0300198
Harald Welte4a129f82019-05-21 16:35:22 +0200199 if (use_sdcch4 == true) {
Harald Welte505cf9b2018-09-15 17:47:23 +0300200 f_vty_config2(BSCVTY, {"network", "bts 0", "trx 0", "timeslot 0"},
201 "phys_chan_config CCCH+SDCCH4+CBCH");
202 f_vty_config2(BSCVTY, {"network", "bts 0", "trx 0", "timeslot 6"},
203 "phys_chan_config SDCCH8");
204 } else {
205 f_vty_config2(BSCVTY, {"network", "bts 0", "trx 0", "timeslot 0"},
206 "phys_chan_config CCCH+SDCCH4");
207 f_vty_config2(BSCVTY, {"network", "bts 0", "trx 0", "timeslot 6"},
208 "phys_chan_config SDCCH8+CBCH");
209 }
210 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
211 f_sleep(2.0);
Harald Welte4a129f82019-05-21 16:35:22 +0200212}
213private function f_smscb_setup(inout CbchTestPars pars) runs on test_CT {
214
215 f_cbch_compute_exp_blocks(pars);
216
217 f_init_vty_bsc();
218 /* ensure that a CBCH is present in channel combination */
219 f_vty_cbch_setup(pars.use_sdcch4);
Harald Welte10474062019-05-30 16:48:17 +0200220 f_init();
Harald Welte505cf9b2018-09-15 17:47:23 +0300221
222 f_init_l1ctl();
Harald Welte990a3612019-05-27 14:02:13 +0200223 f_l1_tune(L1CTL, ccch_mode := CCCH_MODE_COMBINED_CBCH);
Harald Welte505cf9b2018-09-15 17:47:23 +0300224 /* FIXME: switch to dedicated mode for SDCCH/8 */
225
226 /* send SMSCB[s] via RSL */
Harald Weltea3ff6702019-05-20 20:03:50 +0200227 f_smscb_setup_rsl_chan(pars.basic, false);
228 if (ispresent(pars.extended)) {
229 f_smscb_setup_rsl_chan(pars.extended, true);
Harald Welte505cf9b2018-09-15 17:47:23 +0300230 }
Harald Welte88e5dff2019-05-20 15:14:46 +0200231}
232
233private function f_smscb_cleanup() runs on test_CT {
234 /* reset timeslot 0 channel combination to default */
235 f_vty_config2(BSCVTY, {"network", "bts 0", "trx 0", "timeslot 0"},
236 "phys_chan_config CCCH+SDCCH4");
237 f_vty_config2(BSCVTY, {"network", "bts 0", "trx 0", "timeslot 6"},
238 "phys_chan_config SDCCH8");
239}
240
Harald Weltea3ff6702019-05-20 20:03:50 +0200241/* construct a receive/match template for given block_nr in given msg */
242private function f_get_block_template(CbchTestMsg msg, integer block_nr) return template CBCH_Block {
243 var template CBCH_Block tr;
244 if (block_nr < lengthof(msg.blocks)) {
245 var CbchBlock b := msg.blocks[block_nr];
246 tr := tr_CBCH_Block(b.seq_nr, b.is_last, b.payload);
247 } else {
248 tr := tr_CBCH_Block(15, ?, ?);
249 }
250 return tr;
251}
252
253/* the heart of the CBCH test case matching engine for one channel (basic, extended) */
254private function f_cbch_match(inout CbchTestParsChan pars_chan, CBCH_Block cb, integer tb)
255{
256 var integer block_nr := tb mod 4;
257 var integer i;
258
259 if (not match(cb, tr_CBCH_Block)) {
260 setverdict(fail, "Illegal CBCH Block received: ", cb);
261 } else {
262 var boolean matched := false;
263 /* check if it's any of our expected blocks */
264 for (i := 0; i < lengthof(pars_chan.msgs); i := i+1) {
265 if (block_nr < lengthof(pars_chan.msgs[i].blocks)) {
266 if (match(cb, f_get_block_template(pars_chan.msgs[i], block_nr))) {
267 log("Found block_nr ", block_nr, " of msg ", i);
268 if (not pars_chan.msgs[i].blocks[block_nr].seen_once) {
269 pars_chan.msgs[i].blocks[block_nr].seen_once := true;
270 setverdict(pass);
271 } else {
272 setverdict(fail, "Received SMSCB twice! ", cb);
273 }
274 matched := true;
275 break;
276 }
277 }
278 }
279 if (not matched) {
280 var template CBCH_Block tr;
281 if (ispresent(pars_chan.default_msg)) {
282 /* it must be a block of the default message */
283 tr := f_get_block_template(pars_chan.default_msg, block_nr);
284 } else {
285 /* it must be a NULL block */
286 tr := tr_CBCH_Block(15, ?, ?);
287 }
288 if (not match(cb, tr)) {
289 setverdict(fail, "Received unexpected CBCH block: ", cb);
290 } else {
291 log("Found block_nr ", block_nr, " of DEFAULT/NULL");
292 if (ispresent(pars_chan.default_msg) and
293 block_nr < lengthof(pars_chan.default_msg.blocks)) {
294 pars_chan.default_msg.blocks[block_nr].seen_once := true;
295 }
296 }
297 }
298 }
299}
300
301/* Report/Evaluate the per-channel CBCH test results */
302private function f_cbch_report(CbchTestParsChan pars_chan, charstring id)
303{
304 var integer i, j;
305
306 /* verify that each block of each message has been seen once */
307 for (i := 0; i < lengthof(pars_chan.msgs); i := i+1) {
308 for (j := 0; j < lengthof(pars_chan.msgs[i].blocks); j := j+1) {
309 var CbchBlock b := pars_chan.msgs[i].blocks[j];
310 if (not b.seen_once) {
311 setverdict(fail, "Timeout waiting for ", id, " CBCH block ",
312 j, " of msg ", i);
313 }
314 }
315 }
316 if (ispresent(pars_chan.default_msg)) {
317 /* verify that each block of default message has been seen at least once */
318 for (j := 0; j < lengthof(pars_chan.default_msg.blocks); j := j+1) {
319 var CbchBlock b := pars_chan.default_msg.blocks[j];
320 if (not b.seen_once) {
321 setverdict(fail, "Timeout waiting for at leaset one instance of ",
322 "CBCH block ", j, " of DEFAULT msg");
323 }
324 }
325 }
326}
327
Harald Welte6b86b342019-05-27 17:14:36 +0200328private function t_cbch_chan_nr(CbchTestPars pars, template uint8_t tn) return template RslChannelNr {
329 if (pars.use_sdcch4) {
330 return t_RslChanNr_CBCH4(tn);
331 } else {
332 return t_RslChanNr_CBCH8(tn);
333 }
334}
335
Harald Welte88e5dff2019-05-20 15:14:46 +0200336/* shared function doing the heavy lifting for most CBCH tests */
337private function f_TC_smscb(CbchTestPars pars) runs on test_CT {
Harald Welte6b86b342019-05-27 17:14:36 +0200338 var template RslChannelNr t_chan_nr := t_cbch_chan_nr(pars, 0); /* FIXME: TS number */
Harald Welte88e5dff2019-05-20 15:14:46 +0200339 var L1ctlDlMessage dl;
Harald Weltea3ff6702019-05-20 20:03:50 +0200340 var integer msg_count;
341 timer T;
342
343 msg_count := lengthof(pars.basic.msgs);
344 if (ispresent(pars.basic.default_msg)) {
345 msg_count := msg_count + 1;
346 }
347 if (ispresent(pars.extended)) {
348 msg_count := msg_count + lengthof(pars.extended.msgs);
349 if (ispresent(pars.extended.default_msg)) {
350 msg_count := msg_count + 1;
351 }
352 }
Harald Welte88e5dff2019-05-20 15:14:46 +0200353
354 f_smscb_setup(pars);
355
Harald Weltea3ff6702019-05-20 20:03:50 +0200356 /* dynamically adjust timeout based on number of messages */
357 T.start(5.0 + 3.0 * int2float(msg_count));
Harald Welte505cf9b2018-09-15 17:47:23 +0300358 /* Expect this to show up exactly once on the basic CBCH (four blocks) */
359 alt {
Harald Welte6b86b342019-05-27 17:14:36 +0200360 [] L1CTL.receive(tr_L1CTL_DATA_IND(t_chan_nr)) -> value dl {
Harald Weltea3ff6702019-05-20 20:03:50 +0200361 var integer tb := f_cbch_fn2tb(dl.dl_info.frame_nr);
Harald Welte505cf9b2018-09-15 17:47:23 +0300362 var CBCH_Block cb := dec_CBCH_Block(dl.payload.data_ind.payload);
Harald Weltea3ff6702019-05-20 20:03:50 +0200363 log("Tb=", tb, ", CBCH: ", dl, ", block: ", cb);
364
Harald Welte505cf9b2018-09-15 17:47:23 +0300365 /* detect the proper CBCH messages; check frame number */
366 f_cbch_fn_verify(dl.dl_info.frame_nr, cb);
Harald Weltea3ff6702019-05-20 20:03:50 +0200367
368 if (tb < 4) {
369 f_cbch_match(pars.basic, cb, tb);
Harald Welte505cf9b2018-09-15 17:47:23 +0300370 } else {
Harald Weltea3ff6702019-05-20 20:03:50 +0200371 if (not ispresent(pars.extended)) {
372 /* no parameters for ext. BCCH given: ignore */
373 repeat;
Harald Welte505cf9b2018-09-15 17:47:23 +0300374 }
Harald Weltea3ff6702019-05-20 20:03:50 +0200375 f_cbch_match(pars.extended, cb, tb);
Harald Welte505cf9b2018-09-15 17:47:23 +0300376 }
Harald Weltea3ff6702019-05-20 20:03:50 +0200377 repeat;
Harald Welte505cf9b2018-09-15 17:47:23 +0300378 }
379 [] L1CTL.receive { repeat; }
380 [] T.timeout {
Harald Weltea3ff6702019-05-20 20:03:50 +0200381 f_cbch_report(pars.basic, "Basic");
382 if (ispresent(pars.extended)) {
383 f_cbch_report(pars.extended, "Extended");
Harald Welte505cf9b2018-09-15 17:47:23 +0300384 }
385 }
386 }
387
Harald Welte88e5dff2019-05-20 15:14:46 +0200388 f_smscb_cleanup();
389 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, pass);
390}
391
392private function f_TC_smscb_default_only(CbchTestPars pars) runs on test_CT {
Harald Welte6b86b342019-05-27 17:14:36 +0200393 var template RslChannelNr t_chan_nr := t_cbch_chan_nr(pars, 0); /* FIXME: TS number */
Harald Welte88e5dff2019-05-20 15:14:46 +0200394 var L1ctlDlMessage dl;
395 timer T := 5.0;
396
397 f_smscb_setup(pars);
398
399 /* ensure whatever initial NULL messages have all been drained */
400 f_sleep(5.0);
401 L1CTL.clear;
402
403 T.start;
404 alt {
Harald Welte6b86b342019-05-27 17:14:36 +0200405 [] L1CTL.receive(tr_L1CTL_DATA_IND(t_chan_nr)) -> value dl {
Harald Welte88e5dff2019-05-20 15:14:46 +0200406 var integer tb := f_cbch_fn2tb(dl.dl_info.frame_nr);
407 log("CBCH: ", dl);
408 var CBCH_Block cb := dec_CBCH_Block(dl.payload.data_ind.payload);
409 /* detect the proper CBCH messages; check frame number */
410 f_cbch_fn_verify(dl.dl_info.frame_nr, cb);
411 if (tb >= 4) {
412 /* skip extended CBCH for now */
413 repeat;
414 }
415 if (not match(cb, tr_CBCH_Block)) {
416 setverdict(fail, "Illegal CBCH Block received: ", cb);
417 } else {
418 var uint4_t rx_seq_nr := cb.block_type.seq_nr;
419 var template CBCH_Block tr;
Harald Weltea3ff6702019-05-20 20:03:50 +0200420 if (rx_seq_nr < lengthof(pars.basic.msgs[0].blocks)) {
421 var CbchBlock b := pars.basic.msgs[0].blocks[rx_seq_nr];
Harald Welte88e5dff2019-05-20 15:14:46 +0200422 tr := tr_CBCH_Block(b.seq_nr, b.is_last, b.payload);
423 } else {
424 tr := tr_CBCH_Block(15, ?, ?);
425 }
426 if (match(cb, tr)) {
427 setverdict(pass); /* FIXME: check that all blocks are received? */
428 repeat;
429 } else {
430 setverdict(fail, "Unexpected CBCH block ", cb, ", expected ", tr);
431 }
432 }
433 }
434 [] L1CTL.receive { repeat; }
435 [] T.timeout {}
436 }
437
438 f_smscb_cleanup();
439 /* don't shut down; some tests still want to continue */
Harald Welte505cf9b2018-09-15 17:47:23 +0300440}
441
442private const CbchTestMsgs msgs_1m_1b_norm := {
443 { RSL_CB_CMD_NORMAL, 0, '001000320f1141660c344dd3cba09a0c000000000000'O, omit }
444}
445
446private const CbchTestMsgs msgs_1m_2b_norm := {
447 { RSL_CB_CMD_NORMAL, 1, '001000320f1141660c344dd3cba09a0c000000000000'O &
448 '000102030405060708090a0b0c0d0e0f101213141516'O,
449 omit }
450}
451
452private const CbchTestMsgs msgs_1m_3b_norm := {
453 { RSL_CB_CMD_NORMAL, 2, '001000320f1141660c344dd3cba09a0c000000000000'O &
454 '000102030405060708090a0b0c0d0e0f101213141516'O &
455 '101112131415161718191a1b1c1d1e1f202223242526'O,
456 omit }
457}
458
459private const CbchTestMsgs msgs_1m_4b_norm := {
460 { RSL_CB_CMD_NORMAL, 3, '001000320f1141660c344dd3cba09a0c000000000000'O &
461 '000102030405060708090a0b0c0d0e0f101213141516'O &
462 '101112131415161718191a1b1c1d1e1f202223242526'O &
463 '202122232425262728292a2b2c2d2e2f303233343536'O,
464 omit }
465}
466
467private const CbchTestMsgs msgs_1m_4b_sched := {
468 { RSL_CB_CMD_SCHEDULE, 3, '001000320f1141660c344dd3cba09a0c000000000000'O &
469 '000102030405060708090a0b0c0d0e0f101213141516'O &
470 '101112131415161718191a1b1c1d1e1f202223242526'O &
471 '202122232425262728292a2b2c2d2e2f303233343536'O,
472 omit }
473}
474
Harald Weltee0026c32019-05-20 00:27:30 +0200475private const CbchTestMsgs msgs_3m_4b_norm := {
476 { RSL_CB_CMD_NORMAL, 3, '001000320f1141660c344dd3cba09a0c000000000000'O &
477 '000102030405060708090a0b0c0d0e0f101213141516'O &
478 '101112131415161718191a1b1c1d1e1f202223242526'O &
479 '201122232425262728292a2b2c2d2e2f303233343536'O,
480 omit },
481 { RSL_CB_CMD_NORMAL, 3, '002000320f1141660c344dd3cba09a0c000000000000'O &
482 '002102030405060708090a0b0c0d0e0f101213141516'O &
483 '102112131415161718191a1b1c1d1e1f202223242526'O &
484 '202122232425262728292a2b2c2d2e2f303233343536'O,
485 omit },
486 { RSL_CB_CMD_NORMAL, 3, '003000320f1141660c344dd3cba09a0c000000000000'O &
487 '003102030405060708090a0b0c0d0e0f101213141516'O &
488 '103112131415161718191a1b1c1d1e1f202223242526'O &
489 '203122232425262728292a2b2c2d2e2f303233343536'O,
490 omit }
491}
492
Harald Welte88e5dff2019-05-20 15:14:46 +0200493private const CbchTestMsgs msgs_1m_3b_default := {
494 { RSL_CB_CMD_DEFAULT, 2, '001000320f1141660c344dd3cba09a0c000000000000'O &
495 '000102030405060708090a0b0c0d0e0f101213141516'O &
496 '101112131415161718191a1b1c1d1e1f202223242526'O,
497 omit }
498}
Harald Weltea3ff6702019-05-20 20:03:50 +0200499private const CbchTestMsg msg_default := {
500 RSL_CB_CMD_DEFAULT, 0, '010203040506070708090a0b0c0d0e0f101112131415'O,
501 omit
502}
Harald Welte88e5dff2019-05-20 15:14:46 +0200503
Harald Welte505cf9b2018-09-15 17:47:23 +0300504/* transmit single-block SMSCB COMMAND */
505testcase TC_sms_cb_cmd_sdcch4_1block() runs on test_CT {
506 var CbchTestPars pars := {
507 use_sdcch4 := true,
Harald Weltea3ff6702019-05-20 20:03:50 +0200508 basic := valueof(t_CbchPC(msgs_1m_1b_norm)),
509 extended := omit
Harald Welte505cf9b2018-09-15 17:47:23 +0300510 };
511 f_TC_smscb(pars);
512}
513testcase TC_sms_cb_cmd_sdcch8_1block() runs on test_CT {
514 var CbchTestPars pars := {
515 use_sdcch4 := false,
Harald Weltea3ff6702019-05-20 20:03:50 +0200516 basic := valueof(t_CbchPC(msgs_1m_1b_norm)),
517 extended := omit
Harald Welte505cf9b2018-09-15 17:47:23 +0300518 };
519 f_TC_smscb(pars);
520}
521
522/* transmit dual-block SMSCB COMMAND */
523testcase TC_sms_cb_cmd_sdcch4_2block() runs on test_CT {
524 var CbchTestPars pars := {
525 use_sdcch4 := true,
Harald Weltea3ff6702019-05-20 20:03:50 +0200526 basic := valueof(t_CbchPC(msgs_1m_2b_norm)),
527 extended := omit
Harald Welte505cf9b2018-09-15 17:47:23 +0300528 };
529 f_TC_smscb(pars);
530}
531testcase TC_sms_cb_cmd_sdcch8_2block() runs on test_CT {
532 var CbchTestPars pars := {
533 use_sdcch4 := false,
Harald Weltea3ff6702019-05-20 20:03:50 +0200534 basic := valueof(t_CbchPC(msgs_1m_2b_norm)),
535 extended := omit
Harald Welte505cf9b2018-09-15 17:47:23 +0300536 };
537 f_TC_smscb(pars);
538}
539
540/* transmit triple-block SMSCB COMMAND */
541testcase TC_sms_cb_cmd_sdcch4_3block() runs on test_CT {
542 var CbchTestPars pars := {
543 use_sdcch4 := true,
Harald Weltea3ff6702019-05-20 20:03:50 +0200544 basic := valueof(t_CbchPC(msgs_1m_3b_norm)),
545 extended := omit
Harald Welte505cf9b2018-09-15 17:47:23 +0300546 };
547 f_TC_smscb(pars);
548}
549testcase TC_sms_cb_cmd_sdcch8_3block() runs on test_CT {
550 var CbchTestPars pars := {
551 use_sdcch4 := false,
Harald Weltea3ff6702019-05-20 20:03:50 +0200552 basic := valueof(t_CbchPC(msgs_1m_3b_norm)),
553 extended := omit
Harald Welte505cf9b2018-09-15 17:47:23 +0300554 };
555 f_TC_smscb(pars);
556}
557
558/* transmit quad-block SMSCB COMMAND */
559testcase TC_sms_cb_cmd_sdcch4_4block() runs on test_CT {
560 var CbchTestPars pars := {
561 use_sdcch4 := true,
Harald Weltea3ff6702019-05-20 20:03:50 +0200562 basic := valueof(t_CbchPC(msgs_1m_4b_norm)),
563 extended := omit
Harald Welte505cf9b2018-09-15 17:47:23 +0300564 };
565 f_TC_smscb(pars);
566}
567testcase TC_sms_cb_cmd_sdcch8_4block() runs on test_CT {
568 var CbchTestPars pars := {
569 use_sdcch4 := false,
Harald Weltea3ff6702019-05-20 20:03:50 +0200570 basic := valueof(t_CbchPC(msgs_1m_4b_norm)),
571 extended := omit
Harald Welte505cf9b2018-09-15 17:47:23 +0300572 };
573 f_TC_smscb(pars);
574}
575
Harald Weltee0026c32019-05-20 00:27:30 +0200576/* transmit multiple commands of each 4 blocks */
577testcase TC_sms_cb_cmd_sdcch4_multi() runs on test_CT {
578 var CbchTestPars pars := {
579 use_sdcch4 := true,
Harald Weltea3ff6702019-05-20 20:03:50 +0200580 basic := valueof(t_CbchPC(msgs_3m_4b_norm)),
581 extended := omit
Harald Weltee0026c32019-05-20 00:27:30 +0200582 };
583 f_TC_smscb(pars);
584}
585testcase TC_sms_cb_cmd_sdcch8_multi() runs on test_CT {
586 var CbchTestPars pars := {
587 use_sdcch4 := false,
Harald Weltea3ff6702019-05-20 20:03:50 +0200588 basic := valueof(t_CbchPC(msgs_3m_4b_norm)),
589 extended := omit
Harald Weltee0026c32019-05-20 00:27:30 +0200590 };
591 f_TC_smscb(pars);
592}
593
Harald Welte60bd92b2019-05-20 21:42:21 +0200594/* transmit multiple commands of each 4 blocks on CBCH EXTD */
595testcase TC_sms_cb_cmd_sdcch4_extd_multi() runs on test_CT {
596 var CbchTestPars pars := {
597 use_sdcch4 := true,
598 basic := valueof(t_CbchPC({})),
599 extended := valueof(t_CbchPC(msgs_3m_4b_norm))
600 };
601 f_TC_smscb(pars);
602}
603testcase TC_sms_cb_cmd_sdcch8_extd_multi() runs on test_CT {
604 var CbchTestPars pars := {
605 use_sdcch4 := false,
606 basic := valueof(t_CbchPC({})),
607 extended := valueof(t_CbchPC(msgs_3m_4b_norm))
608 };
609 f_TC_smscb(pars);
610}
611
Harald Welte505cf9b2018-09-15 17:47:23 +0300612/* transmit SMSCB COMMAND with SCHEDULE payload */
613testcase TC_sms_cb_cmd_sdcch4_schedule() runs on test_CT {
614 var CbchTestPars pars := {
615 use_sdcch4 := true,
Harald Weltea3ff6702019-05-20 20:03:50 +0200616 basic := valueof(t_CbchPC(msgs_1m_4b_sched)),
617 extended := omit
Harald Welte505cf9b2018-09-15 17:47:23 +0300618 };
619 f_TC_smscb(pars);
620}
621testcase TC_sms_cb_cmd_sdcch8_schedule() runs on test_CT {
622 var CbchTestPars pars := {
623 use_sdcch4 := false,
Harald Weltea3ff6702019-05-20 20:03:50 +0200624 basic := valueof(t_CbchPC(msgs_1m_4b_sched)),
625 extended := omit
Harald Welte505cf9b2018-09-15 17:47:23 +0300626 };
627 f_TC_smscb(pars);
628}
629
Harald Welte88e5dff2019-05-20 15:14:46 +0200630/* set a DEFAULT message; verify it gets transmitted all the time */
631testcase TC_sms_cb_cmd_sdcch4_default_only() runs on test_CT {
632 var CbchTestPars pars := {
633 use_sdcch4 := true,
Harald Weltea3ff6702019-05-20 20:03:50 +0200634 basic := valueof(t_CbchPC(msgs_1m_3b_default)),
635 extended := omit
Harald Welte88e5dff2019-05-20 15:14:46 +0200636 };
637 f_TC_smscb_default_only(pars);
638 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, pass);
639}
640testcase TC_sms_cb_cmd_sdcch8_default_only() runs on test_CT {
641 var CbchTestPars pars := {
642 use_sdcch4 := true,
Harald Weltea3ff6702019-05-20 20:03:50 +0200643 basic := valueof(t_CbchPC(msgs_1m_3b_default)),
644 extended := omit
Harald Welte88e5dff2019-05-20 15:14:46 +0200645 };
646 f_TC_smscb_default_only(pars);
647 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, pass);
648}
649
Harald Welted522ca02019-05-20 20:06:12 +0200650testcase TC_sms_cb_cmd_sdcch4_default_and_normal() runs on test_CT {
651 var CbchTestPars pars := {
652 use_sdcch4 := true,
653 basic := valueof(t_CbchPC(msgs_1m_3b_norm, msg_default)),
654 extended := omit
655 };
656 f_TC_smscb(pars);
657}
658testcase TC_sms_cb_cmd_sdcch8_default_and_normal() runs on test_CT {
659 var CbchTestPars pars := {
660 use_sdcch4 := true,
661 basic := valueof(t_CbchPC(msgs_1m_3b_norm, msg_default)),
662 extended := omit
663 };
664 f_TC_smscb(pars);
665}
666
Harald Weltedf4d0f02019-05-20 16:04:11 +0200667/* first set a DEFAULT message, then disable it again */
668testcase TC_sms_cb_cmd_sdcch4_default_then_null() runs on test_CT {
669 var CbchTestPars pars := {
670 use_sdcch4 := true,
Harald Weltea3ff6702019-05-20 20:03:50 +0200671 basic := valueof(t_CbchPC(msgs_1m_3b_default)),
672 extended := omit
Harald Weltedf4d0f02019-05-20 16:04:11 +0200673 };
Harald Welte6b86b342019-05-27 17:14:36 +0200674 var template RslChannelNr t_chan_nr := t_RslChanNr_CBCH4(0);
Harald Weltedf4d0f02019-05-20 16:04:11 +0200675 var L1ctlDlMessage dl;
676 timer T := 5.0;
677
678 f_TC_smscb_default_only(pars);
679
680 /* disable DEFAULT message; switch back to NULL */
681 f_rsl_smscb_default_null();
682
683 /* ensure whatever initial non-NULL messages have all been drained */
684 f_sleep(5.0);
685 L1CTL.clear;
686
687 T.start;
688 alt {
Harald Welte6b86b342019-05-27 17:14:36 +0200689 [] L1CTL.receive(tr_L1CTL_DATA_IND(t_chan_nr)) -> value dl {
Harald Weltedf4d0f02019-05-20 16:04:11 +0200690 log("CBCH: ", dl);
691 var CBCH_Block cb := dec_CBCH_Block(dl.payload.data_ind.payload);
692 /* detect the proper CBCH messages; check frame number */
693 f_cbch_fn_verify(dl.dl_info.frame_nr, cb);
694 if (not match(cb, tr_CBCH_Block)) {
695 setverdict(fail, "Illegal CBCH Block received: ", cb);
696 } else {
697 if (not match(cb, tr_CBCH_Block(15, ?, ?))) {
698 setverdict(fail, "Unexpected non-NULL CBCH block received");
699 }
700 repeat;
701 }
702 }
703 [] L1CTL.receive { repeat; }
704 [] T.timeout {
705 setverdict(pass);
706 }
707 }
708
709 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, pass);
710}
711
Harald Welte4a129f82019-05-21 16:35:22 +0200712/* Verify there are no CBCH load indications if no CBCH is present */
713testcase TC_cbch_load_idle_no_cbch() runs on test_CT {
714 var ASP_RSL_Unitdata rx_ud;
715 timer T := 10.0;
716
Harald Welte10474062019-05-30 16:48:17 +0200717 f_init();
Harald Welte4a129f82019-05-21 16:35:22 +0200718 f_init_vty_bsc();
719
720 T.start;
721 alt {
722 [] RSL_CCHAN.receive(tr_RSL_UD(tr_RSL_CBCH_LOAD_IND_BASIC)) -> value rx_ud {
723 setverdict(fail, "Received unexpected CBCH LOAD IND: ", rx_ud);
724 }
725 [] RSL_CCHAN.receive(tr_RSL_UD(tr_RSL_CBCH_LOAD_IND_EXTD)) -> value rx_ud {
726 setverdict(fail, "Received unexpected CBCH LOAD IND: ", rx_ud);
727 }
728 [] RSL_CCHAN.receive { repeat; }
729 [] T.timeout {
730 setverdict(pass);
731 }
732 }
733 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
734}
735
736/* Verify the CBCH load indications of an idle cell (without CBCH load) */
737function f_TC_cbc_load_idle() runs on test_CT {
738 template integer tr_slot_count := (2 .. 15);
739 const integer min_load_ind := 4;
740 var integer basic_count := 0;
741 var integer extd_count := 0;
742 var ASP_RSL_Unitdata rx_ud;
743 timer T := 10.0;
744
Harald Welte10474062019-05-30 16:48:17 +0200745 f_init();
Harald Welte4a129f82019-05-21 16:35:22 +0200746
747 RSL_CCHAN.clear;
748 T.start;
749 alt {
750 [] RSL_CCHAN.receive(tr_RSL_UD(tr_RSL_CBCH_LOAD_IND_BASIC(false, tr_slot_count))) {
751 basic_count := basic_count + 1;
752 repeat;
753 }
754 [] RSL_CCHAN.receive(tr_RSL_UD(tr_RSL_CBCH_LOAD_IND_EXTD(false, tr_slot_count))) -> value rx_ud {
755 extd_count := extd_count + 1;
756 repeat;
757 }
758 [] RSL_CCHAN.receive(tr_RSL_UD(tr_RSL_CBCH_LOAD_IND_BASIC)) -> value rx_ud {
759 setverdict(fail, "Received unexpected CBCH LOAD IND: ", rx_ud);
760 }
761 [] RSL_CCHAN.receive(tr_RSL_UD(tr_RSL_CBCH_LOAD_IND_EXTD)) -> value rx_ud {
762 setverdict(fail, "Received unexpected CBCH LOAD IND: ", rx_ud);
763 }
764 [] RSL_CCHAN.receive { repeat; }
765 [] T.timeout {
766 if ((basic_count >= min_load_ind) and (extd_count >= min_load_ind)) {
767 setverdict(pass);
768 } else {
769 setverdict(fail, "Insufficient number of CBCH LOAD IND: ",
770 "BASIC=", basic_count, " EXTD=", extd_count);
771 }
772 }
773 }
774 f_smscb_cleanup();
775 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
776}
777testcase TC_cbc_sdcch4_load_idle() runs on test_CT {
778 f_init_vty_bsc();
779 f_vty_cbch_setup(use_sdcch4 := true);
780 f_TC_cbc_load_idle();
781}
782testcase TC_cbc_sdcch8_load_idle() runs on test_CT {
783 f_init_vty_bsc();
784 f_vty_cbch_setup(use_sdcch4 := false);
785 f_TC_cbc_load_idle();
786}
787
788/* Verify CBCH overload indications are sent when sending too many SMS CB CMD */
789function f_TC_cbc_load_overload(CbchTestPars pars) runs on test_CT {
790 template integer tr_slot_count_basic := (11 .. 13);
791 template integer tr_slot_count_extd := (2 .. 15);
792 const integer min_load_ind := 4;
793 var integer basic_count := 0;
794 var integer extd_count := 0;
795 var ASP_RSL_Unitdata rx_ud;
796 timer T_total := 10.0;
797 timer T_retransmit := 0.2;
798 timer T_initial_guard := 2.0;
799 var integer i;
800
Harald Welte10474062019-05-30 16:48:17 +0200801 f_init();
Harald Welte4a129f82019-05-21 16:35:22 +0200802
803 /* send tons of SMSCB Command */
804 for (i := 0; i < 30; i := i+1) {
805 f_smscb_setup_rsl_chan(pars.basic);
806 }
807
808 /* keep sending SMSCB Commands for another two seconds */
809 T_initial_guard.start;
810 T_retransmit.start;
811 alt {
812 [] T_retransmit.timeout {
813 f_smscb_setup_rsl_chan(pars.basic);
814 T_retransmit.start;
815 repeat;
816 }
817 [] T_initial_guard.timeout { }
818 }
819 /* clear any pending messages (where load may not have peaked yet) */
820 RSL_CCHAN.clear;
821
822 /* keep sending SMSCB Commands while verifying LOAD INDICATIONS */
823 T_total.start;
824 T_retransmit.start;
825 alt {
826 [] RSL_CCHAN.receive(tr_RSL_UD(tr_RSL_CBCH_LOAD_IND_BASIC(true, tr_slot_count_basic))) {
827 basic_count := basic_count + 1;
828 repeat;
829 }
830 [] RSL_CCHAN.receive(tr_RSL_UD(tr_RSL_CBCH_LOAD_IND_EXTD(false, tr_slot_count_extd))) {
831 extd_count := extd_count + 1;
832 repeat;
833 }
834 [] RSL_CCHAN.receive(tr_RSL_UD(tr_RSL_CBCH_LOAD_IND_BASIC)) -> value rx_ud {
835 setverdict(fail, "Received unexpected CBCH LOAD IND: ", rx_ud);
836 }
837 [] RSL_CCHAN.receive(tr_RSL_UD(tr_RSL_CBCH_LOAD_IND_EXTD)) -> value rx_ud {
838 setverdict(fail, "Received unexpected CBCH LOAD IND: ", rx_ud);
839 }
840 [] RSL_CCHAN.receive { repeat; }
841 [] T_retransmit.timeout {
842 f_smscb_setup_rsl_chan(pars.basic);
843 T_retransmit.start;
844 repeat;
845 }
846 [] T_total.timeout {
847 if ((basic_count >= min_load_ind) and (extd_count >= min_load_ind)) {
848 setverdict(pass);
849 } else {
850 setverdict(fail, "Insufficient number of CBCH LOAD IND: ",
851 "BASIC=", basic_count, " EXTD=", extd_count);
852 }
853 }
854 }
855 f_smscb_cleanup();
856 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
857}
858testcase TC_cbc_sdcch4_load_overload() runs on test_CT {
859 var CbchTestPars pars := {
860 use_sdcch4 := true,
861 basic := valueof(t_CbchPC(msgs_1m_3b_norm)),
862 extended := omit
863 };
864
865 f_init_vty_bsc();
866 f_vty_cbch_setup(use_sdcch4 := true);
867 f_TC_cbc_load_overload(pars);
868}
869testcase TC_cbc_sdcch8_load_overload() runs on test_CT {
870 var CbchTestPars pars := {
871 use_sdcch4 := true,
872 basic := valueof(t_CbchPC(msgs_1m_3b_norm)),
873 extended := omit
874 };
875
876 f_init_vty_bsc();
877 f_vty_cbch_setup(use_sdcch4 := true);
878 f_TC_cbc_load_overload(pars);
879}
Harald Weltedf4d0f02019-05-20 16:04:11 +0200880
Harald Welte88e5dff2019-05-20 15:14:46 +0200881
Harald Welte908ce542019-09-04 23:05:40 +0200882private template GsmRrMessage tr_PagingType1 := {
883 header := t_RrHeader(PAGING_REQUEST_TYPE_1, ?),
884 payload :=?
885};
886
887private template GsmRrMessage tr_PagingType1_empty := {
888 header := t_RrHeader(PAGING_REQUEST_TYPE_1, 5),
889 payload := {
890 pag_req_1 := {
891 chan_needed := {
892 second := CHAN_NEED_ANY,
893 first := CHAN_NEED_ANY
894 },
895 page_mode := PAGE_MODE_NORMAL,
896 mi1 := {
897 len := 1,
898 mi := {
899 unused := {
900 pad := '1111'B,
901 odd := false,
902 mi_type := MI_TYPE_NONE
903 }
904 }
905 },
906 mi2 := omit,
907 rest_octets := ?
908 }
909 }
910};
911
912/* we expect four blocks of 14 bytes, let's fill them with content easily distinguishable */
913const octetstring c_etws_seg0 := '000102030405060708090a0b0c0d'O;
914const octetstring c_etws_seg1 := '101112131415161718191a1b1c1d'O;
915const octetstring c_etws_seg2 := '202122232425262728292a2b2c2d'O;
916const octetstring c_etws_seg3 := '303132333435363738393a3b3c3d'O;
917const octetstring c_etws := c_etws_seg0 & c_etws_seg1 & c_etws_seg2 & c_etws_seg3;
918
919/* Ensure only Paging Type 1 with segmented ETWS Primary Notification are sent after RSL_OSMO_ETWS_CMD */
920testcase TC_etws_p1ro() runs on test_CT {
921 var template RslChannelNr t_chan_nr := ts_RslChanNr_PCH_AGCH(0);
922 /* decoding the actual entire P1 rest octets by manually generated code is
923 * too much effort; instead simply do a binary compare to this constant */
924 const bitstring c_P1RO_hdr := '00101011101'B;
925 var integer seg_received[4] := { 0, 0, 0, 0 };
926 var L1ctlDlMessage dl;
927 timer T := 10.0;
928
929 f_init();
930 f_init_l1ctl();
931 f_l1_tune(L1CTL, ccch_mode := CCCH_MODE_COMBINED_CBCH);
932
933 RSL_CCHAN.send(ts_RSL_UD(ts_RSL_OSMO_ETWS_CMD(c_etws)));
934 /* wait for a bit until old non-ETWS Paging messages are gone */
935 f_sleep(1.0);
936 L1CTL.clear;
937 T.start;
938 alt {
939 [] L1CTL.receive(tr_L1CTL_DATA_IND(t_chan_nr)) -> value dl {
940 var GsmRrMessage l3 := dec_GsmRrMessage(dl.payload.data_ind.payload);
941 select (l3) {
942 case (tr_PagingType1_empty) {
943 var octetstring p1ro := l3.payload.pag_req_1.rest_octets;
944 var bitstring midamble := oct2bit(substr(p1ro, 0, 3));
945 var octetstring segment := substr(p1ro, 3, lengthof(p1ro)-3);
946 var BIT1 not_first := substr(midamble, 11, 1);
947 var integer seg_nr := bit2int(substr(midamble, 12, 4));
948 var boolean err := false;
949 if (substr(midamble, 0, 11) != c_P1RO_hdr) {
950 setverdict(fail, "Received unexpected P1 RO header ", midamble);
951 }
952 if (not_first == '1'B) {
953 select (seg_nr) {
954 case (2) {
955 if (segment != c_etws_seg1) {
956 err := true
957 } else {
958 seg_received[1] := seg_received[1] + 1;
959 }}
960 case (3) {
961 if (segment != c_etws_seg2) {
962 err := true
963 } else {
964 seg_received[2] := seg_received[2] + 1;
965 }}
966 case (4) {
967 if (segment != c_etws_seg3) {
968 err := true
969 } else {
970 seg_received[3] := seg_received[3] + 1;
971 }}
972 case else { setverdict(fail, "Unknown segment Nr ", seg_nr); }
973 }
974 if (err) {
975 setverdict(fail, "Unexpected segment ", seg_nr, ": ", segment);
976 }
977 } else {
978 if (seg_nr != 4) {
979 setverdict(fail, "Invalid number of segments ", seg_nr);
980 err := true;
981 }
982 if (segment != c_etws_seg0) {
983 setverdict(fail, "Invalid first segment ", segment);
984 err := true;
985 }
986 if (not err) {
987 seg_received[0] := seg_received[0] + 1;
988 }
989 }
990 }
991 case (tr_PagingType1) {
992 setverdict(fail, "Received unexpected PAGING TYPE 1: ", l3);
993 }
994 }
995 repeat;
996 }
997 [] L1CTL.receive { repeat; }
998 [] T.timeout {
999 setverdict(pass);
1000 }
1001 }
1002 log("Quantity of received ETWS PN segments: ", seg_received);
1003 var integer i;
1004 for (i := 0; i < 4; i := i+1) {
1005 if (seg_received[i] < 15) {
1006 setverdict(fail, "Segment ", i, " not received often enough");
1007 }
1008 }
1009}
1010
1011/* Ensure only Paging Type 1 without ETWS Primary Notification are sent after disabling them */
1012testcase TC_etws_p1ro_end() runs on test_CT {
1013 var template RslChannelNr t_chan_nr := ts_RslChanNr_PCH_AGCH(0);
1014 /* we expect four blocks of 14 bytes, let's fill them with content easily
1015 * distinguishable */
1016 /* decoding the actual entire P1 rest octets by manually generated code is
1017 * too much effort; instead simply do a binary compare to this constant */
1018 const bitstring c_P1RO_hdr := '00101011101'B;
1019 var L1ctlDlMessage dl;
1020 timer T := 10.0;
1021
1022 f_init();
1023 f_init_l1ctl();
1024 f_l1_tune(L1CTL, ccch_mode := CCCH_MODE_COMBINED_CBCH);
1025
1026 RSL_CCHAN.send(ts_RSL_UD(ts_RSL_OSMO_ETWS_CMD(c_etws)));
1027 /* wait for a bit until old non-ETWS Paging messages are gone */
1028 f_sleep(3.0);
1029 /* disable the ETWS PN again */
1030 RSL_CCHAN.send(ts_RSL_UD(ts_RSL_OSMO_ETWS_CMD(''O)));
1031 f_sleep(2.0);
1032 T.start;
1033 L1CTL.clear;
1034 alt {
1035 [] L1CTL.receive(tr_L1CTL_DATA_IND(t_chan_nr)) -> value dl {
1036 var GsmRrMessage l3 := dec_GsmRrMessage(dl.payload.data_ind.payload);
1037 select (l3) {
1038 case (tr_PagingType1_empty) { repeat; }
1039 case (tr_PagingType1) {
1040 setverdict(fail, "Received non-empty PT1 after disabling ETWS PN: ", l3);
1041 }
1042 }
1043 repeat;
1044 }
1045 [] L1CTL.receive { repeat; }
1046 [] T.timeout {
1047 setverdict(pass);
1048 }
1049 }
1050}
1051
Harald Welte11b734c2019-09-05 14:17:54 +02001052/* Ensure ETWS Primary Notification is passed from RSL to PCU interface */
1053testcase TC_etws_pcu() runs on test_CT {
1054 timer T := 10.0;
1055
1056 f_init();
1057 f_init_l1ctl();
1058 f_l1_tune(L1CTL, ccch_mode := CCCH_MODE_COMBINED_CBCH);
1059
1060 RSL_CCHAN.send(ts_RSL_UD(ts_RSL_OSMO_ETWS_CMD(c_etws)));
1061
1062 T.start;
1063 alt {
1064 [] PCU.receive(t_SD_PCUIF(g_pcu_conn_id, tr_PCUIF_APP_INFO_REQ(0, 0, c_etws))) {
1065 setverdict(pass);
1066 }
1067 [] PCU.receive(t_SD_PCUIF(g_pcu_conn_id, tr_PCUIF_APP_INFO_REQ(?, ?, ?))) {
1068 setverdict(fail, "PCU socket received invalid APP INFO");
1069 }
1070 [] PCU.receive { repeat; }
1071 [] T.timeout {
1072 setverdict(fail, "PCU socket timeout receiving APP INFO (ETWS)");
1073 }
1074 }
1075}
1076
1077
Harald Welte908ce542019-09-04 23:05:40 +02001078
Harald Welte505cf9b2018-09-15 17:47:23 +03001079/* SMSCB TODO:
1080 * multiple SMS BC CMD at the same time: Ensure all of them are sent exactly once
1081 * extended CBCH vs. normal CBCH
1082 *
1083 */
1084
1085control {
Harald Welte4a129f82019-05-21 16:35:22 +02001086 execute( TC_cbch_load_idle_no_cbch() );
1087
Harald Welte505cf9b2018-09-15 17:47:23 +03001088 execute( TC_sms_cb_cmd_sdcch4_1block() );
1089 execute( TC_sms_cb_cmd_sdcch4_2block() );
1090 execute( TC_sms_cb_cmd_sdcch4_3block() );
1091 execute( TC_sms_cb_cmd_sdcch4_4block() );
Harald Weltee0026c32019-05-20 00:27:30 +02001092 execute( TC_sms_cb_cmd_sdcch4_multi() );
Harald Welte505cf9b2018-09-15 17:47:23 +03001093 execute( TC_sms_cb_cmd_sdcch4_schedule() );
Harald Welte88e5dff2019-05-20 15:14:46 +02001094 execute( TC_sms_cb_cmd_sdcch4_default_only() );
Harald Welted522ca02019-05-20 20:06:12 +02001095 execute( TC_sms_cb_cmd_sdcch4_default_and_normal() );
Harald Weltedf4d0f02019-05-20 16:04:11 +02001096 execute( TC_sms_cb_cmd_sdcch4_default_then_null() );
Harald Welte4a129f82019-05-21 16:35:22 +02001097 execute( TC_cbc_sdcch4_load_idle() );
1098 execute( TC_cbc_sdcch4_load_overload() );
1099
Harald Welte505cf9b2018-09-15 17:47:23 +03001100 if (false) { /* FIXME: SDCCH/8 support broken, needs trxcon + L1CTL work */
1101 execute( TC_sms_cb_cmd_sdcch8_1block() );
1102 execute( TC_sms_cb_cmd_sdcch8_2block() );
1103 execute( TC_sms_cb_cmd_sdcch8_3block() );
1104 execute( TC_sms_cb_cmd_sdcch8_4block() );
Harald Weltee0026c32019-05-20 00:27:30 +02001105 execute( TC_sms_cb_cmd_sdcch8_multi() );
Harald Welte505cf9b2018-09-15 17:47:23 +03001106 execute( TC_sms_cb_cmd_sdcch8_schedule() );
Harald Welte88e5dff2019-05-20 15:14:46 +02001107 execute( TC_sms_cb_cmd_sdcch8_default_only() );
Harald Welted522ca02019-05-20 20:06:12 +02001108 execute( TC_sms_cb_cmd_sdcch8_default_and_normal() );
Harald Welte4a129f82019-05-21 16:35:22 +02001109 execute( TC_cbc_sdcch8_load_idle() );
1110 execute( TC_cbc_sdcch8_load_overload() );
Harald Welte505cf9b2018-09-15 17:47:23 +03001111 }
Harald Welte908ce542019-09-04 23:05:40 +02001112
1113 execute( TC_etws_p1ro() );
1114 execute( TC_etws_p1ro_end() );
Harald Welte11b734c2019-09-05 14:17:54 +02001115 execute( TC_etws_pcu() );
Harald Welte505cf9b2018-09-15 17:47:23 +03001116}
1117
1118
1119}