blob: 1e1770332444b695ea8c686718421ff99b47b318 [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 {
Harald Weltea3ff6702019-05-20 20:03:50 +020057 /* should we execute on SDCCH4 (true) or SDCCH8 (false) ? */
Harald Welte505cf9b2018-09-15 17:47:23 +030058 boolean use_sdcch4,
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
Harald Welte4a129f82019-05-21 16:35:22 +0200198private function f_vty_cbch_setup(boolean use_sdcch4 := true) runs on test_CT {
Harald Welte505cf9b2018-09-15 17:47:23 +0300199
Harald Welte4a129f82019-05-21 16:35:22 +0200200 if (use_sdcch4 == true) {
Harald Welte505cf9b2018-09-15 17:47:23 +0300201 f_vty_config2(BSCVTY, {"network", "bts 0", "trx 0", "timeslot 0"},
202 "phys_chan_config CCCH+SDCCH4+CBCH");
203 f_vty_config2(BSCVTY, {"network", "bts 0", "trx 0", "timeslot 6"},
204 "phys_chan_config SDCCH8");
205 } else {
206 f_vty_config2(BSCVTY, {"network", "bts 0", "trx 0", "timeslot 0"},
207 "phys_chan_config CCCH+SDCCH4");
208 f_vty_config2(BSCVTY, {"network", "bts 0", "trx 0", "timeslot 6"},
209 "phys_chan_config SDCCH8+CBCH");
210 }
211 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
212 f_sleep(2.0);
Harald Welte4a129f82019-05-21 16:35:22 +0200213}
214private function f_smscb_setup(inout CbchTestPars pars) runs on test_CT {
215
216 f_cbch_compute_exp_blocks(pars);
217
218 f_init_vty_bsc();
219 /* ensure that a CBCH is present in channel combination */
220 f_vty_cbch_setup(pars.use_sdcch4);
Harald Welte10474062019-05-30 16:48:17 +0200221 f_init();
Harald Welte505cf9b2018-09-15 17:47:23 +0300222
223 f_init_l1ctl();
Harald Welte990a3612019-05-27 14:02:13 +0200224 f_l1_tune(L1CTL, ccch_mode := CCCH_MODE_COMBINED_CBCH);
Harald Welte505cf9b2018-09-15 17:47:23 +0300225 /* FIXME: switch to dedicated mode for SDCCH/8 */
226
227 /* send SMSCB[s] via RSL */
Harald Weltea3ff6702019-05-20 20:03:50 +0200228 f_smscb_setup_rsl_chan(pars.basic, false);
229 if (ispresent(pars.extended)) {
230 f_smscb_setup_rsl_chan(pars.extended, true);
Harald Welte505cf9b2018-09-15 17:47:23 +0300231 }
Harald Welte88e5dff2019-05-20 15:14:46 +0200232}
233
234private function f_smscb_cleanup() runs on test_CT {
235 /* reset timeslot 0 channel combination to default */
236 f_vty_config2(BSCVTY, {"network", "bts 0", "trx 0", "timeslot 0"},
237 "phys_chan_config CCCH+SDCCH4");
238 f_vty_config2(BSCVTY, {"network", "bts 0", "trx 0", "timeslot 6"},
239 "phys_chan_config SDCCH8");
240}
241
Harald Weltea3ff6702019-05-20 20:03:50 +0200242/* construct a receive/match template for given block_nr in given msg */
243private function f_get_block_template(CbchTestMsg msg, integer block_nr) return template CBCH_Block {
244 var template CBCH_Block tr;
245 if (block_nr < lengthof(msg.blocks)) {
246 var CbchBlock b := msg.blocks[block_nr];
247 tr := tr_CBCH_Block(b.seq_nr, b.is_last, b.payload);
248 } else {
249 tr := tr_CBCH_Block(15, ?, ?);
250 }
251 return tr;
252}
253
254/* the heart of the CBCH test case matching engine for one channel (basic, extended) */
255private function f_cbch_match(inout CbchTestParsChan pars_chan, CBCH_Block cb, integer tb)
256{
257 var integer block_nr := tb mod 4;
258 var integer i;
259
260 if (not match(cb, tr_CBCH_Block)) {
261 setverdict(fail, "Illegal CBCH Block received: ", cb);
262 } else {
263 var boolean matched := false;
264 /* check if it's any of our expected blocks */
265 for (i := 0; i < lengthof(pars_chan.msgs); i := i+1) {
266 if (block_nr < lengthof(pars_chan.msgs[i].blocks)) {
267 if (match(cb, f_get_block_template(pars_chan.msgs[i], block_nr))) {
268 log("Found block_nr ", block_nr, " of msg ", i);
269 if (not pars_chan.msgs[i].blocks[block_nr].seen_once) {
270 pars_chan.msgs[i].blocks[block_nr].seen_once := true;
271 setverdict(pass);
272 } else {
273 setverdict(fail, "Received SMSCB twice! ", cb);
274 }
275 matched := true;
276 break;
277 }
278 }
279 }
280 if (not matched) {
281 var template CBCH_Block tr;
282 if (ispresent(pars_chan.default_msg)) {
283 /* it must be a block of the default message */
284 tr := f_get_block_template(pars_chan.default_msg, block_nr);
285 } else {
286 /* it must be a NULL block */
287 tr := tr_CBCH_Block(15, ?, ?);
288 }
289 if (not match(cb, tr)) {
290 setverdict(fail, "Received unexpected CBCH block: ", cb);
291 } else {
292 log("Found block_nr ", block_nr, " of DEFAULT/NULL");
293 if (ispresent(pars_chan.default_msg) and
294 block_nr < lengthof(pars_chan.default_msg.blocks)) {
295 pars_chan.default_msg.blocks[block_nr].seen_once := true;
296 }
297 }
298 }
299 }
300}
301
302/* Report/Evaluate the per-channel CBCH test results */
303private function f_cbch_report(CbchTestParsChan pars_chan, charstring id)
304{
305 var integer i, j;
306
307 /* verify that each block of each message has been seen once */
308 for (i := 0; i < lengthof(pars_chan.msgs); i := i+1) {
309 for (j := 0; j < lengthof(pars_chan.msgs[i].blocks); j := j+1) {
310 var CbchBlock b := pars_chan.msgs[i].blocks[j];
311 if (not b.seen_once) {
312 setverdict(fail, "Timeout waiting for ", id, " CBCH block ",
313 j, " of msg ", i);
314 }
315 }
316 }
317 if (ispresent(pars_chan.default_msg)) {
318 /* verify that each block of default message has been seen at least once */
319 for (j := 0; j < lengthof(pars_chan.default_msg.blocks); j := j+1) {
320 var CbchBlock b := pars_chan.default_msg.blocks[j];
321 if (not b.seen_once) {
322 setverdict(fail, "Timeout waiting for at leaset one instance of ",
323 "CBCH block ", j, " of DEFAULT msg");
324 }
325 }
326 }
327}
328
Harald Welte6b86b342019-05-27 17:14:36 +0200329private function t_cbch_chan_nr(CbchTestPars pars, template uint8_t tn) return template RslChannelNr {
330 if (pars.use_sdcch4) {
331 return t_RslChanNr_CBCH4(tn);
332 } else {
333 return t_RslChanNr_CBCH8(tn);
334 }
335}
336
Harald Welte88e5dff2019-05-20 15:14:46 +0200337/* shared function doing the heavy lifting for most CBCH tests */
338private function f_TC_smscb(CbchTestPars pars) runs on test_CT {
Harald Welte6b86b342019-05-27 17:14:36 +0200339 var template RslChannelNr t_chan_nr := t_cbch_chan_nr(pars, 0); /* FIXME: TS number */
Harald Welte88e5dff2019-05-20 15:14:46 +0200340 var L1ctlDlMessage dl;
Harald Weltea3ff6702019-05-20 20:03:50 +0200341 var integer msg_count;
342 timer T;
343
344 msg_count := lengthof(pars.basic.msgs);
345 if (ispresent(pars.basic.default_msg)) {
346 msg_count := msg_count + 1;
347 }
348 if (ispresent(pars.extended)) {
349 msg_count := msg_count + lengthof(pars.extended.msgs);
350 if (ispresent(pars.extended.default_msg)) {
351 msg_count := msg_count + 1;
352 }
353 }
Harald Welte88e5dff2019-05-20 15:14:46 +0200354
355 f_smscb_setup(pars);
356
Harald Weltea3ff6702019-05-20 20:03:50 +0200357 /* dynamically adjust timeout based on number of messages */
358 T.start(5.0 + 3.0 * int2float(msg_count));
Harald Welte505cf9b2018-09-15 17:47:23 +0300359 /* Expect this to show up exactly once on the basic CBCH (four blocks) */
360 alt {
Harald Welte6b86b342019-05-27 17:14:36 +0200361 [] L1CTL.receive(tr_L1CTL_DATA_IND(t_chan_nr)) -> value dl {
Harald Weltea3ff6702019-05-20 20:03:50 +0200362 var integer tb := f_cbch_fn2tb(dl.dl_info.frame_nr);
Harald Welte505cf9b2018-09-15 17:47:23 +0300363 var CBCH_Block cb := dec_CBCH_Block(dl.payload.data_ind.payload);
Harald Weltea3ff6702019-05-20 20:03:50 +0200364 log("Tb=", tb, ", CBCH: ", dl, ", block: ", cb);
365
Harald Welte505cf9b2018-09-15 17:47:23 +0300366 /* detect the proper CBCH messages; check frame number */
367 f_cbch_fn_verify(dl.dl_info.frame_nr, cb);
Harald Weltea3ff6702019-05-20 20:03:50 +0200368
369 if (tb < 4) {
370 f_cbch_match(pars.basic, cb, tb);
Harald Welte505cf9b2018-09-15 17:47:23 +0300371 } else {
Harald Weltea3ff6702019-05-20 20:03:50 +0200372 if (not ispresent(pars.extended)) {
373 /* no parameters for ext. BCCH given: ignore */
374 repeat;
Harald Welte505cf9b2018-09-15 17:47:23 +0300375 }
Harald Weltea3ff6702019-05-20 20:03:50 +0200376 f_cbch_match(pars.extended, cb, tb);
Harald Welte505cf9b2018-09-15 17:47:23 +0300377 }
Harald Weltea3ff6702019-05-20 20:03:50 +0200378 repeat;
Harald Welte505cf9b2018-09-15 17:47:23 +0300379 }
380 [] L1CTL.receive { repeat; }
381 [] T.timeout {
Harald Weltea3ff6702019-05-20 20:03:50 +0200382 f_cbch_report(pars.basic, "Basic");
383 if (ispresent(pars.extended)) {
384 f_cbch_report(pars.extended, "Extended");
Harald Welte505cf9b2018-09-15 17:47:23 +0300385 }
386 }
387 }
388
Harald Welte88e5dff2019-05-20 15:14:46 +0200389 f_smscb_cleanup();
390 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, pass);
391}
392
393private function f_TC_smscb_default_only(CbchTestPars pars) runs on test_CT {
Harald Welte6b86b342019-05-27 17:14:36 +0200394 var template RslChannelNr t_chan_nr := t_cbch_chan_nr(pars, 0); /* FIXME: TS number */
Harald Welte88e5dff2019-05-20 15:14:46 +0200395 var L1ctlDlMessage dl;
396 timer T := 5.0;
397
398 f_smscb_setup(pars);
399
400 /* ensure whatever initial NULL messages have all been drained */
401 f_sleep(5.0);
402 L1CTL.clear;
403
404 T.start;
405 alt {
Harald Welte6b86b342019-05-27 17:14:36 +0200406 [] L1CTL.receive(tr_L1CTL_DATA_IND(t_chan_nr)) -> value dl {
Harald Welte88e5dff2019-05-20 15:14:46 +0200407 var integer tb := f_cbch_fn2tb(dl.dl_info.frame_nr);
408 log("CBCH: ", dl);
409 var CBCH_Block cb := dec_CBCH_Block(dl.payload.data_ind.payload);
410 /* detect the proper CBCH messages; check frame number */
411 f_cbch_fn_verify(dl.dl_info.frame_nr, cb);
412 if (tb >= 4) {
413 /* skip extended CBCH for now */
414 repeat;
415 }
416 if (not match(cb, tr_CBCH_Block)) {
417 setverdict(fail, "Illegal CBCH Block received: ", cb);
418 } else {
419 var uint4_t rx_seq_nr := cb.block_type.seq_nr;
420 var template CBCH_Block tr;
Harald Weltea3ff6702019-05-20 20:03:50 +0200421 if (rx_seq_nr < lengthof(pars.basic.msgs[0].blocks)) {
422 var CbchBlock b := pars.basic.msgs[0].blocks[rx_seq_nr];
Harald Welte88e5dff2019-05-20 15:14:46 +0200423 tr := tr_CBCH_Block(b.seq_nr, b.is_last, b.payload);
424 } else {
425 tr := tr_CBCH_Block(15, ?, ?);
426 }
427 if (match(cb, tr)) {
428 setverdict(pass); /* FIXME: check that all blocks are received? */
429 repeat;
430 } else {
431 setverdict(fail, "Unexpected CBCH block ", cb, ", expected ", tr);
432 }
433 }
434 }
435 [] L1CTL.receive { repeat; }
436 [] T.timeout {}
437 }
438
439 f_smscb_cleanup();
440 /* don't shut down; some tests still want to continue */
Harald Welte505cf9b2018-09-15 17:47:23 +0300441}
442
443private const CbchTestMsgs msgs_1m_1b_norm := {
444 { RSL_CB_CMD_NORMAL, 0, '001000320f1141660c344dd3cba09a0c000000000000'O, omit }
445}
446
447private const CbchTestMsgs msgs_1m_2b_norm := {
448 { RSL_CB_CMD_NORMAL, 1, '001000320f1141660c344dd3cba09a0c000000000000'O &
449 '000102030405060708090a0b0c0d0e0f101213141516'O,
450 omit }
451}
452
453private const CbchTestMsgs msgs_1m_3b_norm := {
454 { RSL_CB_CMD_NORMAL, 2, '001000320f1141660c344dd3cba09a0c000000000000'O &
455 '000102030405060708090a0b0c0d0e0f101213141516'O &
456 '101112131415161718191a1b1c1d1e1f202223242526'O,
457 omit }
458}
459
460private const CbchTestMsgs msgs_1m_4b_norm := {
461 { RSL_CB_CMD_NORMAL, 3, '001000320f1141660c344dd3cba09a0c000000000000'O &
462 '000102030405060708090a0b0c0d0e0f101213141516'O &
463 '101112131415161718191a1b1c1d1e1f202223242526'O &
464 '202122232425262728292a2b2c2d2e2f303233343536'O,
465 omit }
466}
467
468private const CbchTestMsgs msgs_1m_4b_sched := {
469 { RSL_CB_CMD_SCHEDULE, 3, '001000320f1141660c344dd3cba09a0c000000000000'O &
470 '000102030405060708090a0b0c0d0e0f101213141516'O &
471 '101112131415161718191a1b1c1d1e1f202223242526'O &
472 '202122232425262728292a2b2c2d2e2f303233343536'O,
473 omit }
474}
475
Harald Weltee0026c32019-05-20 00:27:30 +0200476private const CbchTestMsgs msgs_3m_4b_norm := {
477 { RSL_CB_CMD_NORMAL, 3, '001000320f1141660c344dd3cba09a0c000000000000'O &
478 '000102030405060708090a0b0c0d0e0f101213141516'O &
479 '101112131415161718191a1b1c1d1e1f202223242526'O &
480 '201122232425262728292a2b2c2d2e2f303233343536'O,
481 omit },
482 { RSL_CB_CMD_NORMAL, 3, '002000320f1141660c344dd3cba09a0c000000000000'O &
483 '002102030405060708090a0b0c0d0e0f101213141516'O &
484 '102112131415161718191a1b1c1d1e1f202223242526'O &
485 '202122232425262728292a2b2c2d2e2f303233343536'O,
486 omit },
487 { RSL_CB_CMD_NORMAL, 3, '003000320f1141660c344dd3cba09a0c000000000000'O &
488 '003102030405060708090a0b0c0d0e0f101213141516'O &
489 '103112131415161718191a1b1c1d1e1f202223242526'O &
490 '203122232425262728292a2b2c2d2e2f303233343536'O,
491 omit }
492}
493
Harald Welte88e5dff2019-05-20 15:14:46 +0200494private const CbchTestMsgs msgs_1m_3b_default := {
495 { RSL_CB_CMD_DEFAULT, 2, '001000320f1141660c344dd3cba09a0c000000000000'O &
496 '000102030405060708090a0b0c0d0e0f101213141516'O &
497 '101112131415161718191a1b1c1d1e1f202223242526'O,
498 omit }
499}
Harald Weltea3ff6702019-05-20 20:03:50 +0200500private const CbchTestMsg msg_default := {
501 RSL_CB_CMD_DEFAULT, 0, '010203040506070708090a0b0c0d0e0f101112131415'O,
502 omit
503}
Harald Welte88e5dff2019-05-20 15:14:46 +0200504
Harald Welte505cf9b2018-09-15 17:47:23 +0300505/* transmit single-block SMSCB COMMAND */
506testcase TC_sms_cb_cmd_sdcch4_1block() runs on test_CT {
507 var CbchTestPars pars := {
508 use_sdcch4 := true,
Harald Weltea3ff6702019-05-20 20:03:50 +0200509 basic := valueof(t_CbchPC(msgs_1m_1b_norm)),
510 extended := omit
Harald Welte505cf9b2018-09-15 17:47:23 +0300511 };
512 f_TC_smscb(pars);
513}
514testcase TC_sms_cb_cmd_sdcch8_1block() runs on test_CT {
515 var CbchTestPars pars := {
516 use_sdcch4 := false,
Harald Weltea3ff6702019-05-20 20:03:50 +0200517 basic := valueof(t_CbchPC(msgs_1m_1b_norm)),
518 extended := omit
Harald Welte505cf9b2018-09-15 17:47:23 +0300519 };
520 f_TC_smscb(pars);
521}
522
523/* transmit dual-block SMSCB COMMAND */
524testcase TC_sms_cb_cmd_sdcch4_2block() runs on test_CT {
525 var CbchTestPars pars := {
526 use_sdcch4 := true,
Harald Weltea3ff6702019-05-20 20:03:50 +0200527 basic := valueof(t_CbchPC(msgs_1m_2b_norm)),
528 extended := omit
Harald Welte505cf9b2018-09-15 17:47:23 +0300529 };
530 f_TC_smscb(pars);
531}
532testcase TC_sms_cb_cmd_sdcch8_2block() runs on test_CT {
533 var CbchTestPars pars := {
534 use_sdcch4 := false,
Harald Weltea3ff6702019-05-20 20:03:50 +0200535 basic := valueof(t_CbchPC(msgs_1m_2b_norm)),
536 extended := omit
Harald Welte505cf9b2018-09-15 17:47:23 +0300537 };
538 f_TC_smscb(pars);
539}
540
541/* transmit triple-block SMSCB COMMAND */
542testcase TC_sms_cb_cmd_sdcch4_3block() runs on test_CT {
543 var CbchTestPars pars := {
544 use_sdcch4 := true,
Harald Weltea3ff6702019-05-20 20:03:50 +0200545 basic := valueof(t_CbchPC(msgs_1m_3b_norm)),
546 extended := omit
Harald Welte505cf9b2018-09-15 17:47:23 +0300547 };
548 f_TC_smscb(pars);
549}
550testcase TC_sms_cb_cmd_sdcch8_3block() runs on test_CT {
551 var CbchTestPars pars := {
552 use_sdcch4 := false,
Harald Weltea3ff6702019-05-20 20:03:50 +0200553 basic := valueof(t_CbchPC(msgs_1m_3b_norm)),
554 extended := omit
Harald Welte505cf9b2018-09-15 17:47:23 +0300555 };
556 f_TC_smscb(pars);
557}
558
559/* transmit quad-block SMSCB COMMAND */
560testcase TC_sms_cb_cmd_sdcch4_4block() runs on test_CT {
561 var CbchTestPars pars := {
562 use_sdcch4 := true,
Harald Weltea3ff6702019-05-20 20:03:50 +0200563 basic := valueof(t_CbchPC(msgs_1m_4b_norm)),
564 extended := omit
Harald Welte505cf9b2018-09-15 17:47:23 +0300565 };
566 f_TC_smscb(pars);
567}
568testcase TC_sms_cb_cmd_sdcch8_4block() runs on test_CT {
569 var CbchTestPars pars := {
570 use_sdcch4 := false,
Harald Weltea3ff6702019-05-20 20:03:50 +0200571 basic := valueof(t_CbchPC(msgs_1m_4b_norm)),
572 extended := omit
Harald Welte505cf9b2018-09-15 17:47:23 +0300573 };
574 f_TC_smscb(pars);
575}
576
Harald Weltee0026c32019-05-20 00:27:30 +0200577/* transmit multiple commands of each 4 blocks */
578testcase TC_sms_cb_cmd_sdcch4_multi() runs on test_CT {
579 var CbchTestPars pars := {
580 use_sdcch4 := true,
Harald Weltea3ff6702019-05-20 20:03:50 +0200581 basic := valueof(t_CbchPC(msgs_3m_4b_norm)),
582 extended := omit
Harald Weltee0026c32019-05-20 00:27:30 +0200583 };
584 f_TC_smscb(pars);
585}
586testcase TC_sms_cb_cmd_sdcch8_multi() runs on test_CT {
587 var CbchTestPars pars := {
588 use_sdcch4 := false,
Harald Weltea3ff6702019-05-20 20:03:50 +0200589 basic := valueof(t_CbchPC(msgs_3m_4b_norm)),
590 extended := omit
Harald Weltee0026c32019-05-20 00:27:30 +0200591 };
592 f_TC_smscb(pars);
593}
594
Harald Welte60bd92b2019-05-20 21:42:21 +0200595/* transmit multiple commands of each 4 blocks on CBCH EXTD */
596testcase TC_sms_cb_cmd_sdcch4_extd_multi() runs on test_CT {
597 var CbchTestPars pars := {
598 use_sdcch4 := true,
599 basic := valueof(t_CbchPC({})),
600 extended := valueof(t_CbchPC(msgs_3m_4b_norm))
601 };
602 f_TC_smscb(pars);
603}
604testcase TC_sms_cb_cmd_sdcch8_extd_multi() runs on test_CT {
605 var CbchTestPars pars := {
606 use_sdcch4 := false,
607 basic := valueof(t_CbchPC({})),
608 extended := valueof(t_CbchPC(msgs_3m_4b_norm))
609 };
610 f_TC_smscb(pars);
611}
612
Harald Welte505cf9b2018-09-15 17:47:23 +0300613/* transmit SMSCB COMMAND with SCHEDULE payload */
614testcase TC_sms_cb_cmd_sdcch4_schedule() runs on test_CT {
615 var CbchTestPars pars := {
616 use_sdcch4 := true,
Harald Weltea3ff6702019-05-20 20:03:50 +0200617 basic := valueof(t_CbchPC(msgs_1m_4b_sched)),
618 extended := omit
Harald Welte505cf9b2018-09-15 17:47:23 +0300619 };
620 f_TC_smscb(pars);
621}
622testcase TC_sms_cb_cmd_sdcch8_schedule() runs on test_CT {
623 var CbchTestPars pars := {
624 use_sdcch4 := false,
Harald Weltea3ff6702019-05-20 20:03:50 +0200625 basic := valueof(t_CbchPC(msgs_1m_4b_sched)),
626 extended := omit
Harald Welte505cf9b2018-09-15 17:47:23 +0300627 };
628 f_TC_smscb(pars);
629}
630
Harald Welte88e5dff2019-05-20 15:14:46 +0200631/* set a DEFAULT message; verify it gets transmitted all the time */
632testcase TC_sms_cb_cmd_sdcch4_default_only() runs on test_CT {
633 var CbchTestPars pars := {
634 use_sdcch4 := true,
Harald Weltea3ff6702019-05-20 20:03:50 +0200635 basic := valueof(t_CbchPC(msgs_1m_3b_default)),
636 extended := omit
Harald Welte88e5dff2019-05-20 15:14:46 +0200637 };
638 f_TC_smscb_default_only(pars);
639 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, pass);
640}
641testcase TC_sms_cb_cmd_sdcch8_default_only() runs on test_CT {
642 var CbchTestPars pars := {
643 use_sdcch4 := true,
Harald Weltea3ff6702019-05-20 20:03:50 +0200644 basic := valueof(t_CbchPC(msgs_1m_3b_default)),
645 extended := omit
Harald Welte88e5dff2019-05-20 15:14:46 +0200646 };
647 f_TC_smscb_default_only(pars);
648 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, pass);
649}
650
Harald Welted522ca02019-05-20 20:06:12 +0200651testcase TC_sms_cb_cmd_sdcch4_default_and_normal() runs on test_CT {
652 var CbchTestPars pars := {
653 use_sdcch4 := true,
654 basic := valueof(t_CbchPC(msgs_1m_3b_norm, msg_default)),
655 extended := omit
656 };
657 f_TC_smscb(pars);
658}
659testcase TC_sms_cb_cmd_sdcch8_default_and_normal() runs on test_CT {
660 var CbchTestPars pars := {
661 use_sdcch4 := true,
662 basic := valueof(t_CbchPC(msgs_1m_3b_norm, msg_default)),
663 extended := omit
664 };
665 f_TC_smscb(pars);
666}
667
Harald Weltedf4d0f02019-05-20 16:04:11 +0200668/* first set a DEFAULT message, then disable it again */
669testcase TC_sms_cb_cmd_sdcch4_default_then_null() runs on test_CT {
670 var CbchTestPars pars := {
671 use_sdcch4 := true,
Harald Weltea3ff6702019-05-20 20:03:50 +0200672 basic := valueof(t_CbchPC(msgs_1m_3b_default)),
673 extended := omit
Harald Weltedf4d0f02019-05-20 16:04:11 +0200674 };
Harald Welte6b86b342019-05-27 17:14:36 +0200675 var template RslChannelNr t_chan_nr := t_RslChanNr_CBCH4(0);
Harald Weltedf4d0f02019-05-20 16:04:11 +0200676 var L1ctlDlMessage dl;
677 timer T := 5.0;
678
679 f_TC_smscb_default_only(pars);
680
681 /* disable DEFAULT message; switch back to NULL */
682 f_rsl_smscb_default_null();
683
684 /* ensure whatever initial non-NULL messages have all been drained */
685 f_sleep(5.0);
686 L1CTL.clear;
687
688 T.start;
689 alt {
Harald Welte6b86b342019-05-27 17:14:36 +0200690 [] L1CTL.receive(tr_L1CTL_DATA_IND(t_chan_nr)) -> value dl {
Harald Weltedf4d0f02019-05-20 16:04:11 +0200691 log("CBCH: ", dl);
692 var CBCH_Block cb := dec_CBCH_Block(dl.payload.data_ind.payload);
693 /* detect the proper CBCH messages; check frame number */
694 f_cbch_fn_verify(dl.dl_info.frame_nr, cb);
695 if (not match(cb, tr_CBCH_Block)) {
696 setverdict(fail, "Illegal CBCH Block received: ", cb);
697 } else {
698 if (not match(cb, tr_CBCH_Block(15, ?, ?))) {
699 setverdict(fail, "Unexpected non-NULL CBCH block received");
700 }
701 repeat;
702 }
703 }
704 [] L1CTL.receive { repeat; }
705 [] T.timeout {
706 setverdict(pass);
707 }
708 }
709
710 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, pass);
711}
712
Harald Welte4a129f82019-05-21 16:35:22 +0200713/* Verify there are no CBCH load indications if no CBCH is present */
714testcase TC_cbch_load_idle_no_cbch() runs on test_CT {
715 var ASP_RSL_Unitdata rx_ud;
716 timer T := 10.0;
717
Harald Welte10474062019-05-30 16:48:17 +0200718 f_init();
Harald Welte4a129f82019-05-21 16:35:22 +0200719 f_init_vty_bsc();
720
721 T.start;
722 alt {
Vadim Yanitskiy493abe72020-05-25 22:03:48 +0700723 [] RSL_CCHAN.receive(tr_ASP_RSL_UD(tr_RSL_CBCH_LOAD_IND_BASIC)) -> value rx_ud {
Harald Welte4a129f82019-05-21 16:35:22 +0200724 setverdict(fail, "Received unexpected CBCH LOAD IND: ", rx_ud);
725 }
Vadim Yanitskiy493abe72020-05-25 22:03:48 +0700726 [] RSL_CCHAN.receive(tr_ASP_RSL_UD(tr_RSL_CBCH_LOAD_IND_EXTD)) -> value rx_ud {
Harald Welte4a129f82019-05-21 16:35:22 +0200727 setverdict(fail, "Received unexpected CBCH LOAD IND: ", rx_ud);
728 }
729 [] RSL_CCHAN.receive { repeat; }
730 [] T.timeout {
731 setverdict(pass);
732 }
733 }
734 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
735}
736
737/* Verify the CBCH load indications of an idle cell (without CBCH load) */
738function f_TC_cbc_load_idle() runs on test_CT {
739 template integer tr_slot_count := (2 .. 15);
740 const integer min_load_ind := 4;
741 var integer basic_count := 0;
742 var integer extd_count := 0;
743 var ASP_RSL_Unitdata rx_ud;
744 timer T := 10.0;
745
Harald Welte10474062019-05-30 16:48:17 +0200746 f_init();
Harald Welte4a129f82019-05-21 16:35:22 +0200747
748 RSL_CCHAN.clear;
749 T.start;
750 alt {
Vadim Yanitskiy493abe72020-05-25 22:03:48 +0700751 [] RSL_CCHAN.receive(tr_ASP_RSL_UD(tr_RSL_CBCH_LOAD_IND_BASIC(false, tr_slot_count))) {
Harald Welte4a129f82019-05-21 16:35:22 +0200752 basic_count := basic_count + 1;
753 repeat;
754 }
Vadim Yanitskiy493abe72020-05-25 22:03:48 +0700755 [] 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 +0200756 extd_count := extd_count + 1;
757 repeat;
758 }
Vadim Yanitskiy493abe72020-05-25 22:03:48 +0700759 [] RSL_CCHAN.receive(tr_ASP_RSL_UD(tr_RSL_CBCH_LOAD_IND_BASIC)) -> value rx_ud {
Harald Welte4a129f82019-05-21 16:35:22 +0200760 setverdict(fail, "Received unexpected CBCH LOAD IND: ", rx_ud);
761 }
Vadim Yanitskiy493abe72020-05-25 22:03:48 +0700762 [] RSL_CCHAN.receive(tr_ASP_RSL_UD(tr_RSL_CBCH_LOAD_IND_EXTD)) -> value rx_ud {
Harald Welte4a129f82019-05-21 16:35:22 +0200763 setverdict(fail, "Received unexpected CBCH LOAD IND: ", rx_ud);
764 }
765 [] RSL_CCHAN.receive { repeat; }
766 [] T.timeout {
767 if ((basic_count >= min_load_ind) and (extd_count >= min_load_ind)) {
768 setverdict(pass);
769 } else {
770 setverdict(fail, "Insufficient number of CBCH LOAD IND: ",
771 "BASIC=", basic_count, " EXTD=", extd_count);
772 }
773 }
774 }
775 f_smscb_cleanup();
776 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
777}
778testcase TC_cbc_sdcch4_load_idle() runs on test_CT {
779 f_init_vty_bsc();
780 f_vty_cbch_setup(use_sdcch4 := true);
781 f_TC_cbc_load_idle();
782}
783testcase TC_cbc_sdcch8_load_idle() runs on test_CT {
784 f_init_vty_bsc();
785 f_vty_cbch_setup(use_sdcch4 := false);
786 f_TC_cbc_load_idle();
787}
788
789/* Verify CBCH overload indications are sent when sending too many SMS CB CMD */
790function f_TC_cbc_load_overload(CbchTestPars pars) runs on test_CT {
791 template integer tr_slot_count_basic := (11 .. 13);
792 template integer tr_slot_count_extd := (2 .. 15);
793 const integer min_load_ind := 4;
794 var integer basic_count := 0;
795 var integer extd_count := 0;
796 var ASP_RSL_Unitdata rx_ud;
797 timer T_total := 10.0;
798 timer T_retransmit := 0.2;
799 timer T_initial_guard := 2.0;
800 var integer i;
801
Harald Welte10474062019-05-30 16:48:17 +0200802 f_init();
Harald Welte4a129f82019-05-21 16:35:22 +0200803
804 /* send tons of SMSCB Command */
805 for (i := 0; i < 30; i := i+1) {
806 f_smscb_setup_rsl_chan(pars.basic);
807 }
808
809 /* keep sending SMSCB Commands for another two seconds */
810 T_initial_guard.start;
811 T_retransmit.start;
812 alt {
813 [] T_retransmit.timeout {
814 f_smscb_setup_rsl_chan(pars.basic);
815 T_retransmit.start;
816 repeat;
817 }
818 [] T_initial_guard.timeout { }
819 }
820 /* clear any pending messages (where load may not have peaked yet) */
821 RSL_CCHAN.clear;
822
823 /* keep sending SMSCB Commands while verifying LOAD INDICATIONS */
824 T_total.start;
825 T_retransmit.start;
826 alt {
Vadim Yanitskiy493abe72020-05-25 22:03:48 +0700827 [] 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 +0200828 basic_count := basic_count + 1;
829 repeat;
830 }
Vadim Yanitskiy493abe72020-05-25 22:03:48 +0700831 [] 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 +0200832 extd_count := extd_count + 1;
833 repeat;
834 }
Vadim Yanitskiy493abe72020-05-25 22:03:48 +0700835 [] RSL_CCHAN.receive(tr_ASP_RSL_UD(tr_RSL_CBCH_LOAD_IND_BASIC)) -> value rx_ud {
Harald Welte4a129f82019-05-21 16:35:22 +0200836 setverdict(fail, "Received unexpected CBCH LOAD IND: ", rx_ud);
837 }
Vadim Yanitskiy493abe72020-05-25 22:03:48 +0700838 [] RSL_CCHAN.receive(tr_ASP_RSL_UD(tr_RSL_CBCH_LOAD_IND_EXTD)) -> value rx_ud {
Harald Welte4a129f82019-05-21 16:35:22 +0200839 setverdict(fail, "Received unexpected CBCH LOAD IND: ", rx_ud);
840 }
841 [] RSL_CCHAN.receive { repeat; }
842 [] T_retransmit.timeout {
843 f_smscb_setup_rsl_chan(pars.basic);
844 T_retransmit.start;
845 repeat;
846 }
847 [] T_total.timeout {
848 if ((basic_count >= min_load_ind) and (extd_count >= min_load_ind)) {
849 setverdict(pass);
850 } else {
851 setverdict(fail, "Insufficient number of CBCH LOAD IND: ",
852 "BASIC=", basic_count, " EXTD=", extd_count);
853 }
854 }
855 }
856 f_smscb_cleanup();
857 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
858}
859testcase TC_cbc_sdcch4_load_overload() runs on test_CT {
860 var CbchTestPars pars := {
861 use_sdcch4 := true,
862 basic := valueof(t_CbchPC(msgs_1m_3b_norm)),
863 extended := omit
864 };
865
866 f_init_vty_bsc();
867 f_vty_cbch_setup(use_sdcch4 := true);
868 f_TC_cbc_load_overload(pars);
869}
870testcase TC_cbc_sdcch8_load_overload() runs on test_CT {
871 var CbchTestPars pars := {
872 use_sdcch4 := true,
873 basic := valueof(t_CbchPC(msgs_1m_3b_norm)),
874 extended := omit
875 };
876
877 f_init_vty_bsc();
878 f_vty_cbch_setup(use_sdcch4 := true);
879 f_TC_cbc_load_overload(pars);
880}
Harald Weltedf4d0f02019-05-20 16:04:11 +0200881
Harald Welte88e5dff2019-05-20 15:14:46 +0200882
Harald Welte908ce542019-09-04 23:05:40 +0200883private template GsmRrMessage tr_PagingType1 := {
884 header := t_RrHeader(PAGING_REQUEST_TYPE_1, ?),
885 payload :=?
886};
887
Harald Welte908ce542019-09-04 23:05:40 +0200888/* we expect four blocks of 14 bytes, let's fill them with content easily distinguishable */
889const octetstring c_etws_seg0 := '000102030405060708090a0b0c0d'O;
890const octetstring c_etws_seg1 := '101112131415161718191a1b1c1d'O;
891const octetstring c_etws_seg2 := '202122232425262728292a2b2c2d'O;
892const octetstring c_etws_seg3 := '303132333435363738393a3b3c3d'O;
893const octetstring c_etws := c_etws_seg0 & c_etws_seg1 & c_etws_seg2 & c_etws_seg3;
894
895/* Ensure only Paging Type 1 with segmented ETWS Primary Notification are sent after RSL_OSMO_ETWS_CMD */
896testcase TC_etws_p1ro() runs on test_CT {
897 var template RslChannelNr t_chan_nr := ts_RslChanNr_PCH_AGCH(0);
898 /* decoding the actual entire P1 rest octets by manually generated code is
899 * too much effort; instead simply do a binary compare to this constant */
900 const bitstring c_P1RO_hdr := '00101011101'B;
901 var integer seg_received[4] := { 0, 0, 0, 0 };
902 var L1ctlDlMessage dl;
903 timer T := 10.0;
904
905 f_init();
906 f_init_l1ctl();
907 f_l1_tune(L1CTL, ccch_mode := CCCH_MODE_COMBINED_CBCH);
908
Vadim Yanitskiy493abe72020-05-25 22:03:48 +0700909 RSL_CCHAN.send(ts_ASP_RSL_UD(ts_RSL_OSMO_ETWS_CMD(c_etws)));
Harald Welte908ce542019-09-04 23:05:40 +0200910 /* wait for a bit until old non-ETWS Paging messages are gone */
911 f_sleep(1.0);
912 L1CTL.clear;
913 T.start;
914 alt {
915 [] L1CTL.receive(tr_L1CTL_DATA_IND(t_chan_nr)) -> value dl {
916 var GsmRrMessage l3 := dec_GsmRrMessage(dl.payload.data_ind.payload);
917 select (l3) {
Vadim Yanitskiya9a198d2020-03-28 05:11:26 +0700918 case (tr_PAG_REQ1(tr_MI_LV(t_MI_NoIdentity()))) {
Harald Welte908ce542019-09-04 23:05:40 +0200919 var octetstring p1ro := l3.payload.pag_req_1.rest_octets;
920 var bitstring midamble := oct2bit(substr(p1ro, 0, 3));
921 var octetstring segment := substr(p1ro, 3, lengthof(p1ro)-3);
922 var BIT1 not_first := substr(midamble, 11, 1);
923 var integer seg_nr := bit2int(substr(midamble, 12, 4));
924 var boolean err := false;
925 if (substr(midamble, 0, 11) != c_P1RO_hdr) {
926 setverdict(fail, "Received unexpected P1 RO header ", midamble);
927 }
928 if (not_first == '1'B) {
929 select (seg_nr) {
930 case (2) {
931 if (segment != c_etws_seg1) {
932 err := true
933 } else {
934 seg_received[1] := seg_received[1] + 1;
935 }}
936 case (3) {
937 if (segment != c_etws_seg2) {
938 err := true
939 } else {
940 seg_received[2] := seg_received[2] + 1;
941 }}
942 case (4) {
943 if (segment != c_etws_seg3) {
944 err := true
945 } else {
946 seg_received[3] := seg_received[3] + 1;
947 }}
948 case else { setverdict(fail, "Unknown segment Nr ", seg_nr); }
949 }
950 if (err) {
951 setverdict(fail, "Unexpected segment ", seg_nr, ": ", segment);
952 }
953 } else {
954 if (seg_nr != 4) {
955 setverdict(fail, "Invalid number of segments ", seg_nr);
956 err := true;
957 }
958 if (segment != c_etws_seg0) {
959 setverdict(fail, "Invalid first segment ", segment);
960 err := true;
961 }
962 if (not err) {
963 seg_received[0] := seg_received[0] + 1;
964 }
965 }
966 }
967 case (tr_PagingType1) {
968 setverdict(fail, "Received unexpected PAGING TYPE 1: ", l3);
969 }
970 }
971 repeat;
972 }
973 [] L1CTL.receive { repeat; }
974 [] T.timeout {
975 setverdict(pass);
976 }
977 }
978 log("Quantity of received ETWS PN segments: ", seg_received);
979 var integer i;
980 for (i := 0; i < 4; i := i+1) {
981 if (seg_received[i] < 15) {
982 setverdict(fail, "Segment ", i, " not received often enough");
983 }
984 }
985}
986
987/* Ensure only Paging Type 1 without ETWS Primary Notification are sent after disabling them */
988testcase TC_etws_p1ro_end() runs on test_CT {
989 var template RslChannelNr t_chan_nr := ts_RslChanNr_PCH_AGCH(0);
990 /* we expect four blocks of 14 bytes, let's fill them with content easily
991 * distinguishable */
992 /* decoding the actual entire P1 rest octets by manually generated code is
993 * too much effort; instead simply do a binary compare to this constant */
994 const bitstring c_P1RO_hdr := '00101011101'B;
995 var L1ctlDlMessage dl;
996 timer T := 10.0;
997
998 f_init();
999 f_init_l1ctl();
1000 f_l1_tune(L1CTL, ccch_mode := CCCH_MODE_COMBINED_CBCH);
1001
Vadim Yanitskiy493abe72020-05-25 22:03:48 +07001002 RSL_CCHAN.send(ts_ASP_RSL_UD(ts_RSL_OSMO_ETWS_CMD(c_etws)));
Harald Welte908ce542019-09-04 23:05:40 +02001003 /* wait for a bit until old non-ETWS Paging messages are gone */
1004 f_sleep(3.0);
1005 /* disable the ETWS PN again */
Vadim Yanitskiy493abe72020-05-25 22:03:48 +07001006 RSL_CCHAN.send(ts_ASP_RSL_UD(ts_RSL_OSMO_ETWS_CMD(''O)));
Harald Welte908ce542019-09-04 23:05:40 +02001007 f_sleep(2.0);
1008 T.start;
1009 L1CTL.clear;
1010 alt {
1011 [] L1CTL.receive(tr_L1CTL_DATA_IND(t_chan_nr)) -> value dl {
1012 var GsmRrMessage l3 := dec_GsmRrMessage(dl.payload.data_ind.payload);
1013 select (l3) {
Vadim Yanitskiya9a198d2020-03-28 05:11:26 +07001014 case (tr_PAG_REQ1(tr_MI_LV(t_MI_NoIdentity()))) { repeat; }
Harald Welte908ce542019-09-04 23:05:40 +02001015 case (tr_PagingType1) {
1016 setverdict(fail, "Received non-empty PT1 after disabling ETWS PN: ", l3);
1017 }
1018 }
1019 repeat;
1020 }
1021 [] L1CTL.receive { repeat; }
1022 [] T.timeout {
1023 setverdict(pass);
1024 }
1025 }
1026}
1027
Harald Welte11b734c2019-09-05 14:17:54 +02001028/* Ensure ETWS Primary Notification is passed from RSL to PCU interface */
1029testcase TC_etws_pcu() runs on test_CT {
1030 timer T := 10.0;
1031
1032 f_init();
1033 f_init_l1ctl();
1034 f_l1_tune(L1CTL, ccch_mode := CCCH_MODE_COMBINED_CBCH);
1035
Vadim Yanitskiy493abe72020-05-25 22:03:48 +07001036 RSL_CCHAN.send(ts_ASP_RSL_UD(ts_RSL_OSMO_ETWS_CMD(c_etws)));
Harald Welte11b734c2019-09-05 14:17:54 +02001037
1038 T.start;
1039 alt {
1040 [] PCU.receive(t_SD_PCUIF(g_pcu_conn_id, tr_PCUIF_APP_INFO_REQ(0, 0, c_etws))) {
1041 setverdict(pass);
1042 }
1043 [] PCU.receive(t_SD_PCUIF(g_pcu_conn_id, tr_PCUIF_APP_INFO_REQ(?, ?, ?))) {
1044 setverdict(fail, "PCU socket received invalid APP INFO");
1045 }
1046 [] PCU.receive { repeat; }
1047 [] T.timeout {
1048 setverdict(fail, "PCU socket timeout receiving APP INFO (ETWS)");
1049 }
1050 }
1051}
1052
1053
Harald Welte908ce542019-09-04 23:05:40 +02001054
Harald Welte505cf9b2018-09-15 17:47:23 +03001055/* SMSCB TODO:
1056 * multiple SMS BC CMD at the same time: Ensure all of them are sent exactly once
1057 * extended CBCH vs. normal CBCH
1058 *
1059 */
1060
1061control {
Harald Welte4a129f82019-05-21 16:35:22 +02001062 execute( TC_cbch_load_idle_no_cbch() );
1063
Harald Welte505cf9b2018-09-15 17:47:23 +03001064 execute( TC_sms_cb_cmd_sdcch4_1block() );
1065 execute( TC_sms_cb_cmd_sdcch4_2block() );
1066 execute( TC_sms_cb_cmd_sdcch4_3block() );
1067 execute( TC_sms_cb_cmd_sdcch4_4block() );
Harald Weltee0026c32019-05-20 00:27:30 +02001068 execute( TC_sms_cb_cmd_sdcch4_multi() );
Harald Welte505cf9b2018-09-15 17:47:23 +03001069 execute( TC_sms_cb_cmd_sdcch4_schedule() );
Harald Welte88e5dff2019-05-20 15:14:46 +02001070 execute( TC_sms_cb_cmd_sdcch4_default_only() );
Harald Welted522ca02019-05-20 20:06:12 +02001071 execute( TC_sms_cb_cmd_sdcch4_default_and_normal() );
Harald Weltedf4d0f02019-05-20 16:04:11 +02001072 execute( TC_sms_cb_cmd_sdcch4_default_then_null() );
Harald Welte4a129f82019-05-21 16:35:22 +02001073 execute( TC_cbc_sdcch4_load_idle() );
1074 execute( TC_cbc_sdcch4_load_overload() );
1075
Harald Welte505cf9b2018-09-15 17:47:23 +03001076 if (false) { /* FIXME: SDCCH/8 support broken, needs trxcon + L1CTL work */
1077 execute( TC_sms_cb_cmd_sdcch8_1block() );
1078 execute( TC_sms_cb_cmd_sdcch8_2block() );
1079 execute( TC_sms_cb_cmd_sdcch8_3block() );
1080 execute( TC_sms_cb_cmd_sdcch8_4block() );
Harald Weltee0026c32019-05-20 00:27:30 +02001081 execute( TC_sms_cb_cmd_sdcch8_multi() );
Harald Welte505cf9b2018-09-15 17:47:23 +03001082 execute( TC_sms_cb_cmd_sdcch8_schedule() );
Harald Welte88e5dff2019-05-20 15:14:46 +02001083 execute( TC_sms_cb_cmd_sdcch8_default_only() );
Harald Welted522ca02019-05-20 20:06:12 +02001084 execute( TC_sms_cb_cmd_sdcch8_default_and_normal() );
Harald Welte4a129f82019-05-21 16:35:22 +02001085 execute( TC_cbc_sdcch8_load_idle() );
1086 execute( TC_cbc_sdcch8_load_overload() );
Harald Welte505cf9b2018-09-15 17:47:23 +03001087 }
Harald Welte908ce542019-09-04 23:05:40 +02001088
1089 execute( TC_etws_p1ro() );
1090 execute( TC_etws_p1ro_end() );
Harald Welte11b734c2019-09-05 14:17:54 +02001091 execute( TC_etws_pcu() );
Harald Welte505cf9b2018-09-15 17:47:23 +03001092}
1093
1094
1095}