blob: 36f6993beb12ee7612b0a1deca30e9f05ea2102a [file] [log] [blame]
Holger Freytheraa0fb362008-12-28 21:55:40 +00001/* simple test for the gsm0408 formatting functions */
2/*
3 * (C) 2008 by Holger Hans Peter Freyther <zecke@selfish.org>
4 * All Rights Reserved
5 *
6 * This program is free software; you can redistribute it and/or modify
Harald Welte9af6ddf2011-01-01 15:25:50 +01007 * it under the terms of the GNU Affero General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
Holger Freytheraa0fb362008-12-28 21:55:40 +00009 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
Harald Welte9af6ddf2011-01-01 15:25:50 +010016 * You should have received a copy of the GNU Affero General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
Holger Freytheraa0fb362008-12-28 21:55:40 +000018 *
19 */
20
21#include <assert.h>
22#include <stdio.h>
23#include <stdlib.h>
Max69e9c0d2016-05-18 13:04:47 +020024#include <stdbool.h>
Harald Welteafedeab2010-03-04 10:55:40 +010025#include <arpa/inet.h>
26
Neels Hofmeyr2d521a02016-05-14 00:57:04 +020027#include <openbsc/common_bsc.h>
Holger Freytheraa0fb362008-12-28 21:55:40 +000028#include <openbsc/gsm_04_08.h>
Holger Hans Peter Freytherca114432014-02-08 15:20:48 +010029#include <openbsc/gsm_04_11.h>
Holger Hans Peter Freyther5d0e56f2009-08-20 08:41:24 +020030#include <openbsc/gsm_subscriber.h>
Max845a3a42017-05-15 12:02:29 +020031#include <openbsc/gsm_data_shared.h>
Holger Hans Peter Freyther5d0e56f2009-08-20 08:41:24 +020032#include <openbsc/debug.h>
Jacob Erlbeck4b903b42014-01-10 17:43:41 +010033#include <openbsc/arfcn_range_encode.h>
Max59a1bf32016-04-15 16:04:46 +020034#include <openbsc/system_information.h>
35#include <openbsc/abis_rsl.h>
36
Jacob Erlbeck4b903b42014-01-10 17:43:41 +010037#include <osmocom/core/application.h>
Max59a1bf32016-04-15 16:04:46 +020038#include <osmocom/gsm/sysinfo.h>
Holger Freytheraa0fb362008-12-28 21:55:40 +000039
40#define COMPARE(result, op, value) \
41 if (!((result) op (value))) {\
42 fprintf(stderr, "Compare failed. Was %x should be %x in %s:%d\n",result, value, __FILE__, __LINE__); \
43 exit(-1); \
44 }
Holger Hans Peter Freyther5d0e56f2009-08-20 08:41:24 +020045
46#define COMPARE_STR(result, value) \
47 if (strcmp(result, value) != 0) { \
48 fprintf(stderr, "Compare failed. Was %s should be %s in %s:%d\n",result, value, __FILE__, __LINE__); \
49 exit(-1); \
50 }
Holger Freytheraa0fb362008-12-28 21:55:40 +000051
Jacob Erlbeck9444d4f2014-01-13 14:43:40 +010052#define DBG(...)
53
54#define VERIFY(res, cmp, wanted) \
55 if (!(res cmp wanted)) { \
56 printf("ASSERT failed: %s:%d Wanted: %d %s %d\n", \
Holger Hans Peter Freytherdaaea0c2015-08-03 09:28:41 +020057 __FILE__, __LINE__, (int) res, # cmp, (int) wanted); \
Jacob Erlbeck9444d4f2014-01-13 14:43:40 +010058 }
59
60
61
Holger Freytheraa0fb362008-12-28 21:55:40 +000062/*
63 * Test Location Area Identifier formatting. Table 10.5.3 of 04.08
64 */
65static void test_location_area_identifier(void)
66{
67 struct gsm48_loc_area_id lai48;
68
69 printf("Testing test location area identifier\n");
70
71 /*
72 * Test the default/test setup. Coming from
73 * bsc_hack.c dumps
74 */
Harald Welteafedeab2010-03-04 10:55:40 +010075 gsm48_generate_lai(&lai48, 1, 1, 1);
Holger Freytheraa0fb362008-12-28 21:55:40 +000076 COMPARE(lai48.digits[0], ==, 0x00);
77 COMPARE(lai48.digits[1], ==, 0xF1);
78 COMPARE(lai48.digits[2], ==, 0x10);
79 COMPARE(lai48.lac, ==, htons(0x0001));
80
Harald Welteafedeab2010-03-04 10:55:40 +010081 gsm48_generate_lai(&lai48, 602, 1, 15);
Holger Freytheraa0fb362008-12-28 21:55:40 +000082 COMPARE(lai48.digits[0], ==, 0x06);
83 COMPARE(lai48.digits[1], ==, 0xF2);
84 COMPARE(lai48.digits[2], ==, 0x10);
85 COMPARE(lai48.lac, ==, htons(0x000f));
86}
87
Maxf39d03a2017-05-12 17:00:30 +020088static inline void gen(struct gsm_bts *bts, const char *s)
Max59a1bf32016-04-15 16:04:46 +020089{
Max845a3a42017-05-15 12:02:29 +020090 int r;
91
Maxf39d03a2017-05-12 17:00:30 +020092 bts->u_offset = 0;
93 bts->e_offset = 0;
94 bts->si2q_index = 0;
95 bts->si2q_count = 0;
Max69e9c0d2016-05-18 13:04:47 +020096 bts->si_valid = 0;
97 bts->si_valid |= (1 << SYSINFO_TYPE_2quater);
Max845a3a42017-05-15 12:02:29 +020098
Max69e9c0d2016-05-18 13:04:47 +020099 /* should be no-op as entire buffer is filled with padding: */
Max6f0e50c2017-04-12 15:30:54 +0200100 memset(GSM_BTS_SI(bts, SYSINFO_TYPE_2quater), 0xAE, GSM_MACBLOCK_LEN);
Max845a3a42017-05-15 12:02:29 +0200101
102 printf("generating SI2quater for %zu EARFCNs and %zu UARFCNs...\n",
103 si2q_earfcn_count(&bts->si_common.si2quater_neigh_list), bts->si_common.uarfcn_length);
104
105 r = gsm_generate_si(bts, SYSINFO_TYPE_2quater);
Max59a1bf32016-04-15 16:04:46 +0200106 if (r > 0)
Max845a3a42017-05-15 12:02:29 +0200107 printf("generated %s SI2quater [%02u/%02u]: [%d] %s\n",
108 (bts->si_valid & (1 << SYSINFO_TYPE_2quater)) ? "valid" : "invalid",
109 bts->si2q_index, bts->si2q_count, r,
110 osmo_hexdump((void *)GSM_BTS_SI2Q(bts), GSM_MACBLOCK_LEN));
Max59a1bf32016-04-15 16:04:46 +0200111 else
Maxf39d03a2017-05-12 17:00:30 +0200112 printf("%s() failed to generate SI2quater: %s\n", s, strerror(-r));
Max59a1bf32016-04-15 16:04:46 +0200113}
114
Max845a3a42017-05-15 12:02:29 +0200115static inline void del_earfcn_b(struct gsm_bts *bts, uint16_t earfcn)
116{
117 struct osmo_earfcn_si2q *e = &bts->si_common.si2quater_neigh_list;
118 int r = osmo_earfcn_del(e, earfcn);
119 if (r)
120 printf("failed to remove EARFCN %u: %s\n", earfcn, strerror(-r));
121 else
122 printf("removed EARFCN %u - ", earfcn);
123
124 gen(bts, __func__);
125}
126
Maxf39d03a2017-05-12 17:00:30 +0200127static inline void add_earfcn_b(struct gsm_bts *bts, uint16_t earfcn, uint8_t bw)
Maxaafff962016-04-20 15:57:14 +0200128{
Maxf39d03a2017-05-12 17:00:30 +0200129 struct osmo_earfcn_si2q *e = &bts->si_common.si2quater_neigh_list;
130 int r = osmo_earfcn_add(e, earfcn, bw);
131 if (r)
132 printf("failed to add EARFCN %u: %s\n", earfcn, strerror(-r));
133 else
134 printf("added EARFCN %u - ", earfcn);
135
136 gen(bts, __func__);
137}
138
139static inline void _bts_uarfcn_add(struct gsm_bts *bts, uint16_t arfcn, uint16_t scramble, bool diversity)
140{
141 int r;
142
143 bts->u_offset = 0;
144
145 r = bts_uarfcn_add(bts, arfcn, scramble, diversity);
Maxaafff962016-04-20 15:57:14 +0200146 if (r < 0)
147 printf("failed to add UARFCN to SI2quater: %s\n", strerror(-r));
148 else
Maxf39d03a2017-05-12 17:00:30 +0200149 gen(bts, __func__);
Maxaafff962016-04-20 15:57:14 +0200150}
151
Max881064e2016-12-14 14:51:40 +0100152static inline void test_si2q_segfault(void)
153{
154 struct gsm_bts *bts;
155 struct gsm_network *network = bsc_network_init(tall_bsc_ctx, 1, 1, NULL);
156 printf("Test SI2quater UARFCN (same scrambling code and diversity):\n");
157
158 if (!network)
159 exit(1);
160 bts = gsm_bts_alloc(network);
161
162 _bts_uarfcn_add(bts, 10564, 319, 0);
163 _bts_uarfcn_add(bts, 10612, 319, 0);
Maxf39d03a2017-05-12 17:00:30 +0200164 gen(bts, __func__);
Max881064e2016-12-14 14:51:40 +0100165}
166
Maxe610e702016-12-19 13:41:48 +0100167static inline void test_si2q_mu(void)
168{
169 struct gsm_bts *bts;
170 struct gsm_network *network = bsc_network_init(tall_bsc_ctx, 1, 1, NULL);
171 printf("Test SI2quater multiple UARFCNs:\n");
172
173 if (!network)
174 exit(1);
175 bts = gsm_bts_alloc(network);
176
177 _bts_uarfcn_add(bts, 10564, 318, 0);
178 _bts_uarfcn_add(bts, 10612, 319, 0);
179 _bts_uarfcn_add(bts, 10612, 31, 0);
180 _bts_uarfcn_add(bts, 10612, 19, 0);
181 _bts_uarfcn_add(bts, 10613, 64, 0);
182 _bts_uarfcn_add(bts, 10613, 164, 0);
183 _bts_uarfcn_add(bts, 10613, 14, 0);
Maxf39d03a2017-05-12 17:00:30 +0200184 gen(bts, __func__);
Maxe610e702016-12-19 13:41:48 +0100185}
186
Max26679e02016-04-20 15:57:13 +0200187static inline void test_si2q_u(void)
Max59a1bf32016-04-15 16:04:46 +0200188{
189 struct gsm_bts *bts;
Neels Hofmeyr27681a32016-05-14 00:45:26 +0200190 struct gsm_network *network = bsc_network_init(tall_bsc_ctx, 1, 1, NULL);
Max26679e02016-04-20 15:57:13 +0200191 printf("Testing SYSINFO_TYPE_2quater UARFCN generation:\n");
192
193 if (!network)
194 exit(1);
195 bts = gsm_bts_alloc(network);
196
Max69e9c0d2016-05-18 13:04:47 +0200197 /* first generate invalid SI as no UARFCN added */
Maxf39d03a2017-05-12 17:00:30 +0200198 gen(bts, __func__);
Max69e9c0d2016-05-18 13:04:47 +0200199 /* subsequent calls should produce valid SI if there's enough memory */
Maxaafff962016-04-20 15:57:14 +0200200 _bts_uarfcn_add(bts, 1982, 13, 1);
201 _bts_uarfcn_add(bts, 1982, 44, 0);
202 _bts_uarfcn_add(bts, 1982, 61, 1);
203 _bts_uarfcn_add(bts, 1982, 89, 1);
204 _bts_uarfcn_add(bts, 1982, 113, 0);
205 _bts_uarfcn_add(bts, 1982, 123, 0);
206 _bts_uarfcn_add(bts, 1982, 56, 1);
207 _bts_uarfcn_add(bts, 1982, 72, 1);
208 _bts_uarfcn_add(bts, 1982, 223, 1);
209 _bts_uarfcn_add(bts, 1982, 14, 0);
210 _bts_uarfcn_add(bts, 1982, 88, 0);
Maxf39d03a2017-05-12 17:00:30 +0200211 gen(bts, __func__);
Max26679e02016-04-20 15:57:13 +0200212}
213
214static inline void test_si2q_e(void)
215{
216 struct gsm_bts *bts;
Neels Hofmeyr27681a32016-05-14 00:45:26 +0200217 struct gsm_network *network = bsc_network_init(tall_bsc_ctx, 1, 1, NULL);
Max26679e02016-04-20 15:57:13 +0200218 printf("Testing SYSINFO_TYPE_2quater EARFCN generation:\n");
Max59a1bf32016-04-15 16:04:46 +0200219
220 if (!network)
221 exit(1);
222 bts = gsm_bts_alloc(network);
223
Maxf39d03a2017-05-12 17:00:30 +0200224 bts->si_common.si2quater_neigh_list.arfcn = bts->si_common.data.earfcn_list;
225 bts->si_common.si2quater_neigh_list.meas_bw = bts->si_common.data.meas_bw_list;
Max59a1bf32016-04-15 16:04:46 +0200226 bts->si_common.si2quater_neigh_list.length = MAX_EARFCN_LIST;
227 bts->si_common.si2quater_neigh_list.thresh_hi = 5;
228
229 osmo_earfcn_init(&bts->si_common.si2quater_neigh_list);
Max69e9c0d2016-05-18 13:04:47 +0200230 /* first generate invalid SI as no EARFCN added */
Maxf39d03a2017-05-12 17:00:30 +0200231 gen(bts, __func__);
Max845a3a42017-05-15 12:02:29 +0200232 /* subsequent calls should produce valid SI if there's enough memory and EARFCNs */
233 add_earfcn_b(bts, 1917, 5);
234 del_earfcn_b(bts, 1917);
Maxf39d03a2017-05-12 17:00:30 +0200235 add_earfcn_b(bts, 1917, 1);
236 add_earfcn_b(bts, 1932, OSMO_EARFCN_MEAS_INVALID);
237 add_earfcn_b(bts, 1937, 2);
238 add_earfcn_b(bts, 1945, OSMO_EARFCN_MEAS_INVALID);
239 add_earfcn_b(bts, 1965, OSMO_EARFCN_MEAS_INVALID);
240 add_earfcn_b(bts, 1967, 4);
241 add_earfcn_b(bts, 1982, 3);
Max59a1bf32016-04-15 16:04:46 +0200242}
243
Holger Hans Peter Freyther5d0e56f2009-08-20 08:41:24 +0200244static void test_mi_functionality(void)
245{
246 const char *imsi_odd = "987654321098763";
247 const char *imsi_even = "9876543210987654";
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +0200248 const uint32_t tmsi = 0xfabeacd0;
249 uint8_t mi[128];
Holger Hans Peter Freyther5d0e56f2009-08-20 08:41:24 +0200250 unsigned int mi_len;
251 char mi_parsed[GSM48_MI_SIZE];
252
253 printf("Testing parsing and generating TMSI/IMSI\n");
254
255 /* tmsi code */
256 mi_len = gsm48_generate_mid_from_tmsi(mi, tmsi);
257 gsm48_mi_to_string(mi_parsed, sizeof(mi_parsed), mi + 2, mi_len - 2);
Harald Welte3ad03462016-03-17 14:41:26 +0100258 COMPARE((uint32_t)strtoul(mi_parsed, NULL, 10), ==, tmsi);
Holger Hans Peter Freyther5d0e56f2009-08-20 08:41:24 +0200259
260 /* imsi code */
261 mi_len = gsm48_generate_mid_from_imsi(mi, imsi_odd);
262 gsm48_mi_to_string(mi_parsed, sizeof(mi_parsed), mi + 2, mi_len -2);
Pablo Neira Ayusoc0d17f22011-05-07 12:12:48 +0200263 printf("hex: %s\n", osmo_hexdump(mi, mi_len));
Holger Hans Peter Freyther5d0e56f2009-08-20 08:41:24 +0200264 COMPARE_STR(mi_parsed, imsi_odd);
265
266 mi_len = gsm48_generate_mid_from_imsi(mi, imsi_even);
267 gsm48_mi_to_string(mi_parsed, sizeof(mi_parsed), mi + 2, mi_len -2);
Pablo Neira Ayusoc0d17f22011-05-07 12:12:48 +0200268 printf("hex: %s\n", osmo_hexdump(mi, mi_len));
Holger Hans Peter Freyther5d0e56f2009-08-20 08:41:24 +0200269 COMPARE_STR(mi_parsed, imsi_even);
270}
271
Jacob Erlbeck4b903b42014-01-10 17:43:41 +0100272struct {
273 int range;
274 int arfcns_num;
275 int arfcns[RANGE_ENC_MAX_ARFCNS];
276} arfcn_test_ranges[] = {
277 {ARFCN_RANGE_512, 12,
278 { 1, 12, 31, 51, 57, 91, 97, 98, 113, 117, 120, 125 }},
279 {ARFCN_RANGE_512, 17,
280 { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17 }},
281 {ARFCN_RANGE_512, 18,
282 { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18 }},
283 {ARFCN_RANGE_512, 18,
284 { 1, 17, 31, 45, 58, 79, 81, 97,
285 113, 127, 213, 277, 287, 311, 331, 391,
286 417, 511 }},
287 {ARFCN_RANGE_512, 6,
288 { 1, 17, 31, 45, 58, 79 }},
289 {ARFCN_RANGE_512, 6,
290 { 10, 17, 31, 45, 58, 79 }},
291 {ARFCN_RANGE_1024, 17,
292 { 0, 17, 31, 45, 58, 79, 81, 97,
293 113, 127, 213, 277, 287, 311, 331, 391,
294 1023 }},
295 {ARFCN_RANGE_1024, 16,
296 { 17, 31, 45, 58, 79, 81, 97, 113,
297 127, 213, 277, 287, 311, 331, 391, 1023 }},
298 {-1}
299};
300
301static int test_single_range_encoding(int range, const int *orig_arfcns,
302 int arfcns_num, int silent)
303{
304 int arfcns[RANGE_ENC_MAX_ARFCNS];
305 int w[RANGE_ENC_MAX_ARFCNS];
306 int f0_included = 0;
307 int rc, f0;
308 uint8_t chan_list[16] = {0};
309 struct gsm_sysinfo_freq dec_freq[1024] = {{0}};
310 int dec_arfcns[RANGE_ENC_MAX_ARFCNS] = {0};
311 int dec_arfcns_count = 0;
312 int arfcns_used = 0;
313 int i;
314
315 arfcns_used = arfcns_num;
316 memmove(arfcns, orig_arfcns, sizeof(arfcns));
317
Jacob Erlbeck45014a02014-01-14 10:42:58 +0100318 f0 = range == ARFCN_RANGE_1024 ? 0 : arfcns[0];
Jacob Erlbeck4b903b42014-01-10 17:43:41 +0100319 /*
320 * Manipulate the ARFCN list according to the rules in J4 depending
321 * on the selected range.
322 */
Jacob Erlbeck45014a02014-01-14 10:42:58 +0100323 arfcns_used = range_enc_filter_arfcns(arfcns, arfcns_used,
Jacob Erlbeck4b903b42014-01-10 17:43:41 +0100324 f0, &f0_included);
325
326 memset(w, 0, sizeof(w));
Max26679e02016-04-20 15:57:13 +0200327 range_enc_arfcns(range, arfcns, arfcns_used, w, 0);
Jacob Erlbeck4b903b42014-01-10 17:43:41 +0100328
329 if (!silent)
330 fprintf(stderr, "range=%d, arfcns_used=%d, f0=%d, f0_included=%d\n",
331 range, arfcns_used, f0, f0_included);
332
333 /* Select the range and the amount of bits needed */
334 switch (range) {
335 case ARFCN_RANGE_128:
Max26679e02016-04-20 15:57:13 +0200336 range_enc_range128(chan_list, f0, w);
Jacob Erlbeck4b903b42014-01-10 17:43:41 +0100337 break;
338 case ARFCN_RANGE_256:
Max26679e02016-04-20 15:57:13 +0200339 range_enc_range256(chan_list, f0, w);
Jacob Erlbeck4b903b42014-01-10 17:43:41 +0100340 break;
341 case ARFCN_RANGE_512:
Max26679e02016-04-20 15:57:13 +0200342 range_enc_range512(chan_list, f0, w);
Jacob Erlbeck4b903b42014-01-10 17:43:41 +0100343 break;
344 case ARFCN_RANGE_1024:
Max26679e02016-04-20 15:57:13 +0200345 range_enc_range1024(chan_list, f0, f0_included, w);
Jacob Erlbeck4b903b42014-01-10 17:43:41 +0100346 break;
347 default:
348 return 1;
349 };
Jacob Erlbeck4b903b42014-01-10 17:43:41 +0100350
351 if (!silent)
352 printf("chan_list = %s\n",
353 osmo_hexdump(chan_list, sizeof(chan_list)));
354
355 rc = gsm48_decode_freq_list(dec_freq, chan_list, sizeof(chan_list),
356 0xfe, 1);
357 if (rc != 0) {
358 printf("Cannot decode freq list, rc = %d\n", rc);
359 return 1;
360 }
361
362 for (i = 0; i < ARRAY_SIZE(dec_freq); i++) {
363 if (dec_freq[i].mask &&
364 dec_arfcns_count < ARRAY_SIZE(dec_arfcns))
365 dec_arfcns[dec_arfcns_count++] = i;
366 }
367
368 if (!silent) {
369 printf("Decoded freqs %d (expected %d)\n",
370 dec_arfcns_count, arfcns_num);
371 printf("Decoded: ");
372 for (i = 0; i < dec_arfcns_count; i++) {
373 printf("%d ", dec_arfcns[i]);
374 if (dec_arfcns[i] != orig_arfcns[i])
375 printf("(!= %d) ", orig_arfcns[i]);
376 }
377 printf("\n");
378 }
379
380 if (dec_arfcns_count != arfcns_num) {
381 printf("Wrong number of arfcns\n");
382 return 1;
383 }
384
385 if (memcmp(dec_arfcns, orig_arfcns, sizeof(dec_arfcns)) != 0) {
386 printf("Decoding error, got wrong freqs\n");
387 fprintf(stderr, " w = ");
388 for (i = 0; i < ARRAY_SIZE(w); i++)
389 fprintf(stderr, "%d ", w[i]);
390 fprintf(stderr, "\n");
391 return 1;
392 }
393
394 return 0;
395}
396
397static void test_random_range_encoding(int range, int max_arfcn_num)
398{
399 int arfcns_num = 0;
400 int test_idx;
401 int rc, max_count;
402 int num_tests = 1024;
403
404 printf("Random range test: range %d, max num ARFCNs %d\n",
405 range, max_arfcn_num);
406
407 srandom(1);
408
409 for (max_count = 1; max_count < max_arfcn_num; max_count++) {
410 for (test_idx = 0; test_idx < num_tests; test_idx++) {
411 int count;
412 int i;
413 int min_freq = 0;
414
415 int rnd_arfcns[RANGE_ENC_MAX_ARFCNS] = {0};
416 char rnd_arfcns_set[1024] = {0};
417
418 if (range < ARFCN_RANGE_1024)
419 min_freq = random() % (1023 - range);
420
421 for (count = max_count; count; ) {
422 int arfcn = min_freq + random() % (range + 1);
423 OSMO_ASSERT(arfcn < ARRAY_SIZE(rnd_arfcns_set));
424
425 if (!rnd_arfcns_set[arfcn]) {
426 rnd_arfcns_set[arfcn] = 1;
427 count -= 1;
428 }
429 }
430
431 arfcns_num = 0;
432 for (i = 0; i < ARRAY_SIZE(rnd_arfcns_set); i++)
433 if (rnd_arfcns_set[i])
434 rnd_arfcns[arfcns_num++] = i;
435
436 rc = test_single_range_encoding(range, rnd_arfcns,
437 arfcns_num, 1);
438 if (rc != 0) {
439 printf("Failed on test %d, range %d, num ARFCNs %d\n",
440 test_idx, range, max_count);
441 test_single_range_encoding(range, rnd_arfcns,
442 arfcns_num, 0);
443 return;
444 }
445 }
446 }
447}
448
449static void test_range_encoding()
450{
451 int *arfcns;
452 int arfcns_num = 0;
453 int test_idx;
454 int range;
455
456 for (test_idx = 0; arfcn_test_ranges[test_idx].arfcns_num > 0; test_idx++)
457 {
458 arfcns_num = arfcn_test_ranges[test_idx].arfcns_num;
459 arfcns = &arfcn_test_ranges[test_idx].arfcns[0];
460 range = arfcn_test_ranges[test_idx].range;
461
462 printf("Range test %d: range %d, num ARFCNs %d\n",
463 test_idx, range, arfcns_num);
464
465 test_single_range_encoding(range, arfcns, arfcns_num, 0);
466 }
467
468 test_random_range_encoding(ARFCN_RANGE_128, 29);
469 test_random_range_encoding(ARFCN_RANGE_256, 22);
470 test_random_range_encoding(ARFCN_RANGE_512, 18);
471 test_random_range_encoding(ARFCN_RANGE_1024, 16);
472}
473
Jacob Erlbeck9444d4f2014-01-13 14:43:40 +0100474static int freqs1[] = {
475 12, 70, 121, 190, 250, 320, 401, 475, 520, 574, 634, 700, 764, 830, 905, 980
476};
477
478static int freqs2[] = {
479 402, 460, 1, 67, 131, 197, 272, 347,
480};
481
482static int freqs3[] = {
483 68, 128, 198, 279, 353, 398, 452,
484
485};
486
487static int w_out[] = {
488 122, 2, 69, 204, 75, 66, 60, 70, 83, 3, 24, 67, 54, 64, 70, 9,
489};
490
491static int range128[] = {
492 1, 1 + 127,
493};
494
495static int range256[] = {
496 1, 1 + 128,
497};
498
499static int range512[] = {
500 1, 1+ 511,
501};
502
503
504static void test_arfcn_filter()
505{
506 int arfcns[50], i, res, f0_included;
507 for (i = 0; i < ARRAY_SIZE(arfcns); ++i)
508 arfcns[i] = (i + 1) * 2;
509
510 /* check that the arfcn is taken out. f0_included is only set for Range1024 */
511 f0_included = 24;
Jacob Erlbeck45014a02014-01-14 10:42:58 +0100512 res = range_enc_filter_arfcns(arfcns, ARRAY_SIZE(arfcns),
Jacob Erlbeck9444d4f2014-01-13 14:43:40 +0100513 arfcns[0], &f0_included);
514 VERIFY(res, ==, ARRAY_SIZE(arfcns) - 1);
515 VERIFY(f0_included, ==, 1);
516 for (i = 0; i < res; ++i)
Jacob Erlbeck45014a02014-01-14 10:42:58 +0100517 VERIFY(arfcns[i], ==, ((i+2) * 2) - (2+1));
Jacob Erlbeck9444d4f2014-01-13 14:43:40 +0100518
Jacob Erlbeck45014a02014-01-14 10:42:58 +0100519 /* check with range1024, ARFCN 0 is included */
520 for (i = 0; i < ARRAY_SIZE(arfcns); ++i)
521 arfcns[i] = i * 2;
522 res = range_enc_filter_arfcns(arfcns, ARRAY_SIZE(arfcns),
523 0, &f0_included);
524 VERIFY(res, ==, ARRAY_SIZE(arfcns) - 1);
525 VERIFY(f0_included, ==, 1);
526 for (i = 0; i < res; ++i)
527 VERIFY(arfcns[i], ==, (i + 1) * 2 - 1);
528
529 /* check with range1024, ARFCN 0 not included */
Jacob Erlbeck9444d4f2014-01-13 14:43:40 +0100530 for (i = 0; i < ARRAY_SIZE(arfcns); ++i)
531 arfcns[i] = (i + 1) * 2;
Jacob Erlbeck45014a02014-01-14 10:42:58 +0100532 res = range_enc_filter_arfcns(arfcns, ARRAY_SIZE(arfcns),
533 0, &f0_included);
Jacob Erlbeck9444d4f2014-01-13 14:43:40 +0100534 VERIFY(res, ==, ARRAY_SIZE(arfcns));
535 VERIFY(f0_included, ==, 0);
536 for (i = 0; i < res; ++i)
537 VERIFY(arfcns[i], ==, ((i + 1) * 2) - 1);
538}
539
540static void test_print_encoding()
541{
542 int rc;
543 int w[17];
544 uint8_t chan_list[16];
545 memset(chan_list, 0x23, sizeof(chan_list));
546
547 for (rc = 0; rc < ARRAY_SIZE(w); ++rc)
548 switch (rc % 3) {
549 case 0:
550 w[rc] = 0xAAAA;
551 break;
552 case 1:
553 w[rc] = 0x5555;
554 break;
555 case 2:
556 w[rc] = 0x9696;
557 break;
558 }
559
Max26679e02016-04-20 15:57:13 +0200560 range_enc_range512(chan_list, (1 << 9) | 0x96, w);
Jacob Erlbeck9444d4f2014-01-13 14:43:40 +0100561
562 printf("Range512: %s\n", osmo_hexdump(chan_list, ARRAY_SIZE(chan_list)));
563}
564
565static void test_si_range_helpers()
566{
567 int ws[(sizeof(freqs1)/sizeof(freqs1[0]))];
568 int i, f0 = 0xFFFFFF;
569
570 memset(&ws[0], 0x23, sizeof(ws));
571
572 i = range_enc_find_index(1023, freqs1, ARRAY_SIZE(freqs1));
Jacob Erlbeck1dc022c2014-01-17 09:22:57 +0100573 printf("Element is: %d => freqs[i] = %d\n", i, i >= 0 ? freqs1[i] : -1);
Jacob Erlbeck9444d4f2014-01-13 14:43:40 +0100574 VERIFY(i, ==, 2);
575
576 i = range_enc_find_index(511, freqs2, ARRAY_SIZE(freqs2));
Jacob Erlbeck1dc022c2014-01-17 09:22:57 +0100577 printf("Element is: %d => freqs[i] = %d\n", i, i >= 0 ? freqs2[i] : -1);
Jacob Erlbeck9444d4f2014-01-13 14:43:40 +0100578 VERIFY(i, ==, 2);
579
580 i = range_enc_find_index(511, freqs3, ARRAY_SIZE(freqs3));
Jacob Erlbeck1dc022c2014-01-17 09:22:57 +0100581 printf("Element is: %d => freqs[i] = %d\n", i, i >= 0 ? freqs3[i] : -1);
Jacob Erlbeck9444d4f2014-01-13 14:43:40 +0100582 VERIFY(i, ==, 0);
583
Max26679e02016-04-20 15:57:13 +0200584 range_enc_arfcns(1023, freqs1, ARRAY_SIZE(freqs1), ws, 0);
Jacob Erlbeck9444d4f2014-01-13 14:43:40 +0100585
586 for (i = 0; i < sizeof(freqs1)/sizeof(freqs1[0]); ++i) {
587 printf("w[%d]=%d\n", i, ws[i]);
588 VERIFY(ws[i], ==, w_out[i]);
589 }
590
591 i = range_enc_determine_range(range128, ARRAY_SIZE(range128), &f0);
592 VERIFY(i, ==, ARFCN_RANGE_128);
593 VERIFY(f0, ==, 1);
594
595 i = range_enc_determine_range(range256, ARRAY_SIZE(range256), &f0);
596 VERIFY(i, ==, ARFCN_RANGE_256);
597 VERIFY(f0, ==, 1);
598
599 i = range_enc_determine_range(range512, ARRAY_SIZE(range512), &f0);
600 VERIFY(i, ==, ARFCN_RANGE_512);
601 VERIFY(f0, ==, 1);
602}
603
Holger Hans Peter Freytherca114432014-02-08 15:20:48 +0100604static void test_gsm411_rp_ref_wrap(void)
605{
606 struct gsm_subscriber_connection conn;
607 int res;
608
609 printf("testing RP-Reference wrap\n");
610
611 memset(&conn, 0, sizeof(conn));
612 conn.next_rp_ref = 255;
613
Neels Hofmeyr05667a02016-05-10 13:27:32 +0200614 res = sms_next_rp_msg_ref(&conn.next_rp_ref);
Holger Hans Peter Freytherca114432014-02-08 15:20:48 +0100615 printf("Allocated reference: %d\n", res);
616 OSMO_ASSERT(res == 255);
617
Neels Hofmeyr05667a02016-05-10 13:27:32 +0200618 res = sms_next_rp_msg_ref(&conn.next_rp_ref);
Holger Hans Peter Freytherca114432014-02-08 15:20:48 +0100619 printf("Allocated reference: %d\n", res);
620 OSMO_ASSERT(res == 0);
621
Neels Hofmeyr05667a02016-05-10 13:27:32 +0200622 res = sms_next_rp_msg_ref(&conn.next_rp_ref);
Holger Hans Peter Freytherca114432014-02-08 15:20:48 +0100623 printf("Allocated reference: %d\n", res);
624 OSMO_ASSERT(res == 1);
625}
626
Holger Hans Peter Freytheradb6e1c2010-09-18 06:44:24 +0800627int main(int argc, char **argv)
Holger Freytheraa0fb362008-12-28 21:55:40 +0000628{
Jacob Erlbeck4b903b42014-01-10 17:43:41 +0100629 osmo_init_logging(&log_info);
630 log_set_log_level(osmo_stderr_target, LOGL_INFO);
631
Holger Hans Peter Freyther5d0e56f2009-08-20 08:41:24 +0200632 test_location_area_identifier();
633 test_mi_functionality();
Jacob Erlbeck9444d4f2014-01-13 14:43:40 +0100634
635 test_si_range_helpers();
636 test_arfcn_filter();
637 test_print_encoding();
Jacob Erlbeck4b903b42014-01-10 17:43:41 +0100638 test_range_encoding();
Holger Hans Peter Freytherca114432014-02-08 15:20:48 +0100639 test_gsm411_rp_ref_wrap();
Harald Welteafedeab2010-03-04 10:55:40 +0100640
Max881064e2016-12-14 14:51:40 +0100641 test_si2q_segfault();
Max26679e02016-04-20 15:57:13 +0200642 test_si2q_e();
643 test_si2q_u();
Maxe610e702016-12-19 13:41:48 +0100644 test_si2q_mu();
Holger Hans Peter Freyther300457b2012-01-06 15:03:28 +0100645 printf("Done.\n");
646 return EXIT_SUCCESS;
Holger Freytheraa0fb362008-12-28 21:55:40 +0000647}