blob: 3cd1919c9d3c43dbf56d6c86f9a5057c82ec500f [file] [log] [blame]
Harald Welte505cf9b2018-09-15 17:47:23 +03001module BTS_Tests_SMSCB {
2
3/* Integration Tests for OsmoBTS
4 * (C) 2019 by Harald Welte <laforge@gnumonks.org>
5 * All rights reserved.
6 *
7 * Released under the terms of GNU General Public License, Version 2 or
8 * (at your option) any later version.
9 *
Harald Welte34b5a952019-05-27 11:54:11 +020010 * SPDX-License-Identifier: GPL-2.0-or-later
11 *
Harald Welte505cf9b2018-09-15 17:47:23 +030012 * This test suite tests the SMSCB (Cell Broadcast) related functionality of
13 * OsmoBTS by attaching to the A-bis RSL and Um interface and emulating both
14 * BSC and MS.
15 */
16
17import from Misc_Helpers all;
18import from General_Types all;
19import from Osmocom_Types all;
20import from GSM_Types all;
21import from L1CTL_PortType all;
22import from L1CTL_Types all;
23import from LAPDm_Types all;
Harald Welte4a129f82019-05-21 16:35:22 +020024import from IPA_Emulation all;
Harald Welte908ce542019-09-04 23:05:40 +020025import from GSM_RR_Types all;
Vadim Yanitskiya9a198d2020-03-28 05:11:26 +070026import from L3_Templates all;
Harald Welte505cf9b2018-09-15 17:47:23 +030027
28import from RSL_Types all;
29
Harald Welte11b734c2019-09-05 14:17:54 +020030import from PCUIF_Types all;
31import from PCUIF_CodecPort all;
32
Harald Welte505cf9b2018-09-15 17:47:23 +030033import from Osmocom_VTY_Functions all;
34
35import from BTS_Tests all;
36
37/***********************************************************************
38 * Cell Broadcast related tests
39 ***********************************************************************/
40
Harald Weltea3ff6702019-05-20 20:03:50 +020041/* Test parameters for one channel (e.g. Basic, Extended) */
42type record CbchTestParsChan {
43 /* list of "normal" (sent-once) SMSCB messages */
44 CbchTestMsgs msgs,
45 /* default message, if any */
46 CbchTestMsg default_msg optional
47}
48
49private template (value) CbchTestParsChan
50t_CbchPC(template (value) CbchTestMsgs msgs, template (omit) CbchTestMsg def := omit) := {
51 msgs := msgs,
52 default_msg := def
53}
54
55/* CBCH test parameters for most of our tests */
Harald Welte505cf9b2018-09-15 17:47:23 +030056type record CbchTestPars {
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +070057 /* Should we execute on SDCCH4 or SDCCH8? */
58 RslChannelNr chan_nr,
Vadim Yanitskiy7fefcee2020-09-12 20:04:08 +070059 /* Frequency Hopping parameters */
60 FreqHopPars fhp,
Harald Weltea3ff6702019-05-20 20:03:50 +020061 /* Parameters for BASIC CBCH */
62 CbchTestParsChan basic,
63 /* Parameters for EXTENDED CBCH */
64 CbchTestParsChan extended optional
Harald Welte505cf9b2018-09-15 17:47:23 +030065};
66
67type record CbchTestMsg {
68 /* config / input data */
69 RSL_CbCommand rsl_cb_cmd,
70 uint2_t last_block, /* 0..3 */
71 octetstring payload,
72 /* computed / result data */
73 CbchBlocks blocks optional
74};
75type record of CbchTestMsg CbchTestMsgs;
76
77/* a single 22byte block within a CbchTestMsg */
78type record CbchBlock {
79 uint4_t seq_nr, /* as per TS 04.12 */
80 boolean is_last,
81 OCT22 payload,
82 boolean seen_once
83};
84type record of CbchBlock CbchBlocks;
85
86/* compute the expected blocks for given test parameters */
87private function f_cbch_compute_exp_blocks(inout CbchTestPars pars) {
Harald Weltea3ff6702019-05-20 20:03:50 +020088 f_cbch_compute_exp_blocks_chan(pars.basic);
89 if (ispresent(pars.extended)) {
90 f_cbch_compute_exp_blocks_chan(pars.extended);
91 }
92}
93private function f_cbch_compute_exp_blocks_chan(inout CbchTestParsChan pars_chan) {
Harald Welte505cf9b2018-09-15 17:47:23 +030094 var integer i;
Harald Weltea3ff6702019-05-20 20:03:50 +020095 for (i := 0; i < lengthof(pars_chan.msgs); i := i+1) {
96 pars_chan.msgs[i].blocks := f_comp_blocks(pars_chan.msgs[i]);
97 }
98 if (ispresent(pars_chan.default_msg)) {
99 pars_chan.default_msg.blocks := f_comp_blocks(pars_chan.default_msg);
Harald Welte505cf9b2018-09-15 17:47:23 +0300100 }
101}
102private function f_comp_blocks(in CbchTestMsg msg) return CbchBlocks {
103 var CbchBlocks blocks := {};
104 var integer i;
105
106 for (i := 0; i <= msg.last_block; i := i+1) {
107 var CbchBlock block := {
108 seq_nr := i,
109 is_last := false,
110 payload := substr(msg.payload, 22*i, 22),
111 seen_once := false
112 };
113 if (msg.rsl_cb_cmd == RSL_CB_CMD_SCHEDULE and i == 0) {
114 block.seq_nr := 8;
115 }
116 if (i == msg.last_block) {
117 block.is_last := true;
118 }
119 blocks := blocks & {block};
120 }
121
122 return blocks;
123};
124
125/* TS 48.058 Section 9.3.41 */
126private function f_cbch_block_nr2rsl(uint2_t nr) return uint2_t {
127 select (nr) {
128 case (0) { return 1; }
129 case (1) { return 2; }
130 case (2) { return 3; }
131 case (3) { return 0; }
132 }
133 setverdict(fail, "Invalid block number");
134 mtc.stop;
135}
136
Harald Welte88e5dff2019-05-20 15:14:46 +0200137private function f_cbch_fn2tb(uint32_t fn) return integer
138{
139 return (fn/51) mod 8; /* TS 05.02 Section 6.5.4 */
140}
141
Harald Welte505cf9b2018-09-15 17:47:23 +0300142/* Verify the CBCH TB scheduling rules of TS 05.02 Section 6.5.4 */
143private function f_cbch_fn_verify(uint32_t fn, CBCH_Block cb)
144{
Harald Welte88e5dff2019-05-20 15:14:46 +0200145 var integer tb := f_cbch_fn2tb(fn);
Harald Welte505cf9b2018-09-15 17:47:23 +0300146 if (cb.block_type.seq_nr == 15 /* null */) {
147 /* always permitted */
148 return;
149 } else if (cb.block_type.seq_nr == 8 /* schedule */) {
150 if (tb != 0) {
151 setverdict(fail, "Schedule block at TB=", tb);
152 }
153 } else if (cb.block_type.seq_nr < 4) {
154 if (cb.block_type.seq_nr != tb and cb.block_type.seq_nr+4 != tb) {
155 setverdict(fail, "Normal block at wrong TB=", tb, ": ", cb);
156 }
157 }
158}
159
Harald Weltedf4d0f02019-05-20 16:04:11 +0200160private function f_rsl_smscb_default_null() runs on test_CT
161{
162 var RSL_IE_CbCommandType cmd_type :=
163 valueof(ts_RSL_IE_CbCmdType(RSL_CB_CMD_DEFAULT, 1, true));
Vadim Yanitskiy493abe72020-05-25 22:03:48 +0700164 RSL_CCHAN.send(ts_ASP_RSL_UD(ts_RSL_SMSCB_CMD(cmd_type, ''O)));
Harald Weltedf4d0f02019-05-20 16:04:11 +0200165}
166
Harald Weltea3ff6702019-05-20 20:03:50 +0200167template RSL_IE t_RSL_IE_SMSCB_EXT := t_RSL_IE(RSL_IE_SMSCB_CHAN_INDICATOR, {smscb_chan_ind := 1});
168
169private function f_smscb_setup_rsl_chan(inout CbchTestParsChan pars_chan, boolean extd := false)
170runs on test_CT {
Harald Welte88e5dff2019-05-20 15:14:46 +0200171 var integer i;
Harald Weltea3ff6702019-05-20 20:03:50 +0200172 var CbchTestMsg msg;
173 var uint2_t rsl_last_block;
174 var RSL_IE_CbCommandType cmd_type;
175 var RSL_Message rsl;
176
177 /* send SMSCB[s] via RSL */
178 for (i := 0; i < lengthof(pars_chan.msgs); i := i+1) {
179 msg := pars_chan.msgs[i];
180 rsl_last_block := f_cbch_block_nr2rsl(msg.last_block);
181 cmd_type := valueof(ts_RSL_IE_CbCmdType(msg.rsl_cb_cmd, rsl_last_block));
182 rsl := valueof(ts_RSL_SMSCB_CMD(cmd_type, msg.payload));
183 if (extd) {
184 rsl.ies := rsl.ies & { valueof(t_RSL_IE_SMSCB_EXT) };
185 }
Vadim Yanitskiy493abe72020-05-25 22:03:48 +0700186 RSL_CCHAN.send(ts_ASP_RSL_UD(rsl));
Harald Weltea3ff6702019-05-20 20:03:50 +0200187 }
188 if (ispresent(pars_chan.default_msg)) {
189 msg := pars_chan.default_msg;
190 rsl_last_block := f_cbch_block_nr2rsl(msg.last_block);
191 cmd_type := valueof(ts_RSL_IE_CbCmdType(msg.rsl_cb_cmd, rsl_last_block, false));
192 rsl := valueof(ts_RSL_SMSCB_CMD(cmd_type, msg.payload));
193 if (extd) {
194 rsl.ies := rsl.ies & { valueof(t_RSL_IE_SMSCB_EXT) };
195 }
Vadim Yanitskiy493abe72020-05-25 22:03:48 +0700196 RSL_CCHAN.send(ts_ASP_RSL_UD(rsl));
Harald Weltea3ff6702019-05-20 20:03:50 +0200197 }
198}
Harald Welte505cf9b2018-09-15 17:47:23 +0300199
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700200private function f_vty_cbch_setup(in RslChannelNr chan_nr) runs on test_CT {
Harald Welte505cf9b2018-09-15 17:47:23 +0300201
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700202 if (match(chan_nr, t_RslChanNr_CBCH4(0))) {
203 f_vty_config2(BSCVTY, { "network", "bts 0", "trx 0", "timeslot 0"},
Harald Welte505cf9b2018-09-15 17:47:23 +0300204 "phys_chan_config CCCH+SDCCH4+CBCH");
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700205 /* (Re)configure timeslots 1..3 as TCH/F */
206 for (var integer tn := 1; tn <= 3; tn := tn + 1) {
207 f_vty_config2(BSCVTY, { "network", "bts 0", "trx 0",
208 "timeslot " & int2str(tn) },
209 "phys_chan_config TCH/F");
210 }
211 } else if (match(chan_nr, t_RslChanNr_CBCH8(?))) {
212 f_vty_config2(BSCVTY, { "network", "bts 0", "trx 0", "timeslot 0"},
Harald Welte505cf9b2018-09-15 17:47:23 +0300213 "phys_chan_config CCCH+SDCCH4");
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700214 f_vty_config2(BSCVTY, { "network", "bts 0", "trx 0",
215 "timeslot " & int2str(chan_nr.tn) },
Harald Welte505cf9b2018-09-15 17:47:23 +0300216 "phys_chan_config SDCCH8+CBCH");
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700217
218 /* (Re)configure timeslots 1..3 (excluding the given one) as TCH/F */
219 for (var integer tn := 1; tn <= 3; tn := tn + 1) {
220 if (tn == chan_nr.tn)
221 { continue; }
222 f_vty_config2(BSCVTY, { "network", "bts 0", "trx 0",
223 "timeslot " & int2str(tn) },
224 "phys_chan_config TCH/F");
225 }
Harald Welte505cf9b2018-09-15 17:47:23 +0300226 }
227 f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
228 f_sleep(2.0);
Harald Welte4a129f82019-05-21 16:35:22 +0200229}
230private function f_smscb_setup(inout CbchTestPars pars) runs on test_CT {
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700231 /* Make sure we've got either SDCCH4+CBCH or SDCCH8+CBCH.
232 * SDCCH4+CBCH can only be allocated on TS0, SDCCH8+CBCH on TS0..3.
233 * On C0 the first timeslot shall always transmit BCCH, thus TS1..3.*/
234 if (not match(pars.chan_nr, (t_RslChanNr_CBCH4(0), t_RslChanNr_CBCH8(1),
235 t_RslChanNr_CBCH8(2), t_RslChanNr_CBCH8(3)))) {
236 setverdict(inconc, "Unhandled channel number: ", pars.chan_nr);
237 mtc.stop;
238 }
Harald Welte4a129f82019-05-21 16:35:22 +0200239
Vadim Yanitskiy7fefcee2020-09-12 20:04:08 +0700240 /* Obtain frequency hopping parameters for a given timeslot */
241 if (mp_freq_hop_enabled and mp_transceiver_num > 1)
242 { f_resolve_fh_params(pars.fhp, pars.chan_nr.tn); }
243 else
244 { pars.fhp.enabled := false; }
245
Harald Welte4a129f82019-05-21 16:35:22 +0200246 f_cbch_compute_exp_blocks(pars);
247
248 f_init_vty_bsc();
249 /* ensure that a CBCH is present in channel combination */
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700250 f_vty_cbch_setup(pars.chan_nr);
Harald Welte10474062019-05-30 16:48:17 +0200251 f_init();
Harald Welte505cf9b2018-09-15 17:47:23 +0300252
253 f_init_l1ctl();
Vadim Yanitskiyf1c95c82020-07-31 06:43:57 +0700254
255 /* Tune L1 to the given CBCH timeslot (SDCCH4+CBCH or SDCCH8+CBCH) */
256 if (match(pars.chan_nr, t_RslChanNr_CBCH4(0))) {
257 f_l1_tune(L1CTL, ccch_mode := CCCH_MODE_COMBINED_CBCH);
258 } else {
259 f_l1_tune(L1CTL, ccch_mode := CCCH_MODE_COMBINED);
Vadim Yanitskiy7fefcee2020-09-12 20:04:08 +0700260
261 if (pars.fhp.enabled) {
Vadim Yanitskiy3191d732020-11-15 20:45:01 +0700262 L1CTL.send(ts_L1CTL_DM_EST_REQ_H1(pars.chan_nr, mp_tsc_def,
Vadim Yanitskiy7fefcee2020-09-12 20:04:08 +0700263 pars.fhp.maio_hsn.hsn,
264 pars.fhp.maio_hsn.maio,
265 pars.fhp.ma));
266 } else {
Vadim Yanitskiy3191d732020-11-15 20:45:01 +0700267 L1CTL.send(ts_L1CTL_DM_EST_REQ_H0(pars.chan_nr, mp_tsc_def,
Vadim Yanitskiy42d8bd52020-11-15 20:41:02 +0700268 mp_trx_pars[0].arfcn));
Vadim Yanitskiy7fefcee2020-09-12 20:04:08 +0700269 }
Vadim Yanitskiyf1c95c82020-07-31 06:43:57 +0700270 }
Harald Welte505cf9b2018-09-15 17:47:23 +0300271
272 /* send SMSCB[s] via RSL */
Harald Weltea3ff6702019-05-20 20:03:50 +0200273 f_smscb_setup_rsl_chan(pars.basic, false);
274 if (ispresent(pars.extended)) {
275 f_smscb_setup_rsl_chan(pars.extended, true);
Harald Welte505cf9b2018-09-15 17:47:23 +0300276 }
Harald Welte88e5dff2019-05-20 15:14:46 +0200277}
278
Harald Weltea3ff6702019-05-20 20:03:50 +0200279/* construct a receive/match template for given block_nr in given msg */
280private function f_get_block_template(CbchTestMsg msg, integer block_nr) return template CBCH_Block {
281 var template CBCH_Block tr;
282 if (block_nr < lengthof(msg.blocks)) {
283 var CbchBlock b := msg.blocks[block_nr];
284 tr := tr_CBCH_Block(b.seq_nr, b.is_last, b.payload);
285 } else {
286 tr := tr_CBCH_Block(15, ?, ?);
287 }
288 return tr;
289}
290
291/* the heart of the CBCH test case matching engine for one channel (basic, extended) */
292private function f_cbch_match(inout CbchTestParsChan pars_chan, CBCH_Block cb, integer tb)
293{
294 var integer block_nr := tb mod 4;
295 var integer i;
296
297 if (not match(cb, tr_CBCH_Block)) {
298 setverdict(fail, "Illegal CBCH Block received: ", cb);
299 } else {
300 var boolean matched := false;
301 /* check if it's any of our expected blocks */
302 for (i := 0; i < lengthof(pars_chan.msgs); i := i+1) {
303 if (block_nr < lengthof(pars_chan.msgs[i].blocks)) {
304 if (match(cb, f_get_block_template(pars_chan.msgs[i], block_nr))) {
305 log("Found block_nr ", block_nr, " of msg ", i);
306 if (not pars_chan.msgs[i].blocks[block_nr].seen_once) {
307 pars_chan.msgs[i].blocks[block_nr].seen_once := true;
308 setverdict(pass);
309 } else {
310 setverdict(fail, "Received SMSCB twice! ", cb);
311 }
312 matched := true;
313 break;
314 }
315 }
316 }
317 if (not matched) {
318 var template CBCH_Block tr;
319 if (ispresent(pars_chan.default_msg)) {
320 /* it must be a block of the default message */
321 tr := f_get_block_template(pars_chan.default_msg, block_nr);
322 } else {
323 /* it must be a NULL block */
324 tr := tr_CBCH_Block(15, ?, ?);
325 }
326 if (not match(cb, tr)) {
327 setverdict(fail, "Received unexpected CBCH block: ", cb);
328 } else {
329 log("Found block_nr ", block_nr, " of DEFAULT/NULL");
330 if (ispresent(pars_chan.default_msg) and
331 block_nr < lengthof(pars_chan.default_msg.blocks)) {
332 pars_chan.default_msg.blocks[block_nr].seen_once := true;
333 }
334 }
335 }
336 }
337}
338
339/* Report/Evaluate the per-channel CBCH test results */
340private function f_cbch_report(CbchTestParsChan pars_chan, charstring id)
341{
342 var integer i, j;
343
344 /* verify that each block of each message has been seen once */
345 for (i := 0; i < lengthof(pars_chan.msgs); i := i+1) {
346 for (j := 0; j < lengthof(pars_chan.msgs[i].blocks); j := j+1) {
347 var CbchBlock b := pars_chan.msgs[i].blocks[j];
348 if (not b.seen_once) {
349 setverdict(fail, "Timeout waiting for ", id, " CBCH block ",
350 j, " of msg ", i);
351 }
352 }
353 }
354 if (ispresent(pars_chan.default_msg)) {
355 /* verify that each block of default message has been seen at least once */
356 for (j := 0; j < lengthof(pars_chan.default_msg.blocks); j := j+1) {
357 var CbchBlock b := pars_chan.default_msg.blocks[j];
358 if (not b.seen_once) {
359 setverdict(fail, "Timeout waiting for at leaset one instance of ",
360 "CBCH block ", j, " of DEFAULT msg");
361 }
362 }
363 }
364}
365
Harald Welte88e5dff2019-05-20 15:14:46 +0200366/* shared function doing the heavy lifting for most CBCH tests */
367private function f_TC_smscb(CbchTestPars pars) runs on test_CT {
Vadim Yanitskiyaf0aae62023-03-18 06:49:18 +0700368 var L1ctlMessage dl;
Harald Weltea3ff6702019-05-20 20:03:50 +0200369 var integer msg_count;
370 timer T;
371
372 msg_count := lengthof(pars.basic.msgs);
373 if (ispresent(pars.basic.default_msg)) {
374 msg_count := msg_count + 1;
375 }
376 if (ispresent(pars.extended)) {
377 msg_count := msg_count + lengthof(pars.extended.msgs);
378 if (ispresent(pars.extended.default_msg)) {
379 msg_count := msg_count + 1;
380 }
381 }
Harald Welte88e5dff2019-05-20 15:14:46 +0200382
383 f_smscb_setup(pars);
384
Harald Weltea3ff6702019-05-20 20:03:50 +0200385 /* dynamically adjust timeout based on number of messages */
386 T.start(5.0 + 3.0 * int2float(msg_count));
Harald Welte505cf9b2018-09-15 17:47:23 +0300387 /* Expect this to show up exactly once on the basic CBCH (four blocks) */
388 alt {
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700389 [] L1CTL.receive(tr_L1CTL_DATA_IND(pars.chan_nr)) -> value dl {
Harald Weltea3ff6702019-05-20 20:03:50 +0200390 var integer tb := f_cbch_fn2tb(dl.dl_info.frame_nr);
Harald Welte505cf9b2018-09-15 17:47:23 +0300391 var CBCH_Block cb := dec_CBCH_Block(dl.payload.data_ind.payload);
Harald Weltea3ff6702019-05-20 20:03:50 +0200392 log("Tb=", tb, ", CBCH: ", dl, ", block: ", cb);
393
Harald Welte505cf9b2018-09-15 17:47:23 +0300394 /* detect the proper CBCH messages; check frame number */
395 f_cbch_fn_verify(dl.dl_info.frame_nr, cb);
Harald Weltea3ff6702019-05-20 20:03:50 +0200396
397 if (tb < 4) {
398 f_cbch_match(pars.basic, cb, tb);
Harald Welte505cf9b2018-09-15 17:47:23 +0300399 } else {
Harald Weltea3ff6702019-05-20 20:03:50 +0200400 if (not ispresent(pars.extended)) {
401 /* no parameters for ext. BCCH given: ignore */
402 repeat;
Harald Welte505cf9b2018-09-15 17:47:23 +0300403 }
Harald Weltea3ff6702019-05-20 20:03:50 +0200404 f_cbch_match(pars.extended, cb, tb);
Harald Welte505cf9b2018-09-15 17:47:23 +0300405 }
Harald Weltea3ff6702019-05-20 20:03:50 +0200406 repeat;
Harald Welte505cf9b2018-09-15 17:47:23 +0300407 }
408 [] L1CTL.receive { repeat; }
409 [] T.timeout {
Harald Weltea3ff6702019-05-20 20:03:50 +0200410 f_cbch_report(pars.basic, "Basic");
411 if (ispresent(pars.extended)) {
412 f_cbch_report(pars.extended, "Extended");
Harald Welte505cf9b2018-09-15 17:47:23 +0300413 }
414 }
415 }
416
Harald Welte88e5dff2019-05-20 15:14:46 +0200417 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, pass);
418}
419
420private function f_TC_smscb_default_only(CbchTestPars pars) runs on test_CT {
Vadim Yanitskiyaf0aae62023-03-18 06:49:18 +0700421 var L1ctlMessage dl;
Harald Welte88e5dff2019-05-20 15:14:46 +0200422 timer T := 5.0;
423
424 f_smscb_setup(pars);
425
426 /* ensure whatever initial NULL messages have all been drained */
427 f_sleep(5.0);
428 L1CTL.clear;
429
430 T.start;
431 alt {
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700432 [] L1CTL.receive(tr_L1CTL_DATA_IND(pars.chan_nr)) -> value dl {
Harald Welte88e5dff2019-05-20 15:14:46 +0200433 var integer tb := f_cbch_fn2tb(dl.dl_info.frame_nr);
434 log("CBCH: ", dl);
435 var CBCH_Block cb := dec_CBCH_Block(dl.payload.data_ind.payload);
436 /* detect the proper CBCH messages; check frame number */
437 f_cbch_fn_verify(dl.dl_info.frame_nr, cb);
438 if (tb >= 4) {
439 /* skip extended CBCH for now */
440 repeat;
441 }
442 if (not match(cb, tr_CBCH_Block)) {
443 setverdict(fail, "Illegal CBCH Block received: ", cb);
444 } else {
445 var uint4_t rx_seq_nr := cb.block_type.seq_nr;
446 var template CBCH_Block tr;
Harald Weltea3ff6702019-05-20 20:03:50 +0200447 if (rx_seq_nr < lengthof(pars.basic.msgs[0].blocks)) {
448 var CbchBlock b := pars.basic.msgs[0].blocks[rx_seq_nr];
Harald Welte88e5dff2019-05-20 15:14:46 +0200449 tr := tr_CBCH_Block(b.seq_nr, b.is_last, b.payload);
450 } else {
451 tr := tr_CBCH_Block(15, ?, ?);
452 }
453 if (match(cb, tr)) {
454 setverdict(pass); /* FIXME: check that all blocks are received? */
455 repeat;
456 } else {
457 setverdict(fail, "Unexpected CBCH block ", cb, ", expected ", tr);
458 }
459 }
460 }
461 [] L1CTL.receive { repeat; }
462 [] T.timeout {}
463 }
464
Harald Welte88e5dff2019-05-20 15:14:46 +0200465 /* don't shut down; some tests still want to continue */
Harald Welte505cf9b2018-09-15 17:47:23 +0300466}
467
468private const CbchTestMsgs msgs_1m_1b_norm := {
469 { RSL_CB_CMD_NORMAL, 0, '001000320f1141660c344dd3cba09a0c000000000000'O, omit }
470}
471
472private const CbchTestMsgs msgs_1m_2b_norm := {
473 { RSL_CB_CMD_NORMAL, 1, '001000320f1141660c344dd3cba09a0c000000000000'O &
474 '000102030405060708090a0b0c0d0e0f101213141516'O,
475 omit }
476}
477
478private const CbchTestMsgs msgs_1m_3b_norm := {
479 { RSL_CB_CMD_NORMAL, 2, '001000320f1141660c344dd3cba09a0c000000000000'O &
480 '000102030405060708090a0b0c0d0e0f101213141516'O &
481 '101112131415161718191a1b1c1d1e1f202223242526'O,
482 omit }
483}
484
485private const CbchTestMsgs msgs_1m_4b_norm := {
486 { RSL_CB_CMD_NORMAL, 3, '001000320f1141660c344dd3cba09a0c000000000000'O &
487 '000102030405060708090a0b0c0d0e0f101213141516'O &
488 '101112131415161718191a1b1c1d1e1f202223242526'O &
489 '202122232425262728292a2b2c2d2e2f303233343536'O,
490 omit }
491}
492
493private const CbchTestMsgs msgs_1m_4b_sched := {
494 { RSL_CB_CMD_SCHEDULE, 3, '001000320f1141660c344dd3cba09a0c000000000000'O &
495 '000102030405060708090a0b0c0d0e0f101213141516'O &
496 '101112131415161718191a1b1c1d1e1f202223242526'O &
497 '202122232425262728292a2b2c2d2e2f303233343536'O,
498 omit }
499}
500
Harald Weltee0026c32019-05-20 00:27:30 +0200501private const CbchTestMsgs msgs_3m_4b_norm := {
502 { RSL_CB_CMD_NORMAL, 3, '001000320f1141660c344dd3cba09a0c000000000000'O &
503 '000102030405060708090a0b0c0d0e0f101213141516'O &
504 '101112131415161718191a1b1c1d1e1f202223242526'O &
505 '201122232425262728292a2b2c2d2e2f303233343536'O,
506 omit },
507 { RSL_CB_CMD_NORMAL, 3, '002000320f1141660c344dd3cba09a0c000000000000'O &
508 '002102030405060708090a0b0c0d0e0f101213141516'O &
509 '102112131415161718191a1b1c1d1e1f202223242526'O &
510 '202122232425262728292a2b2c2d2e2f303233343536'O,
511 omit },
512 { RSL_CB_CMD_NORMAL, 3, '003000320f1141660c344dd3cba09a0c000000000000'O &
513 '003102030405060708090a0b0c0d0e0f101213141516'O &
514 '103112131415161718191a1b1c1d1e1f202223242526'O &
515 '203122232425262728292a2b2c2d2e2f303233343536'O,
516 omit }
517}
518
Harald Welte88e5dff2019-05-20 15:14:46 +0200519private const CbchTestMsgs msgs_1m_3b_default := {
520 { RSL_CB_CMD_DEFAULT, 2, '001000320f1141660c344dd3cba09a0c000000000000'O &
521 '000102030405060708090a0b0c0d0e0f101213141516'O &
522 '101112131415161718191a1b1c1d1e1f202223242526'O,
523 omit }
524}
Harald Weltea3ff6702019-05-20 20:03:50 +0200525private const CbchTestMsg msg_default := {
526 RSL_CB_CMD_DEFAULT, 0, '010203040506070708090a0b0c0d0e0f101112131415'O,
527 omit
528}
Harald Welte88e5dff2019-05-20 15:14:46 +0200529
Harald Welte505cf9b2018-09-15 17:47:23 +0300530/* transmit single-block SMSCB COMMAND */
531testcase TC_sms_cb_cmd_sdcch4_1block() runs on test_CT {
532 var CbchTestPars pars := {
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700533 chan_nr := valueof(ts_RslChanNr_CBCH4(0)),
Harald Weltea3ff6702019-05-20 20:03:50 +0200534 basic := valueof(t_CbchPC(msgs_1m_1b_norm)),
535 extended := omit
Harald Welte505cf9b2018-09-15 17:47:23 +0300536 };
537 f_TC_smscb(pars);
538}
539testcase TC_sms_cb_cmd_sdcch8_1block() runs on test_CT {
540 var CbchTestPars pars := {
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700541 chan_nr := valueof(ts_RslChanNr_CBCH8(2)),
Harald Weltea3ff6702019-05-20 20:03:50 +0200542 basic := valueof(t_CbchPC(msgs_1m_1b_norm)),
543 extended := omit
Harald Welte505cf9b2018-09-15 17:47:23 +0300544 };
545 f_TC_smscb(pars);
546}
547
548/* transmit dual-block SMSCB COMMAND */
549testcase TC_sms_cb_cmd_sdcch4_2block() runs on test_CT {
550 var CbchTestPars pars := {
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700551 chan_nr := valueof(ts_RslChanNr_CBCH4(0)),
Harald Weltea3ff6702019-05-20 20:03:50 +0200552 basic := valueof(t_CbchPC(msgs_1m_2b_norm)),
553 extended := omit
Harald Welte505cf9b2018-09-15 17:47:23 +0300554 };
555 f_TC_smscb(pars);
556}
557testcase TC_sms_cb_cmd_sdcch8_2block() runs on test_CT {
558 var CbchTestPars pars := {
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700559 chan_nr := valueof(ts_RslChanNr_CBCH8(2)),
Harald Weltea3ff6702019-05-20 20:03:50 +0200560 basic := valueof(t_CbchPC(msgs_1m_2b_norm)),
561 extended := omit
Harald Welte505cf9b2018-09-15 17:47:23 +0300562 };
563 f_TC_smscb(pars);
564}
565
566/* transmit triple-block SMSCB COMMAND */
567testcase TC_sms_cb_cmd_sdcch4_3block() runs on test_CT {
568 var CbchTestPars pars := {
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700569 chan_nr := valueof(ts_RslChanNr_CBCH4(0)),
Harald Weltea3ff6702019-05-20 20:03:50 +0200570 basic := valueof(t_CbchPC(msgs_1m_3b_norm)),
571 extended := omit
Harald Welte505cf9b2018-09-15 17:47:23 +0300572 };
573 f_TC_smscb(pars);
574}
575testcase TC_sms_cb_cmd_sdcch8_3block() runs on test_CT {
576 var CbchTestPars pars := {
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700577 chan_nr := valueof(ts_RslChanNr_CBCH8(2)),
Harald Weltea3ff6702019-05-20 20:03:50 +0200578 basic := valueof(t_CbchPC(msgs_1m_3b_norm)),
579 extended := omit
Harald Welte505cf9b2018-09-15 17:47:23 +0300580 };
581 f_TC_smscb(pars);
582}
583
584/* transmit quad-block SMSCB COMMAND */
585testcase TC_sms_cb_cmd_sdcch4_4block() runs on test_CT {
586 var CbchTestPars pars := {
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700587 chan_nr := valueof(ts_RslChanNr_CBCH4(0)),
Harald Weltea3ff6702019-05-20 20:03:50 +0200588 basic := valueof(t_CbchPC(msgs_1m_4b_norm)),
589 extended := omit
Harald Welte505cf9b2018-09-15 17:47:23 +0300590 };
591 f_TC_smscb(pars);
592}
593testcase TC_sms_cb_cmd_sdcch8_4block() runs on test_CT {
594 var CbchTestPars pars := {
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700595 chan_nr := valueof(ts_RslChanNr_CBCH8(2)),
Harald Weltea3ff6702019-05-20 20:03:50 +0200596 basic := valueof(t_CbchPC(msgs_1m_4b_norm)),
597 extended := omit
Harald Welte505cf9b2018-09-15 17:47:23 +0300598 };
599 f_TC_smscb(pars);
600}
601
Harald Weltee0026c32019-05-20 00:27:30 +0200602/* transmit multiple commands of each 4 blocks */
603testcase TC_sms_cb_cmd_sdcch4_multi() runs on test_CT {
604 var CbchTestPars pars := {
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700605 chan_nr := valueof(ts_RslChanNr_CBCH4(0)),
Harald Weltea3ff6702019-05-20 20:03:50 +0200606 basic := valueof(t_CbchPC(msgs_3m_4b_norm)),
607 extended := omit
Harald Weltee0026c32019-05-20 00:27:30 +0200608 };
609 f_TC_smscb(pars);
610}
611testcase TC_sms_cb_cmd_sdcch8_multi() runs on test_CT {
612 var CbchTestPars pars := {
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700613 chan_nr := valueof(ts_RslChanNr_CBCH8(2)),
Harald Weltea3ff6702019-05-20 20:03:50 +0200614 basic := valueof(t_CbchPC(msgs_3m_4b_norm)),
615 extended := omit
Harald Weltee0026c32019-05-20 00:27:30 +0200616 };
617 f_TC_smscb(pars);
618}
619
Harald Welte60bd92b2019-05-20 21:42:21 +0200620/* transmit multiple commands of each 4 blocks on CBCH EXTD */
621testcase TC_sms_cb_cmd_sdcch4_extd_multi() runs on test_CT {
622 var CbchTestPars pars := {
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700623 chan_nr := valueof(ts_RslChanNr_CBCH4(0)),
Harald Welte60bd92b2019-05-20 21:42:21 +0200624 basic := valueof(t_CbchPC({})),
625 extended := valueof(t_CbchPC(msgs_3m_4b_norm))
626 };
627 f_TC_smscb(pars);
628}
629testcase TC_sms_cb_cmd_sdcch8_extd_multi() runs on test_CT {
630 var CbchTestPars pars := {
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700631 chan_nr := valueof(ts_RslChanNr_CBCH8(2)),
Harald Welte60bd92b2019-05-20 21:42:21 +0200632 basic := valueof(t_CbchPC({})),
633 extended := valueof(t_CbchPC(msgs_3m_4b_norm))
634 };
635 f_TC_smscb(pars);
636}
637
Harald Welte505cf9b2018-09-15 17:47:23 +0300638/* transmit SMSCB COMMAND with SCHEDULE payload */
639testcase TC_sms_cb_cmd_sdcch4_schedule() runs on test_CT {
640 var CbchTestPars pars := {
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700641 chan_nr := valueof(ts_RslChanNr_CBCH4(0)),
Harald Weltea3ff6702019-05-20 20:03:50 +0200642 basic := valueof(t_CbchPC(msgs_1m_4b_sched)),
643 extended := omit
Harald Welte505cf9b2018-09-15 17:47:23 +0300644 };
645 f_TC_smscb(pars);
646}
647testcase TC_sms_cb_cmd_sdcch8_schedule() runs on test_CT {
648 var CbchTestPars pars := {
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700649 chan_nr := valueof(ts_RslChanNr_CBCH8(2)),
Harald Weltea3ff6702019-05-20 20:03:50 +0200650 basic := valueof(t_CbchPC(msgs_1m_4b_sched)),
651 extended := omit
Harald Welte505cf9b2018-09-15 17:47:23 +0300652 };
653 f_TC_smscb(pars);
654}
655
Harald Welte88e5dff2019-05-20 15:14:46 +0200656/* set a DEFAULT message; verify it gets transmitted all the time */
657testcase TC_sms_cb_cmd_sdcch4_default_only() runs on test_CT {
658 var CbchTestPars pars := {
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700659 chan_nr := valueof(ts_RslChanNr_CBCH4(0)),
Harald Weltea3ff6702019-05-20 20:03:50 +0200660 basic := valueof(t_CbchPC(msgs_1m_3b_default)),
661 extended := omit
Harald Welte88e5dff2019-05-20 15:14:46 +0200662 };
663 f_TC_smscb_default_only(pars);
664 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, pass);
665}
666testcase TC_sms_cb_cmd_sdcch8_default_only() runs on test_CT {
667 var CbchTestPars pars := {
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700668 chan_nr := valueof(ts_RslChanNr_CBCH4(0)),
Harald Weltea3ff6702019-05-20 20:03:50 +0200669 basic := valueof(t_CbchPC(msgs_1m_3b_default)),
670 extended := omit
Harald Welte88e5dff2019-05-20 15:14:46 +0200671 };
672 f_TC_smscb_default_only(pars);
673 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, pass);
674}
675
Harald Welted522ca02019-05-20 20:06:12 +0200676testcase TC_sms_cb_cmd_sdcch4_default_and_normal() runs on test_CT {
677 var CbchTestPars pars := {
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700678 chan_nr := valueof(ts_RslChanNr_CBCH4(0)),
Harald Welted522ca02019-05-20 20:06:12 +0200679 basic := valueof(t_CbchPC(msgs_1m_3b_norm, msg_default)),
680 extended := omit
681 };
682 f_TC_smscb(pars);
683}
684testcase TC_sms_cb_cmd_sdcch8_default_and_normal() runs on test_CT {
685 var CbchTestPars pars := {
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700686 chan_nr := valueof(ts_RslChanNr_CBCH8(2)),
Harald Welted522ca02019-05-20 20:06:12 +0200687 basic := valueof(t_CbchPC(msgs_1m_3b_norm, msg_default)),
688 extended := omit
689 };
690 f_TC_smscb(pars);
691}
692
Harald Weltedf4d0f02019-05-20 16:04:11 +0200693/* first set a DEFAULT message, then disable it again */
694testcase TC_sms_cb_cmd_sdcch4_default_then_null() runs on test_CT {
695 var CbchTestPars pars := {
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700696 chan_nr := valueof(ts_RslChanNr_CBCH4(0)),
Harald Weltea3ff6702019-05-20 20:03:50 +0200697 basic := valueof(t_CbchPC(msgs_1m_3b_default)),
698 extended := omit
Harald Weltedf4d0f02019-05-20 16:04:11 +0200699 };
Vadim Yanitskiyaf0aae62023-03-18 06:49:18 +0700700 var L1ctlMessage dl;
Harald Weltedf4d0f02019-05-20 16:04:11 +0200701 timer T := 5.0;
702
703 f_TC_smscb_default_only(pars);
704
705 /* disable DEFAULT message; switch back to NULL */
706 f_rsl_smscb_default_null();
707
708 /* ensure whatever initial non-NULL messages have all been drained */
709 f_sleep(5.0);
710 L1CTL.clear;
711
712 T.start;
713 alt {
Vadim Yanitskiyd4e95e82020-11-14 04:20:40 +0700714 [] L1CTL.receive(tr_L1CTL_DATA_IND(t_RslChanNr_CBCH4(0))) -> value dl {
Harald Weltedf4d0f02019-05-20 16:04:11 +0200715 log("CBCH: ", dl);
716 var CBCH_Block cb := dec_CBCH_Block(dl.payload.data_ind.payload);
717 /* detect the proper CBCH messages; check frame number */
718 f_cbch_fn_verify(dl.dl_info.frame_nr, cb);
719 if (not match(cb, tr_CBCH_Block)) {
720 setverdict(fail, "Illegal CBCH Block received: ", cb);
721 } else {
722 if (not match(cb, tr_CBCH_Block(15, ?, ?))) {
723 setverdict(fail, "Unexpected non-NULL CBCH block received");
724 }
725 repeat;
726 }
727 }
728 [] L1CTL.receive { repeat; }
729 [] T.timeout {
730 setverdict(pass);
731 }
732 }
733
734 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, pass);
735}
736
Harald Welte4a129f82019-05-21 16:35:22 +0200737/* Verify there are no CBCH load indications if no CBCH is present */
738testcase TC_cbch_load_idle_no_cbch() runs on test_CT {
739 var ASP_RSL_Unitdata rx_ud;
740 timer T := 10.0;
741
Harald Welte10474062019-05-30 16:48:17 +0200742 f_init();
Harald Welte4a129f82019-05-21 16:35:22 +0200743 f_init_vty_bsc();
744
745 T.start;
746 alt {
Vadim Yanitskiy493abe72020-05-25 22:03:48 +0700747 [] RSL_CCHAN.receive(tr_ASP_RSL_UD(tr_RSL_CBCH_LOAD_IND_BASIC)) -> value rx_ud {
Harald Welte4a129f82019-05-21 16:35:22 +0200748 setverdict(fail, "Received unexpected CBCH LOAD IND: ", rx_ud);
749 }
Vadim Yanitskiy493abe72020-05-25 22:03:48 +0700750 [] RSL_CCHAN.receive(tr_ASP_RSL_UD(tr_RSL_CBCH_LOAD_IND_EXTD)) -> value rx_ud {
Harald Welte4a129f82019-05-21 16:35:22 +0200751 setverdict(fail, "Received unexpected CBCH LOAD IND: ", rx_ud);
752 }
753 [] RSL_CCHAN.receive { repeat; }
754 [] T.timeout {
755 setverdict(pass);
756 }
757 }
758 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
759}
760
761/* Verify the CBCH load indications of an idle cell (without CBCH load) */
762function f_TC_cbc_load_idle() runs on test_CT {
763 template integer tr_slot_count := (2 .. 15);
764 const integer min_load_ind := 4;
765 var integer basic_count := 0;
766 var integer extd_count := 0;
767 var ASP_RSL_Unitdata rx_ud;
768 timer T := 10.0;
769
Harald Welte10474062019-05-30 16:48:17 +0200770 f_init();
Harald Welte4a129f82019-05-21 16:35:22 +0200771
772 RSL_CCHAN.clear;
773 T.start;
774 alt {
Vadim Yanitskiy493abe72020-05-25 22:03:48 +0700775 [] RSL_CCHAN.receive(tr_ASP_RSL_UD(tr_RSL_CBCH_LOAD_IND_BASIC(false, tr_slot_count))) {
Harald Welte4a129f82019-05-21 16:35:22 +0200776 basic_count := basic_count + 1;
777 repeat;
778 }
Vadim Yanitskiy493abe72020-05-25 22:03:48 +0700779 [] RSL_CCHAN.receive(tr_ASP_RSL_UD(tr_RSL_CBCH_LOAD_IND_EXTD(false, tr_slot_count))) -> value rx_ud {
Harald Welte4a129f82019-05-21 16:35:22 +0200780 extd_count := extd_count + 1;
781 repeat;
782 }
Vadim Yanitskiy493abe72020-05-25 22:03:48 +0700783 [] RSL_CCHAN.receive(tr_ASP_RSL_UD(tr_RSL_CBCH_LOAD_IND_BASIC)) -> value rx_ud {
Harald Welte4a129f82019-05-21 16:35:22 +0200784 setverdict(fail, "Received unexpected CBCH LOAD IND: ", rx_ud);
785 }
Vadim Yanitskiy493abe72020-05-25 22:03:48 +0700786 [] RSL_CCHAN.receive(tr_ASP_RSL_UD(tr_RSL_CBCH_LOAD_IND_EXTD)) -> value rx_ud {
Harald Welte4a129f82019-05-21 16:35:22 +0200787 setverdict(fail, "Received unexpected CBCH LOAD IND: ", rx_ud);
788 }
789 [] RSL_CCHAN.receive { repeat; }
790 [] T.timeout {
791 if ((basic_count >= min_load_ind) and (extd_count >= min_load_ind)) {
792 setverdict(pass);
793 } else {
794 setverdict(fail, "Insufficient number of CBCH LOAD IND: ",
795 "BASIC=", basic_count, " EXTD=", extd_count);
796 }
797 }
798 }
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700799
Harald Welte4a129f82019-05-21 16:35:22 +0200800 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
801}
802testcase TC_cbc_sdcch4_load_idle() runs on test_CT {
803 f_init_vty_bsc();
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700804 f_vty_cbch_setup(valueof(ts_RslChanNr_CBCH4(0)));
Harald Welte4a129f82019-05-21 16:35:22 +0200805 f_TC_cbc_load_idle();
806}
807testcase TC_cbc_sdcch8_load_idle() runs on test_CT {
808 f_init_vty_bsc();
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700809 f_vty_cbch_setup(valueof(ts_RslChanNr_CBCH8(2)));
Harald Welte4a129f82019-05-21 16:35:22 +0200810 f_TC_cbc_load_idle();
811}
812
813/* Verify CBCH overload indications are sent when sending too many SMS CB CMD */
814function f_TC_cbc_load_overload(CbchTestPars pars) runs on test_CT {
815 template integer tr_slot_count_basic := (11 .. 13);
816 template integer tr_slot_count_extd := (2 .. 15);
817 const integer min_load_ind := 4;
818 var integer basic_count := 0;
819 var integer extd_count := 0;
820 var ASP_RSL_Unitdata rx_ud;
821 timer T_total := 10.0;
822 timer T_retransmit := 0.2;
823 timer T_initial_guard := 2.0;
824 var integer i;
825
Harald Welte10474062019-05-30 16:48:17 +0200826 f_init();
Harald Welte4a129f82019-05-21 16:35:22 +0200827
828 /* send tons of SMSCB Command */
829 for (i := 0; i < 30; i := i+1) {
830 f_smscb_setup_rsl_chan(pars.basic);
831 }
832
833 /* keep sending SMSCB Commands for another two seconds */
834 T_initial_guard.start;
835 T_retransmit.start;
836 alt {
837 [] T_retransmit.timeout {
838 f_smscb_setup_rsl_chan(pars.basic);
839 T_retransmit.start;
840 repeat;
841 }
842 [] T_initial_guard.timeout { }
843 }
844 /* clear any pending messages (where load may not have peaked yet) */
845 RSL_CCHAN.clear;
846
847 /* keep sending SMSCB Commands while verifying LOAD INDICATIONS */
848 T_total.start;
849 T_retransmit.start;
850 alt {
Vadim Yanitskiy493abe72020-05-25 22:03:48 +0700851 [] RSL_CCHAN.receive(tr_ASP_RSL_UD(tr_RSL_CBCH_LOAD_IND_BASIC(true, tr_slot_count_basic))) {
Harald Welte4a129f82019-05-21 16:35:22 +0200852 basic_count := basic_count + 1;
853 repeat;
854 }
Vadim Yanitskiy493abe72020-05-25 22:03:48 +0700855 [] RSL_CCHAN.receive(tr_ASP_RSL_UD(tr_RSL_CBCH_LOAD_IND_EXTD(false, tr_slot_count_extd))) {
Harald Welte4a129f82019-05-21 16:35:22 +0200856 extd_count := extd_count + 1;
857 repeat;
858 }
Vadim Yanitskiy493abe72020-05-25 22:03:48 +0700859 [] RSL_CCHAN.receive(tr_ASP_RSL_UD(tr_RSL_CBCH_LOAD_IND_BASIC)) -> value rx_ud {
Harald Welte4a129f82019-05-21 16:35:22 +0200860 setverdict(fail, "Received unexpected CBCH LOAD IND: ", rx_ud);
861 }
Vadim Yanitskiy493abe72020-05-25 22:03:48 +0700862 [] RSL_CCHAN.receive(tr_ASP_RSL_UD(tr_RSL_CBCH_LOAD_IND_EXTD)) -> value rx_ud {
Harald Welte4a129f82019-05-21 16:35:22 +0200863 setverdict(fail, "Received unexpected CBCH LOAD IND: ", rx_ud);
864 }
865 [] RSL_CCHAN.receive { repeat; }
866 [] T_retransmit.timeout {
867 f_smscb_setup_rsl_chan(pars.basic);
868 T_retransmit.start;
869 repeat;
870 }
871 [] T_total.timeout {
872 if ((basic_count >= min_load_ind) and (extd_count >= min_load_ind)) {
873 setverdict(pass);
874 } else {
875 setverdict(fail, "Insufficient number of CBCH LOAD IND: ",
876 "BASIC=", basic_count, " EXTD=", extd_count);
877 }
878 }
879 }
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700880
Harald Welte4a129f82019-05-21 16:35:22 +0200881 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
882}
883testcase TC_cbc_sdcch4_load_overload() runs on test_CT {
884 var CbchTestPars pars := {
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700885 chan_nr := valueof(ts_RslChanNr_CBCH4(0)),
Harald Welte4a129f82019-05-21 16:35:22 +0200886 basic := valueof(t_CbchPC(msgs_1m_3b_norm)),
887 extended := omit
888 };
889
890 f_init_vty_bsc();
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700891 f_vty_cbch_setup(pars.chan_nr);
Harald Welte4a129f82019-05-21 16:35:22 +0200892 f_TC_cbc_load_overload(pars);
893}
894testcase TC_cbc_sdcch8_load_overload() runs on test_CT {
895 var CbchTestPars pars := {
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700896 chan_nr := valueof(ts_RslChanNr_CBCH4(2)),
Harald Welte4a129f82019-05-21 16:35:22 +0200897 basic := valueof(t_CbchPC(msgs_1m_3b_norm)),
898 extended := omit
899 };
900
901 f_init_vty_bsc();
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700902 f_vty_cbch_setup(pars.chan_nr);
Harald Welte4a129f82019-05-21 16:35:22 +0200903 f_TC_cbc_load_overload(pars);
904}
Harald Weltedf4d0f02019-05-20 16:04:11 +0200905
Harald Welte88e5dff2019-05-20 15:14:46 +0200906
Harald Welte908ce542019-09-04 23:05:40 +0200907private template GsmRrMessage tr_PagingType1 := {
908 header := t_RrHeader(PAGING_REQUEST_TYPE_1, ?),
909 payload :=?
910};
911
Harald Welte908ce542019-09-04 23:05:40 +0200912/* we expect four blocks of 14 bytes, let's fill them with content easily distinguishable */
913const octetstring c_etws_seg0 := '000102030405060708090a0b0c0d'O;
914const octetstring c_etws_seg1 := '101112131415161718191a1b1c1d'O;
915const octetstring c_etws_seg2 := '202122232425262728292a2b2c2d'O;
916const octetstring c_etws_seg3 := '303132333435363738393a3b3c3d'O;
917const octetstring c_etws := c_etws_seg0 & c_etws_seg1 & c_etws_seg2 & c_etws_seg3;
918
919/* Ensure only Paging Type 1 with segmented ETWS Primary Notification are sent after RSL_OSMO_ETWS_CMD */
920testcase TC_etws_p1ro() runs on test_CT {
Harald Welte908ce542019-09-04 23:05:40 +0200921 /* decoding the actual entire P1 rest octets by manually generated code is
922 * too much effort; instead simply do a binary compare to this constant */
923 const bitstring c_P1RO_hdr := '00101011101'B;
924 var integer seg_received[4] := { 0, 0, 0, 0 };
Vadim Yanitskiyaf0aae62023-03-18 06:49:18 +0700925 var L1ctlMessage dl;
Harald Welte908ce542019-09-04 23:05:40 +0200926 timer T := 10.0;
927
928 f_init();
929 f_init_l1ctl();
930 f_l1_tune(L1CTL, ccch_mode := CCCH_MODE_COMBINED_CBCH);
931
Vadim Yanitskiy493abe72020-05-25 22:03:48 +0700932 RSL_CCHAN.send(ts_ASP_RSL_UD(ts_RSL_OSMO_ETWS_CMD(c_etws)));
Harald Welte908ce542019-09-04 23:05:40 +0200933 /* wait for a bit until old non-ETWS Paging messages are gone */
934 f_sleep(1.0);
935 L1CTL.clear;
936 T.start;
937 alt {
Vadim Yanitskiyd4e95e82020-11-14 04:20:40 +0700938 [] L1CTL.receive(tr_L1CTL_DATA_IND(t_RslChanNr_PCH_AGCH(0))) -> value dl {
Harald Welte908ce542019-09-04 23:05:40 +0200939 var GsmRrMessage l3 := dec_GsmRrMessage(dl.payload.data_ind.payload);
940 select (l3) {
Vadim Yanitskiya9a198d2020-03-28 05:11:26 +0700941 case (tr_PAG_REQ1(tr_MI_LV(t_MI_NoIdentity()))) {
Harald Welte908ce542019-09-04 23:05:40 +0200942 var octetstring p1ro := l3.payload.pag_req_1.rest_octets;
943 var bitstring midamble := oct2bit(substr(p1ro, 0, 3));
944 var octetstring segment := substr(p1ro, 3, lengthof(p1ro)-3);
945 var BIT1 not_first := substr(midamble, 11, 1);
946 var integer seg_nr := bit2int(substr(midamble, 12, 4));
947 var boolean err := false;
948 if (substr(midamble, 0, 11) != c_P1RO_hdr) {
949 setverdict(fail, "Received unexpected P1 RO header ", midamble);
950 }
951 if (not_first == '1'B) {
952 select (seg_nr) {
953 case (2) {
954 if (segment != c_etws_seg1) {
955 err := true
956 } else {
957 seg_received[1] := seg_received[1] + 1;
958 }}
959 case (3) {
960 if (segment != c_etws_seg2) {
961 err := true
962 } else {
963 seg_received[2] := seg_received[2] + 1;
964 }}
965 case (4) {
966 if (segment != c_etws_seg3) {
967 err := true
968 } else {
969 seg_received[3] := seg_received[3] + 1;
970 }}
971 case else { setverdict(fail, "Unknown segment Nr ", seg_nr); }
972 }
973 if (err) {
974 setverdict(fail, "Unexpected segment ", seg_nr, ": ", segment);
975 }
976 } else {
977 if (seg_nr != 4) {
978 setverdict(fail, "Invalid number of segments ", seg_nr);
979 err := true;
980 }
981 if (segment != c_etws_seg0) {
982 setverdict(fail, "Invalid first segment ", segment);
983 err := true;
984 }
985 if (not err) {
986 seg_received[0] := seg_received[0] + 1;
987 }
988 }
989 }
990 case (tr_PagingType1) {
991 setverdict(fail, "Received unexpected PAGING TYPE 1: ", l3);
992 }
993 }
994 repeat;
995 }
996 [] L1CTL.receive { repeat; }
997 [] T.timeout {
998 setverdict(pass);
999 }
1000 }
1001 log("Quantity of received ETWS PN segments: ", seg_received);
1002 var integer i;
1003 for (i := 0; i < 4; i := i+1) {
1004 if (seg_received[i] < 15) {
1005 setverdict(fail, "Segment ", i, " not received often enough");
1006 }
1007 }
Vadim Yanitskiy79e15162021-06-24 01:25:59 +02001008
1009 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
Harald Welte908ce542019-09-04 23:05:40 +02001010}
1011
1012/* Ensure only Paging Type 1 without ETWS Primary Notification are sent after disabling them */
1013testcase TC_etws_p1ro_end() runs on test_CT {
Harald Welte908ce542019-09-04 23:05:40 +02001014 /* we expect four blocks of 14 bytes, let's fill them with content easily
1015 * distinguishable */
1016 /* decoding the actual entire P1 rest octets by manually generated code is
1017 * too much effort; instead simply do a binary compare to this constant */
1018 const bitstring c_P1RO_hdr := '00101011101'B;
Vadim Yanitskiyaf0aae62023-03-18 06:49:18 +07001019 var L1ctlMessage dl;
Harald Welte908ce542019-09-04 23:05:40 +02001020 timer T := 10.0;
1021
1022 f_init();
1023 f_init_l1ctl();
1024 f_l1_tune(L1CTL, ccch_mode := CCCH_MODE_COMBINED_CBCH);
1025
Vadim Yanitskiy493abe72020-05-25 22:03:48 +07001026 RSL_CCHAN.send(ts_ASP_RSL_UD(ts_RSL_OSMO_ETWS_CMD(c_etws)));
Harald Welte908ce542019-09-04 23:05:40 +02001027 /* wait for a bit until old non-ETWS Paging messages are gone */
1028 f_sleep(3.0);
1029 /* disable the ETWS PN again */
Vadim Yanitskiy493abe72020-05-25 22:03:48 +07001030 RSL_CCHAN.send(ts_ASP_RSL_UD(ts_RSL_OSMO_ETWS_CMD(''O)));
Harald Welte908ce542019-09-04 23:05:40 +02001031 f_sleep(2.0);
1032 T.start;
1033 L1CTL.clear;
1034 alt {
Vadim Yanitskiyd4e95e82020-11-14 04:20:40 +07001035 [] L1CTL.receive(tr_L1CTL_DATA_IND(t_RslChanNr_PCH_AGCH(0))) -> value dl {
Harald Welte908ce542019-09-04 23:05:40 +02001036 var GsmRrMessage l3 := dec_GsmRrMessage(dl.payload.data_ind.payload);
1037 select (l3) {
Vadim Yanitskiya9a198d2020-03-28 05:11:26 +07001038 case (tr_PAG_REQ1(tr_MI_LV(t_MI_NoIdentity()))) { repeat; }
Harald Welte908ce542019-09-04 23:05:40 +02001039 case (tr_PagingType1) {
1040 setverdict(fail, "Received non-empty PT1 after disabling ETWS PN: ", l3);
1041 }
1042 }
1043 repeat;
1044 }
1045 [] L1CTL.receive { repeat; }
1046 [] T.timeout {
1047 setverdict(pass);
1048 }
1049 }
Vadim Yanitskiy79e15162021-06-24 01:25:59 +02001050
1051 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
Harald Welte908ce542019-09-04 23:05:40 +02001052}
1053
Harald Welte11b734c2019-09-05 14:17:54 +02001054/* Ensure ETWS Primary Notification is passed from RSL to PCU interface */
1055testcase TC_etws_pcu() runs on test_CT {
1056 timer T := 10.0;
1057
Vadim Yanitskiyec9e9812021-03-21 23:02:44 +01001058 f_init_with_pcuif();
Harald Welte11b734c2019-09-05 14:17:54 +02001059 f_init_l1ctl();
1060 f_l1_tune(L1CTL, ccch_mode := CCCH_MODE_COMBINED_CBCH);
1061
Vadim Yanitskiy493abe72020-05-25 22:03:48 +07001062 RSL_CCHAN.send(ts_ASP_RSL_UD(ts_RSL_OSMO_ETWS_CMD(c_etws)));
Harald Welte11b734c2019-09-05 14:17:54 +02001063
1064 T.start;
1065 alt {
1066 [] PCU.receive(t_SD_PCUIF(g_pcu_conn_id, tr_PCUIF_APP_INFO_REQ(0, 0, c_etws))) {
1067 setverdict(pass);
1068 }
1069 [] PCU.receive(t_SD_PCUIF(g_pcu_conn_id, tr_PCUIF_APP_INFO_REQ(?, ?, ?))) {
1070 setverdict(fail, "PCU socket received invalid APP INFO");
1071 }
1072 [] PCU.receive { repeat; }
1073 [] T.timeout {
1074 setverdict(fail, "PCU socket timeout receiving APP INFO (ETWS)");
1075 }
1076 }
Vadim Yanitskiy79e15162021-06-24 01:25:59 +02001077
1078 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
Harald Welte11b734c2019-09-05 14:17:54 +02001079}
1080
1081
Harald Welte908ce542019-09-04 23:05:40 +02001082
Harald Welte505cf9b2018-09-15 17:47:23 +03001083/* SMSCB TODO:
1084 * multiple SMS BC CMD at the same time: Ensure all of them are sent exactly once
1085 * extended CBCH vs. normal CBCH
1086 *
1087 */
1088
1089control {
Harald Welte4a129f82019-05-21 16:35:22 +02001090 execute( TC_cbch_load_idle_no_cbch() );
1091
Harald Welte505cf9b2018-09-15 17:47:23 +03001092 execute( TC_sms_cb_cmd_sdcch4_1block() );
1093 execute( TC_sms_cb_cmd_sdcch4_2block() );
1094 execute( TC_sms_cb_cmd_sdcch4_3block() );
1095 execute( TC_sms_cb_cmd_sdcch4_4block() );
Harald Weltee0026c32019-05-20 00:27:30 +02001096 execute( TC_sms_cb_cmd_sdcch4_multi() );
Harald Welte505cf9b2018-09-15 17:47:23 +03001097 execute( TC_sms_cb_cmd_sdcch4_schedule() );
Harald Welte88e5dff2019-05-20 15:14:46 +02001098 execute( TC_sms_cb_cmd_sdcch4_default_only() );
Harald Welted522ca02019-05-20 20:06:12 +02001099 execute( TC_sms_cb_cmd_sdcch4_default_and_normal() );
Harald Weltedf4d0f02019-05-20 16:04:11 +02001100 execute( TC_sms_cb_cmd_sdcch4_default_then_null() );
Harald Welte4a129f82019-05-21 16:35:22 +02001101 execute( TC_cbc_sdcch4_load_idle() );
1102 execute( TC_cbc_sdcch4_load_overload() );
1103
Harald Welte505cf9b2018-09-15 17:47:23 +03001104 execute( TC_sms_cb_cmd_sdcch8_1block() );
1105 execute( TC_sms_cb_cmd_sdcch8_2block() );
1106 execute( TC_sms_cb_cmd_sdcch8_3block() );
1107 execute( TC_sms_cb_cmd_sdcch8_4block() );
Harald Weltee0026c32019-05-20 00:27:30 +02001108 execute( TC_sms_cb_cmd_sdcch8_multi() );
Harald Welte505cf9b2018-09-15 17:47:23 +03001109 execute( TC_sms_cb_cmd_sdcch8_schedule() );
Harald Welte88e5dff2019-05-20 15:14:46 +02001110 execute( TC_sms_cb_cmd_sdcch8_default_only() );
Harald Welted522ca02019-05-20 20:06:12 +02001111 execute( TC_sms_cb_cmd_sdcch8_default_and_normal() );
Harald Welte4a129f82019-05-21 16:35:22 +02001112 execute( TC_cbc_sdcch8_load_idle() );
1113 execute( TC_cbc_sdcch8_load_overload() );
Harald Welte908ce542019-09-04 23:05:40 +02001114
1115 execute( TC_etws_p1ro() );
1116 execute( TC_etws_p1ro_end() );
Harald Welte11b734c2019-09-05 14:17:54 +02001117 execute( TC_etws_pcu() );
Harald Welte505cf9b2018-09-15 17:47:23 +03001118}
1119
1120
1121}