blob: 0712a908df8e6ebac3ea89aeb2d333e39fcc8021 [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 Welte505cf9b2018-09-15 17:47:23 +030025
26import from RSL_Types all;
27
28import from Osmocom_VTY_Functions all;
29
30import from BTS_Tests all;
31
32/***********************************************************************
33 * Cell Broadcast related tests
34 ***********************************************************************/
35
Harald Weltea3ff6702019-05-20 20:03:50 +020036/* Test parameters for one channel (e.g. Basic, Extended) */
37type record CbchTestParsChan {
38 /* list of "normal" (sent-once) SMSCB messages */
39 CbchTestMsgs msgs,
40 /* default message, if any */
41 CbchTestMsg default_msg optional
42}
43
44private template (value) CbchTestParsChan
45t_CbchPC(template (value) CbchTestMsgs msgs, template (omit) CbchTestMsg def := omit) := {
46 msgs := msgs,
47 default_msg := def
48}
49
50/* CBCH test parameters for most of our tests */
Harald Welte505cf9b2018-09-15 17:47:23 +030051type record CbchTestPars {
Harald Weltea3ff6702019-05-20 20:03:50 +020052 /* should we execute on SDCCH4 (true) or SDCCH8 (false) ? */
Harald Welte505cf9b2018-09-15 17:47:23 +030053 boolean use_sdcch4,
Harald Weltea3ff6702019-05-20 20:03:50 +020054 /* Parameters for BASIC CBCH */
55 CbchTestParsChan basic,
56 /* Parameters for EXTENDED CBCH */
57 CbchTestParsChan extended optional
Harald Welte505cf9b2018-09-15 17:47:23 +030058};
59
60type record CbchTestMsg {
61 /* config / input data */
62 RSL_CbCommand rsl_cb_cmd,
63 uint2_t last_block, /* 0..3 */
64 octetstring payload,
65 /* computed / result data */
66 CbchBlocks blocks optional
67};
68type record of CbchTestMsg CbchTestMsgs;
69
70/* a single 22byte block within a CbchTestMsg */
71type record CbchBlock {
72 uint4_t seq_nr, /* as per TS 04.12 */
73 boolean is_last,
74 OCT22 payload,
75 boolean seen_once
76};
77type record of CbchBlock CbchBlocks;
78
79/* compute the expected blocks for given test parameters */
80private function f_cbch_compute_exp_blocks(inout CbchTestPars pars) {
Harald Weltea3ff6702019-05-20 20:03:50 +020081 f_cbch_compute_exp_blocks_chan(pars.basic);
82 if (ispresent(pars.extended)) {
83 f_cbch_compute_exp_blocks_chan(pars.extended);
84 }
85}
86private function f_cbch_compute_exp_blocks_chan(inout CbchTestParsChan pars_chan) {
Harald Welte505cf9b2018-09-15 17:47:23 +030087 var integer i;
Harald Weltea3ff6702019-05-20 20:03:50 +020088 for (i := 0; i < lengthof(pars_chan.msgs); i := i+1) {
89 pars_chan.msgs[i].blocks := f_comp_blocks(pars_chan.msgs[i]);
90 }
91 if (ispresent(pars_chan.default_msg)) {
92 pars_chan.default_msg.blocks := f_comp_blocks(pars_chan.default_msg);
Harald Welte505cf9b2018-09-15 17:47:23 +030093 }
94}
95private function f_comp_blocks(in CbchTestMsg msg) return CbchBlocks {
96 var CbchBlocks blocks := {};
97 var integer i;
98
99 for (i := 0; i <= msg.last_block; i := i+1) {
100 var CbchBlock block := {
101 seq_nr := i,
102 is_last := false,
103 payload := substr(msg.payload, 22*i, 22),
104 seen_once := false
105 };
106 if (msg.rsl_cb_cmd == RSL_CB_CMD_SCHEDULE and i == 0) {
107 block.seq_nr := 8;
108 }
109 if (i == msg.last_block) {
110 block.is_last := true;
111 }
112 blocks := blocks & {block};
113 }
114
115 return blocks;
116};
117
118/* TS 48.058 Section 9.3.41 */
119private function f_cbch_block_nr2rsl(uint2_t nr) return uint2_t {
120 select (nr) {
121 case (0) { return 1; }
122 case (1) { return 2; }
123 case (2) { return 3; }
124 case (3) { return 0; }
125 }
126 setverdict(fail, "Invalid block number");
127 mtc.stop;
128}
129
Harald Welte88e5dff2019-05-20 15:14:46 +0200130private function f_cbch_fn2tb(uint32_t fn) return integer
131{
132 return (fn/51) mod 8; /* TS 05.02 Section 6.5.4 */
133}
134
Harald Welte505cf9b2018-09-15 17:47:23 +0300135/* Verify the CBCH TB scheduling rules of TS 05.02 Section 6.5.4 */
136private function f_cbch_fn_verify(uint32_t fn, CBCH_Block cb)
137{
Harald Welte88e5dff2019-05-20 15:14:46 +0200138 var integer tb := f_cbch_fn2tb(fn);
Harald Welte505cf9b2018-09-15 17:47:23 +0300139 if (cb.block_type.seq_nr == 15 /* null */) {
140 /* always permitted */
141 return;
142 } else if (cb.block_type.seq_nr == 8 /* schedule */) {
143 if (tb != 0) {
144 setverdict(fail, "Schedule block at TB=", tb);
145 }
146 } else if (cb.block_type.seq_nr < 4) {
147 if (cb.block_type.seq_nr != tb and cb.block_type.seq_nr+4 != tb) {
148 setverdict(fail, "Normal block at wrong TB=", tb, ": ", cb);
149 }
150 }
151}
152
Harald Weltedf4d0f02019-05-20 16:04:11 +0200153private function f_rsl_smscb_default_null() runs on test_CT
154{
155 var RSL_IE_CbCommandType cmd_type :=
156 valueof(ts_RSL_IE_CbCmdType(RSL_CB_CMD_DEFAULT, 1, true));
157 RSL_CCHAN.send(ts_RSL_UD(ts_RSL_SMSCB_CMD(cmd_type, ''O)));
158}
159
Harald Weltea3ff6702019-05-20 20:03:50 +0200160template RSL_IE t_RSL_IE_SMSCB_EXT := t_RSL_IE(RSL_IE_SMSCB_CHAN_INDICATOR, {smscb_chan_ind := 1});
161
162private function f_smscb_setup_rsl_chan(inout CbchTestParsChan pars_chan, boolean extd := false)
163runs on test_CT {
Harald Welte88e5dff2019-05-20 15:14:46 +0200164 var integer i;
Harald Weltea3ff6702019-05-20 20:03:50 +0200165 var CbchTestMsg msg;
166 var uint2_t rsl_last_block;
167 var RSL_IE_CbCommandType cmd_type;
168 var RSL_Message rsl;
169
170 /* send SMSCB[s] via RSL */
171 for (i := 0; i < lengthof(pars_chan.msgs); i := i+1) {
172 msg := pars_chan.msgs[i];
173 rsl_last_block := f_cbch_block_nr2rsl(msg.last_block);
174 cmd_type := valueof(ts_RSL_IE_CbCmdType(msg.rsl_cb_cmd, rsl_last_block));
175 rsl := valueof(ts_RSL_SMSCB_CMD(cmd_type, msg.payload));
176 if (extd) {
177 rsl.ies := rsl.ies & { valueof(t_RSL_IE_SMSCB_EXT) };
178 }
179 RSL_CCHAN.send(ts_RSL_UD(rsl));
180 }
181 if (ispresent(pars_chan.default_msg)) {
182 msg := pars_chan.default_msg;
183 rsl_last_block := f_cbch_block_nr2rsl(msg.last_block);
184 cmd_type := valueof(ts_RSL_IE_CbCmdType(msg.rsl_cb_cmd, rsl_last_block, false));
185 rsl := valueof(ts_RSL_SMSCB_CMD(cmd_type, msg.payload));
186 if (extd) {
187 rsl.ies := rsl.ies & { valueof(t_RSL_IE_SMSCB_EXT) };
188 }
189 RSL_CCHAN.send(ts_RSL_UD(rsl));
190 }
191}
Harald Welte505cf9b2018-09-15 17:47:23 +0300192
Harald Welte4a129f82019-05-21 16:35:22 +0200193private function f_vty_cbch_setup(boolean use_sdcch4 := true) runs on test_CT {
Harald Welte505cf9b2018-09-15 17:47:23 +0300194
Harald Welte4a129f82019-05-21 16:35:22 +0200195 if (use_sdcch4 == true) {
Harald Welte505cf9b2018-09-15 17:47:23 +0300196 f_vty_config2(BSCVTY, {"network", "bts 0", "trx 0", "timeslot 0"},
197 "phys_chan_config CCCH+SDCCH4+CBCH");
198 f_vty_config2(BSCVTY, {"network", "bts 0", "trx 0", "timeslot 6"},
199 "phys_chan_config SDCCH8");
200 } else {
201 f_vty_config2(BSCVTY, {"network", "bts 0", "trx 0", "timeslot 0"},
202 "phys_chan_config CCCH+SDCCH4");
203 f_vty_config2(BSCVTY, {"network", "bts 0", "trx 0", "timeslot 6"},
204 "phys_chan_config SDCCH8+CBCH");
205 }
206 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
207 f_sleep(2.0);
Harald Welte4a129f82019-05-21 16:35:22 +0200208}
209private function f_smscb_setup(inout CbchTestPars pars) runs on test_CT {
210
211 f_cbch_compute_exp_blocks(pars);
212
213 f_init_vty_bsc();
214 /* ensure that a CBCH is present in channel combination */
215 f_vty_cbch_setup(pars.use_sdcch4);
Harald Welte505cf9b2018-09-15 17:47:23 +0300216 f_init(testcasename());
217
218 f_init_l1ctl();
219 f_l1_tune(L1CTL);
220 /* FIXME: switch to dedicated mode for SDCCH/8 */
221
222 /* send SMSCB[s] via RSL */
Harald Weltea3ff6702019-05-20 20:03:50 +0200223 f_smscb_setup_rsl_chan(pars.basic, false);
224 if (ispresent(pars.extended)) {
225 f_smscb_setup_rsl_chan(pars.extended, true);
Harald Welte505cf9b2018-09-15 17:47:23 +0300226 }
Harald Welte88e5dff2019-05-20 15:14:46 +0200227}
228
229private function f_smscb_cleanup() runs on test_CT {
230 /* reset timeslot 0 channel combination to default */
231 f_vty_config2(BSCVTY, {"network", "bts 0", "trx 0", "timeslot 0"},
232 "phys_chan_config CCCH+SDCCH4");
233 f_vty_config2(BSCVTY, {"network", "bts 0", "trx 0", "timeslot 6"},
234 "phys_chan_config SDCCH8");
235}
236
Harald Weltea3ff6702019-05-20 20:03:50 +0200237/* construct a receive/match template for given block_nr in given msg */
238private function f_get_block_template(CbchTestMsg msg, integer block_nr) return template CBCH_Block {
239 var template CBCH_Block tr;
240 if (block_nr < lengthof(msg.blocks)) {
241 var CbchBlock b := msg.blocks[block_nr];
242 tr := tr_CBCH_Block(b.seq_nr, b.is_last, b.payload);
243 } else {
244 tr := tr_CBCH_Block(15, ?, ?);
245 }
246 return tr;
247}
248
249/* the heart of the CBCH test case matching engine for one channel (basic, extended) */
250private function f_cbch_match(inout CbchTestParsChan pars_chan, CBCH_Block cb, integer tb)
251{
252 var integer block_nr := tb mod 4;
253 var integer i;
254
255 if (not match(cb, tr_CBCH_Block)) {
256 setverdict(fail, "Illegal CBCH Block received: ", cb);
257 } else {
258 var boolean matched := false;
259 /* check if it's any of our expected blocks */
260 for (i := 0; i < lengthof(pars_chan.msgs); i := i+1) {
261 if (block_nr < lengthof(pars_chan.msgs[i].blocks)) {
262 if (match(cb, f_get_block_template(pars_chan.msgs[i], block_nr))) {
263 log("Found block_nr ", block_nr, " of msg ", i);
264 if (not pars_chan.msgs[i].blocks[block_nr].seen_once) {
265 pars_chan.msgs[i].blocks[block_nr].seen_once := true;
266 setverdict(pass);
267 } else {
268 setverdict(fail, "Received SMSCB twice! ", cb);
269 }
270 matched := true;
271 break;
272 }
273 }
274 }
275 if (not matched) {
276 var template CBCH_Block tr;
277 if (ispresent(pars_chan.default_msg)) {
278 /* it must be a block of the default message */
279 tr := f_get_block_template(pars_chan.default_msg, block_nr);
280 } else {
281 /* it must be a NULL block */
282 tr := tr_CBCH_Block(15, ?, ?);
283 }
284 if (not match(cb, tr)) {
285 setverdict(fail, "Received unexpected CBCH block: ", cb);
286 } else {
287 log("Found block_nr ", block_nr, " of DEFAULT/NULL");
288 if (ispresent(pars_chan.default_msg) and
289 block_nr < lengthof(pars_chan.default_msg.blocks)) {
290 pars_chan.default_msg.blocks[block_nr].seen_once := true;
291 }
292 }
293 }
294 }
295}
296
297/* Report/Evaluate the per-channel CBCH test results */
298private function f_cbch_report(CbchTestParsChan pars_chan, charstring id)
299{
300 var integer i, j;
301
302 /* verify that each block of each message has been seen once */
303 for (i := 0; i < lengthof(pars_chan.msgs); i := i+1) {
304 for (j := 0; j < lengthof(pars_chan.msgs[i].blocks); j := j+1) {
305 var CbchBlock b := pars_chan.msgs[i].blocks[j];
306 if (not b.seen_once) {
307 setverdict(fail, "Timeout waiting for ", id, " CBCH block ",
308 j, " of msg ", i);
309 }
310 }
311 }
312 if (ispresent(pars_chan.default_msg)) {
313 /* verify that each block of default message has been seen at least once */
314 for (j := 0; j < lengthof(pars_chan.default_msg.blocks); j := j+1) {
315 var CbchBlock b := pars_chan.default_msg.blocks[j];
316 if (not b.seen_once) {
317 setverdict(fail, "Timeout waiting for at leaset one instance of ",
318 "CBCH block ", j, " of DEFAULT msg");
319 }
320 }
321 }
322}
323
Harald Welte88e5dff2019-05-20 15:14:46 +0200324/* shared function doing the heavy lifting for most CBCH tests */
325private function f_TC_smscb(CbchTestPars pars) runs on test_CT {
326 var L1ctlDlMessage dl;
Harald Weltea3ff6702019-05-20 20:03:50 +0200327 var integer msg_count;
328 timer T;
329
330 msg_count := lengthof(pars.basic.msgs);
331 if (ispresent(pars.basic.default_msg)) {
332 msg_count := msg_count + 1;
333 }
334 if (ispresent(pars.extended)) {
335 msg_count := msg_count + lengthof(pars.extended.msgs);
336 if (ispresent(pars.extended.default_msg)) {
337 msg_count := msg_count + 1;
338 }
339 }
Harald Welte88e5dff2019-05-20 15:14:46 +0200340
341 f_smscb_setup(pars);
342
Harald Weltea3ff6702019-05-20 20:03:50 +0200343 /* dynamically adjust timeout based on number of messages */
344 T.start(5.0 + 3.0 * int2float(msg_count));
Harald Welte505cf9b2018-09-15 17:47:23 +0300345 /* Expect this to show up exactly once on the basic CBCH (four blocks) */
346 alt {
347 /* FIXME: Channel Nr for SDCCH/8 */
348 [] L1CTL.receive(tr_L1CTL_DATA_IND(t_RslChanNr_CBCH(0))) -> value dl {
Harald Weltea3ff6702019-05-20 20:03:50 +0200349 var integer tb := f_cbch_fn2tb(dl.dl_info.frame_nr);
Harald Welte505cf9b2018-09-15 17:47:23 +0300350 var CBCH_Block cb := dec_CBCH_Block(dl.payload.data_ind.payload);
Harald Weltea3ff6702019-05-20 20:03:50 +0200351 log("Tb=", tb, ", CBCH: ", dl, ", block: ", cb);
352
Harald Welte505cf9b2018-09-15 17:47:23 +0300353 /* detect the proper CBCH messages; check frame number */
354 f_cbch_fn_verify(dl.dl_info.frame_nr, cb);
Harald Weltea3ff6702019-05-20 20:03:50 +0200355
356 if (tb < 4) {
357 f_cbch_match(pars.basic, cb, tb);
Harald Welte505cf9b2018-09-15 17:47:23 +0300358 } else {
Harald Weltea3ff6702019-05-20 20:03:50 +0200359 if (not ispresent(pars.extended)) {
360 /* no parameters for ext. BCCH given: ignore */
361 repeat;
Harald Welte505cf9b2018-09-15 17:47:23 +0300362 }
Harald Weltea3ff6702019-05-20 20:03:50 +0200363 f_cbch_match(pars.extended, cb, tb);
Harald Welte505cf9b2018-09-15 17:47:23 +0300364 }
Harald Weltea3ff6702019-05-20 20:03:50 +0200365 repeat;
Harald Welte505cf9b2018-09-15 17:47:23 +0300366 }
367 [] L1CTL.receive { repeat; }
368 [] T.timeout {
Harald Weltea3ff6702019-05-20 20:03:50 +0200369 f_cbch_report(pars.basic, "Basic");
370 if (ispresent(pars.extended)) {
371 f_cbch_report(pars.extended, "Extended");
Harald Welte505cf9b2018-09-15 17:47:23 +0300372 }
373 }
374 }
375
Harald Welte88e5dff2019-05-20 15:14:46 +0200376 f_smscb_cleanup();
377 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, pass);
378}
379
380private function f_TC_smscb_default_only(CbchTestPars pars) runs on test_CT {
381 var L1ctlDlMessage dl;
382 timer T := 5.0;
383
384 f_smscb_setup(pars);
385
386 /* ensure whatever initial NULL messages have all been drained */
387 f_sleep(5.0);
388 L1CTL.clear;
389
390 T.start;
391 alt {
392 [] L1CTL.receive(tr_L1CTL_DATA_IND(t_RslChanNr_CBCH(0))) -> value dl {
393 var integer tb := f_cbch_fn2tb(dl.dl_info.frame_nr);
394 log("CBCH: ", dl);
395 var CBCH_Block cb := dec_CBCH_Block(dl.payload.data_ind.payload);
396 /* detect the proper CBCH messages; check frame number */
397 f_cbch_fn_verify(dl.dl_info.frame_nr, cb);
398 if (tb >= 4) {
399 /* skip extended CBCH for now */
400 repeat;
401 }
402 if (not match(cb, tr_CBCH_Block)) {
403 setverdict(fail, "Illegal CBCH Block received: ", cb);
404 } else {
405 var uint4_t rx_seq_nr := cb.block_type.seq_nr;
406 var template CBCH_Block tr;
Harald Weltea3ff6702019-05-20 20:03:50 +0200407 if (rx_seq_nr < lengthof(pars.basic.msgs[0].blocks)) {
408 var CbchBlock b := pars.basic.msgs[0].blocks[rx_seq_nr];
Harald Welte88e5dff2019-05-20 15:14:46 +0200409 tr := tr_CBCH_Block(b.seq_nr, b.is_last, b.payload);
410 } else {
411 tr := tr_CBCH_Block(15, ?, ?);
412 }
413 if (match(cb, tr)) {
414 setverdict(pass); /* FIXME: check that all blocks are received? */
415 repeat;
416 } else {
417 setverdict(fail, "Unexpected CBCH block ", cb, ", expected ", tr);
418 }
419 }
420 }
421 [] L1CTL.receive { repeat; }
422 [] T.timeout {}
423 }
424
425 f_smscb_cleanup();
426 /* don't shut down; some tests still want to continue */
Harald Welte505cf9b2018-09-15 17:47:23 +0300427}
428
429private const CbchTestMsgs msgs_1m_1b_norm := {
430 { RSL_CB_CMD_NORMAL, 0, '001000320f1141660c344dd3cba09a0c000000000000'O, omit }
431}
432
433private const CbchTestMsgs msgs_1m_2b_norm := {
434 { RSL_CB_CMD_NORMAL, 1, '001000320f1141660c344dd3cba09a0c000000000000'O &
435 '000102030405060708090a0b0c0d0e0f101213141516'O,
436 omit }
437}
438
439private const CbchTestMsgs msgs_1m_3b_norm := {
440 { RSL_CB_CMD_NORMAL, 2, '001000320f1141660c344dd3cba09a0c000000000000'O &
441 '000102030405060708090a0b0c0d0e0f101213141516'O &
442 '101112131415161718191a1b1c1d1e1f202223242526'O,
443 omit }
444}
445
446private const CbchTestMsgs msgs_1m_4b_norm := {
447 { RSL_CB_CMD_NORMAL, 3, '001000320f1141660c344dd3cba09a0c000000000000'O &
448 '000102030405060708090a0b0c0d0e0f101213141516'O &
449 '101112131415161718191a1b1c1d1e1f202223242526'O &
450 '202122232425262728292a2b2c2d2e2f303233343536'O,
451 omit }
452}
453
454private const CbchTestMsgs msgs_1m_4b_sched := {
455 { RSL_CB_CMD_SCHEDULE, 3, '001000320f1141660c344dd3cba09a0c000000000000'O &
456 '000102030405060708090a0b0c0d0e0f101213141516'O &
457 '101112131415161718191a1b1c1d1e1f202223242526'O &
458 '202122232425262728292a2b2c2d2e2f303233343536'O,
459 omit }
460}
461
Harald Weltee0026c32019-05-20 00:27:30 +0200462private const CbchTestMsgs msgs_3m_4b_norm := {
463 { RSL_CB_CMD_NORMAL, 3, '001000320f1141660c344dd3cba09a0c000000000000'O &
464 '000102030405060708090a0b0c0d0e0f101213141516'O &
465 '101112131415161718191a1b1c1d1e1f202223242526'O &
466 '201122232425262728292a2b2c2d2e2f303233343536'O,
467 omit },
468 { RSL_CB_CMD_NORMAL, 3, '002000320f1141660c344dd3cba09a0c000000000000'O &
469 '002102030405060708090a0b0c0d0e0f101213141516'O &
470 '102112131415161718191a1b1c1d1e1f202223242526'O &
471 '202122232425262728292a2b2c2d2e2f303233343536'O,
472 omit },
473 { RSL_CB_CMD_NORMAL, 3, '003000320f1141660c344dd3cba09a0c000000000000'O &
474 '003102030405060708090a0b0c0d0e0f101213141516'O &
475 '103112131415161718191a1b1c1d1e1f202223242526'O &
476 '203122232425262728292a2b2c2d2e2f303233343536'O,
477 omit }
478}
479
Harald Welte88e5dff2019-05-20 15:14:46 +0200480private const CbchTestMsgs msgs_1m_3b_default := {
481 { RSL_CB_CMD_DEFAULT, 2, '001000320f1141660c344dd3cba09a0c000000000000'O &
482 '000102030405060708090a0b0c0d0e0f101213141516'O &
483 '101112131415161718191a1b1c1d1e1f202223242526'O,
484 omit }
485}
Harald Weltea3ff6702019-05-20 20:03:50 +0200486private const CbchTestMsg msg_default := {
487 RSL_CB_CMD_DEFAULT, 0, '010203040506070708090a0b0c0d0e0f101112131415'O,
488 omit
489}
Harald Welte88e5dff2019-05-20 15:14:46 +0200490
Harald Welte505cf9b2018-09-15 17:47:23 +0300491/* transmit single-block SMSCB COMMAND */
492testcase TC_sms_cb_cmd_sdcch4_1block() runs on test_CT {
493 var CbchTestPars pars := {
494 use_sdcch4 := true,
Harald Weltea3ff6702019-05-20 20:03:50 +0200495 basic := valueof(t_CbchPC(msgs_1m_1b_norm)),
496 extended := omit
Harald Welte505cf9b2018-09-15 17:47:23 +0300497 };
498 f_TC_smscb(pars);
499}
500testcase TC_sms_cb_cmd_sdcch8_1block() runs on test_CT {
501 var CbchTestPars pars := {
502 use_sdcch4 := false,
Harald Weltea3ff6702019-05-20 20:03:50 +0200503 basic := valueof(t_CbchPC(msgs_1m_1b_norm)),
504 extended := omit
Harald Welte505cf9b2018-09-15 17:47:23 +0300505 };
506 f_TC_smscb(pars);
507}
508
509/* transmit dual-block SMSCB COMMAND */
510testcase TC_sms_cb_cmd_sdcch4_2block() runs on test_CT {
511 var CbchTestPars pars := {
512 use_sdcch4 := true,
Harald Weltea3ff6702019-05-20 20:03:50 +0200513 basic := valueof(t_CbchPC(msgs_1m_2b_norm)),
514 extended := omit
Harald Welte505cf9b2018-09-15 17:47:23 +0300515 };
516 f_TC_smscb(pars);
517}
518testcase TC_sms_cb_cmd_sdcch8_2block() runs on test_CT {
519 var CbchTestPars pars := {
520 use_sdcch4 := false,
Harald Weltea3ff6702019-05-20 20:03:50 +0200521 basic := valueof(t_CbchPC(msgs_1m_2b_norm)),
522 extended := omit
Harald Welte505cf9b2018-09-15 17:47:23 +0300523 };
524 f_TC_smscb(pars);
525}
526
527/* transmit triple-block SMSCB COMMAND */
528testcase TC_sms_cb_cmd_sdcch4_3block() runs on test_CT {
529 var CbchTestPars pars := {
530 use_sdcch4 := true,
Harald Weltea3ff6702019-05-20 20:03:50 +0200531 basic := valueof(t_CbchPC(msgs_1m_3b_norm)),
532 extended := omit
Harald Welte505cf9b2018-09-15 17:47:23 +0300533 };
534 f_TC_smscb(pars);
535}
536testcase TC_sms_cb_cmd_sdcch8_3block() runs on test_CT {
537 var CbchTestPars pars := {
538 use_sdcch4 := false,
Harald Weltea3ff6702019-05-20 20:03:50 +0200539 basic := valueof(t_CbchPC(msgs_1m_3b_norm)),
540 extended := omit
Harald Welte505cf9b2018-09-15 17:47:23 +0300541 };
542 f_TC_smscb(pars);
543}
544
545/* transmit quad-block SMSCB COMMAND */
546testcase TC_sms_cb_cmd_sdcch4_4block() runs on test_CT {
547 var CbchTestPars pars := {
548 use_sdcch4 := true,
Harald Weltea3ff6702019-05-20 20:03:50 +0200549 basic := valueof(t_CbchPC(msgs_1m_4b_norm)),
550 extended := omit
Harald Welte505cf9b2018-09-15 17:47:23 +0300551 };
552 f_TC_smscb(pars);
553}
554testcase TC_sms_cb_cmd_sdcch8_4block() runs on test_CT {
555 var CbchTestPars pars := {
556 use_sdcch4 := false,
Harald Weltea3ff6702019-05-20 20:03:50 +0200557 basic := valueof(t_CbchPC(msgs_1m_4b_norm)),
558 extended := omit
Harald Welte505cf9b2018-09-15 17:47:23 +0300559 };
560 f_TC_smscb(pars);
561}
562
Harald Weltee0026c32019-05-20 00:27:30 +0200563/* transmit multiple commands of each 4 blocks */
564testcase TC_sms_cb_cmd_sdcch4_multi() runs on test_CT {
565 var CbchTestPars pars := {
566 use_sdcch4 := true,
Harald Weltea3ff6702019-05-20 20:03:50 +0200567 basic := valueof(t_CbchPC(msgs_3m_4b_norm)),
568 extended := omit
Harald Weltee0026c32019-05-20 00:27:30 +0200569 };
570 f_TC_smscb(pars);
571}
572testcase TC_sms_cb_cmd_sdcch8_multi() runs on test_CT {
573 var CbchTestPars pars := {
574 use_sdcch4 := false,
Harald Weltea3ff6702019-05-20 20:03:50 +0200575 basic := valueof(t_CbchPC(msgs_3m_4b_norm)),
576 extended := omit
Harald Weltee0026c32019-05-20 00:27:30 +0200577 };
578 f_TC_smscb(pars);
579}
580
Harald Welte60bd92b2019-05-20 21:42:21 +0200581/* transmit multiple commands of each 4 blocks on CBCH EXTD */
582testcase TC_sms_cb_cmd_sdcch4_extd_multi() runs on test_CT {
583 var CbchTestPars pars := {
584 use_sdcch4 := true,
585 basic := valueof(t_CbchPC({})),
586 extended := valueof(t_CbchPC(msgs_3m_4b_norm))
587 };
588 f_TC_smscb(pars);
589}
590testcase TC_sms_cb_cmd_sdcch8_extd_multi() runs on test_CT {
591 var CbchTestPars pars := {
592 use_sdcch4 := false,
593 basic := valueof(t_CbchPC({})),
594 extended := valueof(t_CbchPC(msgs_3m_4b_norm))
595 };
596 f_TC_smscb(pars);
597}
598
Harald Welte505cf9b2018-09-15 17:47:23 +0300599/* transmit SMSCB COMMAND with SCHEDULE payload */
600testcase TC_sms_cb_cmd_sdcch4_schedule() runs on test_CT {
601 var CbchTestPars pars := {
602 use_sdcch4 := true,
Harald Weltea3ff6702019-05-20 20:03:50 +0200603 basic := valueof(t_CbchPC(msgs_1m_4b_sched)),
604 extended := omit
Harald Welte505cf9b2018-09-15 17:47:23 +0300605 };
606 f_TC_smscb(pars);
607}
608testcase TC_sms_cb_cmd_sdcch8_schedule() runs on test_CT {
609 var CbchTestPars pars := {
610 use_sdcch4 := false,
Harald Weltea3ff6702019-05-20 20:03:50 +0200611 basic := valueof(t_CbchPC(msgs_1m_4b_sched)),
612 extended := omit
Harald Welte505cf9b2018-09-15 17:47:23 +0300613 };
614 f_TC_smscb(pars);
615}
616
Harald Welte88e5dff2019-05-20 15:14:46 +0200617/* set a DEFAULT message; verify it gets transmitted all the time */
618testcase TC_sms_cb_cmd_sdcch4_default_only() runs on test_CT {
619 var CbchTestPars pars := {
620 use_sdcch4 := true,
Harald Weltea3ff6702019-05-20 20:03:50 +0200621 basic := valueof(t_CbchPC(msgs_1m_3b_default)),
622 extended := omit
Harald Welte88e5dff2019-05-20 15:14:46 +0200623 };
624 f_TC_smscb_default_only(pars);
625 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, pass);
626}
627testcase TC_sms_cb_cmd_sdcch8_default_only() runs on test_CT {
628 var CbchTestPars pars := {
629 use_sdcch4 := true,
Harald Weltea3ff6702019-05-20 20:03:50 +0200630 basic := valueof(t_CbchPC(msgs_1m_3b_default)),
631 extended := omit
Harald Welte88e5dff2019-05-20 15:14:46 +0200632 };
633 f_TC_smscb_default_only(pars);
634 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, pass);
635}
636
Harald Welted522ca02019-05-20 20:06:12 +0200637testcase TC_sms_cb_cmd_sdcch4_default_and_normal() runs on test_CT {
638 var CbchTestPars pars := {
639 use_sdcch4 := true,
640 basic := valueof(t_CbchPC(msgs_1m_3b_norm, msg_default)),
641 extended := omit
642 };
643 f_TC_smscb(pars);
644}
645testcase TC_sms_cb_cmd_sdcch8_default_and_normal() runs on test_CT {
646 var CbchTestPars pars := {
647 use_sdcch4 := true,
648 basic := valueof(t_CbchPC(msgs_1m_3b_norm, msg_default)),
649 extended := omit
650 };
651 f_TC_smscb(pars);
652}
653
Harald Weltedf4d0f02019-05-20 16:04:11 +0200654/* first set a DEFAULT message, then disable it again */
655testcase TC_sms_cb_cmd_sdcch4_default_then_null() runs on test_CT {
656 var CbchTestPars pars := {
657 use_sdcch4 := true,
Harald Weltea3ff6702019-05-20 20:03:50 +0200658 basic := valueof(t_CbchPC(msgs_1m_3b_default)),
659 extended := omit
Harald Weltedf4d0f02019-05-20 16:04:11 +0200660 };
661 var L1ctlDlMessage dl;
662 timer T := 5.0;
663
664 f_TC_smscb_default_only(pars);
665
666 /* disable DEFAULT message; switch back to NULL */
667 f_rsl_smscb_default_null();
668
669 /* ensure whatever initial non-NULL messages have all been drained */
670 f_sleep(5.0);
671 L1CTL.clear;
672
673 T.start;
674 alt {
675 [] L1CTL.receive(tr_L1CTL_DATA_IND(t_RslChanNr_CBCH(0))) -> value dl {
676 log("CBCH: ", dl);
677 var CBCH_Block cb := dec_CBCH_Block(dl.payload.data_ind.payload);
678 /* detect the proper CBCH messages; check frame number */
679 f_cbch_fn_verify(dl.dl_info.frame_nr, cb);
680 if (not match(cb, tr_CBCH_Block)) {
681 setverdict(fail, "Illegal CBCH Block received: ", cb);
682 } else {
683 if (not match(cb, tr_CBCH_Block(15, ?, ?))) {
684 setverdict(fail, "Unexpected non-NULL CBCH block received");
685 }
686 repeat;
687 }
688 }
689 [] L1CTL.receive { repeat; }
690 [] T.timeout {
691 setverdict(pass);
692 }
693 }
694
695 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, pass);
696}
697
Harald Welte4a129f82019-05-21 16:35:22 +0200698/* Verify there are no CBCH load indications if no CBCH is present */
699testcase TC_cbch_load_idle_no_cbch() runs on test_CT {
700 var ASP_RSL_Unitdata rx_ud;
701 timer T := 10.0;
702
703 f_init(testcasename());
704 f_init_vty_bsc();
705
706 T.start;
707 alt {
708 [] RSL_CCHAN.receive(tr_RSL_UD(tr_RSL_CBCH_LOAD_IND_BASIC)) -> value rx_ud {
709 setverdict(fail, "Received unexpected CBCH LOAD IND: ", rx_ud);
710 }
711 [] RSL_CCHAN.receive(tr_RSL_UD(tr_RSL_CBCH_LOAD_IND_EXTD)) -> value rx_ud {
712 setverdict(fail, "Received unexpected CBCH LOAD IND: ", rx_ud);
713 }
714 [] RSL_CCHAN.receive { repeat; }
715 [] T.timeout {
716 setverdict(pass);
717 }
718 }
719 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
720}
721
722/* Verify the CBCH load indications of an idle cell (without CBCH load) */
723function f_TC_cbc_load_idle() runs on test_CT {
724 template integer tr_slot_count := (2 .. 15);
725 const integer min_load_ind := 4;
726 var integer basic_count := 0;
727 var integer extd_count := 0;
728 var ASP_RSL_Unitdata rx_ud;
729 timer T := 10.0;
730
731 f_init(testcasename());
732
733 RSL_CCHAN.clear;
734 T.start;
735 alt {
736 [] RSL_CCHAN.receive(tr_RSL_UD(tr_RSL_CBCH_LOAD_IND_BASIC(false, tr_slot_count))) {
737 basic_count := basic_count + 1;
738 repeat;
739 }
740 [] RSL_CCHAN.receive(tr_RSL_UD(tr_RSL_CBCH_LOAD_IND_EXTD(false, tr_slot_count))) -> value rx_ud {
741 extd_count := extd_count + 1;
742 repeat;
743 }
744 [] RSL_CCHAN.receive(tr_RSL_UD(tr_RSL_CBCH_LOAD_IND_BASIC)) -> value rx_ud {
745 setverdict(fail, "Received unexpected CBCH LOAD IND: ", rx_ud);
746 }
747 [] RSL_CCHAN.receive(tr_RSL_UD(tr_RSL_CBCH_LOAD_IND_EXTD)) -> value rx_ud {
748 setverdict(fail, "Received unexpected CBCH LOAD IND: ", rx_ud);
749 }
750 [] RSL_CCHAN.receive { repeat; }
751 [] T.timeout {
752 if ((basic_count >= min_load_ind) and (extd_count >= min_load_ind)) {
753 setverdict(pass);
754 } else {
755 setverdict(fail, "Insufficient number of CBCH LOAD IND: ",
756 "BASIC=", basic_count, " EXTD=", extd_count);
757 }
758 }
759 }
760 f_smscb_cleanup();
761 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
762}
763testcase TC_cbc_sdcch4_load_idle() runs on test_CT {
764 f_init_vty_bsc();
765 f_vty_cbch_setup(use_sdcch4 := true);
766 f_TC_cbc_load_idle();
767}
768testcase TC_cbc_sdcch8_load_idle() runs on test_CT {
769 f_init_vty_bsc();
770 f_vty_cbch_setup(use_sdcch4 := false);
771 f_TC_cbc_load_idle();
772}
773
774/* Verify CBCH overload indications are sent when sending too many SMS CB CMD */
775function f_TC_cbc_load_overload(CbchTestPars pars) runs on test_CT {
776 template integer tr_slot_count_basic := (11 .. 13);
777 template integer tr_slot_count_extd := (2 .. 15);
778 const integer min_load_ind := 4;
779 var integer basic_count := 0;
780 var integer extd_count := 0;
781 var ASP_RSL_Unitdata rx_ud;
782 timer T_total := 10.0;
783 timer T_retransmit := 0.2;
784 timer T_initial_guard := 2.0;
785 var integer i;
786
787 f_init(testcasename());
788
789 /* send tons of SMSCB Command */
790 for (i := 0; i < 30; i := i+1) {
791 f_smscb_setup_rsl_chan(pars.basic);
792 }
793
794 /* keep sending SMSCB Commands for another two seconds */
795 T_initial_guard.start;
796 T_retransmit.start;
797 alt {
798 [] T_retransmit.timeout {
799 f_smscb_setup_rsl_chan(pars.basic);
800 T_retransmit.start;
801 repeat;
802 }
803 [] T_initial_guard.timeout { }
804 }
805 /* clear any pending messages (where load may not have peaked yet) */
806 RSL_CCHAN.clear;
807
808 /* keep sending SMSCB Commands while verifying LOAD INDICATIONS */
809 T_total.start;
810 T_retransmit.start;
811 alt {
812 [] RSL_CCHAN.receive(tr_RSL_UD(tr_RSL_CBCH_LOAD_IND_BASIC(true, tr_slot_count_basic))) {
813 basic_count := basic_count + 1;
814 repeat;
815 }
816 [] RSL_CCHAN.receive(tr_RSL_UD(tr_RSL_CBCH_LOAD_IND_EXTD(false, tr_slot_count_extd))) {
817 extd_count := extd_count + 1;
818 repeat;
819 }
820 [] RSL_CCHAN.receive(tr_RSL_UD(tr_RSL_CBCH_LOAD_IND_BASIC)) -> value rx_ud {
821 setverdict(fail, "Received unexpected CBCH LOAD IND: ", rx_ud);
822 }
823 [] RSL_CCHAN.receive(tr_RSL_UD(tr_RSL_CBCH_LOAD_IND_EXTD)) -> value rx_ud {
824 setverdict(fail, "Received unexpected CBCH LOAD IND: ", rx_ud);
825 }
826 [] RSL_CCHAN.receive { repeat; }
827 [] T_retransmit.timeout {
828 f_smscb_setup_rsl_chan(pars.basic);
829 T_retransmit.start;
830 repeat;
831 }
832 [] T_total.timeout {
833 if ((basic_count >= min_load_ind) and (extd_count >= min_load_ind)) {
834 setverdict(pass);
835 } else {
836 setverdict(fail, "Insufficient number of CBCH LOAD IND: ",
837 "BASIC=", basic_count, " EXTD=", extd_count);
838 }
839 }
840 }
841 f_smscb_cleanup();
842 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
843}
844testcase TC_cbc_sdcch4_load_overload() runs on test_CT {
845 var CbchTestPars pars := {
846 use_sdcch4 := true,
847 basic := valueof(t_CbchPC(msgs_1m_3b_norm)),
848 extended := omit
849 };
850
851 f_init_vty_bsc();
852 f_vty_cbch_setup(use_sdcch4 := true);
853 f_TC_cbc_load_overload(pars);
854}
855testcase TC_cbc_sdcch8_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}
Harald Weltedf4d0f02019-05-20 16:04:11 +0200866
Harald Welte88e5dff2019-05-20 15:14:46 +0200867
Harald Welte505cf9b2018-09-15 17:47:23 +0300868/* SMSCB TODO:
869 * multiple SMS BC CMD at the same time: Ensure all of them are sent exactly once
870 * extended CBCH vs. normal CBCH
871 *
872 */
873
874control {
Harald Welte4a129f82019-05-21 16:35:22 +0200875 execute( TC_cbch_load_idle_no_cbch() );
876
Harald Welte505cf9b2018-09-15 17:47:23 +0300877 execute( TC_sms_cb_cmd_sdcch4_1block() );
878 execute( TC_sms_cb_cmd_sdcch4_2block() );
879 execute( TC_sms_cb_cmd_sdcch4_3block() );
880 execute( TC_sms_cb_cmd_sdcch4_4block() );
Harald Weltee0026c32019-05-20 00:27:30 +0200881 execute( TC_sms_cb_cmd_sdcch4_multi() );
Harald Welte505cf9b2018-09-15 17:47:23 +0300882 execute( TC_sms_cb_cmd_sdcch4_schedule() );
Harald Welte88e5dff2019-05-20 15:14:46 +0200883 execute( TC_sms_cb_cmd_sdcch4_default_only() );
Harald Welted522ca02019-05-20 20:06:12 +0200884 execute( TC_sms_cb_cmd_sdcch4_default_and_normal() );
Harald Weltedf4d0f02019-05-20 16:04:11 +0200885 execute( TC_sms_cb_cmd_sdcch4_default_then_null() );
Harald Welte4a129f82019-05-21 16:35:22 +0200886 execute( TC_cbc_sdcch4_load_idle() );
887 execute( TC_cbc_sdcch4_load_overload() );
888
Harald Welte505cf9b2018-09-15 17:47:23 +0300889 if (false) { /* FIXME: SDCCH/8 support broken, needs trxcon + L1CTL work */
890 execute( TC_sms_cb_cmd_sdcch8_1block() );
891 execute( TC_sms_cb_cmd_sdcch8_2block() );
892 execute( TC_sms_cb_cmd_sdcch8_3block() );
893 execute( TC_sms_cb_cmd_sdcch8_4block() );
Harald Weltee0026c32019-05-20 00:27:30 +0200894 execute( TC_sms_cb_cmd_sdcch8_multi() );
Harald Welte505cf9b2018-09-15 17:47:23 +0300895 execute( TC_sms_cb_cmd_sdcch8_schedule() );
Harald Welte88e5dff2019-05-20 15:14:46 +0200896 execute( TC_sms_cb_cmd_sdcch8_default_only() );
Harald Welted522ca02019-05-20 20:06:12 +0200897 execute( TC_sms_cb_cmd_sdcch8_default_and_normal() );
Harald Welte4a129f82019-05-21 16:35:22 +0200898 execute( TC_cbc_sdcch8_load_idle() );
899 execute( TC_cbc_sdcch8_load_overload() );
Harald Welte505cf9b2018-09-15 17:47:23 +0300900 }
901}
902
903
904}