blob: fc9ef88918b0c0d0c710314d8f11a2f7578ace9e [file] [log] [blame]
Harald Welte56db5fd2017-07-14 18:25:59 +02001module Test {
Harald Welteaf549412017-07-15 21:33:21 +02002 import from GSM_Types all;
Harald Welte56db5fd2017-07-14 18:25:59 +02003 import from GSM_SystemInformation all;
Harald Welteb622a3d2017-07-14 22:26:33 +02004 import from GSMTAP_Types all;
5 import from GSMTAP_PortType all;
6 import from IPL4_GSMTAP_CtrlFunct all;
Harald Welte9a907b32017-07-15 10:34:27 +02007 import from TELNETasp_PortType all;
Harald Welte56db5fd2017-07-14 18:25:59 +02008
9 const octetstring si1 := '5506198fb38000000000000000000000000000e504002b'O;
10 const octetstring si2 := '59061a00000000000000000000000000000000ffe50400'O;
11 const octetstring si3 := '49061b000062f22404d2490301275d40e50400392b2b2b'O;
12 const octetstring si4 := '31061c62f22404d25d40e504002b2b2b2b2b2b2b2b2b2b'O;
Harald Weltebdc5dbd2017-07-16 00:00:43 +020013 const octetstring c_si2bis := '550602bfe809b3ff00000000000000000000007900002b'O;
14 const octetstring c_si2ter := '010603bf66b0aa0a00000002000000000000002b2b2b2b'O;
15 const octetstring c_si2quater := '050607a8a0364aa698d72ff424feee0506d5e7fff02043'O;
Harald Welte56db5fd2017-07-14 18:25:59 +020016
17 type component dummy_CT {
Harald Welteb622a3d2017-07-14 22:26:33 +020018 port GSMTAP_PT GSMTAP;
Harald Welte9a907b32017-07-15 10:34:27 +020019 port TELNETasp_PT BSCVTY;
Harald Weltebdc5dbd2017-07-16 00:00:43 +020020 var boolean initialized := false;
21 var SystemInformationConfig si_cfg := {
22 bcch_extended := false,
23 si1_present := true,
24 si2bis_present := false,
25 si2ter_present := false,
26 si2quater_present := false,
27 si7_present := false,
28 si8_present := false,
29 si9_present := false,
30 si13_present := false,
31 si13alt_present := false,
32 si15_present := false,
33 si16_present := false,
34 si17_present := false,
35 si2n_present := false,
36 si21_present := false,
37 si22_present := false
38 };
Harald Welte56db5fd2017-07-14 18:25:59 +020039 };
40
41 testcase TC_si1() runs on dummy_CT {
Harald Welte56db5fd2017-07-14 18:25:59 +020042 log("SI: ", dec_SystemInformation(si1));
43 log("SI: ", dec_SystemInformation(si2));
44 log("SI: ", dec_SystemInformation(si3));
45 log("SI: ", dec_SystemInformation(si4));
Harald Weltebdc5dbd2017-07-16 00:00:43 +020046 setverdict(pass);
Harald Welte56db5fd2017-07-14 18:25:59 +020047 }
48
Harald Welteb622a3d2017-07-14 22:26:33 +020049 template GsmtapHeader t_GsmtapHeader := {
50 version := GSMTAP_VERSION,
51 hdr_len := 4,
52 msg_type := ?,
53 timeslot := ?,
54 arfcn := ?,
55 signal_dbm := ?,
56 snr_db := ?,
57 frame_number := ?,
58 sub_type := ?,
59 antenna_nr := ?,
60 sub_slot := ?,
61 res := ?
62 }
63
64 template GsmtapHeader t_GsmtapHeaderUm(template GsmtapChannel ch) modifies t_GsmtapHeader := {
65 msg_type := GSMTAP_TYPE_UM,
66 sub_type := ch
67 }
68
Harald Welteb622a3d2017-07-14 22:26:33 +020069 template GsmtapMessage t_bcch := {
70 header := t_GsmtapHeaderUm(GSMTAP_CHANNEL_BCCH),
71 payload := ?
72 }
73
74 template GSMTAP_RecvFrom t_recvfrom(template GsmtapChannel ch) := {
75 connId := ?,
76 remName := ?,
77 remPort := ?,
78 locName := ?,
79 locPort := GSMTAP_PORT,
80 proto := {udp:={}},
81 userData := ?,
82 msg := { header := t_GsmtapHeaderUm(ch), payload := ?}
83 }
84
Harald Welteaf549412017-07-15 21:33:21 +020085 /* tuple of gsmtap header + decoded SI */
86 type record SystemInformationGsmtap {
87 GsmtapHeader gsmtap,
88 SystemInformation si
89 }
90
91 /* an arbitrary-length vector of decoded SI + gsmtap header */
92 type record of SystemInformationGsmtap SystemInformationVector;
93
94 /* an array of SI-vectors indexed by TC value */
95 type SystemInformationVector SystemInformationVectorPerTc[8];
96
97 type record of integer IntegerRecord;
98
99 function f_array_contains(IntegerRecord arr, integer key) return boolean {
100 for (var integer i:= 0; i< sizeof(arr); i := i + 1) {
101 if (arr[i] == key) {
102 return true;
103 }
104 }
105 return false;
106 }
107
108
109 /* compute TC as per 45.002 6.3.1.3 */
110 function f_gsm_compute_tc(integer fn) return integer {
111 return (fn / 51) mod 8;
112 }
113
114 /* determine if a given SI vector contains given SI type at least once */
115 function f_si_vecslot_contains(SystemInformationVector arr, RrMessageType key, boolean bcch_ext := false) return boolean {
116 for (var integer i:= 0; i< sizeof(arr); i := i + 1) {
117 var integer fn_mod51 := arr[i].gsmtap.frame_number mod 51;
118 if (not bcch_ext and fn_mod51 == 2 or
119 bcch_ext and fn_mod51 == 6) {
120 if (arr[i].si.header.message_type == key) {
121 return true;
122 }
123 }
124 }
125 return false;
126 }
127
Harald Welte39276772017-07-16 01:07:42 +0200128 /* ensure a given TC slot of the SI vector contains given SI type at least once at TC */
129 function f_ensure_si_vec_contains(SystemInformationVectorPerTc arr, integer tc, RrMessageType key, boolean ext_bcch := false) {
130 if (not f_si_vecslot_contains(arr[tc], key, ext_bcch)) {
131 log("Fail: No ", key, " in TC=", tc, "!");
132 setverdict(fail);
133 }
134 }
135
Harald Welteaf549412017-07-15 21:33:21 +0200136 /* check if a given SI vector contains given SI type at least once on any TC */
137 function f_si_vec_contains(SystemInformationVectorPerTc arr, RrMessageType key) return boolean {
138 for (var integer tc:= 0; tc < sizeof(arr); tc := tc + 1) {
139 if (f_si_vecslot_contains(arr[tc], key) or
140 f_si_vecslot_contains(arr[tc], key, true)) {
141 return true;
142 }
143 }
144 return false;
145 }
146
Harald Welte39276772017-07-16 01:07:42 +0200147 /* determine if a given SI vector contains given SI type at least N of M times */
148 function f_si_vecslot_contains_n_of_m(SystemInformationVector arr, RrMessageType key, boolean bcch_ext := false, integer n := 1, integer m := 4) return boolean {
149 var integer count := 0;
150 if (sizeof(arr) < m) {
Harald Welte75f761f2017-07-16 03:05:31 +0200151 testcase.stop("Error: Insufficient SI in array");
Harald Welte39276772017-07-16 01:07:42 +0200152 }
153 for (var integer i:= 0; i < m; i := i + 1) {
154 var integer fn_mod51 := arr[i].gsmtap.frame_number mod 51;
155 if (not bcch_ext and fn_mod51 == 2 or
156 bcch_ext and fn_mod51 == 6) {
157 if (arr[i].si.header.message_type == key) {
158 count := count + 1;
159 }
160 }
161 }
162 if (count >= n) {
163 return true;
164 } else {
165 return false;
166 }
167 }
168
169 /* ensure a given TC slot of the SI vector contains given SI type at least N out of M times at TC */
170 function f_ensure_si_vec_contains_n_of_m(SystemInformationVectorPerTc arr, integer tc, RrMessageType key, boolean ext_bcch := false, integer n, integer m) {
171 if (not f_si_vecslot_contains_n_of_m(arr[tc], key, ext_bcch, n, m)) {
172 log("Fail: Not ", n, "/", m, " of ", key, " in TC=", tc, "!");
173 setverdict(fail);
174 }
175 }
176
177 /* determine if a given SI vector contains given SI type at least once */
178 function f_si_vecslot_contains_only(SystemInformationVector arr, RrMessageType key, boolean bcch_ext := false) return boolean {
179 for (var integer i:= 0; i< sizeof(arr); i := i + 1) {
180 var integer fn_mod51 := arr[i].gsmtap.frame_number mod 51;
181 if (not bcch_ext and fn_mod51 == 2 or
182 bcch_ext and fn_mod51 == 6) {
183 if (arr[i].si.header.message_type != key) {
184 return false;
185 }
186 }
187 }
188 return true;
189 }
190
191 /* ensure a given TC slot of the SI vector contains only given SI type */
192 function f_ensure_si_vec_contains_only(SystemInformationVectorPerTc arr, integer tc, RrMessageType key, boolean ext_bcch := false) {
193 if (not f_si_vecslot_contains_only(arr[tc], key, ext_bcch)) {
194 log("Fail: Not all ", key, " in TC=", tc, "!");
Harald Welteaf549412017-07-15 21:33:21 +0200195 setverdict(fail);
196 }
197 }
198
199 /* SI configuration of cell, against which we validate actual SI messages */
200 type set SystemInformationConfig {
201 boolean bcch_extended,
202 boolean si1_present,
203 boolean si2bis_present,
204 boolean si2ter_present,
205 boolean si2quater_present,
206 boolean si7_present,
207 boolean si8_present,
208 boolean si9_present,
209 boolean si13_present,
210 boolean si13alt_present,
211 boolean si15_present,
212 boolean si16_present,
213 boolean si17_present,
214 boolean si2n_present,
215 boolean si21_present,
216 boolean si22_present
217 }
218
219 /* validate the SI scheduling according to TS 45.002 version 14.1.0 Release 14, Section 6.3.1.3 */
220 function f_validate_si_scheduling(SystemInformationConfig cfg, SystemInformationVectorPerTc si_per_tc) {
221 var integer i;
222 for (i := 0; i < sizeof(si_per_tc); i := i + 1) {
223 if (sizeof(si_per_tc[i]) == 0) {
224 setverdict(fail, "No SI messages for TC=0!");
225 }
226 }
227 if (cfg.si1_present) {
228 /* ii) System Information Type 1 needs to be sent if frequency hopping is in use or
229 * when the NCH is present in a cell. If the MS finds another message on BCCH Norm
230 * when TC = 0, it can assume that System Information Type 1 is not in use. */
231 f_ensure_si_vec_contains(si_per_tc, 0, SYSTEM_INFORMATION_TYPE_1);
Harald Welte39276772017-07-16 01:07:42 +0200232 /* make sure *ALL* contain SI1 */
233 f_ensure_si_vec_contains_only(si_per_tc, 0, SYSTEM_INFORMATION_TYPE_1);
Harald Welteaf549412017-07-15 21:33:21 +0200234 }
235 f_ensure_si_vec_contains(si_per_tc, 1, SYSTEM_INFORMATION_TYPE_2);
236 /* iii) A SI 2 message will be sent at least every time TC = 1 */
237 f_ensure_si_vec_contains(si_per_tc, 2, SYSTEM_INFORMATION_TYPE_3);
238 f_ensure_si_vec_contains(si_per_tc, 6, SYSTEM_INFORMATION_TYPE_3);
239 f_ensure_si_vec_contains(si_per_tc, 3, SYSTEM_INFORMATION_TYPE_4);
240 f_ensure_si_vec_contains(si_per_tc, 7, SYSTEM_INFORMATION_TYPE_4);
241
242 /* iii) System information type 2 bis or 2 ter messages are sent if needed, as determined by the
243 * system operator. If only one of them is needed, it is sent when TC = 5. If both are
244 * needed, 2bis is sent when TC = 5 and 2ter is sent at least once within any of 4
245 * consecutive occurrences of TC = 4. */
246 if (cfg.si2bis_present and not cfg.si2ter_present) {
247 f_ensure_si_vec_contains(si_per_tc, 5, SYSTEM_INFORMATION_TYPE_2bis);
248 } else if (cfg.si2ter_present and not cfg.si2bis_present) {
249 f_ensure_si_vec_contains(si_per_tc, 5, SYSTEM_INFORMATION_TYPE_2ter);
250 } else if (cfg.si2ter_present and cfg.si2bis_present) {
251 f_ensure_si_vec_contains(si_per_tc, 5, SYSTEM_INFORMATION_TYPE_2bis);
Harald Welte39276772017-07-16 01:07:42 +0200252 f_ensure_si_vec_contains_n_of_m(si_per_tc, 4, SYSTEM_INFORMATION_TYPE_2ter, false, 1, 4);
Harald Welteaf549412017-07-15 21:33:21 +0200253 }
254
255 if (cfg.si7_present or cfg.si8_present) {
256 /* vi) Use of System Information type 7 and 8 is not always necessary. It is necessary
257 * if System Information type 4 does not contain all information needed for cell
258 * selection and reselection. */
259 if (not cfg.bcch_extended) {
Harald Welte75f761f2017-07-16 03:05:31 +0200260 testcase.stop("Error: SI7/SI8 require BCCH Extd.");
Harald Welteaf549412017-07-15 21:33:21 +0200261 }
262 if (cfg.si7_present) {
263 f_ensure_si_vec_contains(si_per_tc, 7, SYSTEM_INFORMATION_TYPE_7, true);
264 }
265 if (cfg.si8_present) {
266 f_ensure_si_vec_contains(si_per_tc, 3, SYSTEM_INFORMATION_TYPE_8, true);
267 }
268 }
269
270 if (cfg.si2quater_present) {
271 /* iii) System information type 2 quater is sent if needed, as determined by the system
272 * operator. If sent on BCCH Norm, it shall be sent when TC = 5 if neither of 2bis
273 * and 2ter are used, otherwise it shall be sent at least once within any of 4
274 * consecutive occurrences of TC = 4. If sent on BCCH Ext, it is sent at least once
275 * within any of 4 consecutive occurrences of TC = 5. */
276 if (not (cfg.bcch_extended)) {
277 if (not (cfg.si2bis_present or cfg.si2ter_present)) {
278 f_ensure_si_vec_contains(si_per_tc, 5, SYSTEM_INFORMATION_TYPE_2quater);
279 } else {
Harald Welte39276772017-07-16 01:07:42 +0200280 f_ensure_si_vec_contains_n_of_m(si_per_tc, 4, SYSTEM_INFORMATION_TYPE_2quater, false, 1, 4);
Harald Welteaf549412017-07-15 21:33:21 +0200281 }
282 } else {
Harald Welte39276772017-07-16 01:07:42 +0200283 f_ensure_si_vec_contains_n_of_m(si_per_tc, 5, SYSTEM_INFORMATION_TYPE_2quater, true, 1, 4);
Harald Welteaf549412017-07-15 21:33:21 +0200284 }
285 }
286 if (cfg.si9_present) {
287 /* vi) System Information type 9 is sent in those blocks with TC = 4 which are specified
288 * in system information type 3 as defined in 3GPP TS 44.018. */
289 f_ensure_si_vec_contains(si_per_tc, 4, SYSTEM_INFORMATION_TYPE_9); // FIXME SI3
290 }
291 if (cfg.si13_present) {
292 /* vii) System Information type 13 is only related to the GPRS service. System Information
293 * Type 13 need only be sent if GPRS support is indicated in one or more of System
294 * Information Type 3 or 4 or 7 or 8 messages. These messages also indicate if the
295 * message is sent on the BCCH Norm or if the message is transmitted on the BCCH Ext.
296 * In the case that the message is sent on the BCCH Norm, it is sent at least once
297 * within any of 4 consecutive occurrences of TC=4. */
298 if (not cfg.bcch_extended) {
Harald Welte39276772017-07-16 01:07:42 +0200299 f_ensure_si_vec_contains_n_of_m(si_per_tc, 4, SYSTEM_INFORMATION_TYPE_13, false, 1, 4);
Harald Welteaf549412017-07-15 21:33:21 +0200300 } else {
301 f_ensure_si_vec_contains(si_per_tc, 0, SYSTEM_INFORMATION_TYPE_13, true);
302 }
303 if (f_si_vec_contains(si_per_tc, SYSTEM_INFORMATION_TYPE_13alt)) {
304 setverdict(fail, "Cannot have SI13alt and SI13");
305 }
306 }
307 if (cfg.si16_present or cfg.si17_present) {
308 /* viii) System Information type 16 and 17 are only related to the SoLSA service. They
309 * should not be sent in a cell where network sharing is used (see rule xv). */
310 if (cfg.si22_present) {
Harald Welte75f761f2017-07-16 03:05:31 +0200311 testcase.stop("Error: Cannot have SI16/SI17 and SI22!");
Harald Welteaf549412017-07-15 21:33:21 +0200312 }
313 if (f_si_vec_contains(si_per_tc, SYSTEM_INFORMATION_TYPE_22)) {
314 setverdict(fail, "Cannot have SI16/SI17 and SI22!");
315 }
316 if (not cfg.bcch_extended) {
Harald Welte75f761f2017-07-16 03:05:31 +0200317 testcase.stop("Error: SI16/SI17 requires BCCH Extd!");
Harald Welteaf549412017-07-15 21:33:21 +0200318 }
319 if (cfg.si16_present) {
320 f_ensure_si_vec_contains(si_per_tc, 6, SYSTEM_INFORMATION_TYPE_16, true);
321 }
322 if (cfg.si17_present) {
323 f_ensure_si_vec_contains(si_per_tc, 2, SYSTEM_INFORMATION_TYPE_17, true);
324 }
325 }
326
327 /* ix) System Information type 18 and 20 are sent in order to transmit non-GSM
328 * broadcast information. The frequency with which they are sent is determined by the
329 * system operator. System Information type 9 identifies the scheduling of System
330 * Information type 18 and 20 messages. */
331
332 /* x) System Information Type 19 is sent if COMPACT neighbours exist. If System
333 * Information Type 19 is present, then its scheduling shall be indicated in System
334 * Information Type 9. */
335
336 if (cfg.si15_present) {
337 /* xi) System Information Type 15 is broadcast if dynamic ARFCN mapping is used in the
338 * PLMN. If sent on BCCH Norm, it is sent at least once within any of 4 consecutive
339 * occurrences of TC = 4. If sent on BCCH Ext, it is sent at least once within any of
340 * 4 consecutive occurrences of TC = 1. */
341 if (not cfg.bcch_extended) {
Harald Welte39276772017-07-16 01:07:42 +0200342 f_ensure_si_vec_contains_n_of_m(si_per_tc, 4, SYSTEM_INFORMATION_TYPE_15, false, 1, 4);
Harald Welteaf549412017-07-15 21:33:21 +0200343 } else {
Harald Welte39276772017-07-16 01:07:42 +0200344 f_ensure_si_vec_contains_n_of_m(si_per_tc, 1, SYSTEM_INFORMATION_TYPE_15, true, 1, 4);
Harald Welteaf549412017-07-15 21:33:21 +0200345 }
346 }
347 if (cfg.si13alt_present) {
348 /* xii) System Information type 13 alt is only related to the GERAN Iu mode. System
349 * Information Type 13 alt need only be sent if GERAN Iu mode support is indicated in
350 * one or more of System Information Type 3 or 4 or 7 or 8 messages and SI 13 is not
351 * broadcast. These messages also indicate if the message is sent on the BCCH Norm or
352 * if the message is transmitted on the BCCH Ext. In the case that the message is sent
353 * on the BCCH Norm, it is sent at least once within any of 4 consecutive occurrences
354 * of TC = 4. */
355 if (cfg.si13_present) {
Harald Welte75f761f2017-07-16 03:05:31 +0200356 testcase.stop("Error: Cannot have SI13alt and SI13");
Harald Welteaf549412017-07-15 21:33:21 +0200357 }
358 if (f_si_vec_contains(si_per_tc, SYSTEM_INFORMATION_TYPE_13)) {
359 setverdict(fail, "Cannot have SI13alt and SI13");
360 }
361 if (not cfg.bcch_extended) {
Harald Welte39276772017-07-16 01:07:42 +0200362 f_ensure_si_vec_contains_n_of_m(si_per_tc, 4, SYSTEM_INFORMATION_TYPE_13alt, false, 1, 4);
Harald Welteaf549412017-07-15 21:33:21 +0200363 } else {
364 f_ensure_si_vec_contains(si_per_tc, 0, SYSTEM_INFORMATION_TYPE_13alt, true);
365 }
366 }
367 if (cfg.si2n_present) {
368 /* xiii) System Information Type 2n is optionally sent on BCCH Norm or BCCH Ext if needed,
369 * as determined by the system operator. In the case that the message is sent on the
370 * BCCH Norm, it is sent at least once within any of 4 consecutive occurrences of TC =
371 * 4. If the message is sent on BCCH Ext, it is sent at least once within any of 2
372 * consecutive occurrences of TC = 4. */
373 if (not cfg.bcch_extended) {
Harald Welte39276772017-07-16 01:07:42 +0200374 f_ensure_si_vec_contains_n_of_m(si_per_tc, 4, SYSTEM_INFORMATION_TYPE_2n, false, 1, 4);
Harald Welteaf549412017-07-15 21:33:21 +0200375 } else {
Harald Welte39276772017-07-16 01:07:42 +0200376 f_ensure_si_vec_contains_n_of_m(si_per_tc, 4, SYSTEM_INFORMATION_TYPE_2n, true, 2, 4);
Harald Welteaf549412017-07-15 21:33:21 +0200377 }
378 }
379 if (cfg.si21_present) {
380 /* xiv) System Information Type 21 is optionally sent on BCCH Norm or BCCH Ext, as
381 * determined by the system operator. If Extended Access Barring is in use in the cell
382 * then this message is sent at least once within any of 4 consecutive occurrences of
383 * TC = 4 regardless if it is sent on BCCH Norm or BCCH Ext. If BCCH Ext is used in a
384 * cell then this message shall only be sent on BCCH Ext. */
385 if (not cfg.bcch_extended) {
Harald Welte39276772017-07-16 01:07:42 +0200386 f_ensure_si_vec_contains_n_of_m(si_per_tc, 4, SYSTEM_INFORMATION_TYPE_21, false, 1, 4);
Harald Welteaf549412017-07-15 21:33:21 +0200387 } else {
Harald Welte39276772017-07-16 01:07:42 +0200388 f_ensure_si_vec_contains_n_of_m(si_per_tc, 4, SYSTEM_INFORMATION_TYPE_21, true, 1, 4);
Harald Welteaf549412017-07-15 21:33:21 +0200389 if (f_si_vecslot_contains(si_per_tc[4], SYSTEM_INFORMATION_TYPE_21)) {
390 setverdict(fail, "Cannot have SI21 on BCCH Norm if BCCH Extd enabled!");
391 }
392 }
393 }
394 if (cfg.si22_present) {
395 /* xv) System Information Type 22 is sent if network sharing is in use in the cell. It
396 * should not be sent in a cell where SoLSA is used (see rule viii). System
397 * Information Type 22 instances shall be sent on BCCH Ext within any occurrence of TC
398 * =2 and TC=6. */
399 if (cfg.si16_present or cfg.si17_present) {
Harald Welte75f761f2017-07-16 03:05:31 +0200400 testcase.stop("Error: Cannot have SI16/SI17 and SI22!");
Harald Welteaf549412017-07-15 21:33:21 +0200401 }
402 if (f_si_vec_contains(si_per_tc, SYSTEM_INFORMATION_TYPE_16) or
403 f_si_vec_contains(si_per_tc, SYSTEM_INFORMATION_TYPE_17)) {
404 setverdict(fail, "Cannot have SI16/SI17 and SI22!");
405 }
406 if (not cfg.bcch_extended) {
Harald Welte75f761f2017-07-16 03:05:31 +0200407 testcase.stop("Error: SI22 requires BCCH Extd!");
Harald Welte39276772017-07-16 01:07:42 +0200408 } else {
409 f_ensure_si_vec_contains_only(si_per_tc, 2, SYSTEM_INFORMATION_TYPE_22, true);
410 f_ensure_si_vec_contains_only(si_per_tc, 6, SYSTEM_INFORMATION_TYPE_22, true);
Harald Welteaf549412017-07-15 21:33:21 +0200411 }
412 }
413 }
414
415
Harald Welte39276772017-07-16 01:07:42 +0200416 function f_gsmtap_sample_si(GSMTAP_PT pt, float duration := 8.0) return SystemInformationVectorPerTc {
Harald Welteaf549412017-07-15 21:33:21 +0200417 timer T := duration;
418 var SystemInformationVectorPerTc si_per_tc;
419 var GSMTAP_RecvFrom rf;
420
421 /* initialize all per-TC vectors empty */
422 for (var integer i := 0; i < sizeof(si_per_tc); i := i + 1) {
423 si_per_tc[i] := {};
424 }
425
Harald Weltebdc5dbd2017-07-16 00:00:43 +0200426 /* flush all previous/buffered elements */
427 pt.clear
428
Harald Welteaf549412017-07-15 21:33:21 +0200429 T.start;
430 alt {
431 [] pt.receive(t_recvfrom(GSMTAP_CHANNEL_BCCH)) -> value rf {
432 var SystemInformation si := dec_SystemInformation(rf.msg.payload);
433 var SystemInformationGsmtap sig := { rf.msg.header, si };
434 var integer tc := f_gsm_compute_tc(rf.msg.header.frame_number);
435 log("SI received at TC=", tc, ": ", si);
436 /* append to the per-TC bucket */
437 si_per_tc[tc] := si_per_tc[tc] & { sig };
438 repeat;
439 }
440 [] pt.receive { repeat; };
441 [] T.timeout { };
442 }
Harald Welte39276772017-07-16 01:07:42 +0200443 for (var integer i := 0; i < sizeof(si_per_tc); i := i + 1) {
444 log(testcasename(), ": TC=", i, " has #of SI=", sizeof(si_per_tc[i]));
445 }
Harald Welteaf549412017-07-15 21:33:21 +0200446 return si_per_tc;
447 }
448
Harald Weltebdc5dbd2017-07-16 00:00:43 +0200449 function f_init() runs on dummy_CT {
450 if (initialized) {
451 return;
452 }
453 /* GSMTAP initialization */
Harald Welteb622a3d2017-07-14 22:26:33 +0200454 map(self:GSMTAP, system:GSMTAP);
455 IPL4_GSMTAP_CtrlFunct.f_IPL4_listen(GSMTAP, "0.0.0.0", GSMTAP_PORT, {udp := {}});
456
Harald Weltebdc5dbd2017-07-16 00:00:43 +0200457 /* VTY initialization */
458 map(self:BSCVTY, system:BSCVTY);
459 f_vty_set_prompts(BSCVTY)
Harald Weltefd512cb2017-07-16 01:34:15 +0200460 f_vty_transceive(BSCVTY, "enable");
Harald Weltebdc5dbd2017-07-16 00:00:43 +0200461
462 initialized := true;
463 }
464
465 testcase TC_si_default() runs on dummy_CT {
466 var SystemInformationVectorPerTc si_per_tc;
467
468 f_init();
469
Harald Welteaf549412017-07-15 21:33:21 +0200470 si_per_tc := f_gsmtap_sample_si(GSMTAP);
Harald Welteaf549412017-07-15 21:33:21 +0200471 f_validate_si_scheduling(si_cfg, si_per_tc);
Harald Weltebdc5dbd2017-07-16 00:00:43 +0200472
Harald Welteaf549412017-07-15 21:33:21 +0200473 setverdict(pass);
Harald Welteb622a3d2017-07-14 22:26:33 +0200474 }
475
Harald Weltebdc5dbd2017-07-16 00:00:43 +0200476 testcase TC_si_sched_2bis() runs on dummy_CT {
477 var SystemInformationVectorPerTc si_per_tc;
478 f_init();
479
480 /* Enable SI2bis + validate scheduling */
Harald Weltebdc5dbd2017-07-16 00:00:43 +0200481 si_cfg.si2bis_present := true;
Harald Weltefe1052d2017-07-16 01:24:01 +0200482 f_si_cfg_to_vty();
Harald Weltebdc5dbd2017-07-16 00:00:43 +0200483 si_per_tc := f_gsmtap_sample_si(GSMTAP);
484 f_validate_si_scheduling(si_cfg, si_per_tc);
485
486 /* cleanup */
Harald Weltebdc5dbd2017-07-16 00:00:43 +0200487 si_cfg.si2bis_present := false;
Harald Weltefe1052d2017-07-16 01:24:01 +0200488 f_si_cfg_to_vty();
Harald Weltebdc5dbd2017-07-16 00:00:43 +0200489
490 setverdict(pass);
491 }
492
493 testcase TC_si_sched_2ter() runs on dummy_CT {
494 var SystemInformationVectorPerTc si_per_tc;
495 f_init();
496
497 /* Enable SI2ter + validate scheduling */
Harald Weltebdc5dbd2017-07-16 00:00:43 +0200498 si_cfg.si2ter_present := true;
Harald Weltefe1052d2017-07-16 01:24:01 +0200499 f_si_cfg_to_vty();
Harald Weltebdc5dbd2017-07-16 00:00:43 +0200500 si_per_tc := f_gsmtap_sample_si(GSMTAP);
501 f_validate_si_scheduling(si_cfg, si_per_tc);
502
503 /* cleanup */
Harald Weltebdc5dbd2017-07-16 00:00:43 +0200504 si_cfg.si2ter_present := false;
Harald Weltefe1052d2017-07-16 01:24:01 +0200505 f_si_cfg_to_vty();
Harald Weltebdc5dbd2017-07-16 00:00:43 +0200506
507 setverdict(pass);
508 }
509
510 testcase TC_si_sched_2ter_2bis() runs on dummy_CT {
511 var SystemInformationVectorPerTc si_per_tc;
512 f_init();
513
514 /* Enable SI2bis + SI2ter + validate scheduling */
Harald Weltebdc5dbd2017-07-16 00:00:43 +0200515 si_cfg.si2bis_present := true;
516 si_cfg.si2ter_present := true;
Harald Weltefe1052d2017-07-16 01:24:01 +0200517 f_si_cfg_to_vty();
Harald Weltebdc5dbd2017-07-16 00:00:43 +0200518 si_per_tc := f_gsmtap_sample_si(GSMTAP);
519 f_validate_si_scheduling(si_cfg, si_per_tc);
520
521 /* cleanup */
Harald Weltebdc5dbd2017-07-16 00:00:43 +0200522 si_cfg.si2bis_present := false;
523 si_cfg.si2ter_present := false;
Harald Weltefe1052d2017-07-16 01:24:01 +0200524 f_si_cfg_to_vty();
Harald Weltebdc5dbd2017-07-16 00:00:43 +0200525
526 setverdict(pass);
527 }
528
529 testcase TC_si_sched_2quater() runs on dummy_CT {
530 var SystemInformationVectorPerTc si_per_tc;
531 f_init();
532
533 /* Enable SI2quater + validate scheduling */
Harald Weltebdc5dbd2017-07-16 00:00:43 +0200534 si_cfg.si2quater_present := true;
Harald Weltefe1052d2017-07-16 01:24:01 +0200535 f_si_cfg_to_vty();
Harald Weltebdc5dbd2017-07-16 00:00:43 +0200536
537 /* cleanup */
Harald Weltebdc5dbd2017-07-16 00:00:43 +0200538 si_cfg.si2quater_present := false;
Harald Weltefe1052d2017-07-16 01:24:01 +0200539 f_si_cfg_to_vty();
Harald Weltebdc5dbd2017-07-16 00:00:43 +0200540
541 setverdict(pass);
542 }
543
544 testcase TC_si_sched_13() runs on dummy_CT {
545 var SystemInformationVectorPerTc si_per_tc;
546 f_init();
547
548 /* Enable SI2ter + validate scheduling */
Harald Weltebdc5dbd2017-07-16 00:00:43 +0200549 si_cfg.si13_present := true;
Harald Weltefe1052d2017-07-16 01:24:01 +0200550 f_si_cfg_to_vty();
Harald Weltebdc5dbd2017-07-16 00:00:43 +0200551 si_per_tc := f_gsmtap_sample_si(GSMTAP);
552 f_validate_si_scheduling(si_cfg, si_per_tc);
553
554 /* cleanup */
Harald Weltebdc5dbd2017-07-16 00:00:43 +0200555 si_cfg.si13_present := false;
Harald Weltefe1052d2017-07-16 01:24:01 +0200556 f_si_cfg_to_vty();
Harald Weltebdc5dbd2017-07-16 00:00:43 +0200557
558 setverdict(pass);
559 }
Harald Welte9a907b32017-07-15 10:34:27 +0200560
Harald Weltefe1052d2017-07-16 01:24:01 +0200561 testcase TC_si_sched_13_2bis_2ter_2quater() runs on dummy_CT {
562 var SystemInformationVectorPerTc si_per_tc;
563 f_init();
564
565 si_cfg.si2bis_present := true;
566 si_cfg.si2ter_present := true;
567 si_cfg.si2quater_present := true;
568 si_cfg.si13_present := true;
569 f_si_cfg_to_vty();
570 si_per_tc := f_gsmtap_sample_si(GSMTAP);
571 f_validate_si_scheduling(si_cfg, si_per_tc);
572
573 /* cleanup */
574 si_cfg.si2bis_present := false;
575 si_cfg.si2ter_present := false;
576 si_cfg.si2quater_present := false;
577 si_cfg.si13_present := false;
578 f_si_cfg_to_vty();
579
580 setverdict(pass);
581 }
582
583 function f_si_cfg_to_vty() runs on dummy_CT {
584 if (si_cfg.si2bis_present) {
585 f_vty_si_static(BSCVTY, 0, "2bis", c_si2bis);
586 } else {
587 f_vty_si_computed(BSCVTY, 0, "2bis");
588 }
589 if (si_cfg.si2ter_present) {
590 f_vty_si_static(BSCVTY, 0, "2ter", c_si2ter);
591 } else {
592 f_vty_si_computed(BSCVTY, 0, "2ter");
593 }
594 if (si_cfg.si13_present) {
595 f_vty_gprs_mode(BSCVTY, 0, "gprs");
596 } else {
597 f_vty_gprs_mode(BSCVTY, 0, "none");
598 }
599 if (si_cfg.si2quater_present) {
600 f_vty_si2q_add_uarfcn(BSCVTY, 0, 23, 42);
601 } else {
602 f_vty_si2q_del_uarfcn(BSCVTY, 0, 23, 42);
603 }
604 /* for debugging */
605 f_vty_transceive(BSCVTY, "write terminal");
606 /* actually commit the changes from BSC -> BTS */
607 f_vty_si_resend(BSCVTY, 0);
608 }
Harald Welte9a907b32017-07-15 10:34:27 +0200609
610 /* permitted prompts on VTY */
611 const charstring NORMAL_PROMPT := "OpenBSC> ";
612 const charstring ENABLE_PROMPT := "OpenBSC# ";
613 const charstring CONFIG_PROMPT := "OpenBSC(*)\#";
Harald Welted1f74c62017-07-16 03:04:37 +0200614 template charstring t_vty_unknown := pattern "*% Unknown command.";
Harald Welte9a907b32017-07-15 10:34:27 +0200615
616 const ASP_TelnetDynamicConfig vty_prompt[3] := {
617 {
618 prompt := {
619 id := 1,
620 prompt := NORMAL_PROMPT,
621 has_wildcards := false
622 }
623 }, {
624 prompt := {
625 id := 2,
626 prompt := ENABLE_PROMPT,
627 has_wildcards := false
628 }
629 }, {
630 prompt := {
631 id := 3,
632 prompt := CONFIG_PROMPT,
633 has_wildcards := true
634 }
635 }
636 };
637
638 /* configure prompts in TELNETasp module */
639 function f_vty_set_prompts(TELNETasp_PT pt) {
640 /* set some configuration that isn't possible to express
641 * in the config file due to syntactic restrictions (Who invents config
642 * files that don't permit regular expressions? */
643 for (var integer i := 0; i < sizeof(vty_prompt); i:= i + 1) {
644 pt.send(vty_prompt[i])
645 }
646 }
647
648 /* wait for any of the permitted prompts; buffer + return all intermediate output */
649 function f_vty_wait_for_prompt(TELNETasp_PT pt) return charstring {
650 template charstring config_pattern := pattern CONFIG_PROMPT;
651 var charstring rx, buf := "";
652 timer T := 2.0;
653
654 T.start;
655 alt {
656 [] pt.receive(NORMAL_PROMPT) { };
657 [] pt.receive(ENABLE_PROMPT) { };
658 [] pt.receive(config_pattern) { };
Harald Welte75f761f2017-07-16 03:05:31 +0200659 [] pt.receive(t_vty_unknown) { testcase.stop(fail, "VTY: Unknown Command") };
Harald Welte9a907b32017-07-15 10:34:27 +0200660 [] pt.receive(charstring:?) -> value rx { buf := buf & rx; repeat };
Harald Weltebdc5dbd2017-07-16 00:00:43 +0200661 [] T.timeout { setverdict(fail, "VTY Timeout for prompt"); return ""};
Harald Welte9a907b32017-07-15 10:34:27 +0200662 }
663 T.stop;
664 return buf;
665 }
666
667 /* send a VTY command and obtain response until prompt is received */
Harald Welted7bd30f2017-07-16 03:54:54 +0200668 function f_vty_transceive_ret(TELNETasp_PT pt, charstring tx) return charstring {
Harald Welte9a907b32017-07-15 10:34:27 +0200669 pt.send(tx);
670 return f_vty_wait_for_prompt(pt);
671 }
672
Harald Welted7bd30f2017-07-16 03:54:54 +0200673 /* send a VTY command and obtain response until prompt is received */
674 function f_vty_transceive(TELNETasp_PT pt, charstring tx) {
675 f_vty_transceive_ret(pt, tx);
676 }
677
Harald Weltebdc5dbd2017-07-16 00:00:43 +0200678 type integer BtsNr (0..255);
679 type integer BtsTrxNr (0..255);
680 type integer BtsTimeslotNr (0..7);
681
682 type charstring BtsGprsMode ("none", "gprs", "egrps");
683
Harald Welte9a907b32017-07-15 10:34:27 +0200684 /* enter the'confiugration' mode of the VTY */
685 function f_vty_enter_config(TELNETasp_PT pt) {
Harald Welte9a907b32017-07-15 10:34:27 +0200686 f_vty_transceive(pt, "configure terminal")
687 }
688
Harald Weltebdc5dbd2017-07-16 00:00:43 +0200689 function f_vty_enter_cfg_network(TELNETasp_PT pt) {
690 f_vty_enter_config(pt);
691 f_vty_transceive(pt, "network")
692 }
Harald Welte9a907b32017-07-15 10:34:27 +0200693
Harald Weltebdc5dbd2017-07-16 00:00:43 +0200694 function f_vty_enter_cfg_bts(TELNETasp_PT pt, BtsNr bts := 0) {
695 f_vty_enter_cfg_network(pt);
696 f_vty_transceive(pt, "bts " & int2str(bts));
697 }
698
699 function f_vty_enter_cfg_trx(TELNETasp_PT pt, BtsNr bts := 0, BtsTrxNr trx := 0) {
700 f_vty_enter_cfg_bts(pt, bts);
701 f_vty_transceive(pt, "trx " & int2str(trx));
702 }
703
704 function f_vty_enter_cfg_ts(TELNETasp_PT pt, BtsNr bts := 0, BtsTrxNr trx := 0, BtsTimeslotNr ts) {
705 f_vty_enter_cfg_trx(pt, bts, trx);
706 f_vty_transceive(pt, "timeslot " & int2str(ts));
707 }
708
709 function f_vty_si_static(TELNETasp_PT pt, BtsNr bts, charstring si, octetstring bytes) {
710 f_vty_enter_cfg_bts(pt, bts);
711 f_vty_transceive(pt, "system-information " & si & " mode static");
712 f_vty_transceive(pt, "system-information " & si & " static " & hex2str(oct2hex(bytes)));
713 f_vty_transceive(pt, "end");
714 }
715
716 function f_vty_si_computed(TELNETasp_PT pt, BtsNr bts, charstring si) {
717 f_vty_enter_cfg_bts(pt, bts);
718 f_vty_transceive(pt, "system-information " & si & " mode computed");
719 f_vty_transceive(pt, "end");
720 }
721
722 function f_vty_si_resend(TELNETasp_PT pt, BtsNr bts := 0) {
723 f_vty_transceive(pt, "bts " & int2str(bts) & " resend-system-information");
Harald Weltec17c88e2017-07-16 00:39:59 +0200724 /* wait for 1s until changes propagate */
725 timer T := 1.0;
Harald Weltebdc5dbd2017-07-16 00:00:43 +0200726 T.start;
727 T.timeout;
728 }
729
730 function f_vty_gprs_mode(TELNETasp_PT pt, integer bts, BtsGprsMode mode) {
731 f_vty_enter_cfg_bts(pt, bts);
732 f_vty_transceive(pt, "gprs mode " & mode);
733 f_vty_transceive(pt, "end");
734 }
735
736 function f_vty_si2q_add_uarfcn(TELNETasp_PT pt, BtsNr bts, UmtsArfcn uarfcn, UmtsScramblingCode sc, integer diversity := 0) {
737 f_vty_enter_cfg_bts(pt, bts);
738 f_vty_transceive(pt, "si2quater neighbor-list add uarfcn " & int2str(uarfcn) & " " & int2str(sc) & " " & int2str(diversity));
739 f_vty_transceive(pt, "end");
740 }
741
742 function f_vty_si2q_del_uarfcn(TELNETasp_PT pt, BtsNr bts, UmtsArfcn uarfcn, UmtsScramblingCode sc) {
743 f_vty_enter_cfg_bts(pt, bts);
744 f_vty_transceive(pt, "si2quater neighbor-list del uarfcn " & int2str(uarfcn) & " " & int2str(sc));
745 f_vty_transceive(pt, "end");
746 }
747
748 testcase TC_telnet() runs on dummy_CT {
749 f_init();
Harald Weltefd512cb2017-07-16 01:34:15 +0200750 f_vty_enter_config(BSCVTY);
Harald Welte9a907b32017-07-15 10:34:27 +0200751 f_vty_transceive(BSCVTY, "show network")
Harald Welte9a907b32017-07-15 10:34:27 +0200752 f_vty_transceive(BSCVTY, "network")
753 f_vty_transceive(BSCVTY, "bts 0")
Harald Weltebdc5dbd2017-07-16 00:00:43 +0200754 f_vty_transceive(BSCVTY, "end")
755 setverdict(pass);
Harald Welte9a907b32017-07-15 10:34:27 +0200756 }
757
Harald Welte56db5fd2017-07-14 18:25:59 +0200758 control {
759 execute(TC_si1());
Harald Welte9a907b32017-07-15 10:34:27 +0200760 execute(TC_telnet());
Harald Weltebdc5dbd2017-07-16 00:00:43 +0200761 execute(TC_si_default());
762 execute(TC_si_sched_2bis());
763 execute(TC_si_sched_2ter());
764 execute(TC_si_sched_2ter_2bis());
765 execute(TC_si_sched_2quater());
766 execute(TC_si_sched_13());
Harald Weltefe1052d2017-07-16 01:24:01 +0200767 execute(TC_si_sched_13_2bis_2ter_2quater());
Harald Welte56db5fd2017-07-14 18:25:59 +0200768 }
769}