blob: 953801bb97c299a4146dac53cee8f620a47d31b7 [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 */,
270 mp_trx0_arfcn));
271 }
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 };
Harald Welte6b86b342019-05-27 17:14:36 +0200702 var template RslChannelNr t_chan_nr := t_RslChanNr_CBCH4(0);
Harald Weltedf4d0f02019-05-20 16:04:11 +0200703 var L1ctlDlMessage dl;
704 timer T := 5.0;
705
706 f_TC_smscb_default_only(pars);
707
708 /* disable DEFAULT message; switch back to NULL */
709 f_rsl_smscb_default_null();
710
711 /* ensure whatever initial non-NULL messages have all been drained */
712 f_sleep(5.0);
713 L1CTL.clear;
714
715 T.start;
716 alt {
Harald Welte6b86b342019-05-27 17:14:36 +0200717 [] L1CTL.receive(tr_L1CTL_DATA_IND(t_chan_nr)) -> value dl {
Harald Weltedf4d0f02019-05-20 16:04:11 +0200718 log("CBCH: ", dl);
719 var CBCH_Block cb := dec_CBCH_Block(dl.payload.data_ind.payload);
720 /* detect the proper CBCH messages; check frame number */
721 f_cbch_fn_verify(dl.dl_info.frame_nr, cb);
722 if (not match(cb, tr_CBCH_Block)) {
723 setverdict(fail, "Illegal CBCH Block received: ", cb);
724 } else {
725 if (not match(cb, tr_CBCH_Block(15, ?, ?))) {
726 setverdict(fail, "Unexpected non-NULL CBCH block received");
727 }
728 repeat;
729 }
730 }
731 [] L1CTL.receive { repeat; }
732 [] T.timeout {
733 setverdict(pass);
734 }
735 }
736
737 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, pass);
738}
739
Harald Welte4a129f82019-05-21 16:35:22 +0200740/* Verify there are no CBCH load indications if no CBCH is present */
741testcase TC_cbch_load_idle_no_cbch() runs on test_CT {
742 var ASP_RSL_Unitdata rx_ud;
743 timer T := 10.0;
744
Harald Welte10474062019-05-30 16:48:17 +0200745 f_init();
Harald Welte4a129f82019-05-21 16:35:22 +0200746 f_init_vty_bsc();
747
748 T.start;
749 alt {
Vadim Yanitskiy493abe72020-05-25 22:03:48 +0700750 [] RSL_CCHAN.receive(tr_ASP_RSL_UD(tr_RSL_CBCH_LOAD_IND_BASIC)) -> value rx_ud {
Harald Welte4a129f82019-05-21 16:35:22 +0200751 setverdict(fail, "Received unexpected CBCH LOAD IND: ", rx_ud);
752 }
Vadim Yanitskiy493abe72020-05-25 22:03:48 +0700753 [] RSL_CCHAN.receive(tr_ASP_RSL_UD(tr_RSL_CBCH_LOAD_IND_EXTD)) -> value rx_ud {
Harald Welte4a129f82019-05-21 16:35:22 +0200754 setverdict(fail, "Received unexpected CBCH LOAD IND: ", rx_ud);
755 }
756 [] RSL_CCHAN.receive { repeat; }
757 [] T.timeout {
758 setverdict(pass);
759 }
760 }
761 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
762}
763
764/* Verify the CBCH load indications of an idle cell (without CBCH load) */
765function f_TC_cbc_load_idle() runs on test_CT {
766 template integer tr_slot_count := (2 .. 15);
767 const integer min_load_ind := 4;
768 var integer basic_count := 0;
769 var integer extd_count := 0;
770 var ASP_RSL_Unitdata rx_ud;
771 timer T := 10.0;
772
Harald Welte10474062019-05-30 16:48:17 +0200773 f_init();
Harald Welte4a129f82019-05-21 16:35:22 +0200774
775 RSL_CCHAN.clear;
776 T.start;
777 alt {
Vadim Yanitskiy493abe72020-05-25 22:03:48 +0700778 [] RSL_CCHAN.receive(tr_ASP_RSL_UD(tr_RSL_CBCH_LOAD_IND_BASIC(false, tr_slot_count))) {
Harald Welte4a129f82019-05-21 16:35:22 +0200779 basic_count := basic_count + 1;
780 repeat;
781 }
Vadim Yanitskiy493abe72020-05-25 22:03:48 +0700782 [] 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 +0200783 extd_count := extd_count + 1;
784 repeat;
785 }
Vadim Yanitskiy493abe72020-05-25 22:03:48 +0700786 [] RSL_CCHAN.receive(tr_ASP_RSL_UD(tr_RSL_CBCH_LOAD_IND_BASIC)) -> value rx_ud {
Harald Welte4a129f82019-05-21 16:35:22 +0200787 setverdict(fail, "Received unexpected CBCH LOAD IND: ", rx_ud);
788 }
Vadim Yanitskiy493abe72020-05-25 22:03:48 +0700789 [] RSL_CCHAN.receive(tr_ASP_RSL_UD(tr_RSL_CBCH_LOAD_IND_EXTD)) -> value rx_ud {
Harald Welte4a129f82019-05-21 16:35:22 +0200790 setverdict(fail, "Received unexpected CBCH LOAD IND: ", rx_ud);
791 }
792 [] RSL_CCHAN.receive { repeat; }
793 [] T.timeout {
794 if ((basic_count >= min_load_ind) and (extd_count >= min_load_ind)) {
795 setverdict(pass);
796 } else {
797 setverdict(fail, "Insufficient number of CBCH LOAD IND: ",
798 "BASIC=", basic_count, " EXTD=", extd_count);
799 }
800 }
801 }
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700802
Harald Welte4a129f82019-05-21 16:35:22 +0200803 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
804}
805testcase TC_cbc_sdcch4_load_idle() runs on test_CT {
806 f_init_vty_bsc();
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700807 f_vty_cbch_setup(valueof(ts_RslChanNr_CBCH4(0)));
Harald Welte4a129f82019-05-21 16:35:22 +0200808 f_TC_cbc_load_idle();
809}
810testcase TC_cbc_sdcch8_load_idle() runs on test_CT {
811 f_init_vty_bsc();
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700812 f_vty_cbch_setup(valueof(ts_RslChanNr_CBCH8(2)));
Harald Welte4a129f82019-05-21 16:35:22 +0200813 f_TC_cbc_load_idle();
814}
815
816/* Verify CBCH overload indications are sent when sending too many SMS CB CMD */
817function f_TC_cbc_load_overload(CbchTestPars pars) runs on test_CT {
818 template integer tr_slot_count_basic := (11 .. 13);
819 template integer tr_slot_count_extd := (2 .. 15);
820 const integer min_load_ind := 4;
821 var integer basic_count := 0;
822 var integer extd_count := 0;
823 var ASP_RSL_Unitdata rx_ud;
824 timer T_total := 10.0;
825 timer T_retransmit := 0.2;
826 timer T_initial_guard := 2.0;
827 var integer i;
828
Harald Welte10474062019-05-30 16:48:17 +0200829 f_init();
Harald Welte4a129f82019-05-21 16:35:22 +0200830
831 /* send tons of SMSCB Command */
832 for (i := 0; i < 30; i := i+1) {
833 f_smscb_setup_rsl_chan(pars.basic);
834 }
835
836 /* keep sending SMSCB Commands for another two seconds */
837 T_initial_guard.start;
838 T_retransmit.start;
839 alt {
840 [] T_retransmit.timeout {
841 f_smscb_setup_rsl_chan(pars.basic);
842 T_retransmit.start;
843 repeat;
844 }
845 [] T_initial_guard.timeout { }
846 }
847 /* clear any pending messages (where load may not have peaked yet) */
848 RSL_CCHAN.clear;
849
850 /* keep sending SMSCB Commands while verifying LOAD INDICATIONS */
851 T_total.start;
852 T_retransmit.start;
853 alt {
Vadim Yanitskiy493abe72020-05-25 22:03:48 +0700854 [] 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 +0200855 basic_count := basic_count + 1;
856 repeat;
857 }
Vadim Yanitskiy493abe72020-05-25 22:03:48 +0700858 [] 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 +0200859 extd_count := extd_count + 1;
860 repeat;
861 }
Vadim Yanitskiy493abe72020-05-25 22:03:48 +0700862 [] RSL_CCHAN.receive(tr_ASP_RSL_UD(tr_RSL_CBCH_LOAD_IND_BASIC)) -> value rx_ud {
Harald Welte4a129f82019-05-21 16:35:22 +0200863 setverdict(fail, "Received unexpected CBCH LOAD IND: ", rx_ud);
864 }
Vadim Yanitskiy493abe72020-05-25 22:03:48 +0700865 [] RSL_CCHAN.receive(tr_ASP_RSL_UD(tr_RSL_CBCH_LOAD_IND_EXTD)) -> value rx_ud {
Harald Welte4a129f82019-05-21 16:35:22 +0200866 setverdict(fail, "Received unexpected CBCH LOAD IND: ", rx_ud);
867 }
868 [] RSL_CCHAN.receive { repeat; }
869 [] T_retransmit.timeout {
870 f_smscb_setup_rsl_chan(pars.basic);
871 T_retransmit.start;
872 repeat;
873 }
874 [] T_total.timeout {
875 if ((basic_count >= min_load_ind) and (extd_count >= min_load_ind)) {
876 setverdict(pass);
877 } else {
878 setverdict(fail, "Insufficient number of CBCH LOAD IND: ",
879 "BASIC=", basic_count, " EXTD=", extd_count);
880 }
881 }
882 }
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700883
Harald Welte4a129f82019-05-21 16:35:22 +0200884 Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
885}
886testcase TC_cbc_sdcch4_load_overload() runs on test_CT {
887 var CbchTestPars pars := {
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700888 chan_nr := valueof(ts_RslChanNr_CBCH4(0)),
Harald Welte4a129f82019-05-21 16:35:22 +0200889 basic := valueof(t_CbchPC(msgs_1m_3b_norm)),
890 extended := omit
891 };
892
893 f_init_vty_bsc();
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700894 f_vty_cbch_setup(pars.chan_nr);
Harald Welte4a129f82019-05-21 16:35:22 +0200895 f_TC_cbc_load_overload(pars);
896}
897testcase TC_cbc_sdcch8_load_overload() runs on test_CT {
898 var CbchTestPars pars := {
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700899 chan_nr := valueof(ts_RslChanNr_CBCH4(2)),
Harald Welte4a129f82019-05-21 16:35:22 +0200900 basic := valueof(t_CbchPC(msgs_1m_3b_norm)),
901 extended := omit
902 };
903
904 f_init_vty_bsc();
Vadim Yanitskiyffcd1282020-07-31 06:41:52 +0700905 f_vty_cbch_setup(pars.chan_nr);
Harald Welte4a129f82019-05-21 16:35:22 +0200906 f_TC_cbc_load_overload(pars);
907}
Harald Weltedf4d0f02019-05-20 16:04:11 +0200908
Harald Welte88e5dff2019-05-20 15:14:46 +0200909
Harald Welte908ce542019-09-04 23:05:40 +0200910private template GsmRrMessage tr_PagingType1 := {
911 header := t_RrHeader(PAGING_REQUEST_TYPE_1, ?),
912 payload :=?
913};
914
Harald Welte908ce542019-09-04 23:05:40 +0200915/* we expect four blocks of 14 bytes, let's fill them with content easily distinguishable */
916const octetstring c_etws_seg0 := '000102030405060708090a0b0c0d'O;
917const octetstring c_etws_seg1 := '101112131415161718191a1b1c1d'O;
918const octetstring c_etws_seg2 := '202122232425262728292a2b2c2d'O;
919const octetstring c_etws_seg3 := '303132333435363738393a3b3c3d'O;
920const octetstring c_etws := c_etws_seg0 & c_etws_seg1 & c_etws_seg2 & c_etws_seg3;
921
922/* Ensure only Paging Type 1 with segmented ETWS Primary Notification are sent after RSL_OSMO_ETWS_CMD */
923testcase TC_etws_p1ro() runs on test_CT {
924 var template RslChannelNr t_chan_nr := ts_RslChanNr_PCH_AGCH(0);
925 /* decoding the actual entire P1 rest octets by manually generated code is
926 * too much effort; instead simply do a binary compare to this constant */
927 const bitstring c_P1RO_hdr := '00101011101'B;
928 var integer seg_received[4] := { 0, 0, 0, 0 };
929 var L1ctlDlMessage dl;
930 timer T := 10.0;
931
932 f_init();
933 f_init_l1ctl();
934 f_l1_tune(L1CTL, ccch_mode := CCCH_MODE_COMBINED_CBCH);
935
Vadim Yanitskiy493abe72020-05-25 22:03:48 +0700936 RSL_CCHAN.send(ts_ASP_RSL_UD(ts_RSL_OSMO_ETWS_CMD(c_etws)));
Harald Welte908ce542019-09-04 23:05:40 +0200937 /* wait for a bit until old non-ETWS Paging messages are gone */
938 f_sleep(1.0);
939 L1CTL.clear;
940 T.start;
941 alt {
942 [] L1CTL.receive(tr_L1CTL_DATA_IND(t_chan_nr)) -> value dl {
943 var GsmRrMessage l3 := dec_GsmRrMessage(dl.payload.data_ind.payload);
944 select (l3) {
Vadim Yanitskiya9a198d2020-03-28 05:11:26 +0700945 case (tr_PAG_REQ1(tr_MI_LV(t_MI_NoIdentity()))) {
Harald Welte908ce542019-09-04 23:05:40 +0200946 var octetstring p1ro := l3.payload.pag_req_1.rest_octets;
947 var bitstring midamble := oct2bit(substr(p1ro, 0, 3));
948 var octetstring segment := substr(p1ro, 3, lengthof(p1ro)-3);
949 var BIT1 not_first := substr(midamble, 11, 1);
950 var integer seg_nr := bit2int(substr(midamble, 12, 4));
951 var boolean err := false;
952 if (substr(midamble, 0, 11) != c_P1RO_hdr) {
953 setverdict(fail, "Received unexpected P1 RO header ", midamble);
954 }
955 if (not_first == '1'B) {
956 select (seg_nr) {
957 case (2) {
958 if (segment != c_etws_seg1) {
959 err := true
960 } else {
961 seg_received[1] := seg_received[1] + 1;
962 }}
963 case (3) {
964 if (segment != c_etws_seg2) {
965 err := true
966 } else {
967 seg_received[2] := seg_received[2] + 1;
968 }}
969 case (4) {
970 if (segment != c_etws_seg3) {
971 err := true
972 } else {
973 seg_received[3] := seg_received[3] + 1;
974 }}
975 case else { setverdict(fail, "Unknown segment Nr ", seg_nr); }
976 }
977 if (err) {
978 setverdict(fail, "Unexpected segment ", seg_nr, ": ", segment);
979 }
980 } else {
981 if (seg_nr != 4) {
982 setverdict(fail, "Invalid number of segments ", seg_nr);
983 err := true;
984 }
985 if (segment != c_etws_seg0) {
986 setverdict(fail, "Invalid first segment ", segment);
987 err := true;
988 }
989 if (not err) {
990 seg_received[0] := seg_received[0] + 1;
991 }
992 }
993 }
994 case (tr_PagingType1) {
995 setverdict(fail, "Received unexpected PAGING TYPE 1: ", l3);
996 }
997 }
998 repeat;
999 }
1000 [] L1CTL.receive { repeat; }
1001 [] T.timeout {
1002 setverdict(pass);
1003 }
1004 }
1005 log("Quantity of received ETWS PN segments: ", seg_received);
1006 var integer i;
1007 for (i := 0; i < 4; i := i+1) {
1008 if (seg_received[i] < 15) {
1009 setverdict(fail, "Segment ", i, " not received often enough");
1010 }
1011 }
1012}
1013
1014/* Ensure only Paging Type 1 without ETWS Primary Notification are sent after disabling them */
1015testcase TC_etws_p1ro_end() runs on test_CT {
1016 var template RslChannelNr t_chan_nr := ts_RslChanNr_PCH_AGCH(0);
1017 /* we expect four blocks of 14 bytes, let's fill them with content easily
1018 * distinguishable */
1019 /* decoding the actual entire P1 rest octets by manually generated code is
1020 * too much effort; instead simply do a binary compare to this constant */
1021 const bitstring c_P1RO_hdr := '00101011101'B;
1022 var L1ctlDlMessage dl;
1023 timer T := 10.0;
1024
1025 f_init();
1026 f_init_l1ctl();
1027 f_l1_tune(L1CTL, ccch_mode := CCCH_MODE_COMBINED_CBCH);
1028
Vadim Yanitskiy493abe72020-05-25 22:03:48 +07001029 RSL_CCHAN.send(ts_ASP_RSL_UD(ts_RSL_OSMO_ETWS_CMD(c_etws)));
Harald Welte908ce542019-09-04 23:05:40 +02001030 /* wait for a bit until old non-ETWS Paging messages are gone */
1031 f_sleep(3.0);
1032 /* disable the ETWS PN again */
Vadim Yanitskiy493abe72020-05-25 22:03:48 +07001033 RSL_CCHAN.send(ts_ASP_RSL_UD(ts_RSL_OSMO_ETWS_CMD(''O)));
Harald Welte908ce542019-09-04 23:05:40 +02001034 f_sleep(2.0);
1035 T.start;
1036 L1CTL.clear;
1037 alt {
1038 [] L1CTL.receive(tr_L1CTL_DATA_IND(t_chan_nr)) -> value dl {
1039 var GsmRrMessage l3 := dec_GsmRrMessage(dl.payload.data_ind.payload);
1040 select (l3) {
Vadim Yanitskiya9a198d2020-03-28 05:11:26 +07001041 case (tr_PAG_REQ1(tr_MI_LV(t_MI_NoIdentity()))) { repeat; }
Harald Welte908ce542019-09-04 23:05:40 +02001042 case (tr_PagingType1) {
1043 setverdict(fail, "Received non-empty PT1 after disabling ETWS PN: ", l3);
1044 }
1045 }
1046 repeat;
1047 }
1048 [] L1CTL.receive { repeat; }
1049 [] T.timeout {
1050 setverdict(pass);
1051 }
1052 }
1053}
1054
Harald Welte11b734c2019-09-05 14:17:54 +02001055/* Ensure ETWS Primary Notification is passed from RSL to PCU interface */
1056testcase TC_etws_pcu() runs on test_CT {
1057 timer T := 10.0;
1058
1059 f_init();
1060 f_init_l1ctl();
1061 f_l1_tune(L1CTL, ccch_mode := CCCH_MODE_COMBINED_CBCH);
1062
Vadim Yanitskiy493abe72020-05-25 22:03:48 +07001063 RSL_CCHAN.send(ts_ASP_RSL_UD(ts_RSL_OSMO_ETWS_CMD(c_etws)));
Harald Welte11b734c2019-09-05 14:17:54 +02001064
1065 T.start;
1066 alt {
1067 [] PCU.receive(t_SD_PCUIF(g_pcu_conn_id, tr_PCUIF_APP_INFO_REQ(0, 0, c_etws))) {
1068 setverdict(pass);
1069 }
1070 [] PCU.receive(t_SD_PCUIF(g_pcu_conn_id, tr_PCUIF_APP_INFO_REQ(?, ?, ?))) {
1071 setverdict(fail, "PCU socket received invalid APP INFO");
1072 }
1073 [] PCU.receive { repeat; }
1074 [] T.timeout {
1075 setverdict(fail, "PCU socket timeout receiving APP INFO (ETWS)");
1076 }
1077 }
1078}
1079
1080
Harald Welte908ce542019-09-04 23:05:40 +02001081
Harald Welte505cf9b2018-09-15 17:47:23 +03001082/* SMSCB TODO:
1083 * multiple SMS BC CMD at the same time: Ensure all of them are sent exactly once
1084 * extended CBCH vs. normal CBCH
1085 *
1086 */
1087
1088control {
Harald Welte4a129f82019-05-21 16:35:22 +02001089 execute( TC_cbch_load_idle_no_cbch() );
1090
Harald Welte505cf9b2018-09-15 17:47:23 +03001091 execute( TC_sms_cb_cmd_sdcch4_1block() );
1092 execute( TC_sms_cb_cmd_sdcch4_2block() );
1093 execute( TC_sms_cb_cmd_sdcch4_3block() );
1094 execute( TC_sms_cb_cmd_sdcch4_4block() );
Harald Weltee0026c32019-05-20 00:27:30 +02001095 execute( TC_sms_cb_cmd_sdcch4_multi() );
Harald Welte505cf9b2018-09-15 17:47:23 +03001096 execute( TC_sms_cb_cmd_sdcch4_schedule() );
Harald Welte88e5dff2019-05-20 15:14:46 +02001097 execute( TC_sms_cb_cmd_sdcch4_default_only() );
Harald Welted522ca02019-05-20 20:06:12 +02001098 execute( TC_sms_cb_cmd_sdcch4_default_and_normal() );
Harald Weltedf4d0f02019-05-20 16:04:11 +02001099 execute( TC_sms_cb_cmd_sdcch4_default_then_null() );
Harald Welte4a129f82019-05-21 16:35:22 +02001100 execute( TC_cbc_sdcch4_load_idle() );
1101 execute( TC_cbc_sdcch4_load_overload() );
1102
Harald Welte505cf9b2018-09-15 17:47:23 +03001103 execute( TC_sms_cb_cmd_sdcch8_1block() );
1104 execute( TC_sms_cb_cmd_sdcch8_2block() );
1105 execute( TC_sms_cb_cmd_sdcch8_3block() );
1106 execute( TC_sms_cb_cmd_sdcch8_4block() );
Harald Weltee0026c32019-05-20 00:27:30 +02001107 execute( TC_sms_cb_cmd_sdcch8_multi() );
Harald Welte505cf9b2018-09-15 17:47:23 +03001108 execute( TC_sms_cb_cmd_sdcch8_schedule() );
Harald Welte88e5dff2019-05-20 15:14:46 +02001109 execute( TC_sms_cb_cmd_sdcch8_default_only() );
Harald Welted522ca02019-05-20 20:06:12 +02001110 execute( TC_sms_cb_cmd_sdcch8_default_and_normal() );
Harald Welte4a129f82019-05-21 16:35:22 +02001111 execute( TC_cbc_sdcch8_load_idle() );
1112 execute( TC_cbc_sdcch8_load_overload() );
Harald Welte908ce542019-09-04 23:05:40 +02001113
1114 execute( TC_etws_p1ro() );
1115 execute( TC_etws_p1ro_end() );
Harald Welte11b734c2019-09-05 14:17:54 +02001116 execute( TC_etws_pcu() );
Harald Welte505cf9b2018-09-15 17:47:23 +03001117}
1118
1119
1120}