blob: 49416c242407740d783f2ba0b798324fbde56c02 [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
29import from Osmocom_VTY_Functions all;
30
31import from BTS_Tests all;
32
33/***********************************************************************
34 * Cell Broadcast related tests
35 ***********************************************************************/
36
Harald Weltea3ff6702019-05-20 20:03:50 +020037/* Test parameters for one channel (e.g. Basic, Extended) */
38type record CbchTestParsChan {
39 /* list of "normal" (sent-once) SMSCB messages */
40 CbchTestMsgs msgs,
41 /* default message, if any */
42 CbchTestMsg default_msg optional
43}
44
45private template (value) CbchTestParsChan
46t_CbchPC(template (value) CbchTestMsgs msgs, template (omit) CbchTestMsg def := omit) := {
47 msgs := msgs,
48 default_msg := def
49}
50
51/* CBCH test parameters for most of our tests */
Harald Welte505cf9b2018-09-15 17:47:23 +030052type record CbchTestPars {
Harald Weltea3ff6702019-05-20 20:03:50 +020053 /* should we execute on SDCCH4 (true) or SDCCH8 (false) ? */
Harald Welte505cf9b2018-09-15 17:47:23 +030054 boolean use_sdcch4,
Harald Weltea3ff6702019-05-20 20:03:50 +020055 /* Parameters for BASIC CBCH */
56 CbchTestParsChan basic,
57 /* Parameters for EXTENDED CBCH */
58 CbchTestParsChan extended optional
Harald Welte505cf9b2018-09-15 17:47:23 +030059};
60
61type record CbchTestMsg {
62 /* config / input data */
63 RSL_CbCommand rsl_cb_cmd,
64 uint2_t last_block, /* 0..3 */
65 octetstring payload,
66 /* computed / result data */
67 CbchBlocks blocks optional
68};
69type record of CbchTestMsg CbchTestMsgs;
70
71/* a single 22byte block within a CbchTestMsg */
72type record CbchBlock {
73 uint4_t seq_nr, /* as per TS 04.12 */
74 boolean is_last,
75 OCT22 payload,
76 boolean seen_once
77};
78type record of CbchBlock CbchBlocks;
79
80/* compute the expected blocks for given test parameters */
81private function f_cbch_compute_exp_blocks(inout CbchTestPars pars) {
Harald Weltea3ff6702019-05-20 20:03:50 +020082 f_cbch_compute_exp_blocks_chan(pars.basic);
83 if (ispresent(pars.extended)) {
84 f_cbch_compute_exp_blocks_chan(pars.extended);
85 }
86}
87private function f_cbch_compute_exp_blocks_chan(inout CbchTestParsChan pars_chan) {
Harald Welte505cf9b2018-09-15 17:47:23 +030088 var integer i;
Harald Weltea3ff6702019-05-20 20:03:50 +020089 for (i := 0; i < lengthof(pars_chan.msgs); i := i+1) {
90 pars_chan.msgs[i].blocks := f_comp_blocks(pars_chan.msgs[i]);
91 }
92 if (ispresent(pars_chan.default_msg)) {
93 pars_chan.default_msg.blocks := f_comp_blocks(pars_chan.default_msg);
Harald Welte505cf9b2018-09-15 17:47:23 +030094 }
95}
96private function f_comp_blocks(in CbchTestMsg msg) return CbchBlocks {
97 var CbchBlocks blocks := {};
98 var integer i;
99
100 for (i := 0; i <= msg.last_block; i := i+1) {
101 var CbchBlock block := {
102 seq_nr := i,
103 is_last := false,
104 payload := substr(msg.payload, 22*i, 22),
105 seen_once := false
106 };
107 if (msg.rsl_cb_cmd == RSL_CB_CMD_SCHEDULE and i == 0) {
108 block.seq_nr := 8;
109 }
110 if (i == msg.last_block) {
111 block.is_last := true;
112 }
113 blocks := blocks & {block};
114 }
115
116 return blocks;
117};
118
119/* TS 48.058 Section 9.3.41 */
120private function f_cbch_block_nr2rsl(uint2_t nr) return uint2_t {
121 select (nr) {
122 case (0) { return 1; }
123 case (1) { return 2; }
124 case (2) { return 3; }
125 case (3) { return 0; }
126 }
127 setverdict(fail, "Invalid block number");
128 mtc.stop;
129}
130
Harald Welte88e5dff2019-05-20 15:14:46 +0200131private function f_cbch_fn2tb(uint32_t fn) return integer
132{
133 return (fn/51) mod 8; /* TS 05.02 Section 6.5.4 */
134}
135
Harald Welte505cf9b2018-09-15 17:47:23 +0300136/* Verify the CBCH TB scheduling rules of TS 05.02 Section 6.5.4 */
137private function f_cbch_fn_verify(uint32_t fn, CBCH_Block cb)
138{
Harald Welte88e5dff2019-05-20 15:14:46 +0200139 var integer tb := f_cbch_fn2tb(fn);
Harald Welte505cf9b2018-09-15 17:47:23 +0300140 if (cb.block_type.seq_nr == 15 /* null */) {
141 /* always permitted */
142 return;
143 } else if (cb.block_type.seq_nr == 8 /* schedule */) {
144 if (tb != 0) {
145 setverdict(fail, "Schedule block at TB=", tb);
146 }
147 } else if (cb.block_type.seq_nr < 4) {
148 if (cb.block_type.seq_nr != tb and cb.block_type.seq_nr+4 != tb) {
149 setverdict(fail, "Normal block at wrong TB=", tb, ": ", cb);
150 }
151 }
152}
153
Harald Weltedf4d0f02019-05-20 16:04:11 +0200154private function f_rsl_smscb_default_null() runs on test_CT
155{
156 var RSL_IE_CbCommandType cmd_type :=
157 valueof(ts_RSL_IE_CbCmdType(RSL_CB_CMD_DEFAULT, 1, true));
158 RSL_CCHAN.send(ts_RSL_UD(ts_RSL_SMSCB_CMD(cmd_type, ''O)));
159}
160
Harald Weltea3ff6702019-05-20 20:03:50 +0200161template RSL_IE t_RSL_IE_SMSCB_EXT := t_RSL_IE(RSL_IE_SMSCB_CHAN_INDICATOR, {smscb_chan_ind := 1});
162
163private function f_smscb_setup_rsl_chan(inout CbchTestParsChan pars_chan, boolean extd := false)
164runs on test_CT {
Harald Welte88e5dff2019-05-20 15:14:46 +0200165 var integer i;
Harald Weltea3ff6702019-05-20 20:03:50 +0200166 var CbchTestMsg msg;
167 var uint2_t rsl_last_block;
168 var RSL_IE_CbCommandType cmd_type;
169 var RSL_Message rsl;
170
171 /* send SMSCB[s] via RSL */
172 for (i := 0; i < lengthof(pars_chan.msgs); i := i+1) {
173 msg := pars_chan.msgs[i];
174 rsl_last_block := f_cbch_block_nr2rsl(msg.last_block);
175 cmd_type := valueof(ts_RSL_IE_CbCmdType(msg.rsl_cb_cmd, rsl_last_block));
176 rsl := valueof(ts_RSL_SMSCB_CMD(cmd_type, msg.payload));
177 if (extd) {
178 rsl.ies := rsl.ies & { valueof(t_RSL_IE_SMSCB_EXT) };
179 }
180 RSL_CCHAN.send(ts_RSL_UD(rsl));
181 }
182 if (ispresent(pars_chan.default_msg)) {
183 msg := pars_chan.default_msg;
184 rsl_last_block := f_cbch_block_nr2rsl(msg.last_block);
185 cmd_type := valueof(ts_RSL_IE_CbCmdType(msg.rsl_cb_cmd, rsl_last_block, false));
186 rsl := valueof(ts_RSL_SMSCB_CMD(cmd_type, msg.payload));
187 if (extd) {
188 rsl.ies := rsl.ies & { valueof(t_RSL_IE_SMSCB_EXT) };
189 }
190 RSL_CCHAN.send(ts_RSL_UD(rsl));
191 }
192}
Harald Welte505cf9b2018-09-15 17:47:23 +0300193
Harald Welte4a129f82019-05-21 16:35:22 +0200194private function f_vty_cbch_setup(boolean use_sdcch4 := true) runs on test_CT {
Harald Welte505cf9b2018-09-15 17:47:23 +0300195
Harald Welte4a129f82019-05-21 16:35:22 +0200196 if (use_sdcch4 == true) {
Harald Welte505cf9b2018-09-15 17:47:23 +0300197 f_vty_config2(BSCVTY, {"network", "bts 0", "trx 0", "timeslot 0"},
198 "phys_chan_config CCCH+SDCCH4+CBCH");
199 f_vty_config2(BSCVTY, {"network", "bts 0", "trx 0", "timeslot 6"},
200 "phys_chan_config SDCCH8");
201 } else {
202 f_vty_config2(BSCVTY, {"network", "bts 0", "trx 0", "timeslot 0"},
203 "phys_chan_config CCCH+SDCCH4");
204 f_vty_config2(BSCVTY, {"network", "bts 0", "trx 0", "timeslot 6"},
205 "phys_chan_config SDCCH8+CBCH");
206 }
207 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
208 f_sleep(2.0);
Harald Welte4a129f82019-05-21 16:35:22 +0200209}
210private function f_smscb_setup(inout CbchTestPars pars) runs on test_CT {
211
212 f_cbch_compute_exp_blocks(pars);
213
214 f_init_vty_bsc();
215 /* ensure that a CBCH is present in channel combination */
216 f_vty_cbch_setup(pars.use_sdcch4);
Harald Welte10474062019-05-30 16:48:17 +0200217 f_init();
Harald Welte505cf9b2018-09-15 17:47:23 +0300218
219 f_init_l1ctl();
Harald Welte990a3612019-05-27 14:02:13 +0200220 f_l1_tune(L1CTL, ccch_mode := CCCH_MODE_COMBINED_CBCH);
Harald Welte505cf9b2018-09-15 17:47:23 +0300221 /* FIXME: switch to dedicated mode for SDCCH/8 */
222
223 /* send SMSCB[s] via RSL */
Harald Weltea3ff6702019-05-20 20:03:50 +0200224 f_smscb_setup_rsl_chan(pars.basic, false);
225 if (ispresent(pars.extended)) {
226 f_smscb_setup_rsl_chan(pars.extended, true);
Harald Welte505cf9b2018-09-15 17:47:23 +0300227 }
Harald Welte88e5dff2019-05-20 15:14:46 +0200228}
229
230private function f_smscb_cleanup() runs on test_CT {
231 /* reset timeslot 0 channel combination to default */
232 f_vty_config2(BSCVTY, {"network", "bts 0", "trx 0", "timeslot 0"},
233 "phys_chan_config CCCH+SDCCH4");
234 f_vty_config2(BSCVTY, {"network", "bts 0", "trx 0", "timeslot 6"},
235 "phys_chan_config SDCCH8");
236}
237
Harald Weltea3ff6702019-05-20 20:03:50 +0200238/* construct a receive/match template for given block_nr in given msg */
239private function f_get_block_template(CbchTestMsg msg, integer block_nr) return template CBCH_Block {
240 var template CBCH_Block tr;
241 if (block_nr < lengthof(msg.blocks)) {
242 var CbchBlock b := msg.blocks[block_nr];
243 tr := tr_CBCH_Block(b.seq_nr, b.is_last, b.payload);
244 } else {
245 tr := tr_CBCH_Block(15, ?, ?);
246 }
247 return tr;
248}
249
250/* the heart of the CBCH test case matching engine for one channel (basic, extended) */
251private function f_cbch_match(inout CbchTestParsChan pars_chan, CBCH_Block cb, integer tb)
252{
253 var integer block_nr := tb mod 4;
254 var integer i;
255
256 if (not match(cb, tr_CBCH_Block)) {
257 setverdict(fail, "Illegal CBCH Block received: ", cb);
258 } else {
259 var boolean matched := false;
260 /* check if it's any of our expected blocks */
261 for (i := 0; i < lengthof(pars_chan.msgs); i := i+1) {
262 if (block_nr < lengthof(pars_chan.msgs[i].blocks)) {
263 if (match(cb, f_get_block_template(pars_chan.msgs[i], block_nr))) {
264 log("Found block_nr ", block_nr, " of msg ", i);
265 if (not pars_chan.msgs[i].blocks[block_nr].seen_once) {
266 pars_chan.msgs[i].blocks[block_nr].seen_once := true;
267 setverdict(pass);
268 } else {
269 setverdict(fail, "Received SMSCB twice! ", cb);
270 }
271 matched := true;
272 break;
273 }
274 }
275 }
276 if (not matched) {
277 var template CBCH_Block tr;
278 if (ispresent(pars_chan.default_msg)) {
279 /* it must be a block of the default message */
280 tr := f_get_block_template(pars_chan.default_msg, block_nr);
281 } else {
282 /* it must be a NULL block */
283 tr := tr_CBCH_Block(15, ?, ?);
284 }
285 if (not match(cb, tr)) {
286 setverdict(fail, "Received unexpected CBCH block: ", cb);
287 } else {
288 log("Found block_nr ", block_nr, " of DEFAULT/NULL");
289 if (ispresent(pars_chan.default_msg) and
290 block_nr < lengthof(pars_chan.default_msg.blocks)) {
291 pars_chan.default_msg.blocks[block_nr].seen_once := true;
292 }
293 }
294 }
295 }
296}
297
298/* Report/Evaluate the per-channel CBCH test results */
299private function f_cbch_report(CbchTestParsChan pars_chan, charstring id)
300{
301 var integer i, j;
302
303 /* verify that each block of each message has been seen once */
304 for (i := 0; i < lengthof(pars_chan.msgs); i := i+1) {
305 for (j := 0; j < lengthof(pars_chan.msgs[i].blocks); j := j+1) {
306 var CbchBlock b := pars_chan.msgs[i].blocks[j];
307 if (not b.seen_once) {
308 setverdict(fail, "Timeout waiting for ", id, " CBCH block ",
309 j, " of msg ", i);
310 }
311 }
312 }
313 if (ispresent(pars_chan.default_msg)) {
314 /* verify that each block of default message has been seen at least once */
315 for (j := 0; j < lengthof(pars_chan.default_msg.blocks); j := j+1) {
316 var CbchBlock b := pars_chan.default_msg.blocks[j];
317 if (not b.seen_once) {
318 setverdict(fail, "Timeout waiting for at leaset one instance of ",
319 "CBCH block ", j, " of DEFAULT msg");
320 }
321 }
322 }
323}
324
Harald Welte6b86b342019-05-27 17:14:36 +0200325private function t_cbch_chan_nr(CbchTestPars pars, template uint8_t tn) return template RslChannelNr {
326 if (pars.use_sdcch4) {
327 return t_RslChanNr_CBCH4(tn);
328 } else {
329 return t_RslChanNr_CBCH8(tn);
330 }
331}
332
Harald Welte88e5dff2019-05-20 15:14:46 +0200333/* shared function doing the heavy lifting for most CBCH tests */
334private function f_TC_smscb(CbchTestPars pars) runs on test_CT {
Harald Welte6b86b342019-05-27 17:14:36 +0200335 var template RslChannelNr t_chan_nr := t_cbch_chan_nr(pars, 0); /* FIXME: TS number */
Harald Welte88e5dff2019-05-20 15:14:46 +0200336 var L1ctlDlMessage dl;
Harald Weltea3ff6702019-05-20 20:03:50 +0200337 var integer msg_count;
338 timer T;
339
340 msg_count := lengthof(pars.basic.msgs);
341 if (ispresent(pars.basic.default_msg)) {
342 msg_count := msg_count + 1;
343 }
344 if (ispresent(pars.extended)) {
345 msg_count := msg_count + lengthof(pars.extended.msgs);
346 if (ispresent(pars.extended.default_msg)) {
347 msg_count := msg_count + 1;
348 }
349 }
Harald Welte88e5dff2019-05-20 15:14:46 +0200350
351 f_smscb_setup(pars);
352
Harald Weltea3ff6702019-05-20 20:03:50 +0200353 /* dynamically adjust timeout based on number of messages */
354 T.start(5.0 + 3.0 * int2float(msg_count));
Harald Welte505cf9b2018-09-15 17:47:23 +0300355 /* Expect this to show up exactly once on the basic CBCH (four blocks) */
356 alt {
Harald Welte6b86b342019-05-27 17:14:36 +0200357 [] L1CTL.receive(tr_L1CTL_DATA_IND(t_chan_nr)) -> value dl {
Harald Weltea3ff6702019-05-20 20:03:50 +0200358 var integer tb := f_cbch_fn2tb(dl.dl_info.frame_nr);
Harald Welte505cf9b2018-09-15 17:47:23 +0300359 var CBCH_Block cb := dec_CBCH_Block(dl.payload.data_ind.payload);
Harald Weltea3ff6702019-05-20 20:03:50 +0200360 log("Tb=", tb, ", CBCH: ", dl, ", block: ", cb);
361
Harald Welte505cf9b2018-09-15 17:47:23 +0300362 /* detect the proper CBCH messages; check frame number */
363 f_cbch_fn_verify(dl.dl_info.frame_nr, cb);
Harald Weltea3ff6702019-05-20 20:03:50 +0200364
365 if (tb < 4) {
366 f_cbch_match(pars.basic, cb, tb);
Harald Welte505cf9b2018-09-15 17:47:23 +0300367 } else {
Harald Weltea3ff6702019-05-20 20:03:50 +0200368 if (not ispresent(pars.extended)) {
369 /* no parameters for ext. BCCH given: ignore */
370 repeat;
Harald Welte505cf9b2018-09-15 17:47:23 +0300371 }
Harald Weltea3ff6702019-05-20 20:03:50 +0200372 f_cbch_match(pars.extended, cb, tb);
Harald Welte505cf9b2018-09-15 17:47:23 +0300373 }
Harald Weltea3ff6702019-05-20 20:03:50 +0200374 repeat;
Harald Welte505cf9b2018-09-15 17:47:23 +0300375 }
376 [] L1CTL.receive { repeat; }
377 [] T.timeout {
Harald Weltea3ff6702019-05-20 20:03:50 +0200378 f_cbch_report(pars.basic, "Basic");
379 if (ispresent(pars.extended)) {
380 f_cbch_report(pars.extended, "Extended");
Harald Welte505cf9b2018-09-15 17:47:23 +0300381 }
382 }
383 }
384
Harald Welte88e5dff2019-05-20 15:14:46 +0200385 f_smscb_cleanup();
386 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, pass);
387}
388
389private function f_TC_smscb_default_only(CbchTestPars pars) runs on test_CT {
Harald Welte6b86b342019-05-27 17:14:36 +0200390 var template RslChannelNr t_chan_nr := t_cbch_chan_nr(pars, 0); /* FIXME: TS number */
Harald Welte88e5dff2019-05-20 15:14:46 +0200391 var L1ctlDlMessage dl;
392 timer T := 5.0;
393
394 f_smscb_setup(pars);
395
396 /* ensure whatever initial NULL messages have all been drained */
397 f_sleep(5.0);
398 L1CTL.clear;
399
400 T.start;
401 alt {
Harald Welte6b86b342019-05-27 17:14:36 +0200402 [] L1CTL.receive(tr_L1CTL_DATA_IND(t_chan_nr)) -> value dl {
Harald Welte88e5dff2019-05-20 15:14:46 +0200403 var integer tb := f_cbch_fn2tb(dl.dl_info.frame_nr);
404 log("CBCH: ", dl);
405 var CBCH_Block cb := dec_CBCH_Block(dl.payload.data_ind.payload);
406 /* detect the proper CBCH messages; check frame number */
407 f_cbch_fn_verify(dl.dl_info.frame_nr, cb);
408 if (tb >= 4) {
409 /* skip extended CBCH for now */
410 repeat;
411 }
412 if (not match(cb, tr_CBCH_Block)) {
413 setverdict(fail, "Illegal CBCH Block received: ", cb);
414 } else {
415 var uint4_t rx_seq_nr := cb.block_type.seq_nr;
416 var template CBCH_Block tr;
Harald Weltea3ff6702019-05-20 20:03:50 +0200417 if (rx_seq_nr < lengthof(pars.basic.msgs[0].blocks)) {
418 var CbchBlock b := pars.basic.msgs[0].blocks[rx_seq_nr];
Harald Welte88e5dff2019-05-20 15:14:46 +0200419 tr := tr_CBCH_Block(b.seq_nr, b.is_last, b.payload);
420 } else {
421 tr := tr_CBCH_Block(15, ?, ?);
422 }
423 if (match(cb, tr)) {
424 setverdict(pass); /* FIXME: check that all blocks are received? */
425 repeat;
426 } else {
427 setverdict(fail, "Unexpected CBCH block ", cb, ", expected ", tr);
428 }
429 }
430 }
431 [] L1CTL.receive { repeat; }
432 [] T.timeout {}
433 }
434
435 f_smscb_cleanup();
436 /* don't shut down; some tests still want to continue */
Harald Welte505cf9b2018-09-15 17:47:23 +0300437}
438
439private const CbchTestMsgs msgs_1m_1b_norm := {
440 { RSL_CB_CMD_NORMAL, 0, '001000320f1141660c344dd3cba09a0c000000000000'O, omit }
441}
442
443private const CbchTestMsgs msgs_1m_2b_norm := {
444 { RSL_CB_CMD_NORMAL, 1, '001000320f1141660c344dd3cba09a0c000000000000'O &
445 '000102030405060708090a0b0c0d0e0f101213141516'O,
446 omit }
447}
448
449private const CbchTestMsgs msgs_1m_3b_norm := {
450 { RSL_CB_CMD_NORMAL, 2, '001000320f1141660c344dd3cba09a0c000000000000'O &
451 '000102030405060708090a0b0c0d0e0f101213141516'O &
452 '101112131415161718191a1b1c1d1e1f202223242526'O,
453 omit }
454}
455
456private const CbchTestMsgs msgs_1m_4b_norm := {
457 { RSL_CB_CMD_NORMAL, 3, '001000320f1141660c344dd3cba09a0c000000000000'O &
458 '000102030405060708090a0b0c0d0e0f101213141516'O &
459 '101112131415161718191a1b1c1d1e1f202223242526'O &
460 '202122232425262728292a2b2c2d2e2f303233343536'O,
461 omit }
462}
463
464private const CbchTestMsgs msgs_1m_4b_sched := {
465 { RSL_CB_CMD_SCHEDULE, 3, '001000320f1141660c344dd3cba09a0c000000000000'O &
466 '000102030405060708090a0b0c0d0e0f101213141516'O &
467 '101112131415161718191a1b1c1d1e1f202223242526'O &
468 '202122232425262728292a2b2c2d2e2f303233343536'O,
469 omit }
470}
471
Harald Weltee0026c32019-05-20 00:27:30 +0200472private const CbchTestMsgs msgs_3m_4b_norm := {
473 { RSL_CB_CMD_NORMAL, 3, '001000320f1141660c344dd3cba09a0c000000000000'O &
474 '000102030405060708090a0b0c0d0e0f101213141516'O &
475 '101112131415161718191a1b1c1d1e1f202223242526'O &
476 '201122232425262728292a2b2c2d2e2f303233343536'O,
477 omit },
478 { RSL_CB_CMD_NORMAL, 3, '002000320f1141660c344dd3cba09a0c000000000000'O &
479 '002102030405060708090a0b0c0d0e0f101213141516'O &
480 '102112131415161718191a1b1c1d1e1f202223242526'O &
481 '202122232425262728292a2b2c2d2e2f303233343536'O,
482 omit },
483 { RSL_CB_CMD_NORMAL, 3, '003000320f1141660c344dd3cba09a0c000000000000'O &
484 '003102030405060708090a0b0c0d0e0f101213141516'O &
485 '103112131415161718191a1b1c1d1e1f202223242526'O &
486 '203122232425262728292a2b2c2d2e2f303233343536'O,
487 omit }
488}
489
Harald Welte88e5dff2019-05-20 15:14:46 +0200490private const CbchTestMsgs msgs_1m_3b_default := {
491 { RSL_CB_CMD_DEFAULT, 2, '001000320f1141660c344dd3cba09a0c000000000000'O &
492 '000102030405060708090a0b0c0d0e0f101213141516'O &
493 '101112131415161718191a1b1c1d1e1f202223242526'O,
494 omit }
495}
Harald Weltea3ff6702019-05-20 20:03:50 +0200496private const CbchTestMsg msg_default := {
497 RSL_CB_CMD_DEFAULT, 0, '010203040506070708090a0b0c0d0e0f101112131415'O,
498 omit
499}
Harald Welte88e5dff2019-05-20 15:14:46 +0200500
Harald Welte505cf9b2018-09-15 17:47:23 +0300501/* transmit single-block SMSCB COMMAND */
502testcase TC_sms_cb_cmd_sdcch4_1block() runs on test_CT {
503 var CbchTestPars pars := {
504 use_sdcch4 := true,
Harald Weltea3ff6702019-05-20 20:03:50 +0200505 basic := valueof(t_CbchPC(msgs_1m_1b_norm)),
506 extended := omit
Harald Welte505cf9b2018-09-15 17:47:23 +0300507 };
508 f_TC_smscb(pars);
509}
510testcase TC_sms_cb_cmd_sdcch8_1block() runs on test_CT {
511 var CbchTestPars pars := {
512 use_sdcch4 := false,
Harald Weltea3ff6702019-05-20 20:03:50 +0200513 basic := valueof(t_CbchPC(msgs_1m_1b_norm)),
514 extended := omit
Harald Welte505cf9b2018-09-15 17:47:23 +0300515 };
516 f_TC_smscb(pars);
517}
518
519/* transmit dual-block SMSCB COMMAND */
520testcase TC_sms_cb_cmd_sdcch4_2block() runs on test_CT {
521 var CbchTestPars pars := {
522 use_sdcch4 := true,
Harald Weltea3ff6702019-05-20 20:03:50 +0200523 basic := valueof(t_CbchPC(msgs_1m_2b_norm)),
524 extended := omit
Harald Welte505cf9b2018-09-15 17:47:23 +0300525 };
526 f_TC_smscb(pars);
527}
528testcase TC_sms_cb_cmd_sdcch8_2block() runs on test_CT {
529 var CbchTestPars pars := {
530 use_sdcch4 := false,
Harald Weltea3ff6702019-05-20 20:03:50 +0200531 basic := valueof(t_CbchPC(msgs_1m_2b_norm)),
532 extended := omit
Harald Welte505cf9b2018-09-15 17:47:23 +0300533 };
534 f_TC_smscb(pars);
535}
536
537/* transmit triple-block SMSCB COMMAND */
538testcase TC_sms_cb_cmd_sdcch4_3block() runs on test_CT {
539 var CbchTestPars pars := {
540 use_sdcch4 := true,
Harald Weltea3ff6702019-05-20 20:03:50 +0200541 basic := valueof(t_CbchPC(msgs_1m_3b_norm)),
542 extended := omit
Harald Welte505cf9b2018-09-15 17:47:23 +0300543 };
544 f_TC_smscb(pars);
545}
546testcase TC_sms_cb_cmd_sdcch8_3block() runs on test_CT {
547 var CbchTestPars pars := {
548 use_sdcch4 := false,
Harald Weltea3ff6702019-05-20 20:03:50 +0200549 basic := valueof(t_CbchPC(msgs_1m_3b_norm)),
550 extended := omit
Harald Welte505cf9b2018-09-15 17:47:23 +0300551 };
552 f_TC_smscb(pars);
553}
554
555/* transmit quad-block SMSCB COMMAND */
556testcase TC_sms_cb_cmd_sdcch4_4block() runs on test_CT {
557 var CbchTestPars pars := {
558 use_sdcch4 := true,
Harald Weltea3ff6702019-05-20 20:03:50 +0200559 basic := valueof(t_CbchPC(msgs_1m_4b_norm)),
560 extended := omit
Harald Welte505cf9b2018-09-15 17:47:23 +0300561 };
562 f_TC_smscb(pars);
563}
564testcase TC_sms_cb_cmd_sdcch8_4block() runs on test_CT {
565 var CbchTestPars pars := {
566 use_sdcch4 := false,
Harald Weltea3ff6702019-05-20 20:03:50 +0200567 basic := valueof(t_CbchPC(msgs_1m_4b_norm)),
568 extended := omit
Harald Welte505cf9b2018-09-15 17:47:23 +0300569 };
570 f_TC_smscb(pars);
571}
572
Harald Weltee0026c32019-05-20 00:27:30 +0200573/* transmit multiple commands of each 4 blocks */
574testcase TC_sms_cb_cmd_sdcch4_multi() runs on test_CT {
575 var CbchTestPars pars := {
576 use_sdcch4 := true,
Harald Weltea3ff6702019-05-20 20:03:50 +0200577 basic := valueof(t_CbchPC(msgs_3m_4b_norm)),
578 extended := omit
Harald Weltee0026c32019-05-20 00:27:30 +0200579 };
580 f_TC_smscb(pars);
581}
582testcase TC_sms_cb_cmd_sdcch8_multi() runs on test_CT {
583 var CbchTestPars pars := {
584 use_sdcch4 := false,
Harald Weltea3ff6702019-05-20 20:03:50 +0200585 basic := valueof(t_CbchPC(msgs_3m_4b_norm)),
586 extended := omit
Harald Weltee0026c32019-05-20 00:27:30 +0200587 };
588 f_TC_smscb(pars);
589}
590
Harald Welte60bd92b2019-05-20 21:42:21 +0200591/* transmit multiple commands of each 4 blocks on CBCH EXTD */
592testcase TC_sms_cb_cmd_sdcch4_extd_multi() runs on test_CT {
593 var CbchTestPars pars := {
594 use_sdcch4 := true,
595 basic := valueof(t_CbchPC({})),
596 extended := valueof(t_CbchPC(msgs_3m_4b_norm))
597 };
598 f_TC_smscb(pars);
599}
600testcase TC_sms_cb_cmd_sdcch8_extd_multi() runs on test_CT {
601 var CbchTestPars pars := {
602 use_sdcch4 := false,
603 basic := valueof(t_CbchPC({})),
604 extended := valueof(t_CbchPC(msgs_3m_4b_norm))
605 };
606 f_TC_smscb(pars);
607}
608
Harald Welte505cf9b2018-09-15 17:47:23 +0300609/* transmit SMSCB COMMAND with SCHEDULE payload */
610testcase TC_sms_cb_cmd_sdcch4_schedule() runs on test_CT {
611 var CbchTestPars pars := {
612 use_sdcch4 := true,
Harald Weltea3ff6702019-05-20 20:03:50 +0200613 basic := valueof(t_CbchPC(msgs_1m_4b_sched)),
614 extended := omit
Harald Welte505cf9b2018-09-15 17:47:23 +0300615 };
616 f_TC_smscb(pars);
617}
618testcase TC_sms_cb_cmd_sdcch8_schedule() runs on test_CT {
619 var CbchTestPars pars := {
620 use_sdcch4 := false,
Harald Weltea3ff6702019-05-20 20:03:50 +0200621 basic := valueof(t_CbchPC(msgs_1m_4b_sched)),
622 extended := omit
Harald Welte505cf9b2018-09-15 17:47:23 +0300623 };
624 f_TC_smscb(pars);
625}
626
Harald Welte88e5dff2019-05-20 15:14:46 +0200627/* set a DEFAULT message; verify it gets transmitted all the time */
628testcase TC_sms_cb_cmd_sdcch4_default_only() runs on test_CT {
629 var CbchTestPars pars := {
630 use_sdcch4 := true,
Harald Weltea3ff6702019-05-20 20:03:50 +0200631 basic := valueof(t_CbchPC(msgs_1m_3b_default)),
632 extended := omit
Harald Welte88e5dff2019-05-20 15:14:46 +0200633 };
634 f_TC_smscb_default_only(pars);
635 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, pass);
636}
637testcase TC_sms_cb_cmd_sdcch8_default_only() runs on test_CT {
638 var CbchTestPars pars := {
639 use_sdcch4 := true,
Harald Weltea3ff6702019-05-20 20:03:50 +0200640 basic := valueof(t_CbchPC(msgs_1m_3b_default)),
641 extended := omit
Harald Welte88e5dff2019-05-20 15:14:46 +0200642 };
643 f_TC_smscb_default_only(pars);
644 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, pass);
645}
646
Harald Welted522ca02019-05-20 20:06:12 +0200647testcase TC_sms_cb_cmd_sdcch4_default_and_normal() runs on test_CT {
648 var CbchTestPars pars := {
649 use_sdcch4 := true,
650 basic := valueof(t_CbchPC(msgs_1m_3b_norm, msg_default)),
651 extended := omit
652 };
653 f_TC_smscb(pars);
654}
655testcase TC_sms_cb_cmd_sdcch8_default_and_normal() runs on test_CT {
656 var CbchTestPars pars := {
657 use_sdcch4 := true,
658 basic := valueof(t_CbchPC(msgs_1m_3b_norm, msg_default)),
659 extended := omit
660 };
661 f_TC_smscb(pars);
662}
663
Harald Weltedf4d0f02019-05-20 16:04:11 +0200664/* first set a DEFAULT message, then disable it again */
665testcase TC_sms_cb_cmd_sdcch4_default_then_null() runs on test_CT {
666 var CbchTestPars pars := {
667 use_sdcch4 := true,
Harald Weltea3ff6702019-05-20 20:03:50 +0200668 basic := valueof(t_CbchPC(msgs_1m_3b_default)),
669 extended := omit
Harald Weltedf4d0f02019-05-20 16:04:11 +0200670 };
Harald Welte6b86b342019-05-27 17:14:36 +0200671 var template RslChannelNr t_chan_nr := t_RslChanNr_CBCH4(0);
Harald Weltedf4d0f02019-05-20 16:04:11 +0200672 var L1ctlDlMessage dl;
673 timer T := 5.0;
674
675 f_TC_smscb_default_only(pars);
676
677 /* disable DEFAULT message; switch back to NULL */
678 f_rsl_smscb_default_null();
679
680 /* ensure whatever initial non-NULL messages have all been drained */
681 f_sleep(5.0);
682 L1CTL.clear;
683
684 T.start;
685 alt {
Harald Welte6b86b342019-05-27 17:14:36 +0200686 [] L1CTL.receive(tr_L1CTL_DATA_IND(t_chan_nr)) -> value dl {
Harald Weltedf4d0f02019-05-20 16:04:11 +0200687 log("CBCH: ", dl);
688 var CBCH_Block cb := dec_CBCH_Block(dl.payload.data_ind.payload);
689 /* detect the proper CBCH messages; check frame number */
690 f_cbch_fn_verify(dl.dl_info.frame_nr, cb);
691 if (not match(cb, tr_CBCH_Block)) {
692 setverdict(fail, "Illegal CBCH Block received: ", cb);
693 } else {
694 if (not match(cb, tr_CBCH_Block(15, ?, ?))) {
695 setverdict(fail, "Unexpected non-NULL CBCH block received");
696 }
697 repeat;
698 }
699 }
700 [] L1CTL.receive { repeat; }
701 [] T.timeout {
702 setverdict(pass);
703 }
704 }
705
706 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, pass);
707}
708
Harald Welte4a129f82019-05-21 16:35:22 +0200709/* Verify there are no CBCH load indications if no CBCH is present */
710testcase TC_cbch_load_idle_no_cbch() runs on test_CT {
711 var ASP_RSL_Unitdata rx_ud;
712 timer T := 10.0;
713
Harald Welte10474062019-05-30 16:48:17 +0200714 f_init();
Harald Welte4a129f82019-05-21 16:35:22 +0200715 f_init_vty_bsc();
716
717 T.start;
718 alt {
719 [] RSL_CCHAN.receive(tr_RSL_UD(tr_RSL_CBCH_LOAD_IND_BASIC)) -> value rx_ud {
720 setverdict(fail, "Received unexpected CBCH LOAD IND: ", rx_ud);
721 }
722 [] RSL_CCHAN.receive(tr_RSL_UD(tr_RSL_CBCH_LOAD_IND_EXTD)) -> value rx_ud {
723 setverdict(fail, "Received unexpected CBCH LOAD IND: ", rx_ud);
724 }
725 [] RSL_CCHAN.receive { repeat; }
726 [] T.timeout {
727 setverdict(pass);
728 }
729 }
730 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
731}
732
733/* Verify the CBCH load indications of an idle cell (without CBCH load) */
734function f_TC_cbc_load_idle() runs on test_CT {
735 template integer tr_slot_count := (2 .. 15);
736 const integer min_load_ind := 4;
737 var integer basic_count := 0;
738 var integer extd_count := 0;
739 var ASP_RSL_Unitdata rx_ud;
740 timer T := 10.0;
741
Harald Welte10474062019-05-30 16:48:17 +0200742 f_init();
Harald Welte4a129f82019-05-21 16:35:22 +0200743
744 RSL_CCHAN.clear;
745 T.start;
746 alt {
747 [] RSL_CCHAN.receive(tr_RSL_UD(tr_RSL_CBCH_LOAD_IND_BASIC(false, tr_slot_count))) {
748 basic_count := basic_count + 1;
749 repeat;
750 }
751 [] RSL_CCHAN.receive(tr_RSL_UD(tr_RSL_CBCH_LOAD_IND_EXTD(false, tr_slot_count))) -> value rx_ud {
752 extd_count := extd_count + 1;
753 repeat;
754 }
755 [] RSL_CCHAN.receive(tr_RSL_UD(tr_RSL_CBCH_LOAD_IND_BASIC)) -> value rx_ud {
756 setverdict(fail, "Received unexpected CBCH LOAD IND: ", rx_ud);
757 }
758 [] RSL_CCHAN.receive(tr_RSL_UD(tr_RSL_CBCH_LOAD_IND_EXTD)) -> value rx_ud {
759 setverdict(fail, "Received unexpected CBCH LOAD IND: ", rx_ud);
760 }
761 [] RSL_CCHAN.receive { repeat; }
762 [] T.timeout {
763 if ((basic_count >= min_load_ind) and (extd_count >= min_load_ind)) {
764 setverdict(pass);
765 } else {
766 setverdict(fail, "Insufficient number of CBCH LOAD IND: ",
767 "BASIC=", basic_count, " EXTD=", extd_count);
768 }
769 }
770 }
771 f_smscb_cleanup();
772 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
773}
774testcase TC_cbc_sdcch4_load_idle() runs on test_CT {
775 f_init_vty_bsc();
776 f_vty_cbch_setup(use_sdcch4 := true);
777 f_TC_cbc_load_idle();
778}
779testcase TC_cbc_sdcch8_load_idle() runs on test_CT {
780 f_init_vty_bsc();
781 f_vty_cbch_setup(use_sdcch4 := false);
782 f_TC_cbc_load_idle();
783}
784
785/* Verify CBCH overload indications are sent when sending too many SMS CB CMD */
786function f_TC_cbc_load_overload(CbchTestPars pars) runs on test_CT {
787 template integer tr_slot_count_basic := (11 .. 13);
788 template integer tr_slot_count_extd := (2 .. 15);
789 const integer min_load_ind := 4;
790 var integer basic_count := 0;
791 var integer extd_count := 0;
792 var ASP_RSL_Unitdata rx_ud;
793 timer T_total := 10.0;
794 timer T_retransmit := 0.2;
795 timer T_initial_guard := 2.0;
796 var integer i;
797
Harald Welte10474062019-05-30 16:48:17 +0200798 f_init();
Harald Welte4a129f82019-05-21 16:35:22 +0200799
800 /* send tons of SMSCB Command */
801 for (i := 0; i < 30; i := i+1) {
802 f_smscb_setup_rsl_chan(pars.basic);
803 }
804
805 /* keep sending SMSCB Commands for another two seconds */
806 T_initial_guard.start;
807 T_retransmit.start;
808 alt {
809 [] T_retransmit.timeout {
810 f_smscb_setup_rsl_chan(pars.basic);
811 T_retransmit.start;
812 repeat;
813 }
814 [] T_initial_guard.timeout { }
815 }
816 /* clear any pending messages (where load may not have peaked yet) */
817 RSL_CCHAN.clear;
818
819 /* keep sending SMSCB Commands while verifying LOAD INDICATIONS */
820 T_total.start;
821 T_retransmit.start;
822 alt {
823 [] RSL_CCHAN.receive(tr_RSL_UD(tr_RSL_CBCH_LOAD_IND_BASIC(true, tr_slot_count_basic))) {
824 basic_count := basic_count + 1;
825 repeat;
826 }
827 [] RSL_CCHAN.receive(tr_RSL_UD(tr_RSL_CBCH_LOAD_IND_EXTD(false, tr_slot_count_extd))) {
828 extd_count := extd_count + 1;
829 repeat;
830 }
831 [] RSL_CCHAN.receive(tr_RSL_UD(tr_RSL_CBCH_LOAD_IND_BASIC)) -> value rx_ud {
832 setverdict(fail, "Received unexpected CBCH LOAD IND: ", rx_ud);
833 }
834 [] RSL_CCHAN.receive(tr_RSL_UD(tr_RSL_CBCH_LOAD_IND_EXTD)) -> value rx_ud {
835 setverdict(fail, "Received unexpected CBCH LOAD IND: ", rx_ud);
836 }
837 [] RSL_CCHAN.receive { repeat; }
838 [] T_retransmit.timeout {
839 f_smscb_setup_rsl_chan(pars.basic);
840 T_retransmit.start;
841 repeat;
842 }
843 [] T_total.timeout {
844 if ((basic_count >= min_load_ind) and (extd_count >= min_load_ind)) {
845 setverdict(pass);
846 } else {
847 setverdict(fail, "Insufficient number of CBCH LOAD IND: ",
848 "BASIC=", basic_count, " EXTD=", extd_count);
849 }
850 }
851 }
852 f_smscb_cleanup();
853 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
854}
855testcase TC_cbc_sdcch4_load_overload() runs on test_CT {
856 var CbchTestPars pars := {
857 use_sdcch4 := true,
858 basic := valueof(t_CbchPC(msgs_1m_3b_norm)),
859 extended := omit
860 };
861
862 f_init_vty_bsc();
863 f_vty_cbch_setup(use_sdcch4 := true);
864 f_TC_cbc_load_overload(pars);
865}
866testcase TC_cbc_sdcch8_load_overload() runs on test_CT {
867 var CbchTestPars pars := {
868 use_sdcch4 := true,
869 basic := valueof(t_CbchPC(msgs_1m_3b_norm)),
870 extended := omit
871 };
872
873 f_init_vty_bsc();
874 f_vty_cbch_setup(use_sdcch4 := true);
875 f_TC_cbc_load_overload(pars);
876}
Harald Weltedf4d0f02019-05-20 16:04:11 +0200877
Harald Welte88e5dff2019-05-20 15:14:46 +0200878
Harald Welte908ce542019-09-04 23:05:40 +0200879private template GsmRrMessage tr_PagingType1 := {
880 header := t_RrHeader(PAGING_REQUEST_TYPE_1, ?),
881 payload :=?
882};
883
884private template GsmRrMessage tr_PagingType1_empty := {
885 header := t_RrHeader(PAGING_REQUEST_TYPE_1, 5),
886 payload := {
887 pag_req_1 := {
888 chan_needed := {
889 second := CHAN_NEED_ANY,
890 first := CHAN_NEED_ANY
891 },
892 page_mode := PAGE_MODE_NORMAL,
893 mi1 := {
894 len := 1,
895 mi := {
896 unused := {
897 pad := '1111'B,
898 odd := false,
899 mi_type := MI_TYPE_NONE
900 }
901 }
902 },
903 mi2 := omit,
904 rest_octets := ?
905 }
906 }
907};
908
909/* we expect four blocks of 14 bytes, let's fill them with content easily distinguishable */
910const octetstring c_etws_seg0 := '000102030405060708090a0b0c0d'O;
911const octetstring c_etws_seg1 := '101112131415161718191a1b1c1d'O;
912const octetstring c_etws_seg2 := '202122232425262728292a2b2c2d'O;
913const octetstring c_etws_seg3 := '303132333435363738393a3b3c3d'O;
914const octetstring c_etws := c_etws_seg0 & c_etws_seg1 & c_etws_seg2 & c_etws_seg3;
915
916/* Ensure only Paging Type 1 with segmented ETWS Primary Notification are sent after RSL_OSMO_ETWS_CMD */
917testcase TC_etws_p1ro() runs on test_CT {
918 var template RslChannelNr t_chan_nr := ts_RslChanNr_PCH_AGCH(0);
919 /* decoding the actual entire P1 rest octets by manually generated code is
920 * too much effort; instead simply do a binary compare to this constant */
921 const bitstring c_P1RO_hdr := '00101011101'B;
922 var integer seg_received[4] := { 0, 0, 0, 0 };
923 var L1ctlDlMessage dl;
924 timer T := 10.0;
925
926 f_init();
927 f_init_l1ctl();
928 f_l1_tune(L1CTL, ccch_mode := CCCH_MODE_COMBINED_CBCH);
929
930 RSL_CCHAN.send(ts_RSL_UD(ts_RSL_OSMO_ETWS_CMD(c_etws)));
931 /* wait for a bit until old non-ETWS Paging messages are gone */
932 f_sleep(1.0);
933 L1CTL.clear;
934 T.start;
935 alt {
936 [] L1CTL.receive(tr_L1CTL_DATA_IND(t_chan_nr)) -> value dl {
937 var GsmRrMessage l3 := dec_GsmRrMessage(dl.payload.data_ind.payload);
938 select (l3) {
939 case (tr_PagingType1_empty) {
940 var octetstring p1ro := l3.payload.pag_req_1.rest_octets;
941 var bitstring midamble := oct2bit(substr(p1ro, 0, 3));
942 var octetstring segment := substr(p1ro, 3, lengthof(p1ro)-3);
943 var BIT1 not_first := substr(midamble, 11, 1);
944 var integer seg_nr := bit2int(substr(midamble, 12, 4));
945 var boolean err := false;
946 if (substr(midamble, 0, 11) != c_P1RO_hdr) {
947 setverdict(fail, "Received unexpected P1 RO header ", midamble);
948 }
949 if (not_first == '1'B) {
950 select (seg_nr) {
951 case (2) {
952 if (segment != c_etws_seg1) {
953 err := true
954 } else {
955 seg_received[1] := seg_received[1] + 1;
956 }}
957 case (3) {
958 if (segment != c_etws_seg2) {
959 err := true
960 } else {
961 seg_received[2] := seg_received[2] + 1;
962 }}
963 case (4) {
964 if (segment != c_etws_seg3) {
965 err := true
966 } else {
967 seg_received[3] := seg_received[3] + 1;
968 }}
969 case else { setverdict(fail, "Unknown segment Nr ", seg_nr); }
970 }
971 if (err) {
972 setverdict(fail, "Unexpected segment ", seg_nr, ": ", segment);
973 }
974 } else {
975 if (seg_nr != 4) {
976 setverdict(fail, "Invalid number of segments ", seg_nr);
977 err := true;
978 }
979 if (segment != c_etws_seg0) {
980 setverdict(fail, "Invalid first segment ", segment);
981 err := true;
982 }
983 if (not err) {
984 seg_received[0] := seg_received[0] + 1;
985 }
986 }
987 }
988 case (tr_PagingType1) {
989 setverdict(fail, "Received unexpected PAGING TYPE 1: ", l3);
990 }
991 }
992 repeat;
993 }
994 [] L1CTL.receive { repeat; }
995 [] T.timeout {
996 setverdict(pass);
997 }
998 }
999 log("Quantity of received ETWS PN segments: ", seg_received);
1000 var integer i;
1001 for (i := 0; i < 4; i := i+1) {
1002 if (seg_received[i] < 15) {
1003 setverdict(fail, "Segment ", i, " not received often enough");
1004 }
1005 }
1006}
1007
1008/* Ensure only Paging Type 1 without ETWS Primary Notification are sent after disabling them */
1009testcase TC_etws_p1ro_end() runs on test_CT {
1010 var template RslChannelNr t_chan_nr := ts_RslChanNr_PCH_AGCH(0);
1011 /* we expect four blocks of 14 bytes, let's fill them with content easily
1012 * distinguishable */
1013 /* decoding the actual entire P1 rest octets by manually generated code is
1014 * too much effort; instead simply do a binary compare to this constant */
1015 const bitstring c_P1RO_hdr := '00101011101'B;
1016 var L1ctlDlMessage dl;
1017 timer T := 10.0;
1018
1019 f_init();
1020 f_init_l1ctl();
1021 f_l1_tune(L1CTL, ccch_mode := CCCH_MODE_COMBINED_CBCH);
1022
1023 RSL_CCHAN.send(ts_RSL_UD(ts_RSL_OSMO_ETWS_CMD(c_etws)));
1024 /* wait for a bit until old non-ETWS Paging messages are gone */
1025 f_sleep(3.0);
1026 /* disable the ETWS PN again */
1027 RSL_CCHAN.send(ts_RSL_UD(ts_RSL_OSMO_ETWS_CMD(''O)));
1028 f_sleep(2.0);
1029 T.start;
1030 L1CTL.clear;
1031 alt {
1032 [] L1CTL.receive(tr_L1CTL_DATA_IND(t_chan_nr)) -> value dl {
1033 var GsmRrMessage l3 := dec_GsmRrMessage(dl.payload.data_ind.payload);
1034 select (l3) {
1035 case (tr_PagingType1_empty) { repeat; }
1036 case (tr_PagingType1) {
1037 setverdict(fail, "Received non-empty PT1 after disabling ETWS PN: ", l3);
1038 }
1039 }
1040 repeat;
1041 }
1042 [] L1CTL.receive { repeat; }
1043 [] T.timeout {
1044 setverdict(pass);
1045 }
1046 }
1047}
1048
1049
Harald Welte505cf9b2018-09-15 17:47:23 +03001050/* SMSCB TODO:
1051 * multiple SMS BC CMD at the same time: Ensure all of them are sent exactly once
1052 * extended CBCH vs. normal CBCH
1053 *
1054 */
1055
1056control {
Harald Welte4a129f82019-05-21 16:35:22 +02001057 execute( TC_cbch_load_idle_no_cbch() );
1058
Harald Welte505cf9b2018-09-15 17:47:23 +03001059 execute( TC_sms_cb_cmd_sdcch4_1block() );
1060 execute( TC_sms_cb_cmd_sdcch4_2block() );
1061 execute( TC_sms_cb_cmd_sdcch4_3block() );
1062 execute( TC_sms_cb_cmd_sdcch4_4block() );
Harald Weltee0026c32019-05-20 00:27:30 +02001063 execute( TC_sms_cb_cmd_sdcch4_multi() );
Harald Welte505cf9b2018-09-15 17:47:23 +03001064 execute( TC_sms_cb_cmd_sdcch4_schedule() );
Harald Welte88e5dff2019-05-20 15:14:46 +02001065 execute( TC_sms_cb_cmd_sdcch4_default_only() );
Harald Welted522ca02019-05-20 20:06:12 +02001066 execute( TC_sms_cb_cmd_sdcch4_default_and_normal() );
Harald Weltedf4d0f02019-05-20 16:04:11 +02001067 execute( TC_sms_cb_cmd_sdcch4_default_then_null() );
Harald Welte4a129f82019-05-21 16:35:22 +02001068 execute( TC_cbc_sdcch4_load_idle() );
1069 execute( TC_cbc_sdcch4_load_overload() );
1070
Harald Welte505cf9b2018-09-15 17:47:23 +03001071 if (false) { /* FIXME: SDCCH/8 support broken, needs trxcon + L1CTL work */
1072 execute( TC_sms_cb_cmd_sdcch8_1block() );
1073 execute( TC_sms_cb_cmd_sdcch8_2block() );
1074 execute( TC_sms_cb_cmd_sdcch8_3block() );
1075 execute( TC_sms_cb_cmd_sdcch8_4block() );
Harald Weltee0026c32019-05-20 00:27:30 +02001076 execute( TC_sms_cb_cmd_sdcch8_multi() );
Harald Welte505cf9b2018-09-15 17:47:23 +03001077 execute( TC_sms_cb_cmd_sdcch8_schedule() );
Harald Welte88e5dff2019-05-20 15:14:46 +02001078 execute( TC_sms_cb_cmd_sdcch8_default_only() );
Harald Welted522ca02019-05-20 20:06:12 +02001079 execute( TC_sms_cb_cmd_sdcch8_default_and_normal() );
Harald Welte4a129f82019-05-21 16:35:22 +02001080 execute( TC_cbc_sdcch8_load_idle() );
1081 execute( TC_cbc_sdcch8_load_overload() );
Harald Welte505cf9b2018-09-15 17:47:23 +03001082 }
Harald Welte908ce542019-09-04 23:05:40 +02001083
1084 execute( TC_etws_p1ro() );
1085 execute( TC_etws_p1ro_end() );
Harald Welte505cf9b2018-09-15 17:47:23 +03001086}
1087
1088
1089}