blob: 4d357ba5a02c359d11455ae04da6cb6cab3b29b3 [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();
Harald Welte990a3612019-05-27 14:02:13 +0200219 f_l1_tune(L1CTL, ccch_mode := CCCH_MODE_COMBINED_CBCH);
Harald Welte505cf9b2018-09-15 17:47:23 +0300220 /* 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 Welte6b86b342019-05-27 17:14:36 +0200324private function t_cbch_chan_nr(CbchTestPars pars, template uint8_t tn) return template RslChannelNr {
325 if (pars.use_sdcch4) {
326 return t_RslChanNr_CBCH4(tn);
327 } else {
328 return t_RslChanNr_CBCH8(tn);
329 }
330}
331
Harald Welte88e5dff2019-05-20 15:14:46 +0200332/* shared function doing the heavy lifting for most CBCH tests */
333private function f_TC_smscb(CbchTestPars pars) runs on test_CT {
Harald Welte6b86b342019-05-27 17:14:36 +0200334 var template RslChannelNr t_chan_nr := t_cbch_chan_nr(pars, 0); /* FIXME: TS number */
Harald Welte88e5dff2019-05-20 15:14:46 +0200335 var L1ctlDlMessage dl;
Harald Weltea3ff6702019-05-20 20:03:50 +0200336 var integer msg_count;
337 timer T;
338
339 msg_count := lengthof(pars.basic.msgs);
340 if (ispresent(pars.basic.default_msg)) {
341 msg_count := msg_count + 1;
342 }
343 if (ispresent(pars.extended)) {
344 msg_count := msg_count + lengthof(pars.extended.msgs);
345 if (ispresent(pars.extended.default_msg)) {
346 msg_count := msg_count + 1;
347 }
348 }
Harald Welte88e5dff2019-05-20 15:14:46 +0200349
350 f_smscb_setup(pars);
351
Harald Weltea3ff6702019-05-20 20:03:50 +0200352 /* dynamically adjust timeout based on number of messages */
353 T.start(5.0 + 3.0 * int2float(msg_count));
Harald Welte505cf9b2018-09-15 17:47:23 +0300354 /* Expect this to show up exactly once on the basic CBCH (four blocks) */
355 alt {
Harald Welte6b86b342019-05-27 17:14:36 +0200356 [] L1CTL.receive(tr_L1CTL_DATA_IND(t_chan_nr)) -> value dl {
Harald Weltea3ff6702019-05-20 20:03:50 +0200357 var integer tb := f_cbch_fn2tb(dl.dl_info.frame_nr);
Harald Welte505cf9b2018-09-15 17:47:23 +0300358 var CBCH_Block cb := dec_CBCH_Block(dl.payload.data_ind.payload);
Harald Weltea3ff6702019-05-20 20:03:50 +0200359 log("Tb=", tb, ", CBCH: ", dl, ", block: ", cb);
360
Harald Welte505cf9b2018-09-15 17:47:23 +0300361 /* detect the proper CBCH messages; check frame number */
362 f_cbch_fn_verify(dl.dl_info.frame_nr, cb);
Harald Weltea3ff6702019-05-20 20:03:50 +0200363
364 if (tb < 4) {
365 f_cbch_match(pars.basic, cb, tb);
Harald Welte505cf9b2018-09-15 17:47:23 +0300366 } else {
Harald Weltea3ff6702019-05-20 20:03:50 +0200367 if (not ispresent(pars.extended)) {
368 /* no parameters for ext. BCCH given: ignore */
369 repeat;
Harald Welte505cf9b2018-09-15 17:47:23 +0300370 }
Harald Weltea3ff6702019-05-20 20:03:50 +0200371 f_cbch_match(pars.extended, cb, tb);
Harald Welte505cf9b2018-09-15 17:47:23 +0300372 }
Harald Weltea3ff6702019-05-20 20:03:50 +0200373 repeat;
Harald Welte505cf9b2018-09-15 17:47:23 +0300374 }
375 [] L1CTL.receive { repeat; }
376 [] T.timeout {
Harald Weltea3ff6702019-05-20 20:03:50 +0200377 f_cbch_report(pars.basic, "Basic");
378 if (ispresent(pars.extended)) {
379 f_cbch_report(pars.extended, "Extended");
Harald Welte505cf9b2018-09-15 17:47:23 +0300380 }
381 }
382 }
383
Harald Welte88e5dff2019-05-20 15:14:46 +0200384 f_smscb_cleanup();
385 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, pass);
386}
387
388private function f_TC_smscb_default_only(CbchTestPars pars) runs on test_CT {
Harald Welte6b86b342019-05-27 17:14:36 +0200389 var template RslChannelNr t_chan_nr := t_cbch_chan_nr(pars, 0); /* FIXME: TS number */
Harald Welte88e5dff2019-05-20 15:14:46 +0200390 var L1ctlDlMessage dl;
391 timer T := 5.0;
392
393 f_smscb_setup(pars);
394
395 /* ensure whatever initial NULL messages have all been drained */
396 f_sleep(5.0);
397 L1CTL.clear;
398
399 T.start;
400 alt {
Harald Welte6b86b342019-05-27 17:14:36 +0200401 [] L1CTL.receive(tr_L1CTL_DATA_IND(t_chan_nr)) -> value dl {
Harald Welte88e5dff2019-05-20 15:14:46 +0200402 var integer tb := f_cbch_fn2tb(dl.dl_info.frame_nr);
403 log("CBCH: ", dl);
404 var CBCH_Block cb := dec_CBCH_Block(dl.payload.data_ind.payload);
405 /* detect the proper CBCH messages; check frame number */
406 f_cbch_fn_verify(dl.dl_info.frame_nr, cb);
407 if (tb >= 4) {
408 /* skip extended CBCH for now */
409 repeat;
410 }
411 if (not match(cb, tr_CBCH_Block)) {
412 setverdict(fail, "Illegal CBCH Block received: ", cb);
413 } else {
414 var uint4_t rx_seq_nr := cb.block_type.seq_nr;
415 var template CBCH_Block tr;
Harald Weltea3ff6702019-05-20 20:03:50 +0200416 if (rx_seq_nr < lengthof(pars.basic.msgs[0].blocks)) {
417 var CbchBlock b := pars.basic.msgs[0].blocks[rx_seq_nr];
Harald Welte88e5dff2019-05-20 15:14:46 +0200418 tr := tr_CBCH_Block(b.seq_nr, b.is_last, b.payload);
419 } else {
420 tr := tr_CBCH_Block(15, ?, ?);
421 }
422 if (match(cb, tr)) {
423 setverdict(pass); /* FIXME: check that all blocks are received? */
424 repeat;
425 } else {
426 setverdict(fail, "Unexpected CBCH block ", cb, ", expected ", tr);
427 }
428 }
429 }
430 [] L1CTL.receive { repeat; }
431 [] T.timeout {}
432 }
433
434 f_smscb_cleanup();
435 /* don't shut down; some tests still want to continue */
Harald Welte505cf9b2018-09-15 17:47:23 +0300436}
437
438private const CbchTestMsgs msgs_1m_1b_norm := {
439 { RSL_CB_CMD_NORMAL, 0, '001000320f1141660c344dd3cba09a0c000000000000'O, omit }
440}
441
442private const CbchTestMsgs msgs_1m_2b_norm := {
443 { RSL_CB_CMD_NORMAL, 1, '001000320f1141660c344dd3cba09a0c000000000000'O &
444 '000102030405060708090a0b0c0d0e0f101213141516'O,
445 omit }
446}
447
448private const CbchTestMsgs msgs_1m_3b_norm := {
449 { RSL_CB_CMD_NORMAL, 2, '001000320f1141660c344dd3cba09a0c000000000000'O &
450 '000102030405060708090a0b0c0d0e0f101213141516'O &
451 '101112131415161718191a1b1c1d1e1f202223242526'O,
452 omit }
453}
454
455private const CbchTestMsgs msgs_1m_4b_norm := {
456 { RSL_CB_CMD_NORMAL, 3, '001000320f1141660c344dd3cba09a0c000000000000'O &
457 '000102030405060708090a0b0c0d0e0f101213141516'O &
458 '101112131415161718191a1b1c1d1e1f202223242526'O &
459 '202122232425262728292a2b2c2d2e2f303233343536'O,
460 omit }
461}
462
463private const CbchTestMsgs msgs_1m_4b_sched := {
464 { RSL_CB_CMD_SCHEDULE, 3, '001000320f1141660c344dd3cba09a0c000000000000'O &
465 '000102030405060708090a0b0c0d0e0f101213141516'O &
466 '101112131415161718191a1b1c1d1e1f202223242526'O &
467 '202122232425262728292a2b2c2d2e2f303233343536'O,
468 omit }
469}
470
Harald Weltee0026c32019-05-20 00:27:30 +0200471private const CbchTestMsgs msgs_3m_4b_norm := {
472 { RSL_CB_CMD_NORMAL, 3, '001000320f1141660c344dd3cba09a0c000000000000'O &
473 '000102030405060708090a0b0c0d0e0f101213141516'O &
474 '101112131415161718191a1b1c1d1e1f202223242526'O &
475 '201122232425262728292a2b2c2d2e2f303233343536'O,
476 omit },
477 { RSL_CB_CMD_NORMAL, 3, '002000320f1141660c344dd3cba09a0c000000000000'O &
478 '002102030405060708090a0b0c0d0e0f101213141516'O &
479 '102112131415161718191a1b1c1d1e1f202223242526'O &
480 '202122232425262728292a2b2c2d2e2f303233343536'O,
481 omit },
482 { RSL_CB_CMD_NORMAL, 3, '003000320f1141660c344dd3cba09a0c000000000000'O &
483 '003102030405060708090a0b0c0d0e0f101213141516'O &
484 '103112131415161718191a1b1c1d1e1f202223242526'O &
485 '203122232425262728292a2b2c2d2e2f303233343536'O,
486 omit }
487}
488
Harald Welte88e5dff2019-05-20 15:14:46 +0200489private const CbchTestMsgs msgs_1m_3b_default := {
490 { RSL_CB_CMD_DEFAULT, 2, '001000320f1141660c344dd3cba09a0c000000000000'O &
491 '000102030405060708090a0b0c0d0e0f101213141516'O &
492 '101112131415161718191a1b1c1d1e1f202223242526'O,
493 omit }
494}
Harald Weltea3ff6702019-05-20 20:03:50 +0200495private const CbchTestMsg msg_default := {
496 RSL_CB_CMD_DEFAULT, 0, '010203040506070708090a0b0c0d0e0f101112131415'O,
497 omit
498}
Harald Welte88e5dff2019-05-20 15:14:46 +0200499
Harald Welte505cf9b2018-09-15 17:47:23 +0300500/* transmit single-block SMSCB COMMAND */
501testcase TC_sms_cb_cmd_sdcch4_1block() runs on test_CT {
502 var CbchTestPars pars := {
503 use_sdcch4 := true,
Harald Weltea3ff6702019-05-20 20:03:50 +0200504 basic := valueof(t_CbchPC(msgs_1m_1b_norm)),
505 extended := omit
Harald Welte505cf9b2018-09-15 17:47:23 +0300506 };
507 f_TC_smscb(pars);
508}
509testcase TC_sms_cb_cmd_sdcch8_1block() runs on test_CT {
510 var CbchTestPars pars := {
511 use_sdcch4 := false,
Harald Weltea3ff6702019-05-20 20:03:50 +0200512 basic := valueof(t_CbchPC(msgs_1m_1b_norm)),
513 extended := omit
Harald Welte505cf9b2018-09-15 17:47:23 +0300514 };
515 f_TC_smscb(pars);
516}
517
518/* transmit dual-block SMSCB COMMAND */
519testcase TC_sms_cb_cmd_sdcch4_2block() runs on test_CT {
520 var CbchTestPars pars := {
521 use_sdcch4 := true,
Harald Weltea3ff6702019-05-20 20:03:50 +0200522 basic := valueof(t_CbchPC(msgs_1m_2b_norm)),
523 extended := omit
Harald Welte505cf9b2018-09-15 17:47:23 +0300524 };
525 f_TC_smscb(pars);
526}
527testcase TC_sms_cb_cmd_sdcch8_2block() runs on test_CT {
528 var CbchTestPars pars := {
529 use_sdcch4 := false,
Harald Weltea3ff6702019-05-20 20:03:50 +0200530 basic := valueof(t_CbchPC(msgs_1m_2b_norm)),
531 extended := omit
Harald Welte505cf9b2018-09-15 17:47:23 +0300532 };
533 f_TC_smscb(pars);
534}
535
536/* transmit triple-block SMSCB COMMAND */
537testcase TC_sms_cb_cmd_sdcch4_3block() runs on test_CT {
538 var CbchTestPars pars := {
539 use_sdcch4 := true,
Harald Weltea3ff6702019-05-20 20:03:50 +0200540 basic := valueof(t_CbchPC(msgs_1m_3b_norm)),
541 extended := omit
Harald Welte505cf9b2018-09-15 17:47:23 +0300542 };
543 f_TC_smscb(pars);
544}
545testcase TC_sms_cb_cmd_sdcch8_3block() runs on test_CT {
546 var CbchTestPars pars := {
547 use_sdcch4 := false,
Harald Weltea3ff6702019-05-20 20:03:50 +0200548 basic := valueof(t_CbchPC(msgs_1m_3b_norm)),
549 extended := omit
Harald Welte505cf9b2018-09-15 17:47:23 +0300550 };
551 f_TC_smscb(pars);
552}
553
554/* transmit quad-block SMSCB COMMAND */
555testcase TC_sms_cb_cmd_sdcch4_4block() runs on test_CT {
556 var CbchTestPars pars := {
557 use_sdcch4 := true,
Harald Weltea3ff6702019-05-20 20:03:50 +0200558 basic := valueof(t_CbchPC(msgs_1m_4b_norm)),
559 extended := omit
Harald Welte505cf9b2018-09-15 17:47:23 +0300560 };
561 f_TC_smscb(pars);
562}
563testcase TC_sms_cb_cmd_sdcch8_4block() runs on test_CT {
564 var CbchTestPars pars := {
565 use_sdcch4 := false,
Harald Weltea3ff6702019-05-20 20:03:50 +0200566 basic := valueof(t_CbchPC(msgs_1m_4b_norm)),
567 extended := omit
Harald Welte505cf9b2018-09-15 17:47:23 +0300568 };
569 f_TC_smscb(pars);
570}
571
Harald Weltee0026c32019-05-20 00:27:30 +0200572/* transmit multiple commands of each 4 blocks */
573testcase TC_sms_cb_cmd_sdcch4_multi() runs on test_CT {
574 var CbchTestPars pars := {
575 use_sdcch4 := true,
Harald Weltea3ff6702019-05-20 20:03:50 +0200576 basic := valueof(t_CbchPC(msgs_3m_4b_norm)),
577 extended := omit
Harald Weltee0026c32019-05-20 00:27:30 +0200578 };
579 f_TC_smscb(pars);
580}
581testcase TC_sms_cb_cmd_sdcch8_multi() runs on test_CT {
582 var CbchTestPars pars := {
583 use_sdcch4 := false,
Harald Weltea3ff6702019-05-20 20:03:50 +0200584 basic := valueof(t_CbchPC(msgs_3m_4b_norm)),
585 extended := omit
Harald Weltee0026c32019-05-20 00:27:30 +0200586 };
587 f_TC_smscb(pars);
588}
589
Harald Welte60bd92b2019-05-20 21:42:21 +0200590/* transmit multiple commands of each 4 blocks on CBCH EXTD */
591testcase TC_sms_cb_cmd_sdcch4_extd_multi() runs on test_CT {
592 var CbchTestPars pars := {
593 use_sdcch4 := true,
594 basic := valueof(t_CbchPC({})),
595 extended := valueof(t_CbchPC(msgs_3m_4b_norm))
596 };
597 f_TC_smscb(pars);
598}
599testcase TC_sms_cb_cmd_sdcch8_extd_multi() runs on test_CT {
600 var CbchTestPars pars := {
601 use_sdcch4 := false,
602 basic := valueof(t_CbchPC({})),
603 extended := valueof(t_CbchPC(msgs_3m_4b_norm))
604 };
605 f_TC_smscb(pars);
606}
607
Harald Welte505cf9b2018-09-15 17:47:23 +0300608/* transmit SMSCB COMMAND with SCHEDULE payload */
609testcase TC_sms_cb_cmd_sdcch4_schedule() runs on test_CT {
610 var CbchTestPars pars := {
611 use_sdcch4 := true,
Harald Weltea3ff6702019-05-20 20:03:50 +0200612 basic := valueof(t_CbchPC(msgs_1m_4b_sched)),
613 extended := omit
Harald Welte505cf9b2018-09-15 17:47:23 +0300614 };
615 f_TC_smscb(pars);
616}
617testcase TC_sms_cb_cmd_sdcch8_schedule() runs on test_CT {
618 var CbchTestPars pars := {
619 use_sdcch4 := false,
Harald Weltea3ff6702019-05-20 20:03:50 +0200620 basic := valueof(t_CbchPC(msgs_1m_4b_sched)),
621 extended := omit
Harald Welte505cf9b2018-09-15 17:47:23 +0300622 };
623 f_TC_smscb(pars);
624}
625
Harald Welte88e5dff2019-05-20 15:14:46 +0200626/* set a DEFAULT message; verify it gets transmitted all the time */
627testcase TC_sms_cb_cmd_sdcch4_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}
636testcase TC_sms_cb_cmd_sdcch8_default_only() runs on test_CT {
637 var CbchTestPars pars := {
638 use_sdcch4 := true,
Harald Weltea3ff6702019-05-20 20:03:50 +0200639 basic := valueof(t_CbchPC(msgs_1m_3b_default)),
640 extended := omit
Harald Welte88e5dff2019-05-20 15:14:46 +0200641 };
642 f_TC_smscb_default_only(pars);
643 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, pass);
644}
645
Harald Welted522ca02019-05-20 20:06:12 +0200646testcase TC_sms_cb_cmd_sdcch4_default_and_normal() runs on test_CT {
647 var CbchTestPars pars := {
648 use_sdcch4 := true,
649 basic := valueof(t_CbchPC(msgs_1m_3b_norm, msg_default)),
650 extended := omit
651 };
652 f_TC_smscb(pars);
653}
654testcase TC_sms_cb_cmd_sdcch8_default_and_normal() runs on test_CT {
655 var CbchTestPars pars := {
656 use_sdcch4 := true,
657 basic := valueof(t_CbchPC(msgs_1m_3b_norm, msg_default)),
658 extended := omit
659 };
660 f_TC_smscb(pars);
661}
662
Harald Weltedf4d0f02019-05-20 16:04:11 +0200663/* first set a DEFAULT message, then disable it again */
664testcase TC_sms_cb_cmd_sdcch4_default_then_null() runs on test_CT {
665 var CbchTestPars pars := {
666 use_sdcch4 := true,
Harald Weltea3ff6702019-05-20 20:03:50 +0200667 basic := valueof(t_CbchPC(msgs_1m_3b_default)),
668 extended := omit
Harald Weltedf4d0f02019-05-20 16:04:11 +0200669 };
Harald Welte6b86b342019-05-27 17:14:36 +0200670 var template RslChannelNr t_chan_nr := t_RslChanNr_CBCH4(0);
Harald Weltedf4d0f02019-05-20 16:04:11 +0200671 var L1ctlDlMessage dl;
672 timer T := 5.0;
673
674 f_TC_smscb_default_only(pars);
675
676 /* disable DEFAULT message; switch back to NULL */
677 f_rsl_smscb_default_null();
678
679 /* ensure whatever initial non-NULL messages have all been drained */
680 f_sleep(5.0);
681 L1CTL.clear;
682
683 T.start;
684 alt {
Harald Welte6b86b342019-05-27 17:14:36 +0200685 [] L1CTL.receive(tr_L1CTL_DATA_IND(t_chan_nr)) -> value dl {
Harald Weltedf4d0f02019-05-20 16:04:11 +0200686 log("CBCH: ", dl);
687 var CBCH_Block cb := dec_CBCH_Block(dl.payload.data_ind.payload);
688 /* detect the proper CBCH messages; check frame number */
689 f_cbch_fn_verify(dl.dl_info.frame_nr, cb);
690 if (not match(cb, tr_CBCH_Block)) {
691 setverdict(fail, "Illegal CBCH Block received: ", cb);
692 } else {
693 if (not match(cb, tr_CBCH_Block(15, ?, ?))) {
694 setverdict(fail, "Unexpected non-NULL CBCH block received");
695 }
696 repeat;
697 }
698 }
699 [] L1CTL.receive { repeat; }
700 [] T.timeout {
701 setverdict(pass);
702 }
703 }
704
705 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, pass);
706}
707
Harald Welte4a129f82019-05-21 16:35:22 +0200708/* Verify there are no CBCH load indications if no CBCH is present */
709testcase TC_cbch_load_idle_no_cbch() runs on test_CT {
710 var ASP_RSL_Unitdata rx_ud;
711 timer T := 10.0;
712
713 f_init(testcasename());
714 f_init_vty_bsc();
715
716 T.start;
717 alt {
718 [] RSL_CCHAN.receive(tr_RSL_UD(tr_RSL_CBCH_LOAD_IND_BASIC)) -> value rx_ud {
719 setverdict(fail, "Received unexpected CBCH LOAD IND: ", rx_ud);
720 }
721 [] RSL_CCHAN.receive(tr_RSL_UD(tr_RSL_CBCH_LOAD_IND_EXTD)) -> value rx_ud {
722 setverdict(fail, "Received unexpected CBCH LOAD IND: ", rx_ud);
723 }
724 [] RSL_CCHAN.receive { repeat; }
725 [] T.timeout {
726 setverdict(pass);
727 }
728 }
729 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
730}
731
732/* Verify the CBCH load indications of an idle cell (without CBCH load) */
733function f_TC_cbc_load_idle() runs on test_CT {
734 template integer tr_slot_count := (2 .. 15);
735 const integer min_load_ind := 4;
736 var integer basic_count := 0;
737 var integer extd_count := 0;
738 var ASP_RSL_Unitdata rx_ud;
739 timer T := 10.0;
740
741 f_init(testcasename());
742
743 RSL_CCHAN.clear;
744 T.start;
745 alt {
746 [] RSL_CCHAN.receive(tr_RSL_UD(tr_RSL_CBCH_LOAD_IND_BASIC(false, tr_slot_count))) {
747 basic_count := basic_count + 1;
748 repeat;
749 }
750 [] RSL_CCHAN.receive(tr_RSL_UD(tr_RSL_CBCH_LOAD_IND_EXTD(false, tr_slot_count))) -> value rx_ud {
751 extd_count := extd_count + 1;
752 repeat;
753 }
754 [] RSL_CCHAN.receive(tr_RSL_UD(tr_RSL_CBCH_LOAD_IND_BASIC)) -> value rx_ud {
755 setverdict(fail, "Received unexpected CBCH LOAD IND: ", rx_ud);
756 }
757 [] RSL_CCHAN.receive(tr_RSL_UD(tr_RSL_CBCH_LOAD_IND_EXTD)) -> value rx_ud {
758 setverdict(fail, "Received unexpected CBCH LOAD IND: ", rx_ud);
759 }
760 [] RSL_CCHAN.receive { repeat; }
761 [] T.timeout {
762 if ((basic_count >= min_load_ind) and (extd_count >= min_load_ind)) {
763 setverdict(pass);
764 } else {
765 setverdict(fail, "Insufficient number of CBCH LOAD IND: ",
766 "BASIC=", basic_count, " EXTD=", extd_count);
767 }
768 }
769 }
770 f_smscb_cleanup();
771 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
772}
773testcase TC_cbc_sdcch4_load_idle() runs on test_CT {
774 f_init_vty_bsc();
775 f_vty_cbch_setup(use_sdcch4 := true);
776 f_TC_cbc_load_idle();
777}
778testcase TC_cbc_sdcch8_load_idle() runs on test_CT {
779 f_init_vty_bsc();
780 f_vty_cbch_setup(use_sdcch4 := false);
781 f_TC_cbc_load_idle();
782}
783
784/* Verify CBCH overload indications are sent when sending too many SMS CB CMD */
785function f_TC_cbc_load_overload(CbchTestPars pars) runs on test_CT {
786 template integer tr_slot_count_basic := (11 .. 13);
787 template integer tr_slot_count_extd := (2 .. 15);
788 const integer min_load_ind := 4;
789 var integer basic_count := 0;
790 var integer extd_count := 0;
791 var ASP_RSL_Unitdata rx_ud;
792 timer T_total := 10.0;
793 timer T_retransmit := 0.2;
794 timer T_initial_guard := 2.0;
795 var integer i;
796
797 f_init(testcasename());
798
799 /* send tons of SMSCB Command */
800 for (i := 0; i < 30; i := i+1) {
801 f_smscb_setup_rsl_chan(pars.basic);
802 }
803
804 /* keep sending SMSCB Commands for another two seconds */
805 T_initial_guard.start;
806 T_retransmit.start;
807 alt {
808 [] T_retransmit.timeout {
809 f_smscb_setup_rsl_chan(pars.basic);
810 T_retransmit.start;
811 repeat;
812 }
813 [] T_initial_guard.timeout { }
814 }
815 /* clear any pending messages (where load may not have peaked yet) */
816 RSL_CCHAN.clear;
817
818 /* keep sending SMSCB Commands while verifying LOAD INDICATIONS */
819 T_total.start;
820 T_retransmit.start;
821 alt {
822 [] RSL_CCHAN.receive(tr_RSL_UD(tr_RSL_CBCH_LOAD_IND_BASIC(true, tr_slot_count_basic))) {
823 basic_count := basic_count + 1;
824 repeat;
825 }
826 [] RSL_CCHAN.receive(tr_RSL_UD(tr_RSL_CBCH_LOAD_IND_EXTD(false, tr_slot_count_extd))) {
827 extd_count := extd_count + 1;
828 repeat;
829 }
830 [] RSL_CCHAN.receive(tr_RSL_UD(tr_RSL_CBCH_LOAD_IND_BASIC)) -> value rx_ud {
831 setverdict(fail, "Received unexpected CBCH LOAD IND: ", rx_ud);
832 }
833 [] RSL_CCHAN.receive(tr_RSL_UD(tr_RSL_CBCH_LOAD_IND_EXTD)) -> value rx_ud {
834 setverdict(fail, "Received unexpected CBCH LOAD IND: ", rx_ud);
835 }
836 [] RSL_CCHAN.receive { repeat; }
837 [] T_retransmit.timeout {
838 f_smscb_setup_rsl_chan(pars.basic);
839 T_retransmit.start;
840 repeat;
841 }
842 [] T_total.timeout {
843 if ((basic_count >= min_load_ind) and (extd_count >= min_load_ind)) {
844 setverdict(pass);
845 } else {
846 setverdict(fail, "Insufficient number of CBCH LOAD IND: ",
847 "BASIC=", basic_count, " EXTD=", extd_count);
848 }
849 }
850 }
851 f_smscb_cleanup();
852 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
853}
854testcase TC_cbc_sdcch4_load_overload() runs on test_CT {
855 var CbchTestPars pars := {
856 use_sdcch4 := true,
857 basic := valueof(t_CbchPC(msgs_1m_3b_norm)),
858 extended := omit
859 };
860
861 f_init_vty_bsc();
862 f_vty_cbch_setup(use_sdcch4 := true);
863 f_TC_cbc_load_overload(pars);
864}
865testcase TC_cbc_sdcch8_load_overload() runs on test_CT {
866 var CbchTestPars pars := {
867 use_sdcch4 := true,
868 basic := valueof(t_CbchPC(msgs_1m_3b_norm)),
869 extended := omit
870 };
871
872 f_init_vty_bsc();
873 f_vty_cbch_setup(use_sdcch4 := true);
874 f_TC_cbc_load_overload(pars);
875}
Harald Weltedf4d0f02019-05-20 16:04:11 +0200876
Harald Welte88e5dff2019-05-20 15:14:46 +0200877
Harald Welte505cf9b2018-09-15 17:47:23 +0300878/* SMSCB TODO:
879 * multiple SMS BC CMD at the same time: Ensure all of them are sent exactly once
880 * extended CBCH vs. normal CBCH
881 *
882 */
883
884control {
Harald Welte4a129f82019-05-21 16:35:22 +0200885 execute( TC_cbch_load_idle_no_cbch() );
886
Harald Welte505cf9b2018-09-15 17:47:23 +0300887 execute( TC_sms_cb_cmd_sdcch4_1block() );
888 execute( TC_sms_cb_cmd_sdcch4_2block() );
889 execute( TC_sms_cb_cmd_sdcch4_3block() );
890 execute( TC_sms_cb_cmd_sdcch4_4block() );
Harald Weltee0026c32019-05-20 00:27:30 +0200891 execute( TC_sms_cb_cmd_sdcch4_multi() );
Harald Welte505cf9b2018-09-15 17:47:23 +0300892 execute( TC_sms_cb_cmd_sdcch4_schedule() );
Harald Welte88e5dff2019-05-20 15:14:46 +0200893 execute( TC_sms_cb_cmd_sdcch4_default_only() );
Harald Welted522ca02019-05-20 20:06:12 +0200894 execute( TC_sms_cb_cmd_sdcch4_default_and_normal() );
Harald Weltedf4d0f02019-05-20 16:04:11 +0200895 execute( TC_sms_cb_cmd_sdcch4_default_then_null() );
Harald Welte4a129f82019-05-21 16:35:22 +0200896 execute( TC_cbc_sdcch4_load_idle() );
897 execute( TC_cbc_sdcch4_load_overload() );
898
Harald Welte505cf9b2018-09-15 17:47:23 +0300899 if (false) { /* FIXME: SDCCH/8 support broken, needs trxcon + L1CTL work */
900 execute( TC_sms_cb_cmd_sdcch8_1block() );
901 execute( TC_sms_cb_cmd_sdcch8_2block() );
902 execute( TC_sms_cb_cmd_sdcch8_3block() );
903 execute( TC_sms_cb_cmd_sdcch8_4block() );
Harald Weltee0026c32019-05-20 00:27:30 +0200904 execute( TC_sms_cb_cmd_sdcch8_multi() );
Harald Welte505cf9b2018-09-15 17:47:23 +0300905 execute( TC_sms_cb_cmd_sdcch8_schedule() );
Harald Welte88e5dff2019-05-20 15:14:46 +0200906 execute( TC_sms_cb_cmd_sdcch8_default_only() );
Harald Welted522ca02019-05-20 20:06:12 +0200907 execute( TC_sms_cb_cmd_sdcch8_default_and_normal() );
Harald Welte4a129f82019-05-21 16:35:22 +0200908 execute( TC_cbc_sdcch8_load_idle() );
909 execute( TC_cbc_sdcch8_load_overload() );
Harald Welte505cf9b2018-09-15 17:47:23 +0300910 }
911}
912
913
914}