blob: 11855bfd230887d9616178fc359f6dc5f0dd3084 [file] [log] [blame]
Harald Welte505cf9b2018-09-15 17:47:23 +03001module BTS_Tests_SMSCB {
2
3/* Integration Tests for OsmoBTS
4 * (C) 2019 by Harald Welte <laforge@gnumonks.org>
5 * All rights reserved.
6 *
7 * Released under the terms of GNU General Public License, Version 2 or
8 * (at your option) any later version.
9 *
Harald Welte34b5a952019-05-27 11:54:11 +020010 * SPDX-License-Identifier: GPL-2.0-or-later
11 *
Harald Welte505cf9b2018-09-15 17:47:23 +030012 * This test suite tests the SMSCB (Cell Broadcast) related functionality of
13 * OsmoBTS by attaching to the A-bis RSL and Um interface and emulating both
14 * BSC and MS.
15 */
16
17import from Misc_Helpers all;
18import from General_Types all;
19import from Osmocom_Types all;
20import from GSM_Types all;
21import from L1CTL_PortType all;
22import from L1CTL_Types all;
23import from LAPDm_Types all;
Harald Welte4a129f82019-05-21 16:35:22 +020024import from IPA_Emulation all;
Harald Welte908ce542019-09-04 23:05:40 +020025import from GSM_RR_Types all;
Vadim Yanitskiya9a198d2020-03-28 05:11:26 +070026import from L3_Templates all;
Harald Welte505cf9b2018-09-15 17:47:23 +030027
28import from RSL_Types all;
29
Harald Welte11b734c2019-09-05 14:17:54 +020030import from PCUIF_Types all;
31import from PCUIF_CodecPort all;
32
Harald Welte505cf9b2018-09-15 17:47:23 +030033import from Osmocom_VTY_Functions all;
34
35import from BTS_Tests all;
36
37/***********************************************************************
38 * Cell Broadcast related tests
39 ***********************************************************************/
40
Harald Weltea3ff6702019-05-20 20:03:50 +020041/* Test parameters for one channel (e.g. Basic, Extended) */
42type record CbchTestParsChan {
43 /* list of "normal" (sent-once) SMSCB messages */
44 CbchTestMsgs msgs,
45 /* default message, if any */
46 CbchTestMsg default_msg optional
47}
48
49private template (value) CbchTestParsChan
50t_CbchPC(template (value) CbchTestMsgs msgs, template (omit) CbchTestMsg def := omit) := {
51 msgs := msgs,
52 default_msg := def
53}
54
55/* CBCH test parameters for most of our tests */
Harald Welte505cf9b2018-09-15 17:47:23 +030056type record CbchTestPars {
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +070057 /* Should we execute on SDCCH4 or SDCCH8? */
58 RslChannelNr chan_nr,
Harald Weltea3ff6702019-05-20 20:03:50 +020059 /* Parameters for BASIC CBCH */
60 CbchTestParsChan basic,
61 /* Parameters for EXTENDED CBCH */
62 CbchTestParsChan extended optional
Harald Welte505cf9b2018-09-15 17:47:23 +030063};
64
65type record CbchTestMsg {
66 /* config / input data */
67 RSL_CbCommand rsl_cb_cmd,
68 uint2_t last_block, /* 0..3 */
69 octetstring payload,
70 /* computed / result data */
71 CbchBlocks blocks optional
72};
73type record of CbchTestMsg CbchTestMsgs;
74
75/* a single 22byte block within a CbchTestMsg */
76type record CbchBlock {
77 uint4_t seq_nr, /* as per TS 04.12 */
78 boolean is_last,
79 OCT22 payload,
80 boolean seen_once
81};
82type record of CbchBlock CbchBlocks;
83
84/* compute the expected blocks for given test parameters */
85private function f_cbch_compute_exp_blocks(inout CbchTestPars pars) {
Harald Weltea3ff6702019-05-20 20:03:50 +020086 f_cbch_compute_exp_blocks_chan(pars.basic);
87 if (ispresent(pars.extended)) {
88 f_cbch_compute_exp_blocks_chan(pars.extended);
89 }
90}
91private function f_cbch_compute_exp_blocks_chan(inout CbchTestParsChan pars_chan) {
Harald Welte505cf9b2018-09-15 17:47:23 +030092 var integer i;
Harald Weltea3ff6702019-05-20 20:03:50 +020093 for (i := 0; i < lengthof(pars_chan.msgs); i := i+1) {
94 pars_chan.msgs[i].blocks := f_comp_blocks(pars_chan.msgs[i]);
95 }
96 if (ispresent(pars_chan.default_msg)) {
97 pars_chan.default_msg.blocks := f_comp_blocks(pars_chan.default_msg);
Harald Welte505cf9b2018-09-15 17:47:23 +030098 }
99}
100private function f_comp_blocks(in CbchTestMsg msg) return CbchBlocks {
101 var CbchBlocks blocks := {};
102 var integer i;
103
104 for (i := 0; i <= msg.last_block; i := i+1) {
105 var CbchBlock block := {
106 seq_nr := i,
107 is_last := false,
108 payload := substr(msg.payload, 22*i, 22),
109 seen_once := false
110 };
111 if (msg.rsl_cb_cmd == RSL_CB_CMD_SCHEDULE and i == 0) {
112 block.seq_nr := 8;
113 }
114 if (i == msg.last_block) {
115 block.is_last := true;
116 }
117 blocks := blocks & {block};
118 }
119
120 return blocks;
121};
122
123/* TS 48.058 Section 9.3.41 */
124private function f_cbch_block_nr2rsl(uint2_t nr) return uint2_t {
125 select (nr) {
126 case (0) { return 1; }
127 case (1) { return 2; }
128 case (2) { return 3; }
129 case (3) { return 0; }
130 }
131 setverdict(fail, "Invalid block number");
132 mtc.stop;
133}
134
Harald Welte88e5dff2019-05-20 15:14:46 +0200135private function f_cbch_fn2tb(uint32_t fn) return integer
136{
137 return (fn/51) mod 8; /* TS 05.02 Section 6.5.4 */
138}
139
Harald Welte505cf9b2018-09-15 17:47:23 +0300140/* Verify the CBCH TB scheduling rules of TS 05.02 Section 6.5.4 */
141private function f_cbch_fn_verify(uint32_t fn, CBCH_Block cb)
142{
Harald Welte88e5dff2019-05-20 15:14:46 +0200143 var integer tb := f_cbch_fn2tb(fn);
Harald Welte505cf9b2018-09-15 17:47:23 +0300144 if (cb.block_type.seq_nr == 15 /* null */) {
145 /* always permitted */
146 return;
147 } else if (cb.block_type.seq_nr == 8 /* schedule */) {
148 if (tb != 0) {
149 setverdict(fail, "Schedule block at TB=", tb);
150 }
151 } else if (cb.block_type.seq_nr < 4) {
152 if (cb.block_type.seq_nr != tb and cb.block_type.seq_nr+4 != tb) {
153 setverdict(fail, "Normal block at wrong TB=", tb, ": ", cb);
154 }
155 }
156}
157
Harald Weltedf4d0f02019-05-20 16:04:11 +0200158private function f_rsl_smscb_default_null() runs on test_CT
159{
160 var RSL_IE_CbCommandType cmd_type :=
161 valueof(ts_RSL_IE_CbCmdType(RSL_CB_CMD_DEFAULT, 1, true));
Vadim Yanitskiy493abe72020-05-25 22:03:48 +0700162 RSL_CCHAN.send(ts_ASP_RSL_UD(ts_RSL_SMSCB_CMD(cmd_type, ''O)));
Harald Weltedf4d0f02019-05-20 16:04:11 +0200163}
164
Harald Weltea3ff6702019-05-20 20:03:50 +0200165template RSL_IE t_RSL_IE_SMSCB_EXT := t_RSL_IE(RSL_IE_SMSCB_CHAN_INDICATOR, {smscb_chan_ind := 1});
166
167private function f_smscb_setup_rsl_chan(inout CbchTestParsChan pars_chan, boolean extd := false)
168runs on test_CT {
Harald Welte88e5dff2019-05-20 15:14:46 +0200169 var integer i;
Harald Weltea3ff6702019-05-20 20:03:50 +0200170 var CbchTestMsg msg;
171 var uint2_t rsl_last_block;
172 var RSL_IE_CbCommandType cmd_type;
173 var RSL_Message rsl;
174
175 /* send SMSCB[s] via RSL */
176 for (i := 0; i < lengthof(pars_chan.msgs); i := i+1) {
177 msg := pars_chan.msgs[i];
178 rsl_last_block := f_cbch_block_nr2rsl(msg.last_block);
179 cmd_type := valueof(ts_RSL_IE_CbCmdType(msg.rsl_cb_cmd, rsl_last_block));
180 rsl := valueof(ts_RSL_SMSCB_CMD(cmd_type, msg.payload));
181 if (extd) {
182 rsl.ies := rsl.ies & { valueof(t_RSL_IE_SMSCB_EXT) };
183 }
Vadim Yanitskiy493abe72020-05-25 22:03:48 +0700184 RSL_CCHAN.send(ts_ASP_RSL_UD(rsl));
Harald Weltea3ff6702019-05-20 20:03:50 +0200185 }
186 if (ispresent(pars_chan.default_msg)) {
187 msg := pars_chan.default_msg;
188 rsl_last_block := f_cbch_block_nr2rsl(msg.last_block);
189 cmd_type := valueof(ts_RSL_IE_CbCmdType(msg.rsl_cb_cmd, rsl_last_block, false));
190 rsl := valueof(ts_RSL_SMSCB_CMD(cmd_type, msg.payload));
191 if (extd) {
192 rsl.ies := rsl.ies & { valueof(t_RSL_IE_SMSCB_EXT) };
193 }
Vadim Yanitskiy493abe72020-05-25 22:03:48 +0700194 RSL_CCHAN.send(ts_ASP_RSL_UD(rsl));
Harald Weltea3ff6702019-05-20 20:03:50 +0200195 }
196}
Harald Welte505cf9b2018-09-15 17:47:23 +0300197
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700198private function f_vty_cbch_setup(in RslChannelNr chan_nr) runs on test_CT {
Harald Welte505cf9b2018-09-15 17:47:23 +0300199
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700200 if (match(chan_nr, t_RslChanNr_CBCH4(0))) {
201 f_vty_config2(BSCVTY, { "network", "bts 0", "trx 0", "timeslot 0"},
Harald Welte505cf9b2018-09-15 17:47:23 +0300202 "phys_chan_config CCCH+SDCCH4+CBCH");
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700203 /* (Re)configure timeslots 1..3 as TCH/F */
204 for (var integer tn := 1; tn <= 3; tn := tn + 1) {
205 f_vty_config2(BSCVTY, { "network", "bts 0", "trx 0",
206 "timeslot " & int2str(tn) },
207 "phys_chan_config TCH/F");
208 }
209 } else if (match(chan_nr, t_RslChanNr_CBCH8(?))) {
210 f_vty_config2(BSCVTY, { "network", "bts 0", "trx 0", "timeslot 0"},
Harald Welte505cf9b2018-09-15 17:47:23 +0300211 "phys_chan_config CCCH+SDCCH4");
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700212 f_vty_config2(BSCVTY, { "network", "bts 0", "trx 0",
213 "timeslot " & int2str(chan_nr.tn) },
Harald Welte505cf9b2018-09-15 17:47:23 +0300214 "phys_chan_config SDCCH8+CBCH");
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700215
216 /* (Re)configure timeslots 1..3 (excluding the given one) as TCH/F */
217 for (var integer tn := 1; tn <= 3; tn := tn + 1) {
218 if (tn == chan_nr.tn)
219 { continue; }
220 f_vty_config2(BSCVTY, { "network", "bts 0", "trx 0",
221 "timeslot " & int2str(tn) },
222 "phys_chan_config TCH/F");
223 }
Harald Welte505cf9b2018-09-15 17:47:23 +0300224 }
225 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
226 f_sleep(2.0);
Harald Welte4a129f82019-05-21 16:35:22 +0200227}
228private function f_smscb_setup(inout CbchTestPars pars) runs on test_CT {
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700229 /* Make sure we've got either SDCCH4+CBCH or SDCCH8+CBCH.
230 * SDCCH4+CBCH can only be allocated on TS0, SDCCH8+CBCH on TS0..3.
231 * On C0 the first timeslot shall always transmit BCCH, thus TS1..3.*/
232 if (not match(pars.chan_nr, (t_RslChanNr_CBCH4(0), t_RslChanNr_CBCH8(1),
233 t_RslChanNr_CBCH8(2), t_RslChanNr_CBCH8(3)))) {
234 setverdict(inconc, "Unhandled channel number: ", pars.chan_nr);
235 mtc.stop;
236 }
Harald Welte4a129f82019-05-21 16:35:22 +0200237
238 f_cbch_compute_exp_blocks(pars);
239
240 f_init_vty_bsc();
241 /* ensure that a CBCH is present in channel combination */
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700242 f_vty_cbch_setup(pars.chan_nr);
Harald Welte10474062019-05-30 16:48:17 +0200243 f_init();
Harald Welte505cf9b2018-09-15 17:47:23 +0300244
245 f_init_l1ctl();
Harald Welte990a3612019-05-27 14:02:13 +0200246 f_l1_tune(L1CTL, ccch_mode := CCCH_MODE_COMBINED_CBCH);
Harald Welte505cf9b2018-09-15 17:47:23 +0300247 /* FIXME: switch to dedicated mode for SDCCH/8 */
248
249 /* send SMSCB[s] via RSL */
Harald Weltea3ff6702019-05-20 20:03:50 +0200250 f_smscb_setup_rsl_chan(pars.basic, false);
251 if (ispresent(pars.extended)) {
252 f_smscb_setup_rsl_chan(pars.extended, true);
Harald Welte505cf9b2018-09-15 17:47:23 +0300253 }
Harald Welte88e5dff2019-05-20 15:14:46 +0200254}
255
Harald Weltea3ff6702019-05-20 20:03:50 +0200256/* construct a receive/match template for given block_nr in given msg */
257private function f_get_block_template(CbchTestMsg msg, integer block_nr) return template CBCH_Block {
258 var template CBCH_Block tr;
259 if (block_nr < lengthof(msg.blocks)) {
260 var CbchBlock b := msg.blocks[block_nr];
261 tr := tr_CBCH_Block(b.seq_nr, b.is_last, b.payload);
262 } else {
263 tr := tr_CBCH_Block(15, ?, ?);
264 }
265 return tr;
266}
267
268/* the heart of the CBCH test case matching engine for one channel (basic, extended) */
269private function f_cbch_match(inout CbchTestParsChan pars_chan, CBCH_Block cb, integer tb)
270{
271 var integer block_nr := tb mod 4;
272 var integer i;
273
274 if (not match(cb, tr_CBCH_Block)) {
275 setverdict(fail, "Illegal CBCH Block received: ", cb);
276 } else {
277 var boolean matched := false;
278 /* check if it's any of our expected blocks */
279 for (i := 0; i < lengthof(pars_chan.msgs); i := i+1) {
280 if (block_nr < lengthof(pars_chan.msgs[i].blocks)) {
281 if (match(cb, f_get_block_template(pars_chan.msgs[i], block_nr))) {
282 log("Found block_nr ", block_nr, " of msg ", i);
283 if (not pars_chan.msgs[i].blocks[block_nr].seen_once) {
284 pars_chan.msgs[i].blocks[block_nr].seen_once := true;
285 setverdict(pass);
286 } else {
287 setverdict(fail, "Received SMSCB twice! ", cb);
288 }
289 matched := true;
290 break;
291 }
292 }
293 }
294 if (not matched) {
295 var template CBCH_Block tr;
296 if (ispresent(pars_chan.default_msg)) {
297 /* it must be a block of the default message */
298 tr := f_get_block_template(pars_chan.default_msg, block_nr);
299 } else {
300 /* it must be a NULL block */
301 tr := tr_CBCH_Block(15, ?, ?);
302 }
303 if (not match(cb, tr)) {
304 setverdict(fail, "Received unexpected CBCH block: ", cb);
305 } else {
306 log("Found block_nr ", block_nr, " of DEFAULT/NULL");
307 if (ispresent(pars_chan.default_msg) and
308 block_nr < lengthof(pars_chan.default_msg.blocks)) {
309 pars_chan.default_msg.blocks[block_nr].seen_once := true;
310 }
311 }
312 }
313 }
314}
315
316/* Report/Evaluate the per-channel CBCH test results */
317private function f_cbch_report(CbchTestParsChan pars_chan, charstring id)
318{
319 var integer i, j;
320
321 /* verify that each block of each message has been seen once */
322 for (i := 0; i < lengthof(pars_chan.msgs); i := i+1) {
323 for (j := 0; j < lengthof(pars_chan.msgs[i].blocks); j := j+1) {
324 var CbchBlock b := pars_chan.msgs[i].blocks[j];
325 if (not b.seen_once) {
326 setverdict(fail, "Timeout waiting for ", id, " CBCH block ",
327 j, " of msg ", i);
328 }
329 }
330 }
331 if (ispresent(pars_chan.default_msg)) {
332 /* verify that each block of default message has been seen at least once */
333 for (j := 0; j < lengthof(pars_chan.default_msg.blocks); j := j+1) {
334 var CbchBlock b := pars_chan.default_msg.blocks[j];
335 if (not b.seen_once) {
336 setverdict(fail, "Timeout waiting for at leaset one instance of ",
337 "CBCH block ", j, " of DEFAULT msg");
338 }
339 }
340 }
341}
342
Harald Welte88e5dff2019-05-20 15:14:46 +0200343/* shared function doing the heavy lifting for most CBCH tests */
344private function f_TC_smscb(CbchTestPars pars) runs on test_CT {
345 var L1ctlDlMessage dl;
Harald Weltea3ff6702019-05-20 20:03:50 +0200346 var integer msg_count;
347 timer T;
348
349 msg_count := lengthof(pars.basic.msgs);
350 if (ispresent(pars.basic.default_msg)) {
351 msg_count := msg_count + 1;
352 }
353 if (ispresent(pars.extended)) {
354 msg_count := msg_count + lengthof(pars.extended.msgs);
355 if (ispresent(pars.extended.default_msg)) {
356 msg_count := msg_count + 1;
357 }
358 }
Harald Welte88e5dff2019-05-20 15:14:46 +0200359
360 f_smscb_setup(pars);
361
Harald Weltea3ff6702019-05-20 20:03:50 +0200362 /* dynamically adjust timeout based on number of messages */
363 T.start(5.0 + 3.0 * int2float(msg_count));
Harald Welte505cf9b2018-09-15 17:47:23 +0300364 /* Expect this to show up exactly once on the basic CBCH (four blocks) */
365 alt {
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700366 [] L1CTL.receive(tr_L1CTL_DATA_IND(pars.chan_nr)) -> value dl {
Harald Weltea3ff6702019-05-20 20:03:50 +0200367 var integer tb := f_cbch_fn2tb(dl.dl_info.frame_nr);
Harald Welte505cf9b2018-09-15 17:47:23 +0300368 var CBCH_Block cb := dec_CBCH_Block(dl.payload.data_ind.payload);
Harald Weltea3ff6702019-05-20 20:03:50 +0200369 log("Tb=", tb, ", CBCH: ", dl, ", block: ", cb);
370
Harald Welte505cf9b2018-09-15 17:47:23 +0300371 /* detect the proper CBCH messages; check frame number */
372 f_cbch_fn_verify(dl.dl_info.frame_nr, cb);
Harald Weltea3ff6702019-05-20 20:03:50 +0200373
374 if (tb < 4) {
375 f_cbch_match(pars.basic, cb, tb);
Harald Welte505cf9b2018-09-15 17:47:23 +0300376 } else {
Harald Weltea3ff6702019-05-20 20:03:50 +0200377 if (not ispresent(pars.extended)) {
378 /* no parameters for ext. BCCH given: ignore */
379 repeat;
Harald Welte505cf9b2018-09-15 17:47:23 +0300380 }
Harald Weltea3ff6702019-05-20 20:03:50 +0200381 f_cbch_match(pars.extended, cb, tb);
Harald Welte505cf9b2018-09-15 17:47:23 +0300382 }
Harald Weltea3ff6702019-05-20 20:03:50 +0200383 repeat;
Harald Welte505cf9b2018-09-15 17:47:23 +0300384 }
385 [] L1CTL.receive { repeat; }
386 [] T.timeout {
Harald Weltea3ff6702019-05-20 20:03:50 +0200387 f_cbch_report(pars.basic, "Basic");
388 if (ispresent(pars.extended)) {
389 f_cbch_report(pars.extended, "Extended");
Harald Welte505cf9b2018-09-15 17:47:23 +0300390 }
391 }
392 }
393
Harald Welte88e5dff2019-05-20 15:14:46 +0200394 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, pass);
395}
396
397private function f_TC_smscb_default_only(CbchTestPars pars) runs on test_CT {
398 var L1ctlDlMessage dl;
399 timer T := 5.0;
400
401 f_smscb_setup(pars);
402
403 /* ensure whatever initial NULL messages have all been drained */
404 f_sleep(5.0);
405 L1CTL.clear;
406
407 T.start;
408 alt {
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700409 [] L1CTL.receive(tr_L1CTL_DATA_IND(pars.chan_nr)) -> value dl {
Harald Welte88e5dff2019-05-20 15:14:46 +0200410 var integer tb := f_cbch_fn2tb(dl.dl_info.frame_nr);
411 log("CBCH: ", dl);
412 var CBCH_Block cb := dec_CBCH_Block(dl.payload.data_ind.payload);
413 /* detect the proper CBCH messages; check frame number */
414 f_cbch_fn_verify(dl.dl_info.frame_nr, cb);
415 if (tb >= 4) {
416 /* skip extended CBCH for now */
417 repeat;
418 }
419 if (not match(cb, tr_CBCH_Block)) {
420 setverdict(fail, "Illegal CBCH Block received: ", cb);
421 } else {
422 var uint4_t rx_seq_nr := cb.block_type.seq_nr;
423 var template CBCH_Block tr;
Harald Weltea3ff6702019-05-20 20:03:50 +0200424 if (rx_seq_nr < lengthof(pars.basic.msgs[0].blocks)) {
425 var CbchBlock b := pars.basic.msgs[0].blocks[rx_seq_nr];
Harald Welte88e5dff2019-05-20 15:14:46 +0200426 tr := tr_CBCH_Block(b.seq_nr, b.is_last, b.payload);
427 } else {
428 tr := tr_CBCH_Block(15, ?, ?);
429 }
430 if (match(cb, tr)) {
431 setverdict(pass); /* FIXME: check that all blocks are received? */
432 repeat;
433 } else {
434 setverdict(fail, "Unexpected CBCH block ", cb, ", expected ", tr);
435 }
436 }
437 }
438 [] L1CTL.receive { repeat; }
439 [] T.timeout {}
440 }
441
Harald Welte88e5dff2019-05-20 15:14:46 +0200442 /* don't shut down; some tests still want to continue */
Harald Welte505cf9b2018-09-15 17:47:23 +0300443}
444
445private const CbchTestMsgs msgs_1m_1b_norm := {
446 { RSL_CB_CMD_NORMAL, 0, '001000320f1141660c344dd3cba09a0c000000000000'O, omit }
447}
448
449private const CbchTestMsgs msgs_1m_2b_norm := {
450 { RSL_CB_CMD_NORMAL, 1, '001000320f1141660c344dd3cba09a0c000000000000'O &
451 '000102030405060708090a0b0c0d0e0f101213141516'O,
452 omit }
453}
454
455private const CbchTestMsgs msgs_1m_3b_norm := {
456 { RSL_CB_CMD_NORMAL, 2, '001000320f1141660c344dd3cba09a0c000000000000'O &
457 '000102030405060708090a0b0c0d0e0f101213141516'O &
458 '101112131415161718191a1b1c1d1e1f202223242526'O,
459 omit }
460}
461
462private const CbchTestMsgs msgs_1m_4b_norm := {
463 { RSL_CB_CMD_NORMAL, 3, '001000320f1141660c344dd3cba09a0c000000000000'O &
464 '000102030405060708090a0b0c0d0e0f101213141516'O &
465 '101112131415161718191a1b1c1d1e1f202223242526'O &
466 '202122232425262728292a2b2c2d2e2f303233343536'O,
467 omit }
468}
469
470private const CbchTestMsgs msgs_1m_4b_sched := {
471 { RSL_CB_CMD_SCHEDULE, 3, '001000320f1141660c344dd3cba09a0c000000000000'O &
472 '000102030405060708090a0b0c0d0e0f101213141516'O &
473 '101112131415161718191a1b1c1d1e1f202223242526'O &
474 '202122232425262728292a2b2c2d2e2f303233343536'O,
475 omit }
476}
477
Harald Weltee0026c32019-05-20 00:27:30 +0200478private const CbchTestMsgs msgs_3m_4b_norm := {
479 { RSL_CB_CMD_NORMAL, 3, '001000320f1141660c344dd3cba09a0c000000000000'O &
480 '000102030405060708090a0b0c0d0e0f101213141516'O &
481 '101112131415161718191a1b1c1d1e1f202223242526'O &
482 '201122232425262728292a2b2c2d2e2f303233343536'O,
483 omit },
484 { RSL_CB_CMD_NORMAL, 3, '002000320f1141660c344dd3cba09a0c000000000000'O &
485 '002102030405060708090a0b0c0d0e0f101213141516'O &
486 '102112131415161718191a1b1c1d1e1f202223242526'O &
487 '202122232425262728292a2b2c2d2e2f303233343536'O,
488 omit },
489 { RSL_CB_CMD_NORMAL, 3, '003000320f1141660c344dd3cba09a0c000000000000'O &
490 '003102030405060708090a0b0c0d0e0f101213141516'O &
491 '103112131415161718191a1b1c1d1e1f202223242526'O &
492 '203122232425262728292a2b2c2d2e2f303233343536'O,
493 omit }
494}
495
Harald Welte88e5dff2019-05-20 15:14:46 +0200496private const CbchTestMsgs msgs_1m_3b_default := {
497 { RSL_CB_CMD_DEFAULT, 2, '001000320f1141660c344dd3cba09a0c000000000000'O &
498 '000102030405060708090a0b0c0d0e0f101213141516'O &
499 '101112131415161718191a1b1c1d1e1f202223242526'O,
500 omit }
501}
Harald Weltea3ff6702019-05-20 20:03:50 +0200502private const CbchTestMsg msg_default := {
503 RSL_CB_CMD_DEFAULT, 0, '010203040506070708090a0b0c0d0e0f101112131415'O,
504 omit
505}
Harald Welte88e5dff2019-05-20 15:14:46 +0200506
Harald Welte505cf9b2018-09-15 17:47:23 +0300507/* transmit single-block SMSCB COMMAND */
508testcase TC_sms_cb_cmd_sdcch4_1block() runs on test_CT {
509 var CbchTestPars pars := {
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700510 chan_nr := valueof(ts_RslChanNr_CBCH4(0)),
Harald Weltea3ff6702019-05-20 20:03:50 +0200511 basic := valueof(t_CbchPC(msgs_1m_1b_norm)),
512 extended := omit
Harald Welte505cf9b2018-09-15 17:47:23 +0300513 };
514 f_TC_smscb(pars);
515}
516testcase TC_sms_cb_cmd_sdcch8_1block() runs on test_CT {
517 var CbchTestPars pars := {
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700518 chan_nr := valueof(ts_RslChanNr_CBCH8(2)),
Harald Weltea3ff6702019-05-20 20:03:50 +0200519 basic := valueof(t_CbchPC(msgs_1m_1b_norm)),
520 extended := omit
Harald Welte505cf9b2018-09-15 17:47:23 +0300521 };
522 f_TC_smscb(pars);
523}
524
525/* transmit dual-block SMSCB COMMAND */
526testcase TC_sms_cb_cmd_sdcch4_2block() runs on test_CT {
527 var CbchTestPars pars := {
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700528 chan_nr := valueof(ts_RslChanNr_CBCH4(0)),
Harald Weltea3ff6702019-05-20 20:03:50 +0200529 basic := valueof(t_CbchPC(msgs_1m_2b_norm)),
530 extended := omit
Harald Welte505cf9b2018-09-15 17:47:23 +0300531 };
532 f_TC_smscb(pars);
533}
534testcase TC_sms_cb_cmd_sdcch8_2block() runs on test_CT {
535 var CbchTestPars pars := {
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700536 chan_nr := valueof(ts_RslChanNr_CBCH8(2)),
Harald Weltea3ff6702019-05-20 20:03:50 +0200537 basic := valueof(t_CbchPC(msgs_1m_2b_norm)),
538 extended := omit
Harald Welte505cf9b2018-09-15 17:47:23 +0300539 };
540 f_TC_smscb(pars);
541}
542
543/* transmit triple-block SMSCB COMMAND */
544testcase TC_sms_cb_cmd_sdcch4_3block() runs on test_CT {
545 var CbchTestPars pars := {
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700546 chan_nr := valueof(ts_RslChanNr_CBCH4(0)),
Harald Weltea3ff6702019-05-20 20:03:50 +0200547 basic := valueof(t_CbchPC(msgs_1m_3b_norm)),
548 extended := omit
Harald Welte505cf9b2018-09-15 17:47:23 +0300549 };
550 f_TC_smscb(pars);
551}
552testcase TC_sms_cb_cmd_sdcch8_3block() runs on test_CT {
553 var CbchTestPars pars := {
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700554 chan_nr := valueof(ts_RslChanNr_CBCH8(2)),
Harald Weltea3ff6702019-05-20 20:03:50 +0200555 basic := valueof(t_CbchPC(msgs_1m_3b_norm)),
556 extended := omit
Harald Welte505cf9b2018-09-15 17:47:23 +0300557 };
558 f_TC_smscb(pars);
559}
560
561/* transmit quad-block SMSCB COMMAND */
562testcase TC_sms_cb_cmd_sdcch4_4block() runs on test_CT {
563 var CbchTestPars pars := {
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700564 chan_nr := valueof(ts_RslChanNr_CBCH4(0)),
Harald Weltea3ff6702019-05-20 20:03:50 +0200565 basic := valueof(t_CbchPC(msgs_1m_4b_norm)),
566 extended := omit
Harald Welte505cf9b2018-09-15 17:47:23 +0300567 };
568 f_TC_smscb(pars);
569}
570testcase TC_sms_cb_cmd_sdcch8_4block() runs on test_CT {
571 var CbchTestPars pars := {
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700572 chan_nr := valueof(ts_RslChanNr_CBCH8(2)),
Harald Weltea3ff6702019-05-20 20:03:50 +0200573 basic := valueof(t_CbchPC(msgs_1m_4b_norm)),
574 extended := omit
Harald Welte505cf9b2018-09-15 17:47:23 +0300575 };
576 f_TC_smscb(pars);
577}
578
Harald Weltee0026c32019-05-20 00:27:30 +0200579/* transmit multiple commands of each 4 blocks */
580testcase TC_sms_cb_cmd_sdcch4_multi() runs on test_CT {
581 var CbchTestPars pars := {
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700582 chan_nr := valueof(ts_RslChanNr_CBCH4(0)),
Harald Weltea3ff6702019-05-20 20:03:50 +0200583 basic := valueof(t_CbchPC(msgs_3m_4b_norm)),
584 extended := omit
Harald Weltee0026c32019-05-20 00:27:30 +0200585 };
586 f_TC_smscb(pars);
587}
588testcase TC_sms_cb_cmd_sdcch8_multi() runs on test_CT {
589 var CbchTestPars pars := {
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700590 chan_nr := valueof(ts_RslChanNr_CBCH8(2)),
Harald Weltea3ff6702019-05-20 20:03:50 +0200591 basic := valueof(t_CbchPC(msgs_3m_4b_norm)),
592 extended := omit
Harald Weltee0026c32019-05-20 00:27:30 +0200593 };
594 f_TC_smscb(pars);
595}
596
Harald Welte60bd92b2019-05-20 21:42:21 +0200597/* transmit multiple commands of each 4 blocks on CBCH EXTD */
598testcase TC_sms_cb_cmd_sdcch4_extd_multi() runs on test_CT {
599 var CbchTestPars pars := {
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700600 chan_nr := valueof(ts_RslChanNr_CBCH4(0)),
Harald Welte60bd92b2019-05-20 21:42:21 +0200601 basic := valueof(t_CbchPC({})),
602 extended := valueof(t_CbchPC(msgs_3m_4b_norm))
603 };
604 f_TC_smscb(pars);
605}
606testcase TC_sms_cb_cmd_sdcch8_extd_multi() runs on test_CT {
607 var CbchTestPars pars := {
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700608 chan_nr := valueof(ts_RslChanNr_CBCH8(2)),
Harald Welte60bd92b2019-05-20 21:42:21 +0200609 basic := valueof(t_CbchPC({})),
610 extended := valueof(t_CbchPC(msgs_3m_4b_norm))
611 };
612 f_TC_smscb(pars);
613}
614
Harald Welte505cf9b2018-09-15 17:47:23 +0300615/* transmit SMSCB COMMAND with SCHEDULE payload */
616testcase TC_sms_cb_cmd_sdcch4_schedule() runs on test_CT {
617 var CbchTestPars pars := {
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700618 chan_nr := valueof(ts_RslChanNr_CBCH4(0)),
Harald Weltea3ff6702019-05-20 20:03:50 +0200619 basic := valueof(t_CbchPC(msgs_1m_4b_sched)),
620 extended := omit
Harald Welte505cf9b2018-09-15 17:47:23 +0300621 };
622 f_TC_smscb(pars);
623}
624testcase TC_sms_cb_cmd_sdcch8_schedule() runs on test_CT {
625 var CbchTestPars pars := {
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700626 chan_nr := valueof(ts_RslChanNr_CBCH8(2)),
Harald Weltea3ff6702019-05-20 20:03:50 +0200627 basic := valueof(t_CbchPC(msgs_1m_4b_sched)),
628 extended := omit
Harald Welte505cf9b2018-09-15 17:47:23 +0300629 };
630 f_TC_smscb(pars);
631}
632
Harald Welte88e5dff2019-05-20 15:14:46 +0200633/* set a DEFAULT message; verify it gets transmitted all the time */
634testcase TC_sms_cb_cmd_sdcch4_default_only() runs on test_CT {
635 var CbchTestPars pars := {
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700636 chan_nr := valueof(ts_RslChanNr_CBCH4(0)),
Harald Weltea3ff6702019-05-20 20:03:50 +0200637 basic := valueof(t_CbchPC(msgs_1m_3b_default)),
638 extended := omit
Harald Welte88e5dff2019-05-20 15:14:46 +0200639 };
640 f_TC_smscb_default_only(pars);
641 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, pass);
642}
643testcase TC_sms_cb_cmd_sdcch8_default_only() runs on test_CT {
644 var CbchTestPars pars := {
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700645 chan_nr := valueof(ts_RslChanNr_CBCH4(0)),
Harald Weltea3ff6702019-05-20 20:03:50 +0200646 basic := valueof(t_CbchPC(msgs_1m_3b_default)),
647 extended := omit
Harald Welte88e5dff2019-05-20 15:14:46 +0200648 };
649 f_TC_smscb_default_only(pars);
650 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, pass);
651}
652
Harald Welted522ca02019-05-20 20:06:12 +0200653testcase TC_sms_cb_cmd_sdcch4_default_and_normal() runs on test_CT {
654 var CbchTestPars pars := {
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700655 chan_nr := valueof(ts_RslChanNr_CBCH4(0)),
Harald Welted522ca02019-05-20 20:06:12 +0200656 basic := valueof(t_CbchPC(msgs_1m_3b_norm, msg_default)),
657 extended := omit
658 };
659 f_TC_smscb(pars);
660}
661testcase TC_sms_cb_cmd_sdcch8_default_and_normal() runs on test_CT {
662 var CbchTestPars pars := {
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700663 chan_nr := valueof(ts_RslChanNr_CBCH8(2)),
Harald Welted522ca02019-05-20 20:06:12 +0200664 basic := valueof(t_CbchPC(msgs_1m_3b_norm, msg_default)),
665 extended := omit
666 };
667 f_TC_smscb(pars);
668}
669
Harald Weltedf4d0f02019-05-20 16:04:11 +0200670/* first set a DEFAULT message, then disable it again */
671testcase TC_sms_cb_cmd_sdcch4_default_then_null() runs on test_CT {
672 var CbchTestPars pars := {
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700673 chan_nr := valueof(ts_RslChanNr_CBCH4(0)),
Harald Weltea3ff6702019-05-20 20:03:50 +0200674 basic := valueof(t_CbchPC(msgs_1m_3b_default)),
675 extended := omit
Harald Weltedf4d0f02019-05-20 16:04:11 +0200676 };
Harald Welte6b86b342019-05-27 17:14:36 +0200677 var template RslChannelNr t_chan_nr := t_RslChanNr_CBCH4(0);
Harald Weltedf4d0f02019-05-20 16:04:11 +0200678 var L1ctlDlMessage dl;
679 timer T := 5.0;
680
681 f_TC_smscb_default_only(pars);
682
683 /* disable DEFAULT message; switch back to NULL */
684 f_rsl_smscb_default_null();
685
686 /* ensure whatever initial non-NULL messages have all been drained */
687 f_sleep(5.0);
688 L1CTL.clear;
689
690 T.start;
691 alt {
Harald Welte6b86b342019-05-27 17:14:36 +0200692 [] L1CTL.receive(tr_L1CTL_DATA_IND(t_chan_nr)) -> value dl {
Harald Weltedf4d0f02019-05-20 16:04:11 +0200693 log("CBCH: ", dl);
694 var CBCH_Block cb := dec_CBCH_Block(dl.payload.data_ind.payload);
695 /* detect the proper CBCH messages; check frame number */
696 f_cbch_fn_verify(dl.dl_info.frame_nr, cb);
697 if (not match(cb, tr_CBCH_Block)) {
698 setverdict(fail, "Illegal CBCH Block received: ", cb);
699 } else {
700 if (not match(cb, tr_CBCH_Block(15, ?, ?))) {
701 setverdict(fail, "Unexpected non-NULL CBCH block received");
702 }
703 repeat;
704 }
705 }
706 [] L1CTL.receive { repeat; }
707 [] T.timeout {
708 setverdict(pass);
709 }
710 }
711
712 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, pass);
713}
714
Harald Welte4a129f82019-05-21 16:35:22 +0200715/* Verify there are no CBCH load indications if no CBCH is present */
716testcase TC_cbch_load_idle_no_cbch() runs on test_CT {
717 var ASP_RSL_Unitdata rx_ud;
718 timer T := 10.0;
719
Harald Welte10474062019-05-30 16:48:17 +0200720 f_init();
Harald Welte4a129f82019-05-21 16:35:22 +0200721 f_init_vty_bsc();
722
723 T.start;
724 alt {
Vadim Yanitskiy493abe72020-05-25 22:03:48 +0700725 [] RSL_CCHAN.receive(tr_ASP_RSL_UD(tr_RSL_CBCH_LOAD_IND_BASIC)) -> value rx_ud {
Harald Welte4a129f82019-05-21 16:35:22 +0200726 setverdict(fail, "Received unexpected CBCH LOAD IND: ", rx_ud);
727 }
Vadim Yanitskiy493abe72020-05-25 22:03:48 +0700728 [] RSL_CCHAN.receive(tr_ASP_RSL_UD(tr_RSL_CBCH_LOAD_IND_EXTD)) -> value rx_ud {
Harald Welte4a129f82019-05-21 16:35:22 +0200729 setverdict(fail, "Received unexpected CBCH LOAD IND: ", rx_ud);
730 }
731 [] RSL_CCHAN.receive { repeat; }
732 [] T.timeout {
733 setverdict(pass);
734 }
735 }
736 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
737}
738
739/* Verify the CBCH load indications of an idle cell (without CBCH load) */
740function f_TC_cbc_load_idle() runs on test_CT {
741 template integer tr_slot_count := (2 .. 15);
742 const integer min_load_ind := 4;
743 var integer basic_count := 0;
744 var integer extd_count := 0;
745 var ASP_RSL_Unitdata rx_ud;
746 timer T := 10.0;
747
Harald Welte10474062019-05-30 16:48:17 +0200748 f_init();
Harald Welte4a129f82019-05-21 16:35:22 +0200749
750 RSL_CCHAN.clear;
751 T.start;
752 alt {
Vadim Yanitskiy493abe72020-05-25 22:03:48 +0700753 [] RSL_CCHAN.receive(tr_ASP_RSL_UD(tr_RSL_CBCH_LOAD_IND_BASIC(false, tr_slot_count))) {
Harald Welte4a129f82019-05-21 16:35:22 +0200754 basic_count := basic_count + 1;
755 repeat;
756 }
Vadim Yanitskiy493abe72020-05-25 22:03:48 +0700757 [] 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 +0200758 extd_count := extd_count + 1;
759 repeat;
760 }
Vadim Yanitskiy493abe72020-05-25 22:03:48 +0700761 [] RSL_CCHAN.receive(tr_ASP_RSL_UD(tr_RSL_CBCH_LOAD_IND_BASIC)) -> value rx_ud {
Harald Welte4a129f82019-05-21 16:35:22 +0200762 setverdict(fail, "Received unexpected CBCH LOAD IND: ", rx_ud);
763 }
Vadim Yanitskiy493abe72020-05-25 22:03:48 +0700764 [] RSL_CCHAN.receive(tr_ASP_RSL_UD(tr_RSL_CBCH_LOAD_IND_EXTD)) -> value rx_ud {
Harald Welte4a129f82019-05-21 16:35:22 +0200765 setverdict(fail, "Received unexpected CBCH LOAD IND: ", rx_ud);
766 }
767 [] RSL_CCHAN.receive { repeat; }
768 [] T.timeout {
769 if ((basic_count >= min_load_ind) and (extd_count >= min_load_ind)) {
770 setverdict(pass);
771 } else {
772 setverdict(fail, "Insufficient number of CBCH LOAD IND: ",
773 "BASIC=", basic_count, " EXTD=", extd_count);
774 }
775 }
776 }
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700777
Harald Welte4a129f82019-05-21 16:35:22 +0200778 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
779}
780testcase TC_cbc_sdcch4_load_idle() runs on test_CT {
781 f_init_vty_bsc();
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700782 f_vty_cbch_setup(valueof(ts_RslChanNr_CBCH4(0)));
Harald Welte4a129f82019-05-21 16:35:22 +0200783 f_TC_cbc_load_idle();
784}
785testcase TC_cbc_sdcch8_load_idle() runs on test_CT {
786 f_init_vty_bsc();
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700787 f_vty_cbch_setup(valueof(ts_RslChanNr_CBCH8(2)));
Harald Welte4a129f82019-05-21 16:35:22 +0200788 f_TC_cbc_load_idle();
789}
790
791/* Verify CBCH overload indications are sent when sending too many SMS CB CMD */
792function f_TC_cbc_load_overload(CbchTestPars pars) runs on test_CT {
793 template integer tr_slot_count_basic := (11 .. 13);
794 template integer tr_slot_count_extd := (2 .. 15);
795 const integer min_load_ind := 4;
796 var integer basic_count := 0;
797 var integer extd_count := 0;
798 var ASP_RSL_Unitdata rx_ud;
799 timer T_total := 10.0;
800 timer T_retransmit := 0.2;
801 timer T_initial_guard := 2.0;
802 var integer i;
803
Harald Welte10474062019-05-30 16:48:17 +0200804 f_init();
Harald Welte4a129f82019-05-21 16:35:22 +0200805
806 /* send tons of SMSCB Command */
807 for (i := 0; i < 30; i := i+1) {
808 f_smscb_setup_rsl_chan(pars.basic);
809 }
810
811 /* keep sending SMSCB Commands for another two seconds */
812 T_initial_guard.start;
813 T_retransmit.start;
814 alt {
815 [] T_retransmit.timeout {
816 f_smscb_setup_rsl_chan(pars.basic);
817 T_retransmit.start;
818 repeat;
819 }
820 [] T_initial_guard.timeout { }
821 }
822 /* clear any pending messages (where load may not have peaked yet) */
823 RSL_CCHAN.clear;
824
825 /* keep sending SMSCB Commands while verifying LOAD INDICATIONS */
826 T_total.start;
827 T_retransmit.start;
828 alt {
Vadim Yanitskiy493abe72020-05-25 22:03:48 +0700829 [] 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 +0200830 basic_count := basic_count + 1;
831 repeat;
832 }
Vadim Yanitskiy493abe72020-05-25 22:03:48 +0700833 [] 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 +0200834 extd_count := extd_count + 1;
835 repeat;
836 }
Vadim Yanitskiy493abe72020-05-25 22:03:48 +0700837 [] RSL_CCHAN.receive(tr_ASP_RSL_UD(tr_RSL_CBCH_LOAD_IND_BASIC)) -> value rx_ud {
Harald Welte4a129f82019-05-21 16:35:22 +0200838 setverdict(fail, "Received unexpected CBCH LOAD IND: ", rx_ud);
839 }
Vadim Yanitskiy493abe72020-05-25 22:03:48 +0700840 [] RSL_CCHAN.receive(tr_ASP_RSL_UD(tr_RSL_CBCH_LOAD_IND_EXTD)) -> value rx_ud {
Harald Welte4a129f82019-05-21 16:35:22 +0200841 setverdict(fail, "Received unexpected CBCH LOAD IND: ", rx_ud);
842 }
843 [] RSL_CCHAN.receive { repeat; }
844 [] T_retransmit.timeout {
845 f_smscb_setup_rsl_chan(pars.basic);
846 T_retransmit.start;
847 repeat;
848 }
849 [] T_total.timeout {
850 if ((basic_count >= min_load_ind) and (extd_count >= min_load_ind)) {
851 setverdict(pass);
852 } else {
853 setverdict(fail, "Insufficient number of CBCH LOAD IND: ",
854 "BASIC=", basic_count, " EXTD=", extd_count);
855 }
856 }
857 }
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700858
Harald Welte4a129f82019-05-21 16:35:22 +0200859 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
860}
861testcase TC_cbc_sdcch4_load_overload() runs on test_CT {
862 var CbchTestPars pars := {
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700863 chan_nr := valueof(ts_RslChanNr_CBCH4(0)),
Harald Welte4a129f82019-05-21 16:35:22 +0200864 basic := valueof(t_CbchPC(msgs_1m_3b_norm)),
865 extended := omit
866 };
867
868 f_init_vty_bsc();
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700869 f_vty_cbch_setup(pars.chan_nr);
Harald Welte4a129f82019-05-21 16:35:22 +0200870 f_TC_cbc_load_overload(pars);
871}
872testcase TC_cbc_sdcch8_load_overload() runs on test_CT {
873 var CbchTestPars pars := {
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700874 chan_nr := valueof(ts_RslChanNr_CBCH4(2)),
Harald Welte4a129f82019-05-21 16:35:22 +0200875 basic := valueof(t_CbchPC(msgs_1m_3b_norm)),
876 extended := omit
877 };
878
879 f_init_vty_bsc();
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700880 f_vty_cbch_setup(pars.chan_nr);
Harald Welte4a129f82019-05-21 16:35:22 +0200881 f_TC_cbc_load_overload(pars);
882}
Harald Weltedf4d0f02019-05-20 16:04:11 +0200883
Harald Welte88e5dff2019-05-20 15:14:46 +0200884
Harald Welte908ce542019-09-04 23:05:40 +0200885private template GsmRrMessage tr_PagingType1 := {
886 header := t_RrHeader(PAGING_REQUEST_TYPE_1, ?),
887 payload :=?
888};
889
Harald Welte908ce542019-09-04 23:05:40 +0200890/* we expect four blocks of 14 bytes, let's fill them with content easily distinguishable */
891const octetstring c_etws_seg0 := '000102030405060708090a0b0c0d'O;
892const octetstring c_etws_seg1 := '101112131415161718191a1b1c1d'O;
893const octetstring c_etws_seg2 := '202122232425262728292a2b2c2d'O;
894const octetstring c_etws_seg3 := '303132333435363738393a3b3c3d'O;
895const octetstring c_etws := c_etws_seg0 & c_etws_seg1 & c_etws_seg2 & c_etws_seg3;
896
897/* Ensure only Paging Type 1 with segmented ETWS Primary Notification are sent after RSL_OSMO_ETWS_CMD */
898testcase TC_etws_p1ro() runs on test_CT {
899 var template RslChannelNr t_chan_nr := ts_RslChanNr_PCH_AGCH(0);
900 /* decoding the actual entire P1 rest octets by manually generated code is
901 * too much effort; instead simply do a binary compare to this constant */
902 const bitstring c_P1RO_hdr := '00101011101'B;
903 var integer seg_received[4] := { 0, 0, 0, 0 };
904 var L1ctlDlMessage dl;
905 timer T := 10.0;
906
907 f_init();
908 f_init_l1ctl();
909 f_l1_tune(L1CTL, ccch_mode := CCCH_MODE_COMBINED_CBCH);
910
Vadim Yanitskiy493abe72020-05-25 22:03:48 +0700911 RSL_CCHAN.send(ts_ASP_RSL_UD(ts_RSL_OSMO_ETWS_CMD(c_etws)));
Harald Welte908ce542019-09-04 23:05:40 +0200912 /* wait for a bit until old non-ETWS Paging messages are gone */
913 f_sleep(1.0);
914 L1CTL.clear;
915 T.start;
916 alt {
917 [] L1CTL.receive(tr_L1CTL_DATA_IND(t_chan_nr)) -> value dl {
918 var GsmRrMessage l3 := dec_GsmRrMessage(dl.payload.data_ind.payload);
919 select (l3) {
Vadim Yanitskiya9a198d2020-03-28 05:11:26 +0700920 case (tr_PAG_REQ1(tr_MI_LV(t_MI_NoIdentity()))) {
Harald Welte908ce542019-09-04 23:05:40 +0200921 var octetstring p1ro := l3.payload.pag_req_1.rest_octets;
922 var bitstring midamble := oct2bit(substr(p1ro, 0, 3));
923 var octetstring segment := substr(p1ro, 3, lengthof(p1ro)-3);
924 var BIT1 not_first := substr(midamble, 11, 1);
925 var integer seg_nr := bit2int(substr(midamble, 12, 4));
926 var boolean err := false;
927 if (substr(midamble, 0, 11) != c_P1RO_hdr) {
928 setverdict(fail, "Received unexpected P1 RO header ", midamble);
929 }
930 if (not_first == '1'B) {
931 select (seg_nr) {
932 case (2) {
933 if (segment != c_etws_seg1) {
934 err := true
935 } else {
936 seg_received[1] := seg_received[1] + 1;
937 }}
938 case (3) {
939 if (segment != c_etws_seg2) {
940 err := true
941 } else {
942 seg_received[2] := seg_received[2] + 1;
943 }}
944 case (4) {
945 if (segment != c_etws_seg3) {
946 err := true
947 } else {
948 seg_received[3] := seg_received[3] + 1;
949 }}
950 case else { setverdict(fail, "Unknown segment Nr ", seg_nr); }
951 }
952 if (err) {
953 setverdict(fail, "Unexpected segment ", seg_nr, ": ", segment);
954 }
955 } else {
956 if (seg_nr != 4) {
957 setverdict(fail, "Invalid number of segments ", seg_nr);
958 err := true;
959 }
960 if (segment != c_etws_seg0) {
961 setverdict(fail, "Invalid first segment ", segment);
962 err := true;
963 }
964 if (not err) {
965 seg_received[0] := seg_received[0] + 1;
966 }
967 }
968 }
969 case (tr_PagingType1) {
970 setverdict(fail, "Received unexpected PAGING TYPE 1: ", l3);
971 }
972 }
973 repeat;
974 }
975 [] L1CTL.receive { repeat; }
976 [] T.timeout {
977 setverdict(pass);
978 }
979 }
980 log("Quantity of received ETWS PN segments: ", seg_received);
981 var integer i;
982 for (i := 0; i < 4; i := i+1) {
983 if (seg_received[i] < 15) {
984 setverdict(fail, "Segment ", i, " not received often enough");
985 }
986 }
987}
988
989/* Ensure only Paging Type 1 without ETWS Primary Notification are sent after disabling them */
990testcase TC_etws_p1ro_end() runs on test_CT {
991 var template RslChannelNr t_chan_nr := ts_RslChanNr_PCH_AGCH(0);
992 /* we expect four blocks of 14 bytes, let's fill them with content easily
993 * distinguishable */
994 /* decoding the actual entire P1 rest octets by manually generated code is
995 * too much effort; instead simply do a binary compare to this constant */
996 const bitstring c_P1RO_hdr := '00101011101'B;
997 var L1ctlDlMessage dl;
998 timer T := 10.0;
999
1000 f_init();
1001 f_init_l1ctl();
1002 f_l1_tune(L1CTL, ccch_mode := CCCH_MODE_COMBINED_CBCH);
1003
Vadim Yanitskiy493abe72020-05-25 22:03:48 +07001004 RSL_CCHAN.send(ts_ASP_RSL_UD(ts_RSL_OSMO_ETWS_CMD(c_etws)));
Harald Welte908ce542019-09-04 23:05:40 +02001005 /* wait for a bit until old non-ETWS Paging messages are gone */
1006 f_sleep(3.0);
1007 /* disable the ETWS PN again */
Vadim Yanitskiy493abe72020-05-25 22:03:48 +07001008 RSL_CCHAN.send(ts_ASP_RSL_UD(ts_RSL_OSMO_ETWS_CMD(''O)));
Harald Welte908ce542019-09-04 23:05:40 +02001009 f_sleep(2.0);
1010 T.start;
1011 L1CTL.clear;
1012 alt {
1013 [] L1CTL.receive(tr_L1CTL_DATA_IND(t_chan_nr)) -> value dl {
1014 var GsmRrMessage l3 := dec_GsmRrMessage(dl.payload.data_ind.payload);
1015 select (l3) {
Vadim Yanitskiya9a198d2020-03-28 05:11:26 +07001016 case (tr_PAG_REQ1(tr_MI_LV(t_MI_NoIdentity()))) { repeat; }
Harald Welte908ce542019-09-04 23:05:40 +02001017 case (tr_PagingType1) {
1018 setverdict(fail, "Received non-empty PT1 after disabling ETWS PN: ", l3);
1019 }
1020 }
1021 repeat;
1022 }
1023 [] L1CTL.receive { repeat; }
1024 [] T.timeout {
1025 setverdict(pass);
1026 }
1027 }
1028}
1029
Harald Welte11b734c2019-09-05 14:17:54 +02001030/* Ensure ETWS Primary Notification is passed from RSL to PCU interface */
1031testcase TC_etws_pcu() runs on test_CT {
1032 timer T := 10.0;
1033
1034 f_init();
1035 f_init_l1ctl();
1036 f_l1_tune(L1CTL, ccch_mode := CCCH_MODE_COMBINED_CBCH);
1037
Vadim Yanitskiy493abe72020-05-25 22:03:48 +07001038 RSL_CCHAN.send(ts_ASP_RSL_UD(ts_RSL_OSMO_ETWS_CMD(c_etws)));
Harald Welte11b734c2019-09-05 14:17:54 +02001039
1040 T.start;
1041 alt {
1042 [] PCU.receive(t_SD_PCUIF(g_pcu_conn_id, tr_PCUIF_APP_INFO_REQ(0, 0, c_etws))) {
1043 setverdict(pass);
1044 }
1045 [] PCU.receive(t_SD_PCUIF(g_pcu_conn_id, tr_PCUIF_APP_INFO_REQ(?, ?, ?))) {
1046 setverdict(fail, "PCU socket received invalid APP INFO");
1047 }
1048 [] PCU.receive { repeat; }
1049 [] T.timeout {
1050 setverdict(fail, "PCU socket timeout receiving APP INFO (ETWS)");
1051 }
1052 }
1053}
1054
1055
Harald Welte908ce542019-09-04 23:05:40 +02001056
Harald Welte505cf9b2018-09-15 17:47:23 +03001057/* SMSCB TODO:
1058 * multiple SMS BC CMD at the same time: Ensure all of them are sent exactly once
1059 * extended CBCH vs. normal CBCH
1060 *
1061 */
1062
1063control {
Harald Welte4a129f82019-05-21 16:35:22 +02001064 execute( TC_cbch_load_idle_no_cbch() );
1065
Harald Welte505cf9b2018-09-15 17:47:23 +03001066 execute( TC_sms_cb_cmd_sdcch4_1block() );
1067 execute( TC_sms_cb_cmd_sdcch4_2block() );
1068 execute( TC_sms_cb_cmd_sdcch4_3block() );
1069 execute( TC_sms_cb_cmd_sdcch4_4block() );
Harald Weltee0026c32019-05-20 00:27:30 +02001070 execute( TC_sms_cb_cmd_sdcch4_multi() );
Harald Welte505cf9b2018-09-15 17:47:23 +03001071 execute( TC_sms_cb_cmd_sdcch4_schedule() );
Harald Welte88e5dff2019-05-20 15:14:46 +02001072 execute( TC_sms_cb_cmd_sdcch4_default_only() );
Harald Welted522ca02019-05-20 20:06:12 +02001073 execute( TC_sms_cb_cmd_sdcch4_default_and_normal() );
Harald Weltedf4d0f02019-05-20 16:04:11 +02001074 execute( TC_sms_cb_cmd_sdcch4_default_then_null() );
Harald Welte4a129f82019-05-21 16:35:22 +02001075 execute( TC_cbc_sdcch4_load_idle() );
1076 execute( TC_cbc_sdcch4_load_overload() );
1077
Harald Welte505cf9b2018-09-15 17:47:23 +03001078 if (false) { /* FIXME: SDCCH/8 support broken, needs trxcon + L1CTL work */
1079 execute( TC_sms_cb_cmd_sdcch8_1block() );
1080 execute( TC_sms_cb_cmd_sdcch8_2block() );
1081 execute( TC_sms_cb_cmd_sdcch8_3block() );
1082 execute( TC_sms_cb_cmd_sdcch8_4block() );
Harald Weltee0026c32019-05-20 00:27:30 +02001083 execute( TC_sms_cb_cmd_sdcch8_multi() );
Harald Welte505cf9b2018-09-15 17:47:23 +03001084 execute( TC_sms_cb_cmd_sdcch8_schedule() );
Harald Welte88e5dff2019-05-20 15:14:46 +02001085 execute( TC_sms_cb_cmd_sdcch8_default_only() );
Harald Welted522ca02019-05-20 20:06:12 +02001086 execute( TC_sms_cb_cmd_sdcch8_default_and_normal() );
Harald Welte4a129f82019-05-21 16:35:22 +02001087 execute( TC_cbc_sdcch8_load_idle() );
1088 execute( TC_cbc_sdcch8_load_overload() );
Harald Welte505cf9b2018-09-15 17:47:23 +03001089 }
Harald Welte908ce542019-09-04 23:05:40 +02001090
1091 execute( TC_etws_p1ro() );
1092 execute( TC_etws_p1ro_end() );
Harald Welte11b734c2019-09-05 14:17:54 +02001093 execute( TC_etws_pcu() );
Harald Welte505cf9b2018-09-15 17:47:23 +03001094}
1095
1096
1097}