blob: 801a5fcb31bae46dc1b8cb70851ec455e9c6b986 [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 *
10 * This test suite tests the SMSCB (Cell Broadcast) related functionality of
11 * OsmoBTS by attaching to the A-bis RSL and Um interface and emulating both
12 * BSC and MS.
13 */
14
15import from Misc_Helpers all;
16import from General_Types all;
17import from Osmocom_Types all;
18import from GSM_Types all;
19import from L1CTL_PortType all;
20import from L1CTL_Types all;
21import from LAPDm_Types all;
Harald Welte4a129f82019-05-21 16:35:22 +020022import from IPA_Emulation all;
Harald Welte505cf9b2018-09-15 17:47:23 +030023
24import from RSL_Types all;
25
26import from Osmocom_VTY_Functions all;
27
28import from BTS_Tests all;
29
30/***********************************************************************
31 * Cell Broadcast related tests
32 ***********************************************************************/
33
Harald Weltea3ff6702019-05-20 20:03:50 +020034/* Test parameters for one channel (e.g. Basic, Extended) */
35type record CbchTestParsChan {
36 /* list of "normal" (sent-once) SMSCB messages */
37 CbchTestMsgs msgs,
38 /* default message, if any */
39 CbchTestMsg default_msg optional
40}
41
42private template (value) CbchTestParsChan
43t_CbchPC(template (value) CbchTestMsgs msgs, template (omit) CbchTestMsg def := omit) := {
44 msgs := msgs,
45 default_msg := def
46}
47
48/* CBCH test parameters for most of our tests */
Harald Welte505cf9b2018-09-15 17:47:23 +030049type record CbchTestPars {
Harald Weltea3ff6702019-05-20 20:03:50 +020050 /* should we execute on SDCCH4 (true) or SDCCH8 (false) ? */
Harald Welte505cf9b2018-09-15 17:47:23 +030051 boolean use_sdcch4,
Harald Weltea3ff6702019-05-20 20:03:50 +020052 /* Parameters for BASIC CBCH */
53 CbchTestParsChan basic,
54 /* Parameters for EXTENDED CBCH */
55 CbchTestParsChan extended optional
Harald Welte505cf9b2018-09-15 17:47:23 +030056};
57
58type record CbchTestMsg {
59 /* config / input data */
60 RSL_CbCommand rsl_cb_cmd,
61 uint2_t last_block, /* 0..3 */
62 octetstring payload,
63 /* computed / result data */
64 CbchBlocks blocks optional
65};
66type record of CbchTestMsg CbchTestMsgs;
67
68/* a single 22byte block within a CbchTestMsg */
69type record CbchBlock {
70 uint4_t seq_nr, /* as per TS 04.12 */
71 boolean is_last,
72 OCT22 payload,
73 boolean seen_once
74};
75type record of CbchBlock CbchBlocks;
76
77/* compute the expected blocks for given test parameters */
78private function f_cbch_compute_exp_blocks(inout CbchTestPars pars) {
Harald Weltea3ff6702019-05-20 20:03:50 +020079 f_cbch_compute_exp_blocks_chan(pars.basic);
80 if (ispresent(pars.extended)) {
81 f_cbch_compute_exp_blocks_chan(pars.extended);
82 }
83}
84private function f_cbch_compute_exp_blocks_chan(inout CbchTestParsChan pars_chan) {
Harald Welte505cf9b2018-09-15 17:47:23 +030085 var integer i;
Harald Weltea3ff6702019-05-20 20:03:50 +020086 for (i := 0; i < lengthof(pars_chan.msgs); i := i+1) {
87 pars_chan.msgs[i].blocks := f_comp_blocks(pars_chan.msgs[i]);
88 }
89 if (ispresent(pars_chan.default_msg)) {
90 pars_chan.default_msg.blocks := f_comp_blocks(pars_chan.default_msg);
Harald Welte505cf9b2018-09-15 17:47:23 +030091 }
92}
93private function f_comp_blocks(in CbchTestMsg msg) return CbchBlocks {
94 var CbchBlocks blocks := {};
95 var integer i;
96
97 for (i := 0; i <= msg.last_block; i := i+1) {
98 var CbchBlock block := {
99 seq_nr := i,
100 is_last := false,
101 payload := substr(msg.payload, 22*i, 22),
102 seen_once := false
103 };
104 if (msg.rsl_cb_cmd == RSL_CB_CMD_SCHEDULE and i == 0) {
105 block.seq_nr := 8;
106 }
107 if (i == msg.last_block) {
108 block.is_last := true;
109 }
110 blocks := blocks & {block};
111 }
112
113 return blocks;
114};
115
116/* TS 48.058 Section 9.3.41 */
117private function f_cbch_block_nr2rsl(uint2_t nr) return uint2_t {
118 select (nr) {
119 case (0) { return 1; }
120 case (1) { return 2; }
121 case (2) { return 3; }
122 case (3) { return 0; }
123 }
124 setverdict(fail, "Invalid block number");
125 mtc.stop;
126}
127
Harald Welte88e5dff2019-05-20 15:14:46 +0200128private function f_cbch_fn2tb(uint32_t fn) return integer
129{
130 return (fn/51) mod 8; /* TS 05.02 Section 6.5.4 */
131}
132
Harald Welte505cf9b2018-09-15 17:47:23 +0300133/* Verify the CBCH TB scheduling rules of TS 05.02 Section 6.5.4 */
134private function f_cbch_fn_verify(uint32_t fn, CBCH_Block cb)
135{
Harald Welte88e5dff2019-05-20 15:14:46 +0200136 var integer tb := f_cbch_fn2tb(fn);
Harald Welte505cf9b2018-09-15 17:47:23 +0300137 if (cb.block_type.seq_nr == 15 /* null */) {
138 /* always permitted */
139 return;
140 } else if (cb.block_type.seq_nr == 8 /* schedule */) {
141 if (tb != 0) {
142 setverdict(fail, "Schedule block at TB=", tb);
143 }
144 } else if (cb.block_type.seq_nr < 4) {
145 if (cb.block_type.seq_nr != tb and cb.block_type.seq_nr+4 != tb) {
146 setverdict(fail, "Normal block at wrong TB=", tb, ": ", cb);
147 }
148 }
149}
150
Harald Weltedf4d0f02019-05-20 16:04:11 +0200151private function f_rsl_smscb_default_null() runs on test_CT
152{
153 var RSL_IE_CbCommandType cmd_type :=
154 valueof(ts_RSL_IE_CbCmdType(RSL_CB_CMD_DEFAULT, 1, true));
155 RSL_CCHAN.send(ts_RSL_UD(ts_RSL_SMSCB_CMD(cmd_type, ''O)));
156}
157
Harald Weltea3ff6702019-05-20 20:03:50 +0200158template RSL_IE t_RSL_IE_SMSCB_EXT := t_RSL_IE(RSL_IE_SMSCB_CHAN_INDICATOR, {smscb_chan_ind := 1});
159
160private function f_smscb_setup_rsl_chan(inout CbchTestParsChan pars_chan, boolean extd := false)
161runs on test_CT {
Harald Welte88e5dff2019-05-20 15:14:46 +0200162 var integer i;
Harald Weltea3ff6702019-05-20 20:03:50 +0200163 var CbchTestMsg msg;
164 var uint2_t rsl_last_block;
165 var RSL_IE_CbCommandType cmd_type;
166 var RSL_Message rsl;
167
168 /* send SMSCB[s] via RSL */
169 for (i := 0; i < lengthof(pars_chan.msgs); i := i+1) {
170 msg := pars_chan.msgs[i];
171 rsl_last_block := f_cbch_block_nr2rsl(msg.last_block);
172 cmd_type := valueof(ts_RSL_IE_CbCmdType(msg.rsl_cb_cmd, rsl_last_block));
173 rsl := valueof(ts_RSL_SMSCB_CMD(cmd_type, msg.payload));
174 if (extd) {
175 rsl.ies := rsl.ies & { valueof(t_RSL_IE_SMSCB_EXT) };
176 }
177 RSL_CCHAN.send(ts_RSL_UD(rsl));
178 }
179 if (ispresent(pars_chan.default_msg)) {
180 msg := pars_chan.default_msg;
181 rsl_last_block := f_cbch_block_nr2rsl(msg.last_block);
182 cmd_type := valueof(ts_RSL_IE_CbCmdType(msg.rsl_cb_cmd, rsl_last_block, false));
183 rsl := valueof(ts_RSL_SMSCB_CMD(cmd_type, msg.payload));
184 if (extd) {
185 rsl.ies := rsl.ies & { valueof(t_RSL_IE_SMSCB_EXT) };
186 }
187 RSL_CCHAN.send(ts_RSL_UD(rsl));
188 }
189}
Harald Welte505cf9b2018-09-15 17:47:23 +0300190
Harald Welte4a129f82019-05-21 16:35:22 +0200191private function f_vty_cbch_setup(boolean use_sdcch4 := true) runs on test_CT {
Harald Welte505cf9b2018-09-15 17:47:23 +0300192
Harald Welte4a129f82019-05-21 16:35:22 +0200193 if (use_sdcch4 == true) {
Harald Welte505cf9b2018-09-15 17:47:23 +0300194 f_vty_config2(BSCVTY, {"network", "bts 0", "trx 0", "timeslot 0"},
195 "phys_chan_config CCCH+SDCCH4+CBCH");
196 f_vty_config2(BSCVTY, {"network", "bts 0", "trx 0", "timeslot 6"},
197 "phys_chan_config SDCCH8");
198 } else {
199 f_vty_config2(BSCVTY, {"network", "bts 0", "trx 0", "timeslot 0"},
200 "phys_chan_config CCCH+SDCCH4");
201 f_vty_config2(BSCVTY, {"network", "bts 0", "trx 0", "timeslot 6"},
202 "phys_chan_config SDCCH8+CBCH");
203 }
204 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
205 f_sleep(2.0);
Harald Welte4a129f82019-05-21 16:35:22 +0200206}
207private function f_smscb_setup(inout CbchTestPars pars) runs on test_CT {
208
209 f_cbch_compute_exp_blocks(pars);
210
211 f_init_vty_bsc();
212 /* ensure that a CBCH is present in channel combination */
213 f_vty_cbch_setup(pars.use_sdcch4);
Harald Welte505cf9b2018-09-15 17:47:23 +0300214 f_init(testcasename());
215
216 f_init_l1ctl();
217 f_l1_tune(L1CTL);
218 /* FIXME: switch to dedicated mode for SDCCH/8 */
219
220 /* send SMSCB[s] via RSL */
Harald Weltea3ff6702019-05-20 20:03:50 +0200221 f_smscb_setup_rsl_chan(pars.basic, false);
222 if (ispresent(pars.extended)) {
223 f_smscb_setup_rsl_chan(pars.extended, true);
Harald Welte505cf9b2018-09-15 17:47:23 +0300224 }
Harald Welte88e5dff2019-05-20 15:14:46 +0200225}
226
227private function f_smscb_cleanup() runs on test_CT {
228 /* reset timeslot 0 channel combination to default */
229 f_vty_config2(BSCVTY, {"network", "bts 0", "trx 0", "timeslot 0"},
230 "phys_chan_config CCCH+SDCCH4");
231 f_vty_config2(BSCVTY, {"network", "bts 0", "trx 0", "timeslot 6"},
232 "phys_chan_config SDCCH8");
233}
234
Harald Weltea3ff6702019-05-20 20:03:50 +0200235/* construct a receive/match template for given block_nr in given msg */
236private function f_get_block_template(CbchTestMsg msg, integer block_nr) return template CBCH_Block {
237 var template CBCH_Block tr;
238 if (block_nr < lengthof(msg.blocks)) {
239 var CbchBlock b := msg.blocks[block_nr];
240 tr := tr_CBCH_Block(b.seq_nr, b.is_last, b.payload);
241 } else {
242 tr := tr_CBCH_Block(15, ?, ?);
243 }
244 return tr;
245}
246
247/* the heart of the CBCH test case matching engine for one channel (basic, extended) */
248private function f_cbch_match(inout CbchTestParsChan pars_chan, CBCH_Block cb, integer tb)
249{
250 var integer block_nr := tb mod 4;
251 var integer i;
252
253 if (not match(cb, tr_CBCH_Block)) {
254 setverdict(fail, "Illegal CBCH Block received: ", cb);
255 } else {
256 var boolean matched := false;
257 /* check if it's any of our expected blocks */
258 for (i := 0; i < lengthof(pars_chan.msgs); i := i+1) {
259 if (block_nr < lengthof(pars_chan.msgs[i].blocks)) {
260 if (match(cb, f_get_block_template(pars_chan.msgs[i], block_nr))) {
261 log("Found block_nr ", block_nr, " of msg ", i);
262 if (not pars_chan.msgs[i].blocks[block_nr].seen_once) {
263 pars_chan.msgs[i].blocks[block_nr].seen_once := true;
264 setverdict(pass);
265 } else {
266 setverdict(fail, "Received SMSCB twice! ", cb);
267 }
268 matched := true;
269 break;
270 }
271 }
272 }
273 if (not matched) {
274 var template CBCH_Block tr;
275 if (ispresent(pars_chan.default_msg)) {
276 /* it must be a block of the default message */
277 tr := f_get_block_template(pars_chan.default_msg, block_nr);
278 } else {
279 /* it must be a NULL block */
280 tr := tr_CBCH_Block(15, ?, ?);
281 }
282 if (not match(cb, tr)) {
283 setverdict(fail, "Received unexpected CBCH block: ", cb);
284 } else {
285 log("Found block_nr ", block_nr, " of DEFAULT/NULL");
286 if (ispresent(pars_chan.default_msg) and
287 block_nr < lengthof(pars_chan.default_msg.blocks)) {
288 pars_chan.default_msg.blocks[block_nr].seen_once := true;
289 }
290 }
291 }
292 }
293}
294
295/* Report/Evaluate the per-channel CBCH test results */
296private function f_cbch_report(CbchTestParsChan pars_chan, charstring id)
297{
298 var integer i, j;
299
300 /* verify that each block of each message has been seen once */
301 for (i := 0; i < lengthof(pars_chan.msgs); i := i+1) {
302 for (j := 0; j < lengthof(pars_chan.msgs[i].blocks); j := j+1) {
303 var CbchBlock b := pars_chan.msgs[i].blocks[j];
304 if (not b.seen_once) {
305 setverdict(fail, "Timeout waiting for ", id, " CBCH block ",
306 j, " of msg ", i);
307 }
308 }
309 }
310 if (ispresent(pars_chan.default_msg)) {
311 /* verify that each block of default message has been seen at least once */
312 for (j := 0; j < lengthof(pars_chan.default_msg.blocks); j := j+1) {
313 var CbchBlock b := pars_chan.default_msg.blocks[j];
314 if (not b.seen_once) {
315 setverdict(fail, "Timeout waiting for at leaset one instance of ",
316 "CBCH block ", j, " of DEFAULT msg");
317 }
318 }
319 }
320}
321
Harald Welte88e5dff2019-05-20 15:14:46 +0200322/* shared function doing the heavy lifting for most CBCH tests */
323private function f_TC_smscb(CbchTestPars pars) runs on test_CT {
324 var L1ctlDlMessage dl;
Harald Weltea3ff6702019-05-20 20:03:50 +0200325 var integer msg_count;
326 timer T;
327
328 msg_count := lengthof(pars.basic.msgs);
329 if (ispresent(pars.basic.default_msg)) {
330 msg_count := msg_count + 1;
331 }
332 if (ispresent(pars.extended)) {
333 msg_count := msg_count + lengthof(pars.extended.msgs);
334 if (ispresent(pars.extended.default_msg)) {
335 msg_count := msg_count + 1;
336 }
337 }
Harald Welte88e5dff2019-05-20 15:14:46 +0200338
339 f_smscb_setup(pars);
340
Harald Weltea3ff6702019-05-20 20:03:50 +0200341 /* dynamically adjust timeout based on number of messages */
342 T.start(5.0 + 3.0 * int2float(msg_count));
Harald Welte505cf9b2018-09-15 17:47:23 +0300343 /* Expect this to show up exactly once on the basic CBCH (four blocks) */
344 alt {
345 /* FIXME: Channel Nr for SDCCH/8 */
346 [] L1CTL.receive(tr_L1CTL_DATA_IND(t_RslChanNr_CBCH(0))) -> value dl {
Harald Weltea3ff6702019-05-20 20:03:50 +0200347 var integer tb := f_cbch_fn2tb(dl.dl_info.frame_nr);
Harald Welte505cf9b2018-09-15 17:47:23 +0300348 var CBCH_Block cb := dec_CBCH_Block(dl.payload.data_ind.payload);
Harald Weltea3ff6702019-05-20 20:03:50 +0200349 log("Tb=", tb, ", CBCH: ", dl, ", block: ", cb);
350
Harald Welte505cf9b2018-09-15 17:47:23 +0300351 /* detect the proper CBCH messages; check frame number */
352 f_cbch_fn_verify(dl.dl_info.frame_nr, cb);
Harald Weltea3ff6702019-05-20 20:03:50 +0200353
354 if (tb < 4) {
355 f_cbch_match(pars.basic, cb, tb);
Harald Welte505cf9b2018-09-15 17:47:23 +0300356 } else {
Harald Weltea3ff6702019-05-20 20:03:50 +0200357 if (not ispresent(pars.extended)) {
358 /* no parameters for ext. BCCH given: ignore */
359 repeat;
Harald Welte505cf9b2018-09-15 17:47:23 +0300360 }
Harald Weltea3ff6702019-05-20 20:03:50 +0200361 f_cbch_match(pars.extended, cb, tb);
Harald Welte505cf9b2018-09-15 17:47:23 +0300362 }
Harald Weltea3ff6702019-05-20 20:03:50 +0200363 repeat;
Harald Welte505cf9b2018-09-15 17:47:23 +0300364 }
365 [] L1CTL.receive { repeat; }
366 [] T.timeout {
Harald Weltea3ff6702019-05-20 20:03:50 +0200367 f_cbch_report(pars.basic, "Basic");
368 if (ispresent(pars.extended)) {
369 f_cbch_report(pars.extended, "Extended");
Harald Welte505cf9b2018-09-15 17:47:23 +0300370 }
371 }
372 }
373
Harald Welte88e5dff2019-05-20 15:14:46 +0200374 f_smscb_cleanup();
375 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, pass);
376}
377
378private function f_TC_smscb_default_only(CbchTestPars pars) runs on test_CT {
379 var L1ctlDlMessage dl;
380 timer T := 5.0;
381
382 f_smscb_setup(pars);
383
384 /* ensure whatever initial NULL messages have all been drained */
385 f_sleep(5.0);
386 L1CTL.clear;
387
388 T.start;
389 alt {
390 [] L1CTL.receive(tr_L1CTL_DATA_IND(t_RslChanNr_CBCH(0))) -> value dl {
391 var integer tb := f_cbch_fn2tb(dl.dl_info.frame_nr);
392 log("CBCH: ", dl);
393 var CBCH_Block cb := dec_CBCH_Block(dl.payload.data_ind.payload);
394 /* detect the proper CBCH messages; check frame number */
395 f_cbch_fn_verify(dl.dl_info.frame_nr, cb);
396 if (tb >= 4) {
397 /* skip extended CBCH for now */
398 repeat;
399 }
400 if (not match(cb, tr_CBCH_Block)) {
401 setverdict(fail, "Illegal CBCH Block received: ", cb);
402 } else {
403 var uint4_t rx_seq_nr := cb.block_type.seq_nr;
404 var template CBCH_Block tr;
Harald Weltea3ff6702019-05-20 20:03:50 +0200405 if (rx_seq_nr < lengthof(pars.basic.msgs[0].blocks)) {
406 var CbchBlock b := pars.basic.msgs[0].blocks[rx_seq_nr];
Harald Welte88e5dff2019-05-20 15:14:46 +0200407 tr := tr_CBCH_Block(b.seq_nr, b.is_last, b.payload);
408 } else {
409 tr := tr_CBCH_Block(15, ?, ?);
410 }
411 if (match(cb, tr)) {
412 setverdict(pass); /* FIXME: check that all blocks are received? */
413 repeat;
414 } else {
415 setverdict(fail, "Unexpected CBCH block ", cb, ", expected ", tr);
416 }
417 }
418 }
419 [] L1CTL.receive { repeat; }
420 [] T.timeout {}
421 }
422
423 f_smscb_cleanup();
424 /* don't shut down; some tests still want to continue */
Harald Welte505cf9b2018-09-15 17:47:23 +0300425}
426
427private const CbchTestMsgs msgs_1m_1b_norm := {
428 { RSL_CB_CMD_NORMAL, 0, '001000320f1141660c344dd3cba09a0c000000000000'O, omit }
429}
430
431private const CbchTestMsgs msgs_1m_2b_norm := {
432 { RSL_CB_CMD_NORMAL, 1, '001000320f1141660c344dd3cba09a0c000000000000'O &
433 '000102030405060708090a0b0c0d0e0f101213141516'O,
434 omit }
435}
436
437private const CbchTestMsgs msgs_1m_3b_norm := {
438 { RSL_CB_CMD_NORMAL, 2, '001000320f1141660c344dd3cba09a0c000000000000'O &
439 '000102030405060708090a0b0c0d0e0f101213141516'O &
440 '101112131415161718191a1b1c1d1e1f202223242526'O,
441 omit }
442}
443
444private const CbchTestMsgs msgs_1m_4b_norm := {
445 { RSL_CB_CMD_NORMAL, 3, '001000320f1141660c344dd3cba09a0c000000000000'O &
446 '000102030405060708090a0b0c0d0e0f101213141516'O &
447 '101112131415161718191a1b1c1d1e1f202223242526'O &
448 '202122232425262728292a2b2c2d2e2f303233343536'O,
449 omit }
450}
451
452private const CbchTestMsgs msgs_1m_4b_sched := {
453 { RSL_CB_CMD_SCHEDULE, 3, '001000320f1141660c344dd3cba09a0c000000000000'O &
454 '000102030405060708090a0b0c0d0e0f101213141516'O &
455 '101112131415161718191a1b1c1d1e1f202223242526'O &
456 '202122232425262728292a2b2c2d2e2f303233343536'O,
457 omit }
458}
459
Harald Weltee0026c32019-05-20 00:27:30 +0200460private const CbchTestMsgs msgs_3m_4b_norm := {
461 { RSL_CB_CMD_NORMAL, 3, '001000320f1141660c344dd3cba09a0c000000000000'O &
462 '000102030405060708090a0b0c0d0e0f101213141516'O &
463 '101112131415161718191a1b1c1d1e1f202223242526'O &
464 '201122232425262728292a2b2c2d2e2f303233343536'O,
465 omit },
466 { RSL_CB_CMD_NORMAL, 3, '002000320f1141660c344dd3cba09a0c000000000000'O &
467 '002102030405060708090a0b0c0d0e0f101213141516'O &
468 '102112131415161718191a1b1c1d1e1f202223242526'O &
469 '202122232425262728292a2b2c2d2e2f303233343536'O,
470 omit },
471 { RSL_CB_CMD_NORMAL, 3, '003000320f1141660c344dd3cba09a0c000000000000'O &
472 '003102030405060708090a0b0c0d0e0f101213141516'O &
473 '103112131415161718191a1b1c1d1e1f202223242526'O &
474 '203122232425262728292a2b2c2d2e2f303233343536'O,
475 omit }
476}
477
Harald Welte88e5dff2019-05-20 15:14:46 +0200478private const CbchTestMsgs msgs_1m_3b_default := {
479 { RSL_CB_CMD_DEFAULT, 2, '001000320f1141660c344dd3cba09a0c000000000000'O &
480 '000102030405060708090a0b0c0d0e0f101213141516'O &
481 '101112131415161718191a1b1c1d1e1f202223242526'O,
482 omit }
483}
Harald Weltea3ff6702019-05-20 20:03:50 +0200484private const CbchTestMsg msg_default := {
485 RSL_CB_CMD_DEFAULT, 0, '010203040506070708090a0b0c0d0e0f101112131415'O,
486 omit
487}
Harald Welte88e5dff2019-05-20 15:14:46 +0200488
Harald Welte505cf9b2018-09-15 17:47:23 +0300489/* transmit single-block SMSCB COMMAND */
490testcase TC_sms_cb_cmd_sdcch4_1block() runs on test_CT {
491 var CbchTestPars pars := {
492 use_sdcch4 := true,
Harald Weltea3ff6702019-05-20 20:03:50 +0200493 basic := valueof(t_CbchPC(msgs_1m_1b_norm)),
494 extended := omit
Harald Welte505cf9b2018-09-15 17:47:23 +0300495 };
496 f_TC_smscb(pars);
497}
498testcase TC_sms_cb_cmd_sdcch8_1block() runs on test_CT {
499 var CbchTestPars pars := {
500 use_sdcch4 := false,
Harald Weltea3ff6702019-05-20 20:03:50 +0200501 basic := valueof(t_CbchPC(msgs_1m_1b_norm)),
502 extended := omit
Harald Welte505cf9b2018-09-15 17:47:23 +0300503 };
504 f_TC_smscb(pars);
505}
506
507/* transmit dual-block SMSCB COMMAND */
508testcase TC_sms_cb_cmd_sdcch4_2block() runs on test_CT {
509 var CbchTestPars pars := {
510 use_sdcch4 := true,
Harald Weltea3ff6702019-05-20 20:03:50 +0200511 basic := valueof(t_CbchPC(msgs_1m_2b_norm)),
512 extended := omit
Harald Welte505cf9b2018-09-15 17:47:23 +0300513 };
514 f_TC_smscb(pars);
515}
516testcase TC_sms_cb_cmd_sdcch8_2block() runs on test_CT {
517 var CbchTestPars pars := {
518 use_sdcch4 := false,
Harald Weltea3ff6702019-05-20 20:03:50 +0200519 basic := valueof(t_CbchPC(msgs_1m_2b_norm)),
520 extended := omit
Harald Welte505cf9b2018-09-15 17:47:23 +0300521 };
522 f_TC_smscb(pars);
523}
524
525/* transmit triple-block SMSCB COMMAND */
526testcase TC_sms_cb_cmd_sdcch4_3block() runs on test_CT {
527 var CbchTestPars pars := {
528 use_sdcch4 := true,
Harald Weltea3ff6702019-05-20 20:03:50 +0200529 basic := valueof(t_CbchPC(msgs_1m_3b_norm)),
530 extended := omit
Harald Welte505cf9b2018-09-15 17:47:23 +0300531 };
532 f_TC_smscb(pars);
533}
534testcase TC_sms_cb_cmd_sdcch8_3block() runs on test_CT {
535 var CbchTestPars pars := {
536 use_sdcch4 := false,
Harald Weltea3ff6702019-05-20 20:03:50 +0200537 basic := valueof(t_CbchPC(msgs_1m_3b_norm)),
538 extended := omit
Harald Welte505cf9b2018-09-15 17:47:23 +0300539 };
540 f_TC_smscb(pars);
541}
542
543/* transmit quad-block SMSCB COMMAND */
544testcase TC_sms_cb_cmd_sdcch4_4block() runs on test_CT {
545 var CbchTestPars pars := {
546 use_sdcch4 := true,
Harald Weltea3ff6702019-05-20 20:03:50 +0200547 basic := valueof(t_CbchPC(msgs_1m_4b_norm)),
548 extended := omit
Harald Welte505cf9b2018-09-15 17:47:23 +0300549 };
550 f_TC_smscb(pars);
551}
552testcase TC_sms_cb_cmd_sdcch8_4block() runs on test_CT {
553 var CbchTestPars pars := {
554 use_sdcch4 := false,
Harald Weltea3ff6702019-05-20 20:03:50 +0200555 basic := valueof(t_CbchPC(msgs_1m_4b_norm)),
556 extended := omit
Harald Welte505cf9b2018-09-15 17:47:23 +0300557 };
558 f_TC_smscb(pars);
559}
560
Harald Weltee0026c32019-05-20 00:27:30 +0200561/* transmit multiple commands of each 4 blocks */
562testcase TC_sms_cb_cmd_sdcch4_multi() runs on test_CT {
563 var CbchTestPars pars := {
564 use_sdcch4 := true,
Harald Weltea3ff6702019-05-20 20:03:50 +0200565 basic := valueof(t_CbchPC(msgs_3m_4b_norm)),
566 extended := omit
Harald Weltee0026c32019-05-20 00:27:30 +0200567 };
568 f_TC_smscb(pars);
569}
570testcase TC_sms_cb_cmd_sdcch8_multi() runs on test_CT {
571 var CbchTestPars pars := {
572 use_sdcch4 := false,
Harald Weltea3ff6702019-05-20 20:03:50 +0200573 basic := valueof(t_CbchPC(msgs_3m_4b_norm)),
574 extended := omit
Harald Weltee0026c32019-05-20 00:27:30 +0200575 };
576 f_TC_smscb(pars);
577}
578
Harald Welte60bd92b2019-05-20 21:42:21 +0200579/* transmit multiple commands of each 4 blocks on CBCH EXTD */
580testcase TC_sms_cb_cmd_sdcch4_extd_multi() runs on test_CT {
581 var CbchTestPars pars := {
582 use_sdcch4 := true,
583 basic := valueof(t_CbchPC({})),
584 extended := valueof(t_CbchPC(msgs_3m_4b_norm))
585 };
586 f_TC_smscb(pars);
587}
588testcase TC_sms_cb_cmd_sdcch8_extd_multi() runs on test_CT {
589 var CbchTestPars pars := {
590 use_sdcch4 := false,
591 basic := valueof(t_CbchPC({})),
592 extended := valueof(t_CbchPC(msgs_3m_4b_norm))
593 };
594 f_TC_smscb(pars);
595}
596
Harald Welte505cf9b2018-09-15 17:47:23 +0300597/* transmit SMSCB COMMAND with SCHEDULE payload */
598testcase TC_sms_cb_cmd_sdcch4_schedule() runs on test_CT {
599 var CbchTestPars pars := {
600 use_sdcch4 := true,
Harald Weltea3ff6702019-05-20 20:03:50 +0200601 basic := valueof(t_CbchPC(msgs_1m_4b_sched)),
602 extended := omit
Harald Welte505cf9b2018-09-15 17:47:23 +0300603 };
604 f_TC_smscb(pars);
605}
606testcase TC_sms_cb_cmd_sdcch8_schedule() runs on test_CT {
607 var CbchTestPars pars := {
608 use_sdcch4 := false,
Harald Weltea3ff6702019-05-20 20:03:50 +0200609 basic := valueof(t_CbchPC(msgs_1m_4b_sched)),
610 extended := omit
Harald Welte505cf9b2018-09-15 17:47:23 +0300611 };
612 f_TC_smscb(pars);
613}
614
Harald Welte88e5dff2019-05-20 15:14:46 +0200615/* set a DEFAULT message; verify it gets transmitted all the time */
616testcase TC_sms_cb_cmd_sdcch4_default_only() runs on test_CT {
617 var CbchTestPars pars := {
618 use_sdcch4 := true,
Harald Weltea3ff6702019-05-20 20:03:50 +0200619 basic := valueof(t_CbchPC(msgs_1m_3b_default)),
620 extended := omit
Harald Welte88e5dff2019-05-20 15:14:46 +0200621 };
622 f_TC_smscb_default_only(pars);
623 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, pass);
624}
625testcase TC_sms_cb_cmd_sdcch8_default_only() runs on test_CT {
626 var CbchTestPars pars := {
627 use_sdcch4 := true,
Harald Weltea3ff6702019-05-20 20:03:50 +0200628 basic := valueof(t_CbchPC(msgs_1m_3b_default)),
629 extended := omit
Harald Welte88e5dff2019-05-20 15:14:46 +0200630 };
631 f_TC_smscb_default_only(pars);
632 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, pass);
633}
634
Harald Welted522ca02019-05-20 20:06:12 +0200635testcase TC_sms_cb_cmd_sdcch4_default_and_normal() runs on test_CT {
636 var CbchTestPars pars := {
637 use_sdcch4 := true,
638 basic := valueof(t_CbchPC(msgs_1m_3b_norm, msg_default)),
639 extended := omit
640 };
641 f_TC_smscb(pars);
642}
643testcase TC_sms_cb_cmd_sdcch8_default_and_normal() runs on test_CT {
644 var CbchTestPars pars := {
645 use_sdcch4 := true,
646 basic := valueof(t_CbchPC(msgs_1m_3b_norm, msg_default)),
647 extended := omit
648 };
649 f_TC_smscb(pars);
650}
651
Harald Weltedf4d0f02019-05-20 16:04:11 +0200652/* first set a DEFAULT message, then disable it again */
653testcase TC_sms_cb_cmd_sdcch4_default_then_null() runs on test_CT {
654 var CbchTestPars pars := {
655 use_sdcch4 := true,
Harald Weltea3ff6702019-05-20 20:03:50 +0200656 basic := valueof(t_CbchPC(msgs_1m_3b_default)),
657 extended := omit
Harald Weltedf4d0f02019-05-20 16:04:11 +0200658 };
659 var L1ctlDlMessage dl;
660 timer T := 5.0;
661
662 f_TC_smscb_default_only(pars);
663
664 /* disable DEFAULT message; switch back to NULL */
665 f_rsl_smscb_default_null();
666
667 /* ensure whatever initial non-NULL messages have all been drained */
668 f_sleep(5.0);
669 L1CTL.clear;
670
671 T.start;
672 alt {
673 [] L1CTL.receive(tr_L1CTL_DATA_IND(t_RslChanNr_CBCH(0))) -> value dl {
674 log("CBCH: ", dl);
675 var CBCH_Block cb := dec_CBCH_Block(dl.payload.data_ind.payload);
676 /* detect the proper CBCH messages; check frame number */
677 f_cbch_fn_verify(dl.dl_info.frame_nr, cb);
678 if (not match(cb, tr_CBCH_Block)) {
679 setverdict(fail, "Illegal CBCH Block received: ", cb);
680 } else {
681 if (not match(cb, tr_CBCH_Block(15, ?, ?))) {
682 setverdict(fail, "Unexpected non-NULL CBCH block received");
683 }
684 repeat;
685 }
686 }
687 [] L1CTL.receive { repeat; }
688 [] T.timeout {
689 setverdict(pass);
690 }
691 }
692
693 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, pass);
694}
695
Harald Welte4a129f82019-05-21 16:35:22 +0200696/* Verify there are no CBCH load indications if no CBCH is present */
697testcase TC_cbch_load_idle_no_cbch() runs on test_CT {
698 var ASP_RSL_Unitdata rx_ud;
699 timer T := 10.0;
700
701 f_init(testcasename());
702 f_init_vty_bsc();
703
704 T.start;
705 alt {
706 [] RSL_CCHAN.receive(tr_RSL_UD(tr_RSL_CBCH_LOAD_IND_BASIC)) -> value rx_ud {
707 setverdict(fail, "Received unexpected CBCH LOAD IND: ", rx_ud);
708 }
709 [] RSL_CCHAN.receive(tr_RSL_UD(tr_RSL_CBCH_LOAD_IND_EXTD)) -> value rx_ud {
710 setverdict(fail, "Received unexpected CBCH LOAD IND: ", rx_ud);
711 }
712 [] RSL_CCHAN.receive { repeat; }
713 [] T.timeout {
714 setverdict(pass);
715 }
716 }
717 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
718}
719
720/* Verify the CBCH load indications of an idle cell (without CBCH load) */
721function f_TC_cbc_load_idle() runs on test_CT {
722 template integer tr_slot_count := (2 .. 15);
723 const integer min_load_ind := 4;
724 var integer basic_count := 0;
725 var integer extd_count := 0;
726 var ASP_RSL_Unitdata rx_ud;
727 timer T := 10.0;
728
729 f_init(testcasename());
730
731 RSL_CCHAN.clear;
732 T.start;
733 alt {
734 [] RSL_CCHAN.receive(tr_RSL_UD(tr_RSL_CBCH_LOAD_IND_BASIC(false, tr_slot_count))) {
735 basic_count := basic_count + 1;
736 repeat;
737 }
738 [] RSL_CCHAN.receive(tr_RSL_UD(tr_RSL_CBCH_LOAD_IND_EXTD(false, tr_slot_count))) -> value rx_ud {
739 extd_count := extd_count + 1;
740 repeat;
741 }
742 [] RSL_CCHAN.receive(tr_RSL_UD(tr_RSL_CBCH_LOAD_IND_BASIC)) -> value rx_ud {
743 setverdict(fail, "Received unexpected CBCH LOAD IND: ", rx_ud);
744 }
745 [] RSL_CCHAN.receive(tr_RSL_UD(tr_RSL_CBCH_LOAD_IND_EXTD)) -> value rx_ud {
746 setverdict(fail, "Received unexpected CBCH LOAD IND: ", rx_ud);
747 }
748 [] RSL_CCHAN.receive { repeat; }
749 [] T.timeout {
750 if ((basic_count >= min_load_ind) and (extd_count >= min_load_ind)) {
751 setverdict(pass);
752 } else {
753 setverdict(fail, "Insufficient number of CBCH LOAD IND: ",
754 "BASIC=", basic_count, " EXTD=", extd_count);
755 }
756 }
757 }
758 f_smscb_cleanup();
759 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
760}
761testcase TC_cbc_sdcch4_load_idle() runs on test_CT {
762 f_init_vty_bsc();
763 f_vty_cbch_setup(use_sdcch4 := true);
764 f_TC_cbc_load_idle();
765}
766testcase TC_cbc_sdcch8_load_idle() runs on test_CT {
767 f_init_vty_bsc();
768 f_vty_cbch_setup(use_sdcch4 := false);
769 f_TC_cbc_load_idle();
770}
771
772/* Verify CBCH overload indications are sent when sending too many SMS CB CMD */
773function f_TC_cbc_load_overload(CbchTestPars pars) runs on test_CT {
774 template integer tr_slot_count_basic := (11 .. 13);
775 template integer tr_slot_count_extd := (2 .. 15);
776 const integer min_load_ind := 4;
777 var integer basic_count := 0;
778 var integer extd_count := 0;
779 var ASP_RSL_Unitdata rx_ud;
780 timer T_total := 10.0;
781 timer T_retransmit := 0.2;
782 timer T_initial_guard := 2.0;
783 var integer i;
784
785 f_init(testcasename());
786
787 /* send tons of SMSCB Command */
788 for (i := 0; i < 30; i := i+1) {
789 f_smscb_setup_rsl_chan(pars.basic);
790 }
791
792 /* keep sending SMSCB Commands for another two seconds */
793 T_initial_guard.start;
794 T_retransmit.start;
795 alt {
796 [] T_retransmit.timeout {
797 f_smscb_setup_rsl_chan(pars.basic);
798 T_retransmit.start;
799 repeat;
800 }
801 [] T_initial_guard.timeout { }
802 }
803 /* clear any pending messages (where load may not have peaked yet) */
804 RSL_CCHAN.clear;
805
806 /* keep sending SMSCB Commands while verifying LOAD INDICATIONS */
807 T_total.start;
808 T_retransmit.start;
809 alt {
810 [] RSL_CCHAN.receive(tr_RSL_UD(tr_RSL_CBCH_LOAD_IND_BASIC(true, tr_slot_count_basic))) {
811 basic_count := basic_count + 1;
812 repeat;
813 }
814 [] RSL_CCHAN.receive(tr_RSL_UD(tr_RSL_CBCH_LOAD_IND_EXTD(false, tr_slot_count_extd))) {
815 extd_count := extd_count + 1;
816 repeat;
817 }
818 [] RSL_CCHAN.receive(tr_RSL_UD(tr_RSL_CBCH_LOAD_IND_BASIC)) -> value rx_ud {
819 setverdict(fail, "Received unexpected CBCH LOAD IND: ", rx_ud);
820 }
821 [] RSL_CCHAN.receive(tr_RSL_UD(tr_RSL_CBCH_LOAD_IND_EXTD)) -> value rx_ud {
822 setverdict(fail, "Received unexpected CBCH LOAD IND: ", rx_ud);
823 }
824 [] RSL_CCHAN.receive { repeat; }
825 [] T_retransmit.timeout {
826 f_smscb_setup_rsl_chan(pars.basic);
827 T_retransmit.start;
828 repeat;
829 }
830 [] T_total.timeout {
831 if ((basic_count >= min_load_ind) and (extd_count >= min_load_ind)) {
832 setverdict(pass);
833 } else {
834 setverdict(fail, "Insufficient number of CBCH LOAD IND: ",
835 "BASIC=", basic_count, " EXTD=", extd_count);
836 }
837 }
838 }
839 f_smscb_cleanup();
840 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
841}
842testcase TC_cbc_sdcch4_load_overload() runs on test_CT {
843 var CbchTestPars pars := {
844 use_sdcch4 := true,
845 basic := valueof(t_CbchPC(msgs_1m_3b_norm)),
846 extended := omit
847 };
848
849 f_init_vty_bsc();
850 f_vty_cbch_setup(use_sdcch4 := true);
851 f_TC_cbc_load_overload(pars);
852}
853testcase TC_cbc_sdcch8_load_overload() runs on test_CT {
854 var CbchTestPars pars := {
855 use_sdcch4 := true,
856 basic := valueof(t_CbchPC(msgs_1m_3b_norm)),
857 extended := omit
858 };
859
860 f_init_vty_bsc();
861 f_vty_cbch_setup(use_sdcch4 := true);
862 f_TC_cbc_load_overload(pars);
863}
Harald Weltedf4d0f02019-05-20 16:04:11 +0200864
Harald Welte88e5dff2019-05-20 15:14:46 +0200865
Harald Welte505cf9b2018-09-15 17:47:23 +0300866/* SMSCB TODO:
867 * multiple SMS BC CMD at the same time: Ensure all of them are sent exactly once
868 * extended CBCH vs. normal CBCH
869 *
870 */
871
872control {
Harald Welte4a129f82019-05-21 16:35:22 +0200873 execute( TC_cbch_load_idle_no_cbch() );
874
Harald Welte505cf9b2018-09-15 17:47:23 +0300875 execute( TC_sms_cb_cmd_sdcch4_1block() );
876 execute( TC_sms_cb_cmd_sdcch4_2block() );
877 execute( TC_sms_cb_cmd_sdcch4_3block() );
878 execute( TC_sms_cb_cmd_sdcch4_4block() );
Harald Weltee0026c32019-05-20 00:27:30 +0200879 execute( TC_sms_cb_cmd_sdcch4_multi() );
Harald Welte505cf9b2018-09-15 17:47:23 +0300880 execute( TC_sms_cb_cmd_sdcch4_schedule() );
Harald Welte88e5dff2019-05-20 15:14:46 +0200881 execute( TC_sms_cb_cmd_sdcch4_default_only() );
Harald Welted522ca02019-05-20 20:06:12 +0200882 execute( TC_sms_cb_cmd_sdcch4_default_and_normal() );
Harald Weltedf4d0f02019-05-20 16:04:11 +0200883 execute( TC_sms_cb_cmd_sdcch4_default_then_null() );
Harald Welte4a129f82019-05-21 16:35:22 +0200884 execute( TC_cbc_sdcch4_load_idle() );
885 execute( TC_cbc_sdcch4_load_overload() );
886
Harald Welte505cf9b2018-09-15 17:47:23 +0300887 if (false) { /* FIXME: SDCCH/8 support broken, needs trxcon + L1CTL work */
888 execute( TC_sms_cb_cmd_sdcch8_1block() );
889 execute( TC_sms_cb_cmd_sdcch8_2block() );
890 execute( TC_sms_cb_cmd_sdcch8_3block() );
891 execute( TC_sms_cb_cmd_sdcch8_4block() );
Harald Weltee0026c32019-05-20 00:27:30 +0200892 execute( TC_sms_cb_cmd_sdcch8_multi() );
Harald Welte505cf9b2018-09-15 17:47:23 +0300893 execute( TC_sms_cb_cmd_sdcch8_schedule() );
Harald Welte88e5dff2019-05-20 15:14:46 +0200894 execute( TC_sms_cb_cmd_sdcch8_default_only() );
Harald Welted522ca02019-05-20 20:06:12 +0200895 execute( TC_sms_cb_cmd_sdcch8_default_and_normal() );
Harald Welte4a129f82019-05-21 16:35:22 +0200896 execute( TC_cbc_sdcch8_load_idle() );
897 execute( TC_cbc_sdcch8_load_overload() );
Harald Welte505cf9b2018-09-15 17:47:23 +0300898 }
899}
900
901
902}