blob: 5f06f04461e85ae7fe8300eead43922caad62344 [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) {
262 L1CTL.send(ts_L1CTL_DM_EST_REQ_H1(pars.chan_nr,
263 7 /* TODO: mp_tsc */,
264 pars.fhp.maio_hsn.hsn,
265 pars.fhp.maio_hsn.maio,
266 pars.fhp.ma));
267 } else {
268 L1CTL.send(ts_L1CTL_DM_EST_REQ_H0(pars.chan_nr,
269 7 /* TODO: mp_tsc */,
Vadim Yanitskiy42d8bd52020-11-15 20:41:02 +0700270 mp_trx_pars[0].arfcn));
Vadim Yanitskiy7fefcee2020-09-12 20:04:08 +0700271 }
Vadim Yanitskiyf1c95c82020-07-31 06:43:57 +0700272 }
Harald Welte505cf9b2018-09-15 17:47:23 +0300273
274 /* send SMSCB[s] via RSL */
Harald Weltea3ff6702019-05-20 20:03:50 +0200275 f_smscb_setup_rsl_chan(pars.basic, false);
276 if (ispresent(pars.extended)) {
277 f_smscb_setup_rsl_chan(pars.extended, true);
Harald Welte505cf9b2018-09-15 17:47:23 +0300278 }
Harald Welte88e5dff2019-05-20 15:14:46 +0200279}
280
Harald Weltea3ff6702019-05-20 20:03:50 +0200281/* construct a receive/match template for given block_nr in given msg */
282private function f_get_block_template(CbchTestMsg msg, integer block_nr) return template CBCH_Block {
283 var template CBCH_Block tr;
284 if (block_nr < lengthof(msg.blocks)) {
285 var CbchBlock b := msg.blocks[block_nr];
286 tr := tr_CBCH_Block(b.seq_nr, b.is_last, b.payload);
287 } else {
288 tr := tr_CBCH_Block(15, ?, ?);
289 }
290 return tr;
291}
292
293/* the heart of the CBCH test case matching engine for one channel (basic, extended) */
294private function f_cbch_match(inout CbchTestParsChan pars_chan, CBCH_Block cb, integer tb)
295{
296 var integer block_nr := tb mod 4;
297 var integer i;
298
299 if (not match(cb, tr_CBCH_Block)) {
300 setverdict(fail, "Illegal CBCH Block received: ", cb);
301 } else {
302 var boolean matched := false;
303 /* check if it's any of our expected blocks */
304 for (i := 0; i < lengthof(pars_chan.msgs); i := i+1) {
305 if (block_nr < lengthof(pars_chan.msgs[i].blocks)) {
306 if (match(cb, f_get_block_template(pars_chan.msgs[i], block_nr))) {
307 log("Found block_nr ", block_nr, " of msg ", i);
308 if (not pars_chan.msgs[i].blocks[block_nr].seen_once) {
309 pars_chan.msgs[i].blocks[block_nr].seen_once := true;
310 setverdict(pass);
311 } else {
312 setverdict(fail, "Received SMSCB twice! ", cb);
313 }
314 matched := true;
315 break;
316 }
317 }
318 }
319 if (not matched) {
320 var template CBCH_Block tr;
321 if (ispresent(pars_chan.default_msg)) {
322 /* it must be a block of the default message */
323 tr := f_get_block_template(pars_chan.default_msg, block_nr);
324 } else {
325 /* it must be a NULL block */
326 tr := tr_CBCH_Block(15, ?, ?);
327 }
328 if (not match(cb, tr)) {
329 setverdict(fail, "Received unexpected CBCH block: ", cb);
330 } else {
331 log("Found block_nr ", block_nr, " of DEFAULT/NULL");
332 if (ispresent(pars_chan.default_msg) and
333 block_nr < lengthof(pars_chan.default_msg.blocks)) {
334 pars_chan.default_msg.blocks[block_nr].seen_once := true;
335 }
336 }
337 }
338 }
339}
340
341/* Report/Evaluate the per-channel CBCH test results */
342private function f_cbch_report(CbchTestParsChan pars_chan, charstring id)
343{
344 var integer i, j;
345
346 /* verify that each block of each message has been seen once */
347 for (i := 0; i < lengthof(pars_chan.msgs); i := i+1) {
348 for (j := 0; j < lengthof(pars_chan.msgs[i].blocks); j := j+1) {
349 var CbchBlock b := pars_chan.msgs[i].blocks[j];
350 if (not b.seen_once) {
351 setverdict(fail, "Timeout waiting for ", id, " CBCH block ",
352 j, " of msg ", i);
353 }
354 }
355 }
356 if (ispresent(pars_chan.default_msg)) {
357 /* verify that each block of default message has been seen at least once */
358 for (j := 0; j < lengthof(pars_chan.default_msg.blocks); j := j+1) {
359 var CbchBlock b := pars_chan.default_msg.blocks[j];
360 if (not b.seen_once) {
361 setverdict(fail, "Timeout waiting for at leaset one instance of ",
362 "CBCH block ", j, " of DEFAULT msg");
363 }
364 }
365 }
366}
367
Harald Welte88e5dff2019-05-20 15:14:46 +0200368/* shared function doing the heavy lifting for most CBCH tests */
369private function f_TC_smscb(CbchTestPars pars) runs on test_CT {
370 var L1ctlDlMessage dl;
Harald Weltea3ff6702019-05-20 20:03:50 +0200371 var integer msg_count;
372 timer T;
373
374 msg_count := lengthof(pars.basic.msgs);
375 if (ispresent(pars.basic.default_msg)) {
376 msg_count := msg_count + 1;
377 }
378 if (ispresent(pars.extended)) {
379 msg_count := msg_count + lengthof(pars.extended.msgs);
380 if (ispresent(pars.extended.default_msg)) {
381 msg_count := msg_count + 1;
382 }
383 }
Harald Welte88e5dff2019-05-20 15:14:46 +0200384
385 f_smscb_setup(pars);
386
Harald Weltea3ff6702019-05-20 20:03:50 +0200387 /* dynamically adjust timeout based on number of messages */
388 T.start(5.0 + 3.0 * int2float(msg_count));
Harald Welte505cf9b2018-09-15 17:47:23 +0300389 /* Expect this to show up exactly once on the basic CBCH (four blocks) */
390 alt {
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700391 [] L1CTL.receive(tr_L1CTL_DATA_IND(pars.chan_nr)) -> value dl {
Harald Weltea3ff6702019-05-20 20:03:50 +0200392 var integer tb := f_cbch_fn2tb(dl.dl_info.frame_nr);
Harald Welte505cf9b2018-09-15 17:47:23 +0300393 var CBCH_Block cb := dec_CBCH_Block(dl.payload.data_ind.payload);
Harald Weltea3ff6702019-05-20 20:03:50 +0200394 log("Tb=", tb, ", CBCH: ", dl, ", block: ", cb);
395
Harald Welte505cf9b2018-09-15 17:47:23 +0300396 /* detect the proper CBCH messages; check frame number */
397 f_cbch_fn_verify(dl.dl_info.frame_nr, cb);
Harald Weltea3ff6702019-05-20 20:03:50 +0200398
399 if (tb < 4) {
400 f_cbch_match(pars.basic, cb, tb);
Harald Welte505cf9b2018-09-15 17:47:23 +0300401 } else {
Harald Weltea3ff6702019-05-20 20:03:50 +0200402 if (not ispresent(pars.extended)) {
403 /* no parameters for ext. BCCH given: ignore */
404 repeat;
Harald Welte505cf9b2018-09-15 17:47:23 +0300405 }
Harald Weltea3ff6702019-05-20 20:03:50 +0200406 f_cbch_match(pars.extended, cb, tb);
Harald Welte505cf9b2018-09-15 17:47:23 +0300407 }
Harald Weltea3ff6702019-05-20 20:03:50 +0200408 repeat;
Harald Welte505cf9b2018-09-15 17:47:23 +0300409 }
410 [] L1CTL.receive { repeat; }
411 [] T.timeout {
Harald Weltea3ff6702019-05-20 20:03:50 +0200412 f_cbch_report(pars.basic, "Basic");
413 if (ispresent(pars.extended)) {
414 f_cbch_report(pars.extended, "Extended");
Harald Welte505cf9b2018-09-15 17:47:23 +0300415 }
416 }
417 }
418
Harald Welte88e5dff2019-05-20 15:14:46 +0200419 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, pass);
420}
421
422private function f_TC_smscb_default_only(CbchTestPars pars) runs on test_CT {
423 var L1ctlDlMessage dl;
424 timer T := 5.0;
425
426 f_smscb_setup(pars);
427
428 /* ensure whatever initial NULL messages have all been drained */
429 f_sleep(5.0);
430 L1CTL.clear;
431
432 T.start;
433 alt {
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700434 [] L1CTL.receive(tr_L1CTL_DATA_IND(pars.chan_nr)) -> value dl {
Harald Welte88e5dff2019-05-20 15:14:46 +0200435 var integer tb := f_cbch_fn2tb(dl.dl_info.frame_nr);
436 log("CBCH: ", dl);
437 var CBCH_Block cb := dec_CBCH_Block(dl.payload.data_ind.payload);
438 /* detect the proper CBCH messages; check frame number */
439 f_cbch_fn_verify(dl.dl_info.frame_nr, cb);
440 if (tb >= 4) {
441 /* skip extended CBCH for now */
442 repeat;
443 }
444 if (not match(cb, tr_CBCH_Block)) {
445 setverdict(fail, "Illegal CBCH Block received: ", cb);
446 } else {
447 var uint4_t rx_seq_nr := cb.block_type.seq_nr;
448 var template CBCH_Block tr;
Harald Weltea3ff6702019-05-20 20:03:50 +0200449 if (rx_seq_nr < lengthof(pars.basic.msgs[0].blocks)) {
450 var CbchBlock b := pars.basic.msgs[0].blocks[rx_seq_nr];
Harald Welte88e5dff2019-05-20 15:14:46 +0200451 tr := tr_CBCH_Block(b.seq_nr, b.is_last, b.payload);
452 } else {
453 tr := tr_CBCH_Block(15, ?, ?);
454 }
455 if (match(cb, tr)) {
456 setverdict(pass); /* FIXME: check that all blocks are received? */
457 repeat;
458 } else {
459 setverdict(fail, "Unexpected CBCH block ", cb, ", expected ", tr);
460 }
461 }
462 }
463 [] L1CTL.receive { repeat; }
464 [] T.timeout {}
465 }
466
Harald Welte88e5dff2019-05-20 15:14:46 +0200467 /* don't shut down; some tests still want to continue */
Harald Welte505cf9b2018-09-15 17:47:23 +0300468}
469
470private const CbchTestMsgs msgs_1m_1b_norm := {
471 { RSL_CB_CMD_NORMAL, 0, '001000320f1141660c344dd3cba09a0c000000000000'O, omit }
472}
473
474private const CbchTestMsgs msgs_1m_2b_norm := {
475 { RSL_CB_CMD_NORMAL, 1, '001000320f1141660c344dd3cba09a0c000000000000'O &
476 '000102030405060708090a0b0c0d0e0f101213141516'O,
477 omit }
478}
479
480private const CbchTestMsgs msgs_1m_3b_norm := {
481 { RSL_CB_CMD_NORMAL, 2, '001000320f1141660c344dd3cba09a0c000000000000'O &
482 '000102030405060708090a0b0c0d0e0f101213141516'O &
483 '101112131415161718191a1b1c1d1e1f202223242526'O,
484 omit }
485}
486
487private const CbchTestMsgs msgs_1m_4b_norm := {
488 { RSL_CB_CMD_NORMAL, 3, '001000320f1141660c344dd3cba09a0c000000000000'O &
489 '000102030405060708090a0b0c0d0e0f101213141516'O &
490 '101112131415161718191a1b1c1d1e1f202223242526'O &
491 '202122232425262728292a2b2c2d2e2f303233343536'O,
492 omit }
493}
494
495private const CbchTestMsgs msgs_1m_4b_sched := {
496 { RSL_CB_CMD_SCHEDULE, 3, '001000320f1141660c344dd3cba09a0c000000000000'O &
497 '000102030405060708090a0b0c0d0e0f101213141516'O &
498 '101112131415161718191a1b1c1d1e1f202223242526'O &
499 '202122232425262728292a2b2c2d2e2f303233343536'O,
500 omit }
501}
502
Harald Weltee0026c32019-05-20 00:27:30 +0200503private const CbchTestMsgs msgs_3m_4b_norm := {
504 { RSL_CB_CMD_NORMAL, 3, '001000320f1141660c344dd3cba09a0c000000000000'O &
505 '000102030405060708090a0b0c0d0e0f101213141516'O &
506 '101112131415161718191a1b1c1d1e1f202223242526'O &
507 '201122232425262728292a2b2c2d2e2f303233343536'O,
508 omit },
509 { RSL_CB_CMD_NORMAL, 3, '002000320f1141660c344dd3cba09a0c000000000000'O &
510 '002102030405060708090a0b0c0d0e0f101213141516'O &
511 '102112131415161718191a1b1c1d1e1f202223242526'O &
512 '202122232425262728292a2b2c2d2e2f303233343536'O,
513 omit },
514 { RSL_CB_CMD_NORMAL, 3, '003000320f1141660c344dd3cba09a0c000000000000'O &
515 '003102030405060708090a0b0c0d0e0f101213141516'O &
516 '103112131415161718191a1b1c1d1e1f202223242526'O &
517 '203122232425262728292a2b2c2d2e2f303233343536'O,
518 omit }
519}
520
Harald Welte88e5dff2019-05-20 15:14:46 +0200521private const CbchTestMsgs msgs_1m_3b_default := {
522 { RSL_CB_CMD_DEFAULT, 2, '001000320f1141660c344dd3cba09a0c000000000000'O &
523 '000102030405060708090a0b0c0d0e0f101213141516'O &
524 '101112131415161718191a1b1c1d1e1f202223242526'O,
525 omit }
526}
Harald Weltea3ff6702019-05-20 20:03:50 +0200527private const CbchTestMsg msg_default := {
528 RSL_CB_CMD_DEFAULT, 0, '010203040506070708090a0b0c0d0e0f101112131415'O,
529 omit
530}
Harald Welte88e5dff2019-05-20 15:14:46 +0200531
Harald Welte505cf9b2018-09-15 17:47:23 +0300532/* transmit single-block SMSCB COMMAND */
533testcase TC_sms_cb_cmd_sdcch4_1block() runs on test_CT {
534 var CbchTestPars pars := {
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700535 chan_nr := valueof(ts_RslChanNr_CBCH4(0)),
Harald Weltea3ff6702019-05-20 20:03:50 +0200536 basic := valueof(t_CbchPC(msgs_1m_1b_norm)),
537 extended := omit
Harald Welte505cf9b2018-09-15 17:47:23 +0300538 };
539 f_TC_smscb(pars);
540}
541testcase TC_sms_cb_cmd_sdcch8_1block() runs on test_CT {
542 var CbchTestPars pars := {
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700543 chan_nr := valueof(ts_RslChanNr_CBCH8(2)),
Harald Weltea3ff6702019-05-20 20:03:50 +0200544 basic := valueof(t_CbchPC(msgs_1m_1b_norm)),
545 extended := omit
Harald Welte505cf9b2018-09-15 17:47:23 +0300546 };
547 f_TC_smscb(pars);
548}
549
550/* transmit dual-block SMSCB COMMAND */
551testcase TC_sms_cb_cmd_sdcch4_2block() runs on test_CT {
552 var CbchTestPars pars := {
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700553 chan_nr := valueof(ts_RslChanNr_CBCH4(0)),
Harald Weltea3ff6702019-05-20 20:03:50 +0200554 basic := valueof(t_CbchPC(msgs_1m_2b_norm)),
555 extended := omit
Harald Welte505cf9b2018-09-15 17:47:23 +0300556 };
557 f_TC_smscb(pars);
558}
559testcase TC_sms_cb_cmd_sdcch8_2block() runs on test_CT {
560 var CbchTestPars pars := {
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700561 chan_nr := valueof(ts_RslChanNr_CBCH8(2)),
Harald Weltea3ff6702019-05-20 20:03:50 +0200562 basic := valueof(t_CbchPC(msgs_1m_2b_norm)),
563 extended := omit
Harald Welte505cf9b2018-09-15 17:47:23 +0300564 };
565 f_TC_smscb(pars);
566}
567
568/* transmit triple-block SMSCB COMMAND */
569testcase TC_sms_cb_cmd_sdcch4_3block() runs on test_CT {
570 var CbchTestPars pars := {
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700571 chan_nr := valueof(ts_RslChanNr_CBCH4(0)),
Harald Weltea3ff6702019-05-20 20:03:50 +0200572 basic := valueof(t_CbchPC(msgs_1m_3b_norm)),
573 extended := omit
Harald Welte505cf9b2018-09-15 17:47:23 +0300574 };
575 f_TC_smscb(pars);
576}
577testcase TC_sms_cb_cmd_sdcch8_3block() runs on test_CT {
578 var CbchTestPars pars := {
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700579 chan_nr := valueof(ts_RslChanNr_CBCH8(2)),
Harald Weltea3ff6702019-05-20 20:03:50 +0200580 basic := valueof(t_CbchPC(msgs_1m_3b_norm)),
581 extended := omit
Harald Welte505cf9b2018-09-15 17:47:23 +0300582 };
583 f_TC_smscb(pars);
584}
585
586/* transmit quad-block SMSCB COMMAND */
587testcase TC_sms_cb_cmd_sdcch4_4block() runs on test_CT {
588 var CbchTestPars pars := {
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700589 chan_nr := valueof(ts_RslChanNr_CBCH4(0)),
Harald Weltea3ff6702019-05-20 20:03:50 +0200590 basic := valueof(t_CbchPC(msgs_1m_4b_norm)),
591 extended := omit
Harald Welte505cf9b2018-09-15 17:47:23 +0300592 };
593 f_TC_smscb(pars);
594}
595testcase TC_sms_cb_cmd_sdcch8_4block() runs on test_CT {
596 var CbchTestPars pars := {
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700597 chan_nr := valueof(ts_RslChanNr_CBCH8(2)),
Harald Weltea3ff6702019-05-20 20:03:50 +0200598 basic := valueof(t_CbchPC(msgs_1m_4b_norm)),
599 extended := omit
Harald Welte505cf9b2018-09-15 17:47:23 +0300600 };
601 f_TC_smscb(pars);
602}
603
Harald Weltee0026c32019-05-20 00:27:30 +0200604/* transmit multiple commands of each 4 blocks */
605testcase TC_sms_cb_cmd_sdcch4_multi() runs on test_CT {
606 var CbchTestPars pars := {
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700607 chan_nr := valueof(ts_RslChanNr_CBCH4(0)),
Harald Weltea3ff6702019-05-20 20:03:50 +0200608 basic := valueof(t_CbchPC(msgs_3m_4b_norm)),
609 extended := omit
Harald Weltee0026c32019-05-20 00:27:30 +0200610 };
611 f_TC_smscb(pars);
612}
613testcase TC_sms_cb_cmd_sdcch8_multi() runs on test_CT {
614 var CbchTestPars pars := {
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700615 chan_nr := valueof(ts_RslChanNr_CBCH8(2)),
Harald Weltea3ff6702019-05-20 20:03:50 +0200616 basic := valueof(t_CbchPC(msgs_3m_4b_norm)),
617 extended := omit
Harald Weltee0026c32019-05-20 00:27:30 +0200618 };
619 f_TC_smscb(pars);
620}
621
Harald Welte60bd92b2019-05-20 21:42:21 +0200622/* transmit multiple commands of each 4 blocks on CBCH EXTD */
623testcase TC_sms_cb_cmd_sdcch4_extd_multi() runs on test_CT {
624 var CbchTestPars pars := {
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700625 chan_nr := valueof(ts_RslChanNr_CBCH4(0)),
Harald Welte60bd92b2019-05-20 21:42:21 +0200626 basic := valueof(t_CbchPC({})),
627 extended := valueof(t_CbchPC(msgs_3m_4b_norm))
628 };
629 f_TC_smscb(pars);
630}
631testcase TC_sms_cb_cmd_sdcch8_extd_multi() runs on test_CT {
632 var CbchTestPars pars := {
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700633 chan_nr := valueof(ts_RslChanNr_CBCH8(2)),
Harald Welte60bd92b2019-05-20 21:42:21 +0200634 basic := valueof(t_CbchPC({})),
635 extended := valueof(t_CbchPC(msgs_3m_4b_norm))
636 };
637 f_TC_smscb(pars);
638}
639
Harald Welte505cf9b2018-09-15 17:47:23 +0300640/* transmit SMSCB COMMAND with SCHEDULE payload */
641testcase TC_sms_cb_cmd_sdcch4_schedule() runs on test_CT {
642 var CbchTestPars pars := {
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700643 chan_nr := valueof(ts_RslChanNr_CBCH4(0)),
Harald Weltea3ff6702019-05-20 20:03:50 +0200644 basic := valueof(t_CbchPC(msgs_1m_4b_sched)),
645 extended := omit
Harald Welte505cf9b2018-09-15 17:47:23 +0300646 };
647 f_TC_smscb(pars);
648}
649testcase TC_sms_cb_cmd_sdcch8_schedule() runs on test_CT {
650 var CbchTestPars pars := {
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700651 chan_nr := valueof(ts_RslChanNr_CBCH8(2)),
Harald Weltea3ff6702019-05-20 20:03:50 +0200652 basic := valueof(t_CbchPC(msgs_1m_4b_sched)),
653 extended := omit
Harald Welte505cf9b2018-09-15 17:47:23 +0300654 };
655 f_TC_smscb(pars);
656}
657
Harald Welte88e5dff2019-05-20 15:14:46 +0200658/* set a DEFAULT message; verify it gets transmitted all the time */
659testcase TC_sms_cb_cmd_sdcch4_default_only() runs on test_CT {
660 var CbchTestPars pars := {
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700661 chan_nr := valueof(ts_RslChanNr_CBCH4(0)),
Harald Weltea3ff6702019-05-20 20:03:50 +0200662 basic := valueof(t_CbchPC(msgs_1m_3b_default)),
663 extended := omit
Harald Welte88e5dff2019-05-20 15:14:46 +0200664 };
665 f_TC_smscb_default_only(pars);
666 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, pass);
667}
668testcase TC_sms_cb_cmd_sdcch8_default_only() runs on test_CT {
669 var CbchTestPars pars := {
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700670 chan_nr := valueof(ts_RslChanNr_CBCH4(0)),
Harald Weltea3ff6702019-05-20 20:03:50 +0200671 basic := valueof(t_CbchPC(msgs_1m_3b_default)),
672 extended := omit
Harald Welte88e5dff2019-05-20 15:14:46 +0200673 };
674 f_TC_smscb_default_only(pars);
675 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, pass);
676}
677
Harald Welted522ca02019-05-20 20:06:12 +0200678testcase TC_sms_cb_cmd_sdcch4_default_and_normal() runs on test_CT {
679 var CbchTestPars pars := {
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700680 chan_nr := valueof(ts_RslChanNr_CBCH4(0)),
Harald Welted522ca02019-05-20 20:06:12 +0200681 basic := valueof(t_CbchPC(msgs_1m_3b_norm, msg_default)),
682 extended := omit
683 };
684 f_TC_smscb(pars);
685}
686testcase TC_sms_cb_cmd_sdcch8_default_and_normal() runs on test_CT {
687 var CbchTestPars pars := {
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700688 chan_nr := valueof(ts_RslChanNr_CBCH8(2)),
Harald Welted522ca02019-05-20 20:06:12 +0200689 basic := valueof(t_CbchPC(msgs_1m_3b_norm, msg_default)),
690 extended := omit
691 };
692 f_TC_smscb(pars);
693}
694
Harald Weltedf4d0f02019-05-20 16:04:11 +0200695/* first set a DEFAULT message, then disable it again */
696testcase TC_sms_cb_cmd_sdcch4_default_then_null() runs on test_CT {
697 var CbchTestPars pars := {
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700698 chan_nr := valueof(ts_RslChanNr_CBCH4(0)),
Harald Weltea3ff6702019-05-20 20:03:50 +0200699 basic := valueof(t_CbchPC(msgs_1m_3b_default)),
700 extended := omit
Harald Weltedf4d0f02019-05-20 16:04:11 +0200701 };
702 var L1ctlDlMessage dl;
703 timer T := 5.0;
704
705 f_TC_smscb_default_only(pars);
706
707 /* disable DEFAULT message; switch back to NULL */
708 f_rsl_smscb_default_null();
709
710 /* ensure whatever initial non-NULL messages have all been drained */
711 f_sleep(5.0);
712 L1CTL.clear;
713
714 T.start;
715 alt {
Vadim Yanitskiyd4e95e82020-11-14 04:20:40 +0700716 [] L1CTL.receive(tr_L1CTL_DATA_IND(t_RslChanNr_CBCH4(0))) -> value dl {
Harald Weltedf4d0f02019-05-20 16:04:11 +0200717 log("CBCH: ", dl);
718 var CBCH_Block cb := dec_CBCH_Block(dl.payload.data_ind.payload);
719 /* detect the proper CBCH messages; check frame number */
720 f_cbch_fn_verify(dl.dl_info.frame_nr, cb);
721 if (not match(cb, tr_CBCH_Block)) {
722 setverdict(fail, "Illegal CBCH Block received: ", cb);
723 } else {
724 if (not match(cb, tr_CBCH_Block(15, ?, ?))) {
725 setverdict(fail, "Unexpected non-NULL CBCH block received");
726 }
727 repeat;
728 }
729 }
730 [] L1CTL.receive { repeat; }
731 [] T.timeout {
732 setverdict(pass);
733 }
734 }
735
736 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, pass);
737}
738
Harald Welte4a129f82019-05-21 16:35:22 +0200739/* Verify there are no CBCH load indications if no CBCH is present */
740testcase TC_cbch_load_idle_no_cbch() runs on test_CT {
741 var ASP_RSL_Unitdata rx_ud;
742 timer T := 10.0;
743
Harald Welte10474062019-05-30 16:48:17 +0200744 f_init();
Harald Welte4a129f82019-05-21 16:35:22 +0200745 f_init_vty_bsc();
746
747 T.start;
748 alt {
Vadim Yanitskiy493abe72020-05-25 22:03:48 +0700749 [] RSL_CCHAN.receive(tr_ASP_RSL_UD(tr_RSL_CBCH_LOAD_IND_BASIC)) -> value rx_ud {
Harald Welte4a129f82019-05-21 16:35:22 +0200750 setverdict(fail, "Received unexpected CBCH LOAD IND: ", rx_ud);
751 }
Vadim Yanitskiy493abe72020-05-25 22:03:48 +0700752 [] RSL_CCHAN.receive(tr_ASP_RSL_UD(tr_RSL_CBCH_LOAD_IND_EXTD)) -> value rx_ud {
Harald Welte4a129f82019-05-21 16:35:22 +0200753 setverdict(fail, "Received unexpected CBCH LOAD IND: ", rx_ud);
754 }
755 [] RSL_CCHAN.receive { repeat; }
756 [] T.timeout {
757 setverdict(pass);
758 }
759 }
760 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
761}
762
763/* Verify the CBCH load indications of an idle cell (without CBCH load) */
764function f_TC_cbc_load_idle() runs on test_CT {
765 template integer tr_slot_count := (2 .. 15);
766 const integer min_load_ind := 4;
767 var integer basic_count := 0;
768 var integer extd_count := 0;
769 var ASP_RSL_Unitdata rx_ud;
770 timer T := 10.0;
771
Harald Welte10474062019-05-30 16:48:17 +0200772 f_init();
Harald Welte4a129f82019-05-21 16:35:22 +0200773
774 RSL_CCHAN.clear;
775 T.start;
776 alt {
Vadim Yanitskiy493abe72020-05-25 22:03:48 +0700777 [] RSL_CCHAN.receive(tr_ASP_RSL_UD(tr_RSL_CBCH_LOAD_IND_BASIC(false, tr_slot_count))) {
Harald Welte4a129f82019-05-21 16:35:22 +0200778 basic_count := basic_count + 1;
779 repeat;
780 }
Vadim Yanitskiy493abe72020-05-25 22:03:48 +0700781 [] 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 +0200782 extd_count := extd_count + 1;
783 repeat;
784 }
Vadim Yanitskiy493abe72020-05-25 22:03:48 +0700785 [] RSL_CCHAN.receive(tr_ASP_RSL_UD(tr_RSL_CBCH_LOAD_IND_BASIC)) -> value rx_ud {
Harald Welte4a129f82019-05-21 16:35:22 +0200786 setverdict(fail, "Received unexpected CBCH LOAD IND: ", rx_ud);
787 }
Vadim Yanitskiy493abe72020-05-25 22:03:48 +0700788 [] RSL_CCHAN.receive(tr_ASP_RSL_UD(tr_RSL_CBCH_LOAD_IND_EXTD)) -> value rx_ud {
Harald Welte4a129f82019-05-21 16:35:22 +0200789 setverdict(fail, "Received unexpected CBCH LOAD IND: ", rx_ud);
790 }
791 [] RSL_CCHAN.receive { repeat; }
792 [] T.timeout {
793 if ((basic_count >= min_load_ind) and (extd_count >= min_load_ind)) {
794 setverdict(pass);
795 } else {
796 setverdict(fail, "Insufficient number of CBCH LOAD IND: ",
797 "BASIC=", basic_count, " EXTD=", extd_count);
798 }
799 }
800 }
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700801
Harald Welte4a129f82019-05-21 16:35:22 +0200802 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
803}
804testcase TC_cbc_sdcch4_load_idle() runs on test_CT {
805 f_init_vty_bsc();
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700806 f_vty_cbch_setup(valueof(ts_RslChanNr_CBCH4(0)));
Harald Welte4a129f82019-05-21 16:35:22 +0200807 f_TC_cbc_load_idle();
808}
809testcase TC_cbc_sdcch8_load_idle() runs on test_CT {
810 f_init_vty_bsc();
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700811 f_vty_cbch_setup(valueof(ts_RslChanNr_CBCH8(2)));
Harald Welte4a129f82019-05-21 16:35:22 +0200812 f_TC_cbc_load_idle();
813}
814
815/* Verify CBCH overload indications are sent when sending too many SMS CB CMD */
816function f_TC_cbc_load_overload(CbchTestPars pars) runs on test_CT {
817 template integer tr_slot_count_basic := (11 .. 13);
818 template integer tr_slot_count_extd := (2 .. 15);
819 const integer min_load_ind := 4;
820 var integer basic_count := 0;
821 var integer extd_count := 0;
822 var ASP_RSL_Unitdata rx_ud;
823 timer T_total := 10.0;
824 timer T_retransmit := 0.2;
825 timer T_initial_guard := 2.0;
826 var integer i;
827
Harald Welte10474062019-05-30 16:48:17 +0200828 f_init();
Harald Welte4a129f82019-05-21 16:35:22 +0200829
830 /* send tons of SMSCB Command */
831 for (i := 0; i < 30; i := i+1) {
832 f_smscb_setup_rsl_chan(pars.basic);
833 }
834
835 /* keep sending SMSCB Commands for another two seconds */
836 T_initial_guard.start;
837 T_retransmit.start;
838 alt {
839 [] T_retransmit.timeout {
840 f_smscb_setup_rsl_chan(pars.basic);
841 T_retransmit.start;
842 repeat;
843 }
844 [] T_initial_guard.timeout { }
845 }
846 /* clear any pending messages (where load may not have peaked yet) */
847 RSL_CCHAN.clear;
848
849 /* keep sending SMSCB Commands while verifying LOAD INDICATIONS */
850 T_total.start;
851 T_retransmit.start;
852 alt {
Vadim Yanitskiy493abe72020-05-25 22:03:48 +0700853 [] 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 +0200854 basic_count := basic_count + 1;
855 repeat;
856 }
Vadim Yanitskiy493abe72020-05-25 22:03:48 +0700857 [] 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 +0200858 extd_count := extd_count + 1;
859 repeat;
860 }
Vadim Yanitskiy493abe72020-05-25 22:03:48 +0700861 [] RSL_CCHAN.receive(tr_ASP_RSL_UD(tr_RSL_CBCH_LOAD_IND_BASIC)) -> value rx_ud {
Harald Welte4a129f82019-05-21 16:35:22 +0200862 setverdict(fail, "Received unexpected CBCH LOAD IND: ", rx_ud);
863 }
Vadim Yanitskiy493abe72020-05-25 22:03:48 +0700864 [] RSL_CCHAN.receive(tr_ASP_RSL_UD(tr_RSL_CBCH_LOAD_IND_EXTD)) -> value rx_ud {
Harald Welte4a129f82019-05-21 16:35:22 +0200865 setverdict(fail, "Received unexpected CBCH LOAD IND: ", rx_ud);
866 }
867 [] RSL_CCHAN.receive { repeat; }
868 [] T_retransmit.timeout {
869 f_smscb_setup_rsl_chan(pars.basic);
870 T_retransmit.start;
871 repeat;
872 }
873 [] T_total.timeout {
874 if ((basic_count >= min_load_ind) and (extd_count >= min_load_ind)) {
875 setverdict(pass);
876 } else {
877 setverdict(fail, "Insufficient number of CBCH LOAD IND: ",
878 "BASIC=", basic_count, " EXTD=", extd_count);
879 }
880 }
881 }
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700882
Harald Welte4a129f82019-05-21 16:35:22 +0200883 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
884}
885testcase TC_cbc_sdcch4_load_overload() runs on test_CT {
886 var CbchTestPars pars := {
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700887 chan_nr := valueof(ts_RslChanNr_CBCH4(0)),
Harald Welte4a129f82019-05-21 16:35:22 +0200888 basic := valueof(t_CbchPC(msgs_1m_3b_norm)),
889 extended := omit
890 };
891
892 f_init_vty_bsc();
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700893 f_vty_cbch_setup(pars.chan_nr);
Harald Welte4a129f82019-05-21 16:35:22 +0200894 f_TC_cbc_load_overload(pars);
895}
896testcase TC_cbc_sdcch8_load_overload() runs on test_CT {
897 var CbchTestPars pars := {
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700898 chan_nr := valueof(ts_RslChanNr_CBCH4(2)),
Harald Welte4a129f82019-05-21 16:35:22 +0200899 basic := valueof(t_CbchPC(msgs_1m_3b_norm)),
900 extended := omit
901 };
902
903 f_init_vty_bsc();
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700904 f_vty_cbch_setup(pars.chan_nr);
Harald Welte4a129f82019-05-21 16:35:22 +0200905 f_TC_cbc_load_overload(pars);
906}
Harald Weltedf4d0f02019-05-20 16:04:11 +0200907
Harald Welte88e5dff2019-05-20 15:14:46 +0200908
Harald Welte908ce542019-09-04 23:05:40 +0200909private template GsmRrMessage tr_PagingType1 := {
910 header := t_RrHeader(PAGING_REQUEST_TYPE_1, ?),
911 payload :=?
912};
913
Harald Welte908ce542019-09-04 23:05:40 +0200914/* we expect four blocks of 14 bytes, let's fill them with content easily distinguishable */
915const octetstring c_etws_seg0 := '000102030405060708090a0b0c0d'O;
916const octetstring c_etws_seg1 := '101112131415161718191a1b1c1d'O;
917const octetstring c_etws_seg2 := '202122232425262728292a2b2c2d'O;
918const octetstring c_etws_seg3 := '303132333435363738393a3b3c3d'O;
919const octetstring c_etws := c_etws_seg0 & c_etws_seg1 & c_etws_seg2 & c_etws_seg3;
920
921/* Ensure only Paging Type 1 with segmented ETWS Primary Notification are sent after RSL_OSMO_ETWS_CMD */
922testcase TC_etws_p1ro() runs on test_CT {
Harald Welte908ce542019-09-04 23:05:40 +0200923 /* decoding the actual entire P1 rest octets by manually generated code is
924 * too much effort; instead simply do a binary compare to this constant */
925 const bitstring c_P1RO_hdr := '00101011101'B;
926 var integer seg_received[4] := { 0, 0, 0, 0 };
927 var L1ctlDlMessage dl;
928 timer T := 10.0;
929
930 f_init();
931 f_init_l1ctl();
932 f_l1_tune(L1CTL, ccch_mode := CCCH_MODE_COMBINED_CBCH);
933
Vadim Yanitskiy493abe72020-05-25 22:03:48 +0700934 RSL_CCHAN.send(ts_ASP_RSL_UD(ts_RSL_OSMO_ETWS_CMD(c_etws)));
Harald Welte908ce542019-09-04 23:05:40 +0200935 /* wait for a bit until old non-ETWS Paging messages are gone */
936 f_sleep(1.0);
937 L1CTL.clear;
938 T.start;
939 alt {
Vadim Yanitskiyd4e95e82020-11-14 04:20:40 +0700940 [] L1CTL.receive(tr_L1CTL_DATA_IND(t_RslChanNr_PCH_AGCH(0))) -> value dl {
Harald Welte908ce542019-09-04 23:05:40 +0200941 var GsmRrMessage l3 := dec_GsmRrMessage(dl.payload.data_ind.payload);
942 select (l3) {
Vadim Yanitskiya9a198d2020-03-28 05:11:26 +0700943 case (tr_PAG_REQ1(tr_MI_LV(t_MI_NoIdentity()))) {
Harald Welte908ce542019-09-04 23:05:40 +0200944 var octetstring p1ro := l3.payload.pag_req_1.rest_octets;
945 var bitstring midamble := oct2bit(substr(p1ro, 0, 3));
946 var octetstring segment := substr(p1ro, 3, lengthof(p1ro)-3);
947 var BIT1 not_first := substr(midamble, 11, 1);
948 var integer seg_nr := bit2int(substr(midamble, 12, 4));
949 var boolean err := false;
950 if (substr(midamble, 0, 11) != c_P1RO_hdr) {
951 setverdict(fail, "Received unexpected P1 RO header ", midamble);
952 }
953 if (not_first == '1'B) {
954 select (seg_nr) {
955 case (2) {
956 if (segment != c_etws_seg1) {
957 err := true
958 } else {
959 seg_received[1] := seg_received[1] + 1;
960 }}
961 case (3) {
962 if (segment != c_etws_seg2) {
963 err := true
964 } else {
965 seg_received[2] := seg_received[2] + 1;
966 }}
967 case (4) {
968 if (segment != c_etws_seg3) {
969 err := true
970 } else {
971 seg_received[3] := seg_received[3] + 1;
972 }}
973 case else { setverdict(fail, "Unknown segment Nr ", seg_nr); }
974 }
975 if (err) {
976 setverdict(fail, "Unexpected segment ", seg_nr, ": ", segment);
977 }
978 } else {
979 if (seg_nr != 4) {
980 setverdict(fail, "Invalid number of segments ", seg_nr);
981 err := true;
982 }
983 if (segment != c_etws_seg0) {
984 setverdict(fail, "Invalid first segment ", segment);
985 err := true;
986 }
987 if (not err) {
988 seg_received[0] := seg_received[0] + 1;
989 }
990 }
991 }
992 case (tr_PagingType1) {
993 setverdict(fail, "Received unexpected PAGING TYPE 1: ", l3);
994 }
995 }
996 repeat;
997 }
998 [] L1CTL.receive { repeat; }
999 [] T.timeout {
1000 setverdict(pass);
1001 }
1002 }
1003 log("Quantity of received ETWS PN segments: ", seg_received);
1004 var integer i;
1005 for (i := 0; i < 4; i := i+1) {
1006 if (seg_received[i] < 15) {
1007 setverdict(fail, "Segment ", i, " not received often enough");
1008 }
1009 }
1010}
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;
1019 var L1ctlDlMessage dl;
1020 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 }
1050}
1051
Harald Welte11b734c2019-09-05 14:17:54 +02001052/* Ensure ETWS Primary Notification is passed from RSL to PCU interface */
1053testcase TC_etws_pcu() runs on test_CT {
1054 timer T := 10.0;
1055
1056 f_init();
1057 f_init_l1ctl();
1058 f_l1_tune(L1CTL, ccch_mode := CCCH_MODE_COMBINED_CBCH);
1059
Vadim Yanitskiy493abe72020-05-25 22:03:48 +07001060 RSL_CCHAN.send(ts_ASP_RSL_UD(ts_RSL_OSMO_ETWS_CMD(c_etws)));
Harald Welte11b734c2019-09-05 14:17:54 +02001061
1062 T.start;
1063 alt {
1064 [] PCU.receive(t_SD_PCUIF(g_pcu_conn_id, tr_PCUIF_APP_INFO_REQ(0, 0, c_etws))) {
1065 setverdict(pass);
1066 }
1067 [] PCU.receive(t_SD_PCUIF(g_pcu_conn_id, tr_PCUIF_APP_INFO_REQ(?, ?, ?))) {
1068 setverdict(fail, "PCU socket received invalid APP INFO");
1069 }
1070 [] PCU.receive { repeat; }
1071 [] T.timeout {
1072 setverdict(fail, "PCU socket timeout receiving APP INFO (ETWS)");
1073 }
1074 }
1075}
1076
1077
Harald Welte908ce542019-09-04 23:05:40 +02001078
Harald Welte505cf9b2018-09-15 17:47:23 +03001079/* SMSCB TODO:
1080 * multiple SMS BC CMD at the same time: Ensure all of them are sent exactly once
1081 * extended CBCH vs. normal CBCH
1082 *
1083 */
1084
1085control {
Harald Welte4a129f82019-05-21 16:35:22 +02001086 execute( TC_cbch_load_idle_no_cbch() );
1087
Harald Welte505cf9b2018-09-15 17:47:23 +03001088 execute( TC_sms_cb_cmd_sdcch4_1block() );
1089 execute( TC_sms_cb_cmd_sdcch4_2block() );
1090 execute( TC_sms_cb_cmd_sdcch4_3block() );
1091 execute( TC_sms_cb_cmd_sdcch4_4block() );
Harald Weltee0026c32019-05-20 00:27:30 +02001092 execute( TC_sms_cb_cmd_sdcch4_multi() );
Harald Welte505cf9b2018-09-15 17:47:23 +03001093 execute( TC_sms_cb_cmd_sdcch4_schedule() );
Harald Welte88e5dff2019-05-20 15:14:46 +02001094 execute( TC_sms_cb_cmd_sdcch4_default_only() );
Harald Welted522ca02019-05-20 20:06:12 +02001095 execute( TC_sms_cb_cmd_sdcch4_default_and_normal() );
Harald Weltedf4d0f02019-05-20 16:04:11 +02001096 execute( TC_sms_cb_cmd_sdcch4_default_then_null() );
Harald Welte4a129f82019-05-21 16:35:22 +02001097 execute( TC_cbc_sdcch4_load_idle() );
1098 execute( TC_cbc_sdcch4_load_overload() );
1099
Harald Welte505cf9b2018-09-15 17:47:23 +03001100 execute( TC_sms_cb_cmd_sdcch8_1block() );
1101 execute( TC_sms_cb_cmd_sdcch8_2block() );
1102 execute( TC_sms_cb_cmd_sdcch8_3block() );
1103 execute( TC_sms_cb_cmd_sdcch8_4block() );
Harald Weltee0026c32019-05-20 00:27:30 +02001104 execute( TC_sms_cb_cmd_sdcch8_multi() );
Harald Welte505cf9b2018-09-15 17:47:23 +03001105 execute( TC_sms_cb_cmd_sdcch8_schedule() );
Harald Welte88e5dff2019-05-20 15:14:46 +02001106 execute( TC_sms_cb_cmd_sdcch8_default_only() );
Harald Welted522ca02019-05-20 20:06:12 +02001107 execute( TC_sms_cb_cmd_sdcch8_default_and_normal() );
Harald Welte4a129f82019-05-21 16:35:22 +02001108 execute( TC_cbc_sdcch8_load_idle() );
1109 execute( TC_cbc_sdcch8_load_overload() );
Harald Welte908ce542019-09-04 23:05:40 +02001110
1111 execute( TC_etws_p1ro() );
1112 execute( TC_etws_p1ro_end() );
Harald Welte11b734c2019-09-05 14:17:54 +02001113 execute( TC_etws_pcu() );
Harald Welte505cf9b2018-09-15 17:47:23 +03001114}
1115
1116
1117}