blob: 3ef4730dbb6fe5e4cedf2ba56a7f41dc3ed4b741 [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
128 /* check if a given SI vector contains given SI type at least once on any TC */
129 function f_si_vec_contains(SystemInformationVectorPerTc arr, RrMessageType key) return boolean {
130 for (var integer tc:= 0; tc < sizeof(arr); tc := tc + 1) {
131 if (f_si_vecslot_contains(arr[tc], key) or
132 f_si_vecslot_contains(arr[tc], key, true)) {
133 return true;
134 }
135 }
136 return false;
137 }
138
139 /* ensure a given TC slot of the SI vector contains given SI type at least once at TC */
140 function f_ensure_si_vec_contains(SystemInformationVectorPerTc arr, integer tc, RrMessageType key,
141 boolean ext_bcch := false) {
142 if (not f_si_vecslot_contains(arr[tc], key, ext_bcch)) {
143 log("Fail: No ", key, " in TC=", tc, "!");
144 setverdict(fail);
145 }
146 }
147
148 /* SI configuration of cell, against which we validate actual SI messages */
149 type set SystemInformationConfig {
150 boolean bcch_extended,
151 boolean si1_present,
152 boolean si2bis_present,
153 boolean si2ter_present,
154 boolean si2quater_present,
155 boolean si7_present,
156 boolean si8_present,
157 boolean si9_present,
158 boolean si13_present,
159 boolean si13alt_present,
160 boolean si15_present,
161 boolean si16_present,
162 boolean si17_present,
163 boolean si2n_present,
164 boolean si21_present,
165 boolean si22_present
166 }
167
168 /* validate the SI scheduling according to TS 45.002 version 14.1.0 Release 14, Section 6.3.1.3 */
169 function f_validate_si_scheduling(SystemInformationConfig cfg, SystemInformationVectorPerTc si_per_tc) {
170 var integer i;
171 for (i := 0; i < sizeof(si_per_tc); i := i + 1) {
172 if (sizeof(si_per_tc[i]) == 0) {
173 setverdict(fail, "No SI messages for TC=0!");
174 }
175 }
176 if (cfg.si1_present) {
177 /* ii) System Information Type 1 needs to be sent if frequency hopping is in use or
178 * when the NCH is present in a cell. If the MS finds another message on BCCH Norm
179 * when TC = 0, it can assume that System Information Type 1 is not in use. */
180 f_ensure_si_vec_contains(si_per_tc, 0, SYSTEM_INFORMATION_TYPE_1);
181 /* FIXME: make sure *ALL* contain SI1 */
182 }
183 f_ensure_si_vec_contains(si_per_tc, 1, SYSTEM_INFORMATION_TYPE_2);
184 /* iii) A SI 2 message will be sent at least every time TC = 1 */
185 f_ensure_si_vec_contains(si_per_tc, 2, SYSTEM_INFORMATION_TYPE_3);
186 f_ensure_si_vec_contains(si_per_tc, 6, SYSTEM_INFORMATION_TYPE_3);
187 f_ensure_si_vec_contains(si_per_tc, 3, SYSTEM_INFORMATION_TYPE_4);
188 f_ensure_si_vec_contains(si_per_tc, 7, SYSTEM_INFORMATION_TYPE_4);
189
190 /* iii) System information type 2 bis or 2 ter messages are sent if needed, as determined by the
191 * system operator. If only one of them is needed, it is sent when TC = 5. If both are
192 * needed, 2bis is sent when TC = 5 and 2ter is sent at least once within any of 4
193 * consecutive occurrences of TC = 4. */
194 if (cfg.si2bis_present and not cfg.si2ter_present) {
195 f_ensure_si_vec_contains(si_per_tc, 5, SYSTEM_INFORMATION_TYPE_2bis);
196 } else if (cfg.si2ter_present and not cfg.si2bis_present) {
197 f_ensure_si_vec_contains(si_per_tc, 5, SYSTEM_INFORMATION_TYPE_2ter);
198 } else if (cfg.si2ter_present and cfg.si2bis_present) {
199 f_ensure_si_vec_contains(si_per_tc, 5, SYSTEM_INFORMATION_TYPE_2bis);
200 f_ensure_si_vec_contains(si_per_tc, 4, SYSTEM_INFORMATION_TYPE_2ter); //FIXME 1/4
201 }
202
203 if (cfg.si7_present or cfg.si8_present) {
204 /* vi) Use of System Information type 7 and 8 is not always necessary. It is necessary
205 * if System Information type 4 does not contain all information needed for cell
206 * selection and reselection. */
207 if (not cfg.bcch_extended) {
208 setverdict(fail, "Error: SI7/SI8 require BCCH Extd.");
209 }
210 if (cfg.si7_present) {
211 f_ensure_si_vec_contains(si_per_tc, 7, SYSTEM_INFORMATION_TYPE_7, true);
212 }
213 if (cfg.si8_present) {
214 f_ensure_si_vec_contains(si_per_tc, 3, SYSTEM_INFORMATION_TYPE_8, true);
215 }
216 }
217
218 if (cfg.si2quater_present) {
219 /* iii) System information type 2 quater is sent if needed, as determined by the system
220 * operator. If sent on BCCH Norm, it shall be sent when TC = 5 if neither of 2bis
221 * and 2ter are used, otherwise it shall be sent at least once within any of 4
222 * consecutive occurrences of TC = 4. If sent on BCCH Ext, it is sent at least once
223 * within any of 4 consecutive occurrences of TC = 5. */
224 if (not (cfg.bcch_extended)) {
225 if (not (cfg.si2bis_present or cfg.si2ter_present)) {
226 f_ensure_si_vec_contains(si_per_tc, 5, SYSTEM_INFORMATION_TYPE_2quater);
227 } else {
228 f_ensure_si_vec_contains(si_per_tc, 4, SYSTEM_INFORMATION_TYPE_2quater); // FIXME 1/4
229 }
230 } else {
231 f_ensure_si_vec_contains(si_per_tc, 5, SYSTEM_INFORMATION_TYPE_2quater, true); // FIXME: 1/4
232 }
233 }
234 if (cfg.si9_present) {
235 /* vi) System Information type 9 is sent in those blocks with TC = 4 which are specified
236 * in system information type 3 as defined in 3GPP TS 44.018. */
237 f_ensure_si_vec_contains(si_per_tc, 4, SYSTEM_INFORMATION_TYPE_9); // FIXME SI3
238 }
239 if (cfg.si13_present) {
240 /* vii) System Information type 13 is only related to the GPRS service. System Information
241 * Type 13 need only be sent if GPRS support is indicated in one or more of System
242 * Information Type 3 or 4 or 7 or 8 messages. These messages also indicate if the
243 * message is sent on the BCCH Norm or if the message is transmitted on the BCCH Ext.
244 * In the case that the message is sent on the BCCH Norm, it is sent at least once
245 * within any of 4 consecutive occurrences of TC=4. */
246 if (not cfg.bcch_extended) {
247 f_ensure_si_vec_contains(si_per_tc, 4, SYSTEM_INFORMATION_TYPE_13); // FIXME 1/4
248 } else {
249 f_ensure_si_vec_contains(si_per_tc, 0, SYSTEM_INFORMATION_TYPE_13, true);
250 }
251 if (f_si_vec_contains(si_per_tc, SYSTEM_INFORMATION_TYPE_13alt)) {
252 setverdict(fail, "Cannot have SI13alt and SI13");
253 }
254 }
255 if (cfg.si16_present or cfg.si17_present) {
256 /* viii) System Information type 16 and 17 are only related to the SoLSA service. They
257 * should not be sent in a cell where network sharing is used (see rule xv). */
258 if (cfg.si22_present) {
259 setverdict(fail, "Error: Cannot have SI16/SI17 and SI22!");
260 }
261 if (f_si_vec_contains(si_per_tc, SYSTEM_INFORMATION_TYPE_22)) {
262 setverdict(fail, "Cannot have SI16/SI17 and SI22!");
263 }
264 if (not cfg.bcch_extended) {
265 setverdict(fail, "Error: SI16/SI17 requires BCCH Extd!");
266 }
267 if (cfg.si16_present) {
268 f_ensure_si_vec_contains(si_per_tc, 6, SYSTEM_INFORMATION_TYPE_16, true);
269 }
270 if (cfg.si17_present) {
271 f_ensure_si_vec_contains(si_per_tc, 2, SYSTEM_INFORMATION_TYPE_17, true);
272 }
273 }
274
275 /* ix) System Information type 18 and 20 are sent in order to transmit non-GSM
276 * broadcast information. The frequency with which they are sent is determined by the
277 * system operator. System Information type 9 identifies the scheduling of System
278 * Information type 18 and 20 messages. */
279
280 /* x) System Information Type 19 is sent if COMPACT neighbours exist. If System
281 * Information Type 19 is present, then its scheduling shall be indicated in System
282 * Information Type 9. */
283
284 if (cfg.si15_present) {
285 /* xi) System Information Type 15 is broadcast if dynamic ARFCN mapping is used in the
286 * PLMN. If sent on BCCH Norm, it is sent at least once within any of 4 consecutive
287 * occurrences of TC = 4. If sent on BCCH Ext, it is sent at least once within any of
288 * 4 consecutive occurrences of TC = 1. */
289 if (not cfg.bcch_extended) {
290 f_ensure_si_vec_contains(si_per_tc, 4, SYSTEM_INFORMATION_TYPE_15); // FIXME 1/4
291 } else {
292 f_ensure_si_vec_contains(si_per_tc, 1, SYSTEM_INFORMATION_TYPE_15, true); // FIXME 1/4
293 }
294 }
295 if (cfg.si13alt_present) {
296 /* xii) System Information type 13 alt is only related to the GERAN Iu mode. System
297 * Information Type 13 alt need only be sent if GERAN Iu mode support is indicated in
298 * one or more of System Information Type 3 or 4 or 7 or 8 messages and SI 13 is not
299 * broadcast. These messages also indicate if the message is sent on the BCCH Norm or
300 * if the message is transmitted on the BCCH Ext. In the case that the message is sent
301 * on the BCCH Norm, it is sent at least once within any of 4 consecutive occurrences
302 * of TC = 4. */
303 if (cfg.si13_present) {
304 setverdict(fail, "Error: Cannot have SI13alt and SI13");
305 }
306 if (f_si_vec_contains(si_per_tc, SYSTEM_INFORMATION_TYPE_13)) {
307 setverdict(fail, "Cannot have SI13alt and SI13");
308 }
309 if (not cfg.bcch_extended) {
310 f_ensure_si_vec_contains(si_per_tc, 4, SYSTEM_INFORMATION_TYPE_13alt); // FIXME 1/4
311 } else {
312 f_ensure_si_vec_contains(si_per_tc, 0, SYSTEM_INFORMATION_TYPE_13alt, true);
313 }
314 }
315 if (cfg.si2n_present) {
316 /* xiii) System Information Type 2n is optionally sent on BCCH Norm or BCCH Ext if needed,
317 * as determined by the system operator. In the case that the message is sent on the
318 * BCCH Norm, it is sent at least once within any of 4 consecutive occurrences of TC =
319 * 4. If the message is sent on BCCH Ext, it is sent at least once within any of 2
320 * consecutive occurrences of TC = 4. */
321 if (not cfg.bcch_extended) {
322 f_ensure_si_vec_contains(si_per_tc, 4, SYSTEM_INFORMATION_TYPE_2n); // FIXME 1/4
323 } else {
324 f_ensure_si_vec_contains(si_per_tc, 4, SYSTEM_INFORMATION_TYPE_2n, true); // FIXME 2/4
325 }
326 }
327 if (cfg.si21_present) {
328 /* xiv) System Information Type 21 is optionally sent on BCCH Norm or BCCH Ext, as
329 * determined by the system operator. If Extended Access Barring is in use in the cell
330 * then this message is sent at least once within any of 4 consecutive occurrences of
331 * TC = 4 regardless if it is sent on BCCH Norm or BCCH Ext. If BCCH Ext is used in a
332 * cell then this message shall only be sent on BCCH Ext. */
333 if (not cfg.bcch_extended) {
334 f_ensure_si_vec_contains(si_per_tc, 4, SYSTEM_INFORMATION_TYPE_21); // FIXME 1/4
335 } else {
336 f_ensure_si_vec_contains(si_per_tc, 4, SYSTEM_INFORMATION_TYPE_21, true); // FIXME 1/4
337 if (f_si_vecslot_contains(si_per_tc[4], SYSTEM_INFORMATION_TYPE_21)) {
338 setverdict(fail, "Cannot have SI21 on BCCH Norm if BCCH Extd enabled!");
339 }
340 }
341 }
342 if (cfg.si22_present) {
343 /* xv) System Information Type 22 is sent if network sharing is in use in the cell. It
344 * should not be sent in a cell where SoLSA is used (see rule viii). System
345 * Information Type 22 instances shall be sent on BCCH Ext within any occurrence of TC
346 * =2 and TC=6. */
347 if (cfg.si16_present or cfg.si17_present) {
348 setverdict(fail, "Error: Cannot have SI16/SI17 and SI22!");
349 }
350 if (f_si_vec_contains(si_per_tc, SYSTEM_INFORMATION_TYPE_16) or
351 f_si_vec_contains(si_per_tc, SYSTEM_INFORMATION_TYPE_17)) {
352 setverdict(fail, "Cannot have SI16/SI17 and SI22!");
353 }
354 if (not cfg.bcch_extended) {
355 setverdict(fail, "Error: SI22 requires BCCH Extd!");
356 }
357 }
358 }
359
360
361 function f_gsmtap_sample_si(GSMTAP_PT pt, float duration := 5.0) return SystemInformationVectorPerTc {
362 timer T := duration;
363 var SystemInformationVectorPerTc si_per_tc;
364 var GSMTAP_RecvFrom rf;
365
366 /* initialize all per-TC vectors empty */
367 for (var integer i := 0; i < sizeof(si_per_tc); i := i + 1) {
368 si_per_tc[i] := {};
369 }
370
Harald Weltebdc5dbd2017-07-16 00:00:43 +0200371 /* flush all previous/buffered elements */
372 pt.clear
373
Harald Welteaf549412017-07-15 21:33:21 +0200374 T.start;
375 alt {
376 [] pt.receive(t_recvfrom(GSMTAP_CHANNEL_BCCH)) -> value rf {
377 var SystemInformation si := dec_SystemInformation(rf.msg.payload);
378 var SystemInformationGsmtap sig := { rf.msg.header, si };
379 var integer tc := f_gsm_compute_tc(rf.msg.header.frame_number);
380 log("SI received at TC=", tc, ": ", si);
381 /* append to the per-TC bucket */
382 si_per_tc[tc] := si_per_tc[tc] & { sig };
383 repeat;
384 }
385 [] pt.receive { repeat; };
386 [] T.timeout { };
387 }
388 return si_per_tc;
389 }
390
Harald Weltebdc5dbd2017-07-16 00:00:43 +0200391 function f_init() runs on dummy_CT {
392 if (initialized) {
393 return;
394 }
395 /* GSMTAP initialization */
Harald Welteb622a3d2017-07-14 22:26:33 +0200396 map(self:GSMTAP, system:GSMTAP);
397 IPL4_GSMTAP_CtrlFunct.f_IPL4_listen(GSMTAP, "0.0.0.0", GSMTAP_PORT, {udp := {}});
398
Harald Weltebdc5dbd2017-07-16 00:00:43 +0200399 /* VTY initialization */
400 map(self:BSCVTY, system:BSCVTY);
401 f_vty_set_prompts(BSCVTY)
402
403 initialized := true;
404 }
405
406 testcase TC_si_default() runs on dummy_CT {
407 var SystemInformationVectorPerTc si_per_tc;
408
409 f_init();
410
Harald Welteaf549412017-07-15 21:33:21 +0200411 si_per_tc := f_gsmtap_sample_si(GSMTAP);
412 log("SI per TC: ", si_per_tc);
413 f_validate_si_scheduling(si_cfg, si_per_tc);
Harald Weltebdc5dbd2017-07-16 00:00:43 +0200414
Harald Welteaf549412017-07-15 21:33:21 +0200415 setverdict(pass);
Harald Welteb622a3d2017-07-14 22:26:33 +0200416 }
417
Harald Weltebdc5dbd2017-07-16 00:00:43 +0200418 testcase TC_si_sched_2bis() runs on dummy_CT {
419 var SystemInformationVectorPerTc si_per_tc;
420 f_init();
421
422 /* Enable SI2bis + validate scheduling */
423 f_vty_enter_cfg_bts(BSCVTY, 0);
424 f_vty_si_static(BSCVTY, 0, "2bis", c_si2bis);
425 f_vty_si_resend(BSCVTY, 0);
426 f_vty_transceive(BSCVTY, "do write terminal");
427 si_cfg.si2bis_present := true;
428 si_per_tc := f_gsmtap_sample_si(GSMTAP);
429 f_validate_si_scheduling(si_cfg, si_per_tc);
430
431 /* cleanup */
432 f_vty_si_computed(BSCVTY, 0, "2bis");
433 f_vty_si_resend(BSCVTY, 0);
434 si_cfg.si2bis_present := false;
435
436 setverdict(pass);
437 }
438
439 testcase TC_si_sched_2ter() runs on dummy_CT {
440 var SystemInformationVectorPerTc si_per_tc;
441 f_init();
442
443 /* Enable SI2ter + validate scheduling */
444 f_vty_enter_cfg_bts(BSCVTY, 0);
445 f_vty_si_static(BSCVTY, 0, "2ter", c_si2ter);
446 f_vty_transceive(BSCVTY, "write terminal");
447 f_vty_si_resend(BSCVTY, 0);
448 si_cfg.si2ter_present := true;
449 si_per_tc := f_gsmtap_sample_si(GSMTAP);
450 f_validate_si_scheduling(si_cfg, si_per_tc);
451
452 /* cleanup */
453 f_vty_si_computed(BSCVTY, 0, "2ter");
454 f_vty_si_resend(BSCVTY, 0);
455 si_cfg.si2ter_present := false;
456
457 setverdict(pass);
458 }
459
460 testcase TC_si_sched_2ter_2bis() runs on dummy_CT {
461 var SystemInformationVectorPerTc si_per_tc;
462 f_init();
463
464 /* Enable SI2bis + SI2ter + validate scheduling */
465 f_vty_enter_cfg_bts(BSCVTY, 0);
466 f_vty_si_static(BSCVTY, 0, "2bis", c_si2bis);
467 f_vty_si_static(BSCVTY, 0, "2ter", c_si2ter);
468 f_vty_transceive(BSCVTY, "write terminal");
469 f_vty_si_resend(BSCVTY, 0);
470 si_cfg.si2bis_present := true;
471 si_cfg.si2ter_present := true;
472 si_per_tc := f_gsmtap_sample_si(GSMTAP);
473 f_validate_si_scheduling(si_cfg, si_per_tc);
474
475 /* cleanup */
476 f_vty_si_computed(BSCVTY, 0, "2bis");
477 f_vty_si_computed(BSCVTY, 0, "2ter");
478 f_vty_si_resend(BSCVTY, 0);
479 si_cfg.si2bis_present := false;
480 si_cfg.si2ter_present := false;
481
482 setverdict(pass);
483 }
484
485 testcase TC_si_sched_2quater() runs on dummy_CT {
486 var SystemInformationVectorPerTc si_per_tc;
487 f_init();
488
489 /* Enable SI2quater + validate scheduling */
490 f_vty_si2q_add_uarfcn(BSCVTY, 0, 23, 42);
491 f_vty_transceive(BSCVTY, "write terminal");
492 f_vty_si_resend(BSCVTY, 0);
493 si_cfg.si2quater_present := true;
494 si_per_tc := f_gsmtap_sample_si(GSMTAP);
495 f_validate_si_scheduling(si_cfg, si_per_tc);
496
497 /* cleanup */
498 f_vty_si2q_del_uarfcn(BSCVTY, 0, 23, 42);
499 f_vty_si_resend(BSCVTY, 0);
500 si_cfg.si2quater_present := false;
501
502 setverdict(pass);
503 }
504
505 testcase TC_si_sched_13() runs on dummy_CT {
506 var SystemInformationVectorPerTc si_per_tc;
507 f_init();
508
509 /* Enable SI2ter + validate scheduling */
510 f_vty_enter_cfg_bts(BSCVTY, 0);
511 f_vty_gprs_mode(BSCVTY, 0, "gprs");
512 f_vty_transceive(BSCVTY, "write terminal");
513 f_vty_si_resend(BSCVTY, 0);
514 si_cfg.si13_present := true;
515 si_per_tc := f_gsmtap_sample_si(GSMTAP);
516 f_validate_si_scheduling(si_cfg, si_per_tc);
517
518 /* cleanup */
519 f_vty_gprs_mode(BSCVTY, 0, "none");
520 f_vty_si_resend(BSCVTY, 0);
521 si_cfg.si13_present := false;
522
523 setverdict(pass);
524 }
Harald Welte9a907b32017-07-15 10:34:27 +0200525
526
527 /* permitted prompts on VTY */
528 const charstring NORMAL_PROMPT := "OpenBSC> ";
529 const charstring ENABLE_PROMPT := "OpenBSC# ";
530 const charstring CONFIG_PROMPT := "OpenBSC(*)\#";
531
532 const ASP_TelnetDynamicConfig vty_prompt[3] := {
533 {
534 prompt := {
535 id := 1,
536 prompt := NORMAL_PROMPT,
537 has_wildcards := false
538 }
539 }, {
540 prompt := {
541 id := 2,
542 prompt := ENABLE_PROMPT,
543 has_wildcards := false
544 }
545 }, {
546 prompt := {
547 id := 3,
548 prompt := CONFIG_PROMPT,
549 has_wildcards := true
550 }
551 }
552 };
553
554 /* configure prompts in TELNETasp module */
555 function f_vty_set_prompts(TELNETasp_PT pt) {
556 /* set some configuration that isn't possible to express
557 * in the config file due to syntactic restrictions (Who invents config
558 * files that don't permit regular expressions? */
559 for (var integer i := 0; i < sizeof(vty_prompt); i:= i + 1) {
560 pt.send(vty_prompt[i])
561 }
562 }
563
564 /* wait for any of the permitted prompts; buffer + return all intermediate output */
565 function f_vty_wait_for_prompt(TELNETasp_PT pt) return charstring {
566 template charstring config_pattern := pattern CONFIG_PROMPT;
567 var charstring rx, buf := "";
568 timer T := 2.0;
569
570 T.start;
571 alt {
572 [] pt.receive(NORMAL_PROMPT) { };
573 [] pt.receive(ENABLE_PROMPT) { };
574 [] pt.receive(config_pattern) { };
Harald Weltebdc5dbd2017-07-16 00:00:43 +0200575 /* FIXME: "% Unknown command" and the like! */
Harald Welte9a907b32017-07-15 10:34:27 +0200576 [] pt.receive(charstring:?) -> value rx { buf := buf & rx; repeat };
Harald Weltebdc5dbd2017-07-16 00:00:43 +0200577 [] T.timeout { setverdict(fail, "VTY Timeout for prompt"); return ""};
Harald Welte9a907b32017-07-15 10:34:27 +0200578 }
579 T.stop;
580 return buf;
581 }
582
583 /* send a VTY command and obtain response until prompt is received */
584 function f_vty_transceive(TELNETasp_PT pt, charstring tx) return charstring {
585 pt.send(tx);
586 return f_vty_wait_for_prompt(pt);
587 }
588
Harald Weltebdc5dbd2017-07-16 00:00:43 +0200589 type integer BtsNr (0..255);
590 type integer BtsTrxNr (0..255);
591 type integer BtsTimeslotNr (0..7);
592
593 type charstring BtsGprsMode ("none", "gprs", "egrps");
594
Harald Welte9a907b32017-07-15 10:34:27 +0200595 /* enter the'confiugration' mode of the VTY */
596 function f_vty_enter_config(TELNETasp_PT pt) {
597 f_vty_transceive(pt, "enable");
598 f_vty_transceive(pt, "configure terminal")
599 }
600
Harald Weltebdc5dbd2017-07-16 00:00:43 +0200601 function f_vty_enter_cfg_network(TELNETasp_PT pt) {
602 f_vty_enter_config(pt);
603 f_vty_transceive(pt, "network")
604 }
Harald Welte9a907b32017-07-15 10:34:27 +0200605
Harald Weltebdc5dbd2017-07-16 00:00:43 +0200606 function f_vty_enter_cfg_bts(TELNETasp_PT pt, BtsNr bts := 0) {
607 f_vty_enter_cfg_network(pt);
608 f_vty_transceive(pt, "bts " & int2str(bts));
609 }
610
611 function f_vty_enter_cfg_trx(TELNETasp_PT pt, BtsNr bts := 0, BtsTrxNr trx := 0) {
612 f_vty_enter_cfg_bts(pt, bts);
613 f_vty_transceive(pt, "trx " & int2str(trx));
614 }
615
616 function f_vty_enter_cfg_ts(TELNETasp_PT pt, BtsNr bts := 0, BtsTrxNr trx := 0, BtsTimeslotNr ts) {
617 f_vty_enter_cfg_trx(pt, bts, trx);
618 f_vty_transceive(pt, "timeslot " & int2str(ts));
619 }
620
621 function f_vty_si_static(TELNETasp_PT pt, BtsNr bts, charstring si, octetstring bytes) {
622 f_vty_enter_cfg_bts(pt, bts);
623 f_vty_transceive(pt, "system-information " & si & " mode static");
624 f_vty_transceive(pt, "system-information " & si & " static " & hex2str(oct2hex(bytes)));
625 f_vty_transceive(pt, "end");
626 }
627
628 function f_vty_si_computed(TELNETasp_PT pt, BtsNr bts, charstring si) {
629 f_vty_enter_cfg_bts(pt, bts);
630 f_vty_transceive(pt, "system-information " & si & " mode computed");
631 f_vty_transceive(pt, "end");
632 }
633
634 function f_vty_si_resend(TELNETasp_PT pt, BtsNr bts := 0) {
635 f_vty_transceive(pt, "bts " & int2str(bts) & " resend-system-information");
636 /* wait for 2s until changes propagate */
637 timer T := 2.0;
638 T.start;
639 T.timeout;
640 }
641
642 function f_vty_gprs_mode(TELNETasp_PT pt, integer bts, BtsGprsMode mode) {
643 f_vty_enter_cfg_bts(pt, bts);
644 f_vty_transceive(pt, "gprs mode " & mode);
645 f_vty_transceive(pt, "end");
646 }
647
648 function f_vty_si2q_add_uarfcn(TELNETasp_PT pt, BtsNr bts, UmtsArfcn uarfcn, UmtsScramblingCode sc, integer diversity := 0) {
649 f_vty_enter_cfg_bts(pt, bts);
650 f_vty_transceive(pt, "si2quater neighbor-list add uarfcn " & int2str(uarfcn) & " " & int2str(sc) & " " & int2str(diversity));
651 f_vty_transceive(pt, "end");
652 }
653
654 function f_vty_si2q_del_uarfcn(TELNETasp_PT pt, BtsNr bts, UmtsArfcn uarfcn, UmtsScramblingCode sc) {
655 f_vty_enter_cfg_bts(pt, bts);
656 f_vty_transceive(pt, "si2quater neighbor-list del uarfcn " & int2str(uarfcn) & " " & int2str(sc));
657 f_vty_transceive(pt, "end");
658 }
659
660 testcase TC_telnet() runs on dummy_CT {
661 f_init();
Harald Welte9a907b32017-07-15 10:34:27 +0200662
663 f_vty_transceive(BSCVTY, "show network")
Harald Welte9a907b32017-07-15 10:34:27 +0200664 f_vty_transceive(BSCVTY, "network")
665 f_vty_transceive(BSCVTY, "bts 0")
Harald Weltebdc5dbd2017-07-16 00:00:43 +0200666 f_vty_transceive(BSCVTY, "end")
667 setverdict(pass);
Harald Welte9a907b32017-07-15 10:34:27 +0200668 }
669
Harald Welte56db5fd2017-07-14 18:25:59 +0200670 control {
671 execute(TC_si1());
Harald Welte9a907b32017-07-15 10:34:27 +0200672 execute(TC_telnet());
Harald Weltebdc5dbd2017-07-16 00:00:43 +0200673 execute(TC_si_default());
674 execute(TC_si_sched_2bis());
675 execute(TC_si_sched_2ter());
676 execute(TC_si_sched_2ter_2bis());
677 execute(TC_si_sched_2quater());
678 execute(TC_si_sched_13());
Harald Welte56db5fd2017-07-14 18:25:59 +0200679 }
680}