blob: d9640aa3b3f5c79a2d5f1a76007115d35052e655 [file] [log] [blame]
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +01001/*
2 * (C) 2012 by Holger Hans Peter Freyther
3 * All Rights Reserved
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 */
20
21#include <osmocom/gsm/gsm0808.h>
Philipp Maier22401432017-03-24 17:59:26 +010022#include <osmocom/gsm/gsm0808_utils.h>
23#include <osmocom/gsm/protocol/gsm_08_08.h>
Philipp Maier3d48ec02017-03-29 17:37:55 +020024#include <osmocom/gsm/protocol/gsm_08_58.h>
Max969fb2e2018-12-10 11:01:10 +010025#include <osmocom/core/logging.h>
26#include <osmocom/core/application.h>
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +010027
28#include <stdio.h>
29#include <stdlib.h>
Philipp Maier22401432017-03-24 17:59:26 +010030#include <sys/socket.h>
31#include <netinet/in.h>
32#include <arpa/inet.h>
Neels Hofmeyr74663d92018-03-23 01:46:42 +010033#include <errno.h>
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +010034
Philipp Maier4f4905f2018-11-30 13:36:12 +010035#define EXPECT_ENCODED(hexstr) do { \
36 const char *enc_str = msgb_hexdump(msg); \
37 printf("%s: encoded: %s(rc = %u)\n", __func__, enc_str, rc_enc); \
38 OSMO_ASSERT(strcmp(enc_str, hexstr " ") == 0); \
39 OSMO_ASSERT(rc_enc == msg->len); \
40 } while(0)
41
Vadim Yanitskiycf6ee642018-12-20 05:23:00 +070042#define VERIFY(msg, data, data_len) do { \
43 if (!msgb_eq_l3_data_print(msg, data, data_len)) \
44 abort(); \
45 } while(0)
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +010046
Philipp Maierfa896ab2017-03-27 16:55:32 +020047/* Setup a fake codec list for testing */
48static void setup_codec_list(struct gsm0808_speech_codec_list *scl)
49{
50 memset(scl, 0, sizeof(*scl));
51
52 scl->codec[0].pi = true;
53 scl->codec[0].tf = true;
Philipp Maierbb839662017-06-01 17:11:19 +020054 scl->codec[0].type = GSM0808_SCT_FR3;
Philipp Maierfa896ab2017-03-27 16:55:32 +020055 scl->codec[0].cfg = 0xcdef;
56
57 scl->codec[1].fi = true;
58 scl->codec[1].pt = true;
Philipp Maierbb839662017-06-01 17:11:19 +020059 scl->codec[1].type = GSM0808_SCT_FR2;
Philipp Maierfa896ab2017-03-27 16:55:32 +020060
61 scl->codec[2].fi = true;
62 scl->codec[2].tf = true;
Philipp Maierbb839662017-06-01 17:11:19 +020063 scl->codec[2].type = GSM0808_SCT_CSD;
64 scl->codec[2].cfg = 0xc0;
Philipp Maierfa896ab2017-03-27 16:55:32 +020065
66 scl->len = 3;
67}
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +010068
Philipp Maier4f4905f2018-11-30 13:36:12 +010069void test_gsm0808_enc_cause(void)
70{
71 /* NOTE: This must be tested early because many of the following tests
72 * rely on the generation of a proper cause code. */
73
74 uint8_t rc_enc;
75 struct msgb *msg;
76
77 /* Test with a single byte cause code */
78 msg = msgb_alloc(1024, "output buffer");
79 rc_enc = gsm0808_enc_cause(msg, 0x41);
80 EXPECT_ENCODED("04 01 41");
81 msgb_free(msg);
82
83 /* Test with an extended (two byte) cause code */
84 msg = msgb_alloc(1024, "output buffer");
85 rc_enc = gsm0808_enc_cause(msg, 0x8041);
86 EXPECT_ENCODED("04 02 80 41");
87 msgb_free(msg);
88}
89
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +010090static void test_create_layer3(void)
91{
92 static const uint8_t res[] = {
93 0x00, 0x0e, 0x57, 0x05, 0x08, 0x00, 0x77, 0x62,
94 0x83, 0x33, 0x66, 0x44, 0x88, 0x17, 0x01, 0x23 };
95 struct msgb *msg, *in_msg;
Neels Hofmeyr178bf7a2018-04-20 12:23:45 +020096 struct osmo_cell_global_id cgi = {
97 .lai = {
98 .plmn = {
99 .mcc = 0x2244,
100 .mnc = 0x1122,
101 },
102 .lac = 0x3366,
103 },
104 .cell_identity = 0x4488,
105 };
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +0100106 printf("Testing creating Layer3\n");
107
108 in_msg = msgb_alloc_headroom(512, 128, "foo");
109 in_msg->l3h = in_msg->data;
110 msgb_v_put(in_msg, 0x23);
111
Neels Hofmeyr178bf7a2018-04-20 12:23:45 +0200112 msg = gsm0808_create_layer3_2(in_msg, &cgi, NULL);
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +0100113 VERIFY(msg, res, ARRAY_SIZE(res));
114 msgb_free(msg);
115 msgb_free(in_msg);
116}
117
Philipp Maierfa896ab2017-03-27 16:55:32 +0200118static void test_create_layer3_aoip()
119{
120 static const uint8_t res[] = {
121 0x00, 0x17, 0x57, 0x05, 0x08, 0x00, 0x77, 0x62,
122 0x83, 0x33, 0x66, 0x44, 0x88, 0x17, 0x01, 0x23,
Philipp Maierbb839662017-06-01 17:11:19 +0200123 GSM0808_IE_SPEECH_CODEC_LIST, 0x07, GSM0808_SCT_FR3 | 0x50,
Philipp Maier7e27b142018-03-22 17:26:46 +0100124 0xef, 0xcd, GSM0808_SCT_FR2 | 0xa0, 0x9f,
Philipp Maierbb839662017-06-01 17:11:19 +0200125 GSM0808_SCT_CSD | 0x90, 0xc0
Philipp Maierfa896ab2017-03-27 16:55:32 +0200126 };
Maxfa3b4822018-11-05 14:59:54 +0100127 struct osmo_cell_global_id cgi = {
128 .lai = {
129 .plmn = {
130 .mcc = 0x2244,
131 .mnc = 0x1122,
132 },
133 .lac = 0x3366,
134 },
135 .cell_identity = 0x4488,
136 };
Philipp Maierfa896ab2017-03-27 16:55:32 +0200137 struct msgb *msg, *in_msg;
138 struct gsm0808_speech_codec_list sc_list;
139 printf("Testing creating Layer3 (AoIP)\n");
140
141 setup_codec_list(&sc_list);
142
143 in_msg = msgb_alloc_headroom(512, 128, "foo");
144 in_msg->l3h = in_msg->data;
145 msgb_v_put(in_msg, 0x23);
146
Maxfa3b4822018-11-05 14:59:54 +0100147 msg = gsm0808_create_layer3_2(in_msg, &cgi, &sc_list);
148
Philipp Maierfa896ab2017-03-27 16:55:32 +0200149 VERIFY(msg, res, ARRAY_SIZE(res));
150
151 msgb_free(msg);
152 msgb_free(in_msg);
153}
154
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +0100155static void test_create_reset()
156{
157 static const uint8_t res[] = { 0x00, 0x04, 0x30, 0x04, 0x01, 0x20 };
158 struct msgb *msg;
159
160 printf("Testing creating Reset\n");
161 msg = gsm0808_create_reset();
162 VERIFY(msg, res, ARRAY_SIZE(res));
163 msgb_free(msg);
164}
165
Philipp Maier15596e22017-04-05 17:55:27 +0200166static void test_create_reset_ack()
167{
168 static const uint8_t res[] = { 0x00, 0x01, 0x31 };
169 struct msgb *msg;
170
171 printf("Testing creating Reset Ack\n");
172 msg = gsm0808_create_reset_ack();
173 VERIFY(msg, res, ARRAY_SIZE(res));
174 msgb_free(msg);
175}
176
177
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +0100178static void test_create_clear_command()
179{
180 static const uint8_t res[] = { 0x20, 0x04, 0x01, 0x23 };
181 struct msgb *msg;
182
183 printf("Testing creating Clear Command\n");
184 msg = gsm0808_create_clear_command(0x23);
185 VERIFY(msg, res, ARRAY_SIZE(res));
186 msgb_free(msg);
187}
188
Harald Weltecf665fc2019-02-18 13:45:36 +0100189static void test_create_clear_command2()
190{
191 static const uint8_t res[] = { 0x00, 0x04, 0x20, 0x04, 0x01, 0x23 };
192 struct msgb *msg;
193
194 printf("Testing creating Clear Command 2\n");
195 msg = gsm0808_create_clear_command2(0x23, false);
196 VERIFY(msg, res, ARRAY_SIZE(res));
197 msgb_free(msg);
198}
199
200static void test_create_clear_command2_csfb()
201{
202 static const uint8_t res[] = { 0x00, 0x05, 0x20, 0x04, 0x01, 0x23, 0x8F };
203 struct msgb *msg;
204
205 printf("Testing creating Clear Command 2 (CSFB)\n");
206 msg = gsm0808_create_clear_command2(0x23, true);
207 VERIFY(msg, res, ARRAY_SIZE(res));
208 msgb_free(msg);
209}
210
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +0100211static void test_create_clear_complete()
212{
213 static const uint8_t res[] = { 0x00, 0x01, 0x21 };
214 struct msgb *msg;
215
216 printf("Testing creating Clear Complete\n");
217 msg = gsm0808_create_clear_complete();
218 VERIFY(msg, res, ARRAY_SIZE(res));
219 msgb_free(msg);
220}
221
Philipp Maierb478dd32017-03-29 15:50:05 +0200222static void test_create_cipher()
223{
224 static const uint8_t res[] =
225 { 0x00, 0x0c, 0x53, 0x0a, 0x09, 0x03, 0xaa,
226 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x23, 0x42 };
227 static const uint8_t res2[] =
228 { 0x00, 0x0e, 0x53, 0x0a, 0x09, 0x03, 0xaa,
229 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x23, 0x42,
230 GSM0808_IE_CIPHER_RESPONSE_MODE, 0x01 };
231 struct msgb *msg;
232 struct gsm0808_encrypt_info ei;
233 uint8_t include_imeisv;
234
235 memset(&ei, 0, sizeof(ei));
236 ei.perm_algo[0] = GSM0808_ALG_ID_A5_0;
237 ei.perm_algo[1] = GSM0808_ALG_ID_A5_1;
238 ei.perm_algo_len = 2;
239 ei.key[0] = 0xaa;
240 ei.key[1] = 0xbb;
241 ei.key[2] = 0xcc;
242 ei.key[3] = 0xdd;
243 ei.key[4] = 0xee;
244 ei.key[5] = 0xff;
245 ei.key[6] = 0x23;
246 ei.key[7] = 0x42;
247 ei.key_len = 8;
248 include_imeisv = 1;
249
250 printf("Testing creating Chipher Mode Command\n");
251 msg = gsm0808_create_cipher(&ei, NULL);
252 OSMO_ASSERT(msg);
253 VERIFY(msg, res, ARRAY_SIZE(res));
254 msgb_free(msg);
255
256 msg = gsm0808_create_cipher(&ei, &include_imeisv);
257 OSMO_ASSERT(msg);
258 VERIFY(msg, res2, ARRAY_SIZE(res2));
259 msgb_free(msg);
260}
261
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +0100262static void test_create_cipher_complete()
263{
264 static const uint8_t res1[] = {
265 0x00, 0x08, 0x55, 0x20, 0x03, 0x23, 0x42, 0x21, 0x2c, 0x04 };
266 static const uint8_t res2[] = { 0x00, 0x03, 0x55, 0x2c, 0x04};
267 struct msgb *l3, *msg;
268
269 printf("Testing creating Cipher Complete\n");
270 l3 = msgb_alloc_headroom(512, 128, "l3h");
271 l3->l3h = l3->data;
272 msgb_v_put(l3, 0x23);
273 msgb_v_put(l3, 0x42);
274 msgb_v_put(l3, 0x21);
275
276 /* with l3 data */
277 msg = gsm0808_create_cipher_complete(l3, 4);
278 VERIFY(msg, res1, ARRAY_SIZE(res1));
279 msgb_free(msg);
280
281 /* with l3 data but short */
282 l3->len -= 1;
283 l3->tail -= 1;
284 msg = gsm0808_create_cipher_complete(l3, 4);
285 VERIFY(msg, res2, ARRAY_SIZE(res2));
286 msgb_free(msg);
287
288 /* without l3 data */
289 msg = gsm0808_create_cipher_complete(NULL, 4);
290 VERIFY(msg, res2, ARRAY_SIZE(res2));
291 msgb_free(msg);
292
293
294 msgb_free(l3);
295}
296
Maxed651d22018-11-07 15:25:05 +0100297static inline void parse_cipher_reject(struct msgb *msg, uint8_t exp)
298{
299 struct tlv_parsed tp;
300 int rc;
301
302 /* skip header and message type so we can parse Cause IE directly */
303 msg->l2h = msgb_data(msg) + sizeof(struct bssmap_header) + 1;
304
305 rc = osmo_bssap_tlv_parse(&tp, msg->l2h, msgb_l2len(msg));
306 if (rc < 0)
307 printf("FIXME: failed (%d) to parse created message %s\n", rc, msgb_hexdump(msg));
308
Alexander Chemerisfdfe25b2020-05-12 23:21:56 +0300309 rc = gsm0808_get_cause(&tp);
Maxed651d22018-11-07 15:25:05 +0100310 if (rc < 0)
311 printf("FIXME: failed (%s) to extract Cause from created message %s\n",
312 strerror(-rc), msgb_hexdump(msg));
313
314 if (exp != (enum gsm0808_cause)rc)
315 printf("FIXME: wrong Cause %d != %u (" OSMO_BIN_SPEC ") extracted from created message %s\n",
316 rc, exp, OSMO_BIT_PRINT(exp), msgb_hexdump(msg));
317}
318
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +0100319static void test_create_cipher_reject()
320{
Harald Welte62e40852017-12-17 20:50:34 +0100321 static const uint8_t res[] = { 0x00, 0x04, 0x59, 0x04, 0x01, 0x23 };
Maxed651d22018-11-07 15:25:05 +0100322 enum gsm0808_cause cause = GSM0808_CAUSE_CCCH_OVERLOAD;
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +0100323 struct msgb *msg;
324
325 printf("Testing creating Cipher Reject\n");
Maxed651d22018-11-07 15:25:05 +0100326 msg = gsm0808_create_cipher_reject(cause);
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +0100327 VERIFY(msg, res, ARRAY_SIZE(res));
Maxed651d22018-11-07 15:25:05 +0100328
329 parse_cipher_reject(msg, cause);
330
331 msgb_free(msg);
332}
333
334static void test_create_cipher_reject_ext()
335{
336 static const uint8_t res[] = { 0x00, 0x05, 0x59, 0x04, 0x02, 0xd0, 0xFA };
337 uint8_t cause = 0xFA;
338 struct msgb *msg;
339
340 printf("Testing creating Cipher Reject (extended)\n");
341 msg = gsm0808_create_cipher_reject_ext(GSM0808_CAUSE_CLASS_INVAL, cause);
342 VERIFY(msg, res, ARRAY_SIZE(res));
343
344 parse_cipher_reject(msg, cause);
345
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +0100346 msgb_free(msg);
347}
348
349static void test_create_cm_u()
350{
Harald Welte07b625d2012-01-23 10:02:58 +0100351 static const uint8_t res[] = {
352 0x00, 0x07, 0x54, 0x12, 0x01, 0x23, 0x13, 0x01, 0x42 };
353 static const uint8_t res2o[] = {
354 0x00, 0x04, 0x54, 0x12, 0x01, 0x23 };
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +0100355 struct msgb *msg;
Harald Welte07b625d2012-01-23 10:02:58 +0100356 const uint8_t cm2 = 0x23;
357 const uint8_t cm3 = 0x42;
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +0100358
359 printf("Testing creating CM U\n");
Harald Welte07b625d2012-01-23 10:02:58 +0100360 msg = gsm0808_create_classmark_update(&cm2, 1, &cm3, 1);
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +0100361 VERIFY(msg, res, ARRAY_SIZE(res));
Harald Welte07b625d2012-01-23 10:02:58 +0100362
Neels Hofmeyr9a938ae2017-11-16 17:34:07 +0100363 msgb_free(msg);
364
Harald Welte07b625d2012-01-23 10:02:58 +0100365 msg = gsm0808_create_classmark_update(&cm2, 1, NULL, 0);
366 VERIFY(msg, res2o, ARRAY_SIZE(res2o));
367
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +0100368 msgb_free(msg);
369}
370
371static void test_create_sapi_reject()
372{
Alexander Chemerisa5b1b862020-05-12 01:03:08 +0300373 static const uint8_t res[] = { 0x00, 0x06, 0x25, 0x18, 0x03, 0x04, 0x01, 0x25 };
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +0100374 struct msgb *msg;
375
376 printf("Testing creating SAPI Reject\n");
377 msg = gsm0808_create_sapi_reject(3);
378 VERIFY(msg, res, ARRAY_SIZE(res));
379 msgb_free(msg);
380}
381
Alexander Chemeris22630e62020-05-13 00:44:04 +0300382static void test_dec_confusion()
383{
384 static const uint8_t hex[] =
385 { 0x26, 0x04, 0x01, 0x52, 0x1f, 0x07, 0x00, 0xff, 0x00, 0x03, 0x25, 0x03, 0x25 };
386 struct tlv_parsed tp;
387 int diag_len;
388 enum gsm0808_cause cause;
389 enum gsm0808_cause_class cause_class;
390 struct gsm0808_diagnostics *diag;
391
392 printf("Testing decoding CONFUSION\n");
393
394 tlv_parse(&tp, gsm0808_att_tlvdef(), hex+1, sizeof(hex)-1, 0, 0);
395
396 /* Check for the Cause and Diagnostic mandatory elements */
397 if (!TLVP_PRESENT(&tp, GSM0808_IE_CAUSE) || !TLVP_PRESENT(&tp, GSM0808_IE_DIAGNOSTIC)) {
398 printf("Either Cause or Diagnostic mandatory IE are not detected\n");
399 return;
400 }
401
402 diag_len = TLVP_LEN(&tp, GSM0808_IE_DIAGNOSTIC);
403 if (diag_len < 5) {
404 printf("Diagnostic length is too short: %d (expected > 5)\n",
405 diag_len);
406 return;
407 }
408
409 cause = gsm0808_get_cause(&tp);
410 if ((int)cause < 0) {
411 printf("ERROR: failed (%s) to extract Cause, aborting\n", strerror(-(int)cause));
412 return;
413 }
414 cause_class = gsm0808_cause_class(cause);
415 printf(" Cause class %d/0x%x (%s)\n",
416 cause_class, cause_class, gsm0808_cause_class_name(cause_class));
417 printf(" Cause %d/0x%x (%s)\n",
418 cause, cause, gsm0808_cause_name(cause));
419
420 diag = (struct gsm0808_diagnostics *)TLVP_VAL(&tp, GSM0808_IE_DIAGNOSTIC);
421 printf(" Diagnostics error octet location %d (%s)\n",
422 diag->error_pointer_octet,
423 gsm0808_diagnostics_octet_location_str(diag->error_pointer_octet));
424 printf(" Diagnostics error bit location %d (%s)\n",
425 diag->error_pointer_bit,
426 gsm0808_diagnostics_bit_location_str(diag->error_pointer_bit));
427 printf(" Diagnostics message that provoked the error: %s\n",
428 osmo_hexdump(diag->msg, diag_len-2));
429}
430
Philipp Maierc6144a22017-03-29 17:53:43 +0200431static void test_create_ass()
432{
433 static const uint8_t res1[] =
434 { 0x00, 0x0a, 0x01, 0x0b, 0x04, 0x01, 0x0b, 0xa1, 0x25, 0x01, 0x00,
435 0x04 };
436 static const uint8_t res2[] =
437 { 0x00, 0x20, 0x01, 0x0b, 0x04, 0x01, 0x0b, 0xa1, 0x25, 0x01, 0x00,
438 0x04, GSM0808_IE_AOIP_TRASP_ADDR, 0x06, 0xc0, 0xa8, 0x64, 0x17,
Philipp Maierbb839662017-06-01 17:11:19 +0200439 0x04, 0xd2, GSM0808_IE_SPEECH_CODEC_LIST, 0x07,
Philipp Maier7e27b142018-03-22 17:26:46 +0100440 GSM0808_SCT_FR3 | 0x50, 0xef, 0xcd, GSM0808_SCT_FR2 | 0xa0, 0x9f,
Philipp Maierbb839662017-06-01 17:11:19 +0200441 GSM0808_SCT_CSD | 0x90, 0xc0, GSM0808_IE_CALL_ID, 0xaa, 0xbb,
442 0xcc, 0xdd };
Philipp Maierc6144a22017-03-29 17:53:43 +0200443
444 struct msgb *msg;
445 struct gsm0808_channel_type ct;
446 uint16_t cic = 0004;
447 struct sockaddr_storage ss;
448 struct sockaddr_in sin;
449 struct gsm0808_speech_codec_list sc_list;
450 uint32_t call_id = 0xAABBCCDD;
451
452 memset(&ct, 0, sizeof(ct));
453 ct.ch_indctr = GSM0808_CHAN_SPEECH;
454 ct.ch_rate_type = GSM0808_SPEECH_HALF_PREF;
455 ct.perm_spch[0] = GSM0808_PERM_FR3;
456 ct.perm_spch[1] = GSM0808_PERM_HR3;
457 ct.perm_spch_len = 2;
458
459 memset(&sin, 0, sizeof(sin));
460 sin.sin_family = AF_INET;
461 sin.sin_port = htons(1234);
462 inet_aton("192.168.100.23", &sin.sin_addr);
463
464 memset(&ss, 0, sizeof(ss));
465 memcpy(&ss, &sin, sizeof(sin));
466
467 setup_codec_list(&sc_list);
468
469 printf("Testing creating Assignment Request\n");
470 msg = gsm0808_create_ass(&ct, &cic, NULL, NULL, NULL);
471 OSMO_ASSERT(msg);
472 VERIFY(msg, res1, ARRAY_SIZE(res1));
473 msgb_free(msg);
474
475 msg = gsm0808_create_ass(&ct, &cic, &ss, &sc_list, &call_id);
476 OSMO_ASSERT(msg);
477 VERIFY(msg, res2, ARRAY_SIZE(res2));
478 msgb_free(msg);
479}
480
Max52074322018-11-30 10:44:07 +0100481static void test_create_ass2()
482{
483 static const uint8_t res[] = {
484 BSSAP_MSG_BSS_MANAGEMENT,
485 0x45,
486 BSS_MAP_MSG_ASSIGMENT_RQST,
487 GSM0808_IE_CHANNEL_TYPE,
488 0x04, 0x01, 0x0b, 0x91, 0x15, 0x01, 0x00, 0x04,
489 GSM0808_IE_AOIP_TRASP_ADDR,
490 0x06,
491 0xac, 0x0c, 0x65, 0x0d, /* IPv4 */
492 0x02, 0x9a,
493 GSM0808_IE_SPEECH_CODEC_LIST,
494 0x07,
495 GSM0808_SCT_FR3 | 0x50,
496 0xef, 0xcd,
497 GSM0808_SCT_FR2 | 0xa0,
498 0x9f,
499 GSM0808_SCT_CSD | 0x90,
500 0xc0,
501 GSM0808_IE_CALL_ID,
502 0xde, 0xad, 0xfa, 0xce, /* CallID */
503 0x83, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, /* Kc */
504 GSM0808_IE_GLOBAL_CALL_REF, 0x0d, /* GCR, length */
505 0x03, 0x44, 0x44, 0x44, /* GCR, Net ID */
506 0x02, 0xfe, 0xed, /* GCR, Node ID */
507 0x05, 0x41, 0x41, 0x41, 0x41, 0x41, /* GCR, Call ref. ID */
508 GSM0808_IE_LCLS_CONFIG, GSM0808_LCLS_CFG_BOTH_WAY,
509 GSM0808_IE_LCLS_CONN_STATUS_CTRL, GSM0808_LCLS_CSC_CONNECT,
510 GSM0808_IE_LCLS_CORR_NOT_NEEDED,
511 };
512 struct msgb *msg;
513 struct gsm0808_channel_type ct;
514 uint16_t cic = 4;
515 struct sockaddr_storage ss;
516 struct sockaddr_in sin;
517 struct gsm0808_speech_codec_list sc_list;
518 uint32_t call_id = 0xDEADFACE;
Max52074322018-11-30 10:44:07 +0100519 uint8_t Kc[16];
520 struct osmo_lcls lcls = {
521 .config = GSM0808_LCLS_CFG_BOTH_WAY,
522 .control = GSM0808_LCLS_CSC_CONNECT,
Max3b901252019-01-15 14:15:11 +0100523 .gcr = { .net_len = 3, .node = 0xFEED },
524 .gcr_available = true,
Max52074322018-11-30 10:44:07 +0100525 .corr_needed = false
526 };
527
Max3b901252019-01-15 14:15:11 +0100528 memset(lcls.gcr.cr, 'A', 5);
529 memset(lcls.gcr.net, 'D', lcls.gcr.net_len);
Max52074322018-11-30 10:44:07 +0100530 memset(Kc, 'E', 16);
531
532 memset(&ct, 0, sizeof(ct));
533 ct.ch_indctr = GSM0808_CHAN_SPEECH;
534 ct.ch_rate_type = GSM0808_SPEECH_HALF_PREF;
535 ct.perm_spch[0] = GSM0808_PERM_FR2;
536 ct.perm_spch[1] = GSM0808_PERM_HR2;
537 ct.perm_spch_len = 2;
538
539 memset(&sin, 0, sizeof(sin));
540 sin.sin_family = AF_INET;
541 sin.sin_port = htons(666);
542 inet_aton("172.12.101.13", &sin.sin_addr); /* IPv4 */
543
544 memset(&ss, 0, sizeof(ss));
545 memcpy(&ss, &sin, sizeof(sin));
546
547 setup_codec_list(&sc_list);
548
549 printf("Testing creating Assignment Request with Kc and LCLS\n");
550
551 msg = gsm0808_create_ass2(&ct, &cic, &ss, &sc_list, &call_id, Kc, &lcls);
552 if (!msgb_eq_l3_data_print(msg, res, ARRAY_SIZE(res)))
553 abort();
554
555 msgb_free(msg);
556}
557
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +0100558static void test_create_ass_compl()
559{
560 static const uint8_t res1[] = {
561 0x00, 0x09, 0x02, 0x15, 0x23, 0x21, 0x42, 0x2c,
562 0x11, 0x40, 0x22 };
563 static const uint8_t res2[] = {
564 0x00, 0x07, 0x02, 0x15, 0x23, 0x21, 0x42, 0x2c, 0x11};
565 struct msgb *msg;
566
567 printf("Testing creating Assignment Complete\n");
568 msg = gsm0808_create_assignment_completed(0x23, 0x42, 0x11, 0x22);
569 VERIFY(msg, res1, ARRAY_SIZE(res1));
570 msgb_free(msg);
571
572 msg = gsm0808_create_assignment_completed(0x23, 0x42, 0x11, 0);
573 VERIFY(msg, res2, ARRAY_SIZE(res2));
574 msgb_free(msg);
575}
576
Philipp Maierfa896ab2017-03-27 16:55:32 +0200577static void test_create_ass_compl_aoip()
578{
579 struct sockaddr_storage ss;
580 struct sockaddr_in sin;
581 struct gsm0808_speech_codec sc;
582 struct gsm0808_speech_codec_list sc_list;
583 static const uint8_t res[] =
Max414c8f52019-01-08 14:44:24 +0100584 { 0x00, 0x1f, 0x02, 0x15, 0x23, 0x21, 0x42, 0x2c, 0x11, 0x40, 0x22,
Philipp Maierfa896ab2017-03-27 16:55:32 +0200585 GSM0808_IE_AOIP_TRASP_ADDR, 0x06, 0xc0, 0xa8, 0x64, 0x17, 0x04,
Philipp Maierbb839662017-06-01 17:11:19 +0200586 0xd2, GSM0808_IE_SPEECH_CODEC, 0x01, GSM0808_SCT_HR1 | 0x90,
Philipp Maier7e27b142018-03-22 17:26:46 +0100587 GSM0808_IE_SPEECH_CODEC_LIST, 0x07, GSM0808_SCT_FR3 | 0x50, 0xef,
Max414c8f52019-01-08 14:44:24 +0100588 0xcd, GSM0808_SCT_FR2 | 0xa0, 0x9f, GSM0808_SCT_CSD | 0x90, 0xc0,
589 GSM0808_IE_LCLS_BSS_STATUS, GSM0808_LCLS_STS_LOCALLY_SWITCHED };
Philipp Maierfa896ab2017-03-27 16:55:32 +0200590 struct msgb *msg;
591
592 memset(&sin, 0, sizeof(sin));
593 sin.sin_family = AF_INET;
594 sin.sin_port = htons(1234);
595 inet_aton("192.168.100.23", &sin.sin_addr);
596
597 memset(&ss, 0, sizeof(ss));
598 memcpy(&ss, &sin, sizeof(sin));
599
600 memset(&sc, 0, sizeof(sc));
601 sc.fi = true;
602 sc.tf = true;
Philipp Maierbb839662017-06-01 17:11:19 +0200603 sc.type = GSM0808_SCT_HR1;
Philipp Maierfa896ab2017-03-27 16:55:32 +0200604
605 setup_codec_list(&sc_list);
606
607 printf("Testing creating Assignment Complete (AoIP)\n");
Max414c8f52019-01-08 14:44:24 +0100608 msg = gsm0808_create_ass_compl2(0x23, 0x42, 0x11, 0x22,
609 &ss, &sc, &sc_list, GSM0808_LCLS_STS_LOCALLY_SWITCHED);
Philipp Maierfa896ab2017-03-27 16:55:32 +0200610 VERIFY(msg, res, ARRAY_SIZE(res));
611 msgb_free(msg);
612}
613
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +0100614static void test_create_ass_fail()
615{
616 static const uint8_t res1[] = { 0x00, 0x04, 0x03, 0x04, 0x01, 0x23 };
617 static const uint8_t res2[] = {
618 0x00, 0x06, 0x03, 0x04, 0x01, 0x23, 0x15, 0x02};
619 uint8_t rr_res = 2;
620 struct msgb *msg;
621
622 printf("Testing creating Assignment Failure\n");
623 msg = gsm0808_create_assignment_failure(0x23, NULL);
624 VERIFY(msg, res1, ARRAY_SIZE(res1));
625 msgb_free(msg);
626
627 msg = gsm0808_create_assignment_failure(0x23, &rr_res);
628 VERIFY(msg, res2, ARRAY_SIZE(res2));
629 msgb_free(msg);
630}
631
Philipp Maierfa896ab2017-03-27 16:55:32 +0200632static void test_create_ass_fail_aoip()
633{
634 static const uint8_t res1[] =
635 { 0x00, 0x0d, 0x03, 0x04, 0x01, 0x23, GSM0808_IE_SPEECH_CODEC_LIST,
Philipp Maier7e27b142018-03-22 17:26:46 +0100636 0x07, GSM0808_SCT_FR3 | 0x50, 0xef, 0xcd, GSM0808_SCT_FR2 | 0xa0,
Philipp Maierbb839662017-06-01 17:11:19 +0200637 0x9f, GSM0808_SCT_CSD | 0x90, 0xc0 };
Philipp Maierfa896ab2017-03-27 16:55:32 +0200638 static const uint8_t res2[] =
639 { 0x00, 0x0f, 0x03, 0x04, 0x01, 0x23, 0x15, 0x02,
Philipp Maier7e27b142018-03-22 17:26:46 +0100640 GSM0808_IE_SPEECH_CODEC_LIST, 0x07, GSM0808_SCT_FR3 | 0x50, 0xef,
641 0xcd, GSM0808_SCT_FR2 | 0xa0, 0x9f, GSM0808_SCT_CSD | 0x90, 0xc0 };
Philipp Maierfa896ab2017-03-27 16:55:32 +0200642 uint8_t rr_res = 2;
643 struct msgb *msg;
644 struct gsm0808_speech_codec_list sc_list;
645
646 setup_codec_list(&sc_list);
647
648 printf("Testing creating Assignment Failure (AoIP)\n");
649 msg = gsm0808_create_ass_fail(0x23, NULL, &sc_list);
650 VERIFY(msg, res1, ARRAY_SIZE(res1));
651 msgb_free(msg);
652
653 msg = gsm0808_create_ass_fail(0x23, &rr_res, &sc_list);
654 VERIFY(msg, res2, ARRAY_SIZE(res2));
655 msgb_free(msg);
656}
657
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +0100658static void test_create_clear_rqst()
659{
660 static const uint8_t res[] = { 0x00, 0x04, 0x22, 0x04, 0x01, 0x23 };
661 struct msgb *msg;
662
663 printf("Testing creating Clear Request\n");
664 msg = gsm0808_create_clear_rqst(0x23);
665 VERIFY(msg, res, ARRAY_SIZE(res));
666 msgb_free(msg);
667}
668
Philipp Maier3d48ec02017-03-29 17:37:55 +0200669static void test_create_paging()
670{
671 static const uint8_t res[] =
672 { 0x00, 0x10, 0x52, 0x08, 0x08, 0x09, 0x10, 0x10, 0x00, 0x00, 0x00,
673 0x21, 0x43, 0x1a, 0x03, 0x05, 0x23, 0x42 };
674 static const uint8_t res2[] =
675 { 0x00, 0x16, 0x52, 0x08, 0x08, 0x09, 0x10, 0x10, 0x00, 0x00, 0x00,
676 0x21, 0x43, GSM0808_IE_TMSI, 0x04, 0x12, 0x34, 0x56, 0x78, 0x1a,
677 0x03, 0x05, 0x23, 0x42 };
678 static const uint8_t res3[] =
679 { 0x00, 0x18, 0x52, 0x08, 0x08, 0x09, 0x10, 0x10, 0x00, 0x00, 0x00,
680 0x21, 0x43, GSM0808_IE_TMSI, 0x04, 0x12, 0x34, 0x56, 0x78, 0x1a,
681 0x03, 0x05, 0x23, 0x42, GSM0808_IE_CHANNEL_NEEDED,
682 RSL_CHANNEED_TCH_ForH };
683
684 struct msgb *msg;
Stefan Sperling11a4d9d2018-02-15 18:28:04 +0100685 struct gsm0808_cell_id_list2 cil;
Philipp Maier3d48ec02017-03-29 17:37:55 +0200686 uint32_t tmsi = 0x12345678;
687 uint8_t chan_needed = RSL_CHANNEED_TCH_ForH;
688
689 char imsi[] = "001010000001234";
690
691 cil.id_discr = CELL_IDENT_LAC;
Stefan Sperling11a4d9d2018-02-15 18:28:04 +0100692 cil.id_list[0].lac = 0x2342;
Philipp Maier3d48ec02017-03-29 17:37:55 +0200693 cil.id_list_len = 1;
694
695 printf("Testing creating Paging Request\n");
Stefan Sperling11a4d9d2018-02-15 18:28:04 +0100696 msg = gsm0808_create_paging2(imsi, NULL, &cil, NULL);
Philipp Maier3d48ec02017-03-29 17:37:55 +0200697 VERIFY(msg, res, ARRAY_SIZE(res));
698 msgb_free(msg);
699
Stefan Sperling11a4d9d2018-02-15 18:28:04 +0100700 msg = gsm0808_create_paging2(imsi, &tmsi, &cil, NULL);
Philipp Maier3d48ec02017-03-29 17:37:55 +0200701 VERIFY(msg, res2, ARRAY_SIZE(res2));
702 msgb_free(msg);
703
Stefan Sperling11a4d9d2018-02-15 18:28:04 +0100704 msg = gsm0808_create_paging2(imsi, &tmsi, &cil, &chan_needed);
Philipp Maier3d48ec02017-03-29 17:37:55 +0200705 VERIFY(msg, res3, ARRAY_SIZE(res3));
706 msgb_free(msg);
707}
708
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +0100709static void test_create_dtap()
710{
711 static const uint8_t res[] = { 0x01, 0x03, 0x02, 0x23, 0x42 };
712 struct msgb *msg, *l3;
713
714 printf("Testing creating DTAP\n");
715 l3 = msgb_alloc_headroom(512, 128, "test");
716 l3->l3h = l3->data;
717 msgb_v_put(l3, 0x23);
718 msgb_v_put(l3, 0x42);
719
720 msg = gsm0808_create_dtap(l3, 0x3);
721 VERIFY(msg, res, ARRAY_SIZE(res));
722 msgb_free(msg);
723 msgb_free(l3);
724}
725
726static void test_prepend_dtap()
727{
728 static const uint8_t res[] = { 0x01, 0x03, 0x02, 0x23, 0x42 };
729 struct msgb *in_msg;
730
731 printf("Testing prepend DTAP\n");
732
733 in_msg = msgb_alloc_headroom(512, 128, "test");
734 msgb_v_put(in_msg, 0x23);
735 msgb_v_put(in_msg, 0x42);
736
737 gsm0808_prepend_dtap_header(in_msg, 0x3);
738 in_msg->l3h = in_msg->data;
739 VERIFY(in_msg, res, ARRAY_SIZE(res));
740 msgb_free(in_msg);
741}
742
Max47022152018-12-19 18:51:00 +0100743static void test_enc_dec_lcls()
Max969fb2e2018-12-10 11:01:10 +0100744{
745 static const uint8_t res[] = {
746 GSM0808_IE_GLOBAL_CALL_REF,
747 0x0d, /* GCR length */
748 0x03, /* .net_len */
749 0xf1, 0xf2, 0xf3, /* .net */
750 0x02, /* .node length */
751 0xde, 0xad, /* .node */
752 0x05, /* length of Call. Ref. */
753 0x41, 0x42, 0x43, 0x44, 0x45 /* .cr - Call. Ref. */
754 };
755 uint8_t len;
756 struct msgb *msg;
Max969fb2e2018-12-10 11:01:10 +0100757 int rc;
758 struct tlv_parsed tp;
Max3b901252019-01-15 14:15:11 +0100759 struct osmo_lcls *lcls_out, lcls_in = {
760 .gcr = {
761 .net_len = 3,
762 .net = { 0xf1, 0xf2, 0xf3 },
763 .node = 0xDEAD,
764 .cr = { 0x41, 0x42, 0x43, 0x44, 0x45 },
765 },
766 .gcr_available = true,
Max47022152018-12-19 18:51:00 +0100767 .config = GSM0808_LCLS_CFG_NA,
768 .control = GSM0808_LCLS_CSC_NA,
769 .corr_needed = true,
770 };
771
772 msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM, "LCLS IE");
Max969fb2e2018-12-10 11:01:10 +0100773 if (!msg)
774 return;
775
Max3b901252019-01-15 14:15:11 +0100776 lcls_out = talloc_zero(msg, struct osmo_lcls);
777 if (!lcls_out)
778 return;
779
Max47022152018-12-19 18:51:00 +0100780 len = gsm0808_enc_lcls(msg, &lcls_in);
Max969fb2e2018-12-10 11:01:10 +0100781 printf("Testing Global Call Reference IE encoder...\n\t%d bytes added: %s\n",
782 len, len == ARRAY_SIZE(res) ? "OK" : "FAIL");
783
784 if (!msgb_eq_data_print(msg, res, ARRAY_SIZE(res)))
785 abort();
786
787 rc = osmo_bssap_tlv_parse(&tp, msgb_data(msg), msgb_length(msg));
788 if (rc < 0) {
789 printf("parsing failed: %s [%s]\n", strerror(-rc), msgb_hexdump(msg));
790 abort();
791 }
792
Max3b901252019-01-15 14:15:11 +0100793 rc = gsm0808_dec_lcls(lcls_out, &tp);
Max969fb2e2018-12-10 11:01:10 +0100794 if (rc < 0) {
795 printf("decoding failed: %s [%s]\n", strerror(-rc), msgb_hexdump(msg));
796 abort();
797 }
798
Max3b901252019-01-15 14:15:11 +0100799 if (lcls_out->config != lcls_in.config) {
Max4fd64e52019-01-14 19:27:44 +0100800 printf("LCLS Config parsed wrong: %s != %s\n",
Max3b901252019-01-15 14:15:11 +0100801 gsm0808_lcls_config_name(lcls_out->config), gsm0808_lcls_config_name(lcls_in.config));
Max4fd64e52019-01-14 19:27:44 +0100802 abort();
803 }
804
Max3b901252019-01-15 14:15:11 +0100805 if (lcls_out->control != lcls_in.control) {
Max4fd64e52019-01-14 19:27:44 +0100806 printf("LCLS Control parsed wrong: %s != %s\n",
Max3b901252019-01-15 14:15:11 +0100807 gsm0808_lcls_control_name(lcls_out->control), gsm0808_lcls_control_name(lcls_in.control));
Max4fd64e52019-01-14 19:27:44 +0100808 abort();
809 }
810
Max3b901252019-01-15 14:15:11 +0100811 if (!osmo_gcr_eq(&lcls_out->gcr, &lcls_in.gcr)) {
Max5ec0cf52019-01-15 16:37:09 +0100812 printf("GCR parsed wrong:\n\t%s\n\t%s\n", osmo_gcr_dump(lcls_out), osmo_gcr_dump(&lcls_in));
Max1bec3902019-01-14 19:31:42 +0100813 abort();
814 }
Max969fb2e2018-12-10 11:01:10 +0100815
Max5ec0cf52019-01-15 16:37:09 +0100816 printf("\tdecoded %d bytes: %s:\n%s\n", rc, rc == len ? "OK" : "FAIL", osmo_lcls_dump(lcls_out));
817 printf("\t%s\n", osmo_gcr_dump(lcls_out));
Max969fb2e2018-12-10 11:01:10 +0100818 msgb_free(msg);
819}
820
Philipp Maier22401432017-03-24 17:59:26 +0100821static void test_enc_dec_aoip_trasp_addr_v4()
822{
823 struct sockaddr_storage enc_addr;
824 struct sockaddr_storage dec_addr;
825 struct sockaddr_in enc_addr_in;
826 struct msgb *msg;
827 uint8_t rc_enc;
828 int rc_dec;
829
830 memset(&enc_addr_in, 0, sizeof(enc_addr_in));
831 enc_addr_in.sin_family = AF_INET;
832 enc_addr_in.sin_port = htons(1234);
833 inet_aton("255.0.255.255", &enc_addr_in.sin_addr);
834
835 memset(&enc_addr, 0, sizeof(enc_addr));
836 memcpy(&enc_addr, &enc_addr_in, sizeof(enc_addr_in));
837
838 msg = msgb_alloc(1024, "output buffer");
839 rc_enc = gsm0808_enc_aoip_trasp_addr(msg, &enc_addr);
840 OSMO_ASSERT(rc_enc == 8);
841 rc_dec =
842 gsm0808_dec_aoip_trasp_addr(&dec_addr, msg->data + 2, msg->len - 2);
843 OSMO_ASSERT(rc_dec == 6);
844 OSMO_ASSERT(memcmp(&enc_addr, &dec_addr, sizeof(enc_addr)) == 0);
845
846 msgb_free(msg);
847}
848
849static void test_enc_dec_aoip_trasp_addr_v6()
850{
851 struct sockaddr_storage enc_addr;
852 struct sockaddr_storage dec_addr;
853 struct sockaddr_in6 enc_addr_in;
854 struct msgb *msg;
855 uint8_t rc_enc;
856 int rc_dec;
857
858 memset(&enc_addr_in, 0, sizeof(enc_addr_in));
859 enc_addr_in.sin6_family = AF_INET6;
860 enc_addr_in.sin6_port = htons(4567);
861 inet_pton(AF_INET6, "2001:0db8:85a3:08d3:1319:8a2e:0370:7344",
862 &enc_addr_in.sin6_addr);
863
864 memset(&enc_addr, 0, sizeof(enc_addr));
865 memcpy(&enc_addr, &enc_addr_in, sizeof(enc_addr_in));
866
867 msg = msgb_alloc(1024, "output buffer");
868 rc_enc = gsm0808_enc_aoip_trasp_addr(msg, &enc_addr);
869 OSMO_ASSERT(rc_enc == 20);
870 rc_dec =
871 gsm0808_dec_aoip_trasp_addr(&dec_addr, msg->data + 2, msg->len - 2);
872 OSMO_ASSERT(rc_dec == 18);
873 OSMO_ASSERT(memcmp(&enc_addr, &dec_addr, sizeof(enc_addr)) == 0);
874
875 msgb_free(msg);
876}
877
Philipp Maier6f725d62017-03-24 18:03:17 +0100878static void test_gsm0808_enc_dec_speech_codec()
879{
Neels Hofmeyr9a4286b2018-04-20 12:27:52 +0200880 struct gsm0808_speech_codec enc_sc = {
881 .pi = true,
882 .tf = true,
883 .type = GSM0808_SCT_FR2,
884 };
885 struct gsm0808_speech_codec dec_sc = {};
Philipp Maier6f725d62017-03-24 18:03:17 +0100886 struct msgb *msg;
887 uint8_t rc_enc;
888 int rc_dec;
889
Philipp Maier6f725d62017-03-24 18:03:17 +0100890 msg = msgb_alloc(1024, "output buffer");
891 rc_enc = gsm0808_enc_speech_codec(msg, &enc_sc);
892 OSMO_ASSERT(rc_enc == 3);
893
894 rc_dec = gsm0808_dec_speech_codec(&dec_sc, msg->data + 2, msg->len - 2);
895 OSMO_ASSERT(rc_dec == 1);
896
897 OSMO_ASSERT(memcmp(&enc_sc, &dec_sc, sizeof(enc_sc)) == 0);
898
899 msgb_free(msg);
900}
901
902
Philipp Maierbb839662017-06-01 17:11:19 +0200903static void test_gsm0808_enc_dec_speech_codec_with_cfg()
904{
Neels Hofmeyrc62c9342018-04-15 23:31:47 +0200905 struct gsm0808_speech_codec enc_sc = {
906 .pi = true,
907 .tf = true,
908 .type = GSM0808_SCT_FR3,
909 .cfg = 0xabcd,
910 };
911 struct gsm0808_speech_codec dec_sc = {};
Philipp Maierbb839662017-06-01 17:11:19 +0200912 struct msgb *msg;
913 uint8_t rc_enc;
914 int rc_dec;
915
Philipp Maierbb839662017-06-01 17:11:19 +0200916 msg = msgb_alloc(1024, "output buffer");
917 rc_enc = gsm0808_enc_speech_codec(msg, &enc_sc);
918 OSMO_ASSERT(rc_enc == 5);
919
920 rc_dec = gsm0808_dec_speech_codec(&dec_sc, msg->data + 2, msg->len - 2);
921 OSMO_ASSERT(rc_dec == 3);
922
923 OSMO_ASSERT(memcmp(&enc_sc, &dec_sc, sizeof(enc_sc)) == 0);
924
925 msgb_free(msg);
926}
927
Philipp Maier6f725d62017-03-24 18:03:17 +0100928static void test_gsm0808_enc_dec_speech_codec_ext_with_cfg()
929{
Neels Hofmeyr9a4286b2018-04-20 12:27:52 +0200930 struct gsm0808_speech_codec enc_sc = {
931 .pi = true,
932 .tf = true,
933 .type = GSM0808_SCT_CSD,
934 .cfg = 0xc0,
935 };
936 struct gsm0808_speech_codec dec_sc = {};
Philipp Maier6f725d62017-03-24 18:03:17 +0100937 struct msgb *msg;
938 uint8_t rc_enc;
939 int rc_dec;
940
Philipp Maier6f725d62017-03-24 18:03:17 +0100941 msg = msgb_alloc(1024, "output buffer");
942 rc_enc = gsm0808_enc_speech_codec(msg, &enc_sc);
Philipp Maierbb839662017-06-01 17:11:19 +0200943 OSMO_ASSERT(rc_enc == 5);
Philipp Maier6f725d62017-03-24 18:03:17 +0100944
945 rc_dec = gsm0808_dec_speech_codec(&dec_sc, msg->data + 2, msg->len - 2);
Philipp Maierbb839662017-06-01 17:11:19 +0200946 OSMO_ASSERT(rc_dec == 3);
Philipp Maier6f725d62017-03-24 18:03:17 +0100947
948 OSMO_ASSERT(memcmp(&enc_sc, &dec_sc, sizeof(enc_sc)) == 0);
949
950 msgb_free(msg);
951}
952
953static void test_gsm0808_enc_dec_speech_codec_list()
954{
Neels Hofmeyr9a4286b2018-04-20 12:27:52 +0200955 struct gsm0808_speech_codec_list enc_scl = {
956 .codec = {
957 {
958 .pi = true,
959 .tf = true,
960 .type = GSM0808_SCT_FR3,
961 .cfg = 0xcdef,
962 },
963
964 {
965 .fi = true,
966 .pt = true,
967 .type = GSM0808_SCT_FR2,
968 },
969
970 {
971 .fi = true,
972 .tf = true,
973 .type = GSM0808_SCT_CSD,
974 .cfg = 0xc0,
975 },
976 },
977 .len = 3,
978 };
979 struct gsm0808_speech_codec_list dec_scl = {};
Philipp Maier6f725d62017-03-24 18:03:17 +0100980 struct msgb *msg;
981 uint8_t rc_enc;
982 int rc_dec;
983
Philipp Maier6f725d62017-03-24 18:03:17 +0100984 msg = msgb_alloc(1024, "output buffer");
985 rc_enc = gsm0808_enc_speech_codec_list(msg, &enc_scl);
986 OSMO_ASSERT(rc_enc == 9);
987
988 rc_dec = gsm0808_dec_speech_codec_list(&dec_scl, msg->data + 2, msg->len - 2);
989 OSMO_ASSERT(rc_dec == 7);
990
991 OSMO_ASSERT(memcmp(&enc_scl, &dec_scl, sizeof(enc_scl)) == 0);
992
993 msgb_free(msg);
994}
995
Philipp Maierf6c369f2018-10-16 15:24:47 +0200996static void test_gsm0808_enc_dec_empty_speech_codec_list()
997{
998 struct gsm0808_speech_codec_list enc_scl = {
999 .len = 0,
1000 };
1001 struct gsm0808_speech_codec_list dec_scl = {};
1002 struct msgb *msg;
1003 uint8_t rc_enc;
1004 int rc_dec;
1005
1006 msg = msgb_alloc(1024, "output buffer");
1007 rc_enc = gsm0808_enc_speech_codec_list(msg, &enc_scl);
1008 OSMO_ASSERT(rc_enc == 2);
1009
1010 rc_dec = gsm0808_dec_speech_codec_list(&dec_scl, msg->data + 2, msg->len - 2);
1011 OSMO_ASSERT(rc_dec == 0);
1012
1013 OSMO_ASSERT(memcmp(&enc_scl, &dec_scl, sizeof(enc_scl)) == 0);
1014
1015 msgb_free(msg);
1016}
1017
Philipp Maiere0c65302017-03-28 17:05:40 +02001018static void test_gsm0808_enc_dec_channel_type()
1019{
Neels Hofmeyr9a4286b2018-04-20 12:27:52 +02001020 struct gsm0808_channel_type enc_ct = {
1021 .ch_indctr = GSM0808_CHAN_SPEECH,
1022 .ch_rate_type = GSM0808_SPEECH_HALF_PREF,
1023 .perm_spch = { GSM0808_PERM_FR3, GSM0808_PERM_HR3 },
1024 .perm_spch_len = 2,
1025 };
1026 struct gsm0808_channel_type dec_ct = {};
Philipp Maiere0c65302017-03-28 17:05:40 +02001027 struct msgb *msg;
1028 uint8_t ct_enc_expected[] = { GSM0808_IE_CHANNEL_TYPE,
1029 0x04, 0x01, 0x0b, 0xa1, 0x25
1030 };
1031 uint8_t rc_enc;
1032 int rc_dec;
1033
Philipp Maiere0c65302017-03-28 17:05:40 +02001034 msg = msgb_alloc(1024, "output buffer");
1035 rc_enc = gsm0808_enc_channel_type(msg, &enc_ct);
1036 OSMO_ASSERT(rc_enc == 6);
1037 OSMO_ASSERT(memcmp(ct_enc_expected, msg->data, msg->len) == 0);
1038
1039 rc_dec = gsm0808_dec_channel_type(&dec_ct, msg->data + 2, msg->len - 2);
1040 OSMO_ASSERT(rc_dec == 4);
Pau Espin Pedrol2605ffc2019-07-29 16:44:22 +02001041 OSMO_ASSERT(enc_ct.ch_indctr == dec_ct.ch_indctr);
1042 OSMO_ASSERT(enc_ct.ch_rate_type == dec_ct.ch_rate_type);
1043 OSMO_ASSERT(enc_ct.perm_spch_len == dec_ct.perm_spch_len);
1044 OSMO_ASSERT(memcmp(&enc_ct.perm_spch[0], &dec_ct.perm_spch[0], enc_ct.perm_spch_len) == 0);
Philipp Maiere0c65302017-03-28 17:05:40 +02001045
1046 msgb_free(msg);
1047}
1048
Philipp Maier14e76b92017-03-28 18:36:52 +02001049static void test_gsm0808_enc_dec_encrypt_info()
1050{
Neels Hofmeyr9a4286b2018-04-20 12:27:52 +02001051 struct gsm0808_encrypt_info enc_ei = {
1052 .perm_algo = { GSM0808_ALG_ID_A5_0, GSM0808_ALG_ID_A5_1 },
1053 .perm_algo_len = 2,
1054 .key = { 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x23, 0x42, },
1055 .key_len = 8,
1056 };
1057 struct gsm0808_encrypt_info dec_ei = {};
Philipp Maier14e76b92017-03-28 18:36:52 +02001058 struct msgb *msg;
1059 uint8_t ei_enc_expected[] =
1060 { GSM0808_IE_ENCRYPTION_INFORMATION, 0x09, 0x03, 0xaa, 0xbb,
1061 0xcc, 0xdd, 0xee, 0xff, 0x23, 0x42
1062 };
1063 uint8_t rc_enc;
1064 int rc_dec;
1065
Philipp Maier14e76b92017-03-28 18:36:52 +02001066 msg = msgb_alloc(1024, "output buffer");
1067 rc_enc = gsm0808_enc_encrypt_info(msg, &enc_ei);
1068 OSMO_ASSERT(rc_enc == 11);
1069 OSMO_ASSERT(memcmp(ei_enc_expected, msg->data, msg->len) == 0);
1070
1071 rc_dec = gsm0808_dec_encrypt_info(&dec_ei, msg->data + 2, msg->len - 2);
1072 OSMO_ASSERT(rc_dec == 9);
1073
1074 OSMO_ASSERT(memcmp(&enc_ei, &dec_ei, sizeof(enc_ei)) == 0);
1075
1076 msgb_free(msg);
1077}
1078
Philipp Maier783047e2017-03-29 11:35:50 +02001079static void test_gsm0808_enc_dec_cell_id_list_lac()
1080{
Stefan Sperling11a4d9d2018-02-15 18:28:04 +01001081 struct gsm0808_cell_id_list2 enc_cil;
1082 struct gsm0808_cell_id_list2 dec_cil;
Philipp Maier783047e2017-03-29 11:35:50 +02001083 struct msgb *msg;
1084 uint8_t rc_enc;
1085 int rc_dec;
1086
1087 memset(&enc_cil, 0, sizeof(enc_cil));
1088 enc_cil.id_discr = CELL_IDENT_LAC;
Stefan Sperling11a4d9d2018-02-15 18:28:04 +01001089 enc_cil.id_list[0].lac = 0x0124;
Neels Hofmeyrdb2fa4e2018-04-13 04:11:20 +02001090 enc_cil.id_list[1].lac = 0xABCD;
1091 enc_cil.id_list[2].lac = 0x5678;
Philipp Maier783047e2017-03-29 11:35:50 +02001092 enc_cil.id_list_len = 3;
1093
1094 msg = msgb_alloc(1024, "output buffer");
Stefan Sperling11a4d9d2018-02-15 18:28:04 +01001095 rc_enc = gsm0808_enc_cell_id_list2(msg, &enc_cil);
Neels Hofmeyrdb2fa4e2018-04-13 04:11:20 +02001096 EXPECT_ENCODED("1a 07 05 01 24 ab cd 56 78");
Philipp Maier783047e2017-03-29 11:35:50 +02001097
Stefan Sperling11a4d9d2018-02-15 18:28:04 +01001098 rc_dec = gsm0808_dec_cell_id_list2(&dec_cil, msg->data + 2, msg->len - 2);
Philipp Maier783047e2017-03-29 11:35:50 +02001099 OSMO_ASSERT(rc_dec == 7);
1100
1101 OSMO_ASSERT(memcmp(&enc_cil, &dec_cil, sizeof(enc_cil)) == 0);
1102
1103 msgb_free(msg);
1104}
1105
1106static void test_gsm0808_enc_dec_cell_id_list_single_lac()
1107{
Stefan Sperling11a4d9d2018-02-15 18:28:04 +01001108 struct gsm0808_cell_id_list2 enc_cil;
1109 struct gsm0808_cell_id_list2 dec_cil;
Philipp Maier783047e2017-03-29 11:35:50 +02001110 struct msgb *msg;
1111 uint8_t cil_enc_expected[] = { GSM0808_IE_CELL_IDENTIFIER_LIST, 0x03,
1112 0x05, 0x23, 0x42
1113 };
1114 uint8_t rc_enc;
1115 int rc_dec;
1116
1117 memset(&enc_cil, 0, sizeof(enc_cil));
1118 enc_cil.id_discr = CELL_IDENT_LAC;
Stefan Sperling11a4d9d2018-02-15 18:28:04 +01001119 enc_cil.id_list[0].lac = 0x2342;
Philipp Maier783047e2017-03-29 11:35:50 +02001120 enc_cil.id_list_len = 1;
1121
1122 msg = msgb_alloc(1024, "output buffer");
Stefan Sperling11a4d9d2018-02-15 18:28:04 +01001123 rc_enc = gsm0808_enc_cell_id_list2(msg, &enc_cil);
Philipp Maier783047e2017-03-29 11:35:50 +02001124 OSMO_ASSERT(rc_enc == 5);
1125 OSMO_ASSERT(memcmp(cil_enc_expected, msg->data, msg->len) == 0);
1126
Stefan Sperling11a4d9d2018-02-15 18:28:04 +01001127 rc_dec = gsm0808_dec_cell_id_list2(&dec_cil, msg->data + 2, msg->len - 2);
Philipp Maier783047e2017-03-29 11:35:50 +02001128 OSMO_ASSERT(rc_dec == 3);
1129
1130 OSMO_ASSERT(memcmp(&enc_cil, &dec_cil, sizeof(enc_cil)) == 0);
1131
1132 msgb_free(msg);
1133}
1134
Stefan Sperlinge1a86742018-03-15 18:05:02 +01001135static void test_gsm0808_enc_dec_cell_id_list_multi_lac()
1136{
1137 struct gsm0808_cell_id_list2 enc_cil;
1138 struct gsm0808_cell_id_list2 dec_cil;
1139 struct msgb *msg;
1140 uint8_t cil_enc_expected[] = { GSM0808_IE_CELL_IDENTIFIER_LIST, 0x0b, 0x05,
1141 0x23, 0x42,
1142 0x24, 0x43,
1143 0x25, 0x44,
1144 0x26, 0x45,
1145 0x27, 0x46
1146 };
1147 uint8_t rc_enc;
1148 int rc_dec;
1149
1150 memset(&enc_cil, 0, sizeof(enc_cil));
1151 enc_cil.id_discr = CELL_IDENT_LAC;
1152 enc_cil.id_list[0].lac = 0x2342;
1153 enc_cil.id_list[1].lac = 0x2443;
1154 enc_cil.id_list[2].lac = 0x2544;
1155 enc_cil.id_list[3].lac = 0x2645;
1156 enc_cil.id_list[4].lac = 0x2746;
1157 enc_cil.id_list_len = 5;
1158
1159 msg = msgb_alloc(1024, "output buffer");
1160 rc_enc = gsm0808_enc_cell_id_list2(msg, &enc_cil);
1161 OSMO_ASSERT(rc_enc == sizeof(cil_enc_expected));
1162 OSMO_ASSERT(memcmp(cil_enc_expected, msg->data, msg->len) == 0);
1163
1164 rc_dec = gsm0808_dec_cell_id_list2(&dec_cil, msg->data + 2, msg->len - 2);
1165 OSMO_ASSERT(rc_dec == msg->len - 2);
1166 OSMO_ASSERT(memcmp(&enc_cil, &dec_cil, sizeof(enc_cil)) == 0);
1167
1168 msgb_free(msg);
1169}
1170
Philipp Maier783047e2017-03-29 11:35:50 +02001171static void test_gsm0808_enc_dec_cell_id_list_bss()
1172{
Stefan Sperling11a4d9d2018-02-15 18:28:04 +01001173 struct gsm0808_cell_id_list2 enc_cil;
1174 struct gsm0808_cell_id_list2 dec_cil;
Philipp Maier783047e2017-03-29 11:35:50 +02001175 struct msgb *msg;
1176 uint8_t rc_enc;
1177 int rc_dec;
1178
1179 memset(&enc_cil, 0, sizeof(enc_cil));
Stefan Sperling11a4d9d2018-02-15 18:28:04 +01001180 enc_cil.id_discr = CELL_IDENT_BSS;
Philipp Maier783047e2017-03-29 11:35:50 +02001181
1182 msg = msgb_alloc(1024, "output buffer");
Stefan Sperling11a4d9d2018-02-15 18:28:04 +01001183 rc_enc = gsm0808_enc_cell_id_list2(msg, &enc_cil);
Philipp Maier783047e2017-03-29 11:35:50 +02001184 OSMO_ASSERT(rc_enc == 3);
1185
Stefan Sperling11a4d9d2018-02-15 18:28:04 +01001186 rc_dec = gsm0808_dec_cell_id_list2(&dec_cil, msg->data + 2, msg->len - 2);
Philipp Maier783047e2017-03-29 11:35:50 +02001187 OSMO_ASSERT(rc_dec == 1);
1188
1189 OSMO_ASSERT(memcmp(&enc_cil, &dec_cil, sizeof(enc_cil)) == 0);
1190
1191 msgb_free(msg);
1192}
1193
Stefan Sperling23381452018-03-15 19:38:15 +01001194static void test_gsm0808_enc_dec_cell_id_list_multi_lai_and_lac()
1195{
1196 struct gsm0808_cell_id_list2 enc_cil;
1197 struct gsm0808_cell_id_list2 dec_cil;
1198 struct osmo_location_area_id id;
1199 struct msgb *msg;
1200 uint8_t cil_enc_expected[] = { GSM0808_IE_CELL_IDENTIFIER_LIST, 0x10, 0x04,
1201 0x92, 0x61, 0x54, 0x23, 0x42,
1202 0x92, 0x72, 0x54, 0x24, 0x43,
1203 0x92, 0x83, 0x54, 0x25, 0x44
1204 };
1205 uint8_t rc_enc;
1206 int rc_dec, i;
1207
1208 memset(&enc_cil, 0, sizeof(enc_cil));
1209 enc_cil.id_discr = CELL_IDENT_LAI_AND_LAC;
1210
1211 id.plmn.mcc = 0x123;
1212 osmo_mnc_from_str("456", &id.plmn.mnc, &id.plmn.mnc_3_digits);
1213 id.lac = 0x2342;
1214 memcpy(&enc_cil.id_list[0].lai_and_lac, &id, sizeof(id));
1215
1216 id.plmn.mcc = 0x124;
1217 osmo_mnc_from_str("457", &id.plmn.mnc, &id.plmn.mnc_3_digits);
1218 id.lac = 0x2443;
1219 memcpy(&enc_cil.id_list[1].lai_and_lac, &id, sizeof(id));
1220
1221 id.plmn.mcc = 0x125;
1222 osmo_mnc_from_str("458", &id.plmn.mnc, &id.plmn.mnc_3_digits);
1223 id.lac = 0x2544;
1224 memcpy(&enc_cil.id_list[2].lai_and_lac, &id, sizeof(id));
1225
1226 enc_cil.id_list_len = 3;
1227
1228 msg = msgb_alloc(1024, "output buffer");
1229 rc_enc = gsm0808_enc_cell_id_list2(msg, &enc_cil);
1230 OSMO_ASSERT(rc_enc == sizeof(cil_enc_expected));
1231 OSMO_ASSERT(memcmp(cil_enc_expected, msg->data, msg->len) == 0);
1232
1233 rc_dec = gsm0808_dec_cell_id_list2(&dec_cil, msg->data + 2, msg->len - 2);
1234 OSMO_ASSERT(rc_dec == msg->len - 2);
1235
1236 OSMO_ASSERT(dec_cil.id_list_len == 3);
1237 /* Check MAXLEN elements to ensure everything has been initialized. */
1238 for (i = 0; i < GSM0808_CELL_ID_LIST2_MAXLEN; i++) {
1239 struct osmo_location_area_id *enc_id;
1240 struct osmo_location_area_id *dec_id;
1241 enc_id = &enc_cil.id_list[i].lai_and_lac;
1242 dec_id = &dec_cil.id_list[i].lai_and_lac;
1243 OSMO_ASSERT(osmo_plmn_cmp(&enc_id->plmn, &dec_id->plmn) == 0);
1244 OSMO_ASSERT(enc_id->lac == dec_id->lac);
1245 }
1246
1247 msgb_free(msg);
1248}
1249
Stefan Sperling9c62fc62018-03-16 10:23:34 +01001250static void test_gsm0808_enc_dec_cell_id_list_multi_ci()
1251{
1252 struct gsm0808_cell_id_list2 enc_cil;
1253 struct gsm0808_cell_id_list2 dec_cil;
1254 struct msgb *msg;
1255 uint8_t cil_enc_expected[] = { GSM0808_IE_CELL_IDENTIFIER_LIST, 0x09, 0x02,
1256 0x00, 0x01,
1257 0x00, 0x02,
1258 0x00, 0x77,
1259 0x01, 0xff,
1260 };
1261 uint8_t rc_enc;
1262 int rc_dec;
1263
1264 memset(&enc_cil, 0, sizeof(enc_cil));
1265 enc_cil.id_discr = CELL_IDENT_CI;
1266 enc_cil.id_list[0].ci = 1;
1267 enc_cil.id_list[1].ci = 2;
1268 enc_cil.id_list[2].ci = 119;
1269 enc_cil.id_list[3].ci = 511;
1270 enc_cil.id_list_len = 4;
1271
1272 msg = msgb_alloc(1024, "output buffer");
1273 rc_enc = gsm0808_enc_cell_id_list2(msg, &enc_cil);
1274 OSMO_ASSERT(rc_enc == sizeof(cil_enc_expected));
1275 OSMO_ASSERT(memcmp(cil_enc_expected, msg->data, msg->len) == 0);
1276
1277 rc_dec = gsm0808_dec_cell_id_list2(&dec_cil, msg->data + 2, msg->len - 2);
1278 OSMO_ASSERT(rc_dec == msg->len - 2);
1279 OSMO_ASSERT(memcmp(&enc_cil, &dec_cil, sizeof(enc_cil)) == 0);
1280
1281 msgb_free(msg);
1282}
1283
Stefan Sperlinged4327c2018-03-16 11:02:59 +01001284static void test_gsm0808_enc_dec_cell_id_list_multi_lac_and_ci()
1285{
1286 struct gsm0808_cell_id_list2 enc_cil;
1287 struct gsm0808_cell_id_list2 dec_cil;
1288 struct msgb *msg;
1289 uint8_t cil_enc_expected[] = { GSM0808_IE_CELL_IDENTIFIER_LIST, 0x15, 0x01,
1290 0x23, 0x42, 0x00, 0x01,
1291 0x24, 0x43, 0x00, 0x02,
1292 0x25, 0x44, 0x00, 0x77,
1293 0x26, 0x45, 0x01, 0xff,
1294 0x27, 0x46, 0x02, 0xfe,
1295 };
1296 uint8_t rc_enc;
1297 int rc_dec;
1298
1299 memset(&enc_cil, 0, sizeof(enc_cil));
1300 enc_cil.id_discr = CELL_IDENT_LAC_AND_CI;
1301 enc_cil.id_list[0].lac_and_ci.lac = 0x2342;
1302 enc_cil.id_list[0].lac_and_ci.ci = 1;
1303 enc_cil.id_list[1].lac_and_ci.lac = 0x2443;
1304 enc_cil.id_list[1].lac_and_ci.ci = 2;
1305 enc_cil.id_list[2].lac_and_ci.lac = 0x2544;
1306 enc_cil.id_list[2].lac_and_ci.ci = 119;
1307 enc_cil.id_list[3].lac_and_ci.lac = 0x2645;
1308 enc_cil.id_list[3].lac_and_ci.ci = 511;
1309 enc_cil.id_list[4].lac_and_ci.lac = 0x2746;
1310 enc_cil.id_list[4].lac_and_ci.ci = 766;
1311 enc_cil.id_list_len = 5;
1312
1313 msg = msgb_alloc(1024, "output buffer");
1314 rc_enc = gsm0808_enc_cell_id_list2(msg, &enc_cil);
1315 OSMO_ASSERT(rc_enc == sizeof(cil_enc_expected));
1316 OSMO_ASSERT(memcmp(cil_enc_expected, msg->data, msg->len) == 0);
1317
1318 rc_dec = gsm0808_dec_cell_id_list2(&dec_cil, msg->data + 2, msg->len - 2);
1319 OSMO_ASSERT(rc_dec == msg->len - 2);
1320 OSMO_ASSERT(memcmp(&enc_cil, &dec_cil, sizeof(enc_cil)) == 0);
1321
1322 msgb_free(msg);
1323}
1324
Stefan Sperling483f3862018-03-16 12:21:26 +01001325static void test_gsm0808_enc_dec_cell_id_list_multi_global()
1326{
1327 struct gsm0808_cell_id_list2 enc_cil;
1328 struct gsm0808_cell_id_list2 dec_cil;
1329 struct msgb *msg;
1330 uint8_t cil_enc_expected[] = { GSM0808_IE_CELL_IDENTIFIER_LIST, 0x16, 0x00,
Neels Hofmeyr473485c2018-03-23 02:04:18 +01001331 0x21, 0x63, 0x54, 0x23, 0x42, 0x00, 0x1,
Neels Hofmeyrc44fc232018-03-23 02:15:12 +01001332 0x21, 0xf4, 0x75, 0x24, 0x43, 0x00, 0x2,
Neels Hofmeyr8b8cd932018-03-23 01:47:37 +01001333 0x21, 0x75, 0x00, 0x25, 0x44, 0x00, 0x77
Stefan Sperling483f3862018-03-16 12:21:26 +01001334 };
Stefan Sperling483f3862018-03-16 12:21:26 +01001335 uint8_t rc_enc;
1336 int rc_dec, i;
1337
Neels Hofmeyrc1991df2018-03-23 02:00:00 +01001338 enc_cil = (struct gsm0808_cell_id_list2){
1339 .id_discr = CELL_IDENT_WHOLE_GLOBAL,
1340 .id_list_len = 3,
1341 .id_list = {
1342 {
1343 .global = {
Neels Hofmeyr473485c2018-03-23 02:04:18 +01001344 .lai = { .plmn = { .mcc = 123, .mnc = 456 },
Neels Hofmeyrc1991df2018-03-23 02:00:00 +01001345 .lac = 0x2342 },
1346 .cell_identity = 1,
1347 }
1348 },
1349 {
1350 .global = {
Neels Hofmeyrc44fc232018-03-23 02:15:12 +01001351 .lai = { .plmn = { .mcc = 124, .mnc = 57 },
Neels Hofmeyrc1991df2018-03-23 02:00:00 +01001352 .lac = 0x2443 },
1353 .cell_identity = 2,
1354 }
1355 },
1356 {
1357 .global = {
Neels Hofmeyrc44fc232018-03-23 02:15:12 +01001358 .lai = { .plmn = { .mcc = 125, .mnc = 7,
1359 .mnc_3_digits = true },
Neels Hofmeyrc1991df2018-03-23 02:00:00 +01001360 .lac = 0x2544 },
1361 .cell_identity = 119,
1362 }
1363 },
1364 }
1365 };
Stefan Sperling483f3862018-03-16 12:21:26 +01001366
1367 msg = msgb_alloc(1024, "output buffer");
1368 rc_enc = gsm0808_enc_cell_id_list2(msg, &enc_cil);
1369 OSMO_ASSERT(rc_enc == sizeof(cil_enc_expected));
Neels Hofmeyrc1991df2018-03-23 02:00:00 +01001370 if (memcmp(cil_enc_expected, msg->data, msg->len)) {
1371 printf(" got: %s\n", osmo_hexdump(msg->data, msg->len));
1372 printf("expect: %s\n", osmo_hexdump(cil_enc_expected, sizeof(cil_enc_expected)));
1373 OSMO_ASSERT(false);
1374 }
Stefan Sperling483f3862018-03-16 12:21:26 +01001375
1376 rc_dec = gsm0808_dec_cell_id_list2(&dec_cil, msg->data + 2, msg->len - 2);
1377 OSMO_ASSERT(rc_dec == msg->len - 2);
1378
1379 /* Check MAXLEN elements to ensure everything has been initialized. */
1380 for (i = 0; i < GSM0808_CELL_ID_LIST2_MAXLEN; i++) {
1381 struct osmo_cell_global_id *enc_id;
1382 struct osmo_cell_global_id *dec_id;
1383 enc_id = &enc_cil.id_list[i].global;
1384 dec_id = &dec_cil.id_list[i].global;
1385 OSMO_ASSERT(osmo_plmn_cmp(&enc_id->lai.plmn, &dec_id->lai.plmn) == 0);
1386 OSMO_ASSERT(enc_id->lai.lac == dec_id->lai.lac);
1387 OSMO_ASSERT(enc_id->cell_identity == dec_id->cell_identity);
1388 }
1389
1390 msgb_free(msg);
1391}
1392
Neels Hofmeyr74663d92018-03-23 01:46:42 +01001393static void print_cil(const struct gsm0808_cell_id_list2 *cil)
1394{
Neels Hofmeyra4399c82018-04-17 02:26:10 +02001395 printf(" cell_id_list == %s\n", gsm0808_cell_id_list_name(cil));
Neels Hofmeyr74663d92018-03-23 01:46:42 +01001396}
1397
1398void test_cell_id_list_add() {
Neels Hofmeyra4399c82018-04-17 02:26:10 +02001399 size_t zu;
1400
Neels Hofmeyr74663d92018-03-23 01:46:42 +01001401 const struct gsm0808_cell_id_list2 cgi1 = {
1402 .id_discr = CELL_IDENT_WHOLE_GLOBAL,
1403 .id_list_len = 1,
1404 .id_list = {
1405 {
1406 .global = {
1407 .lai = {
1408 .plmn = { .mcc = 1, .mnc = 2, .mnc_3_digits = false },
1409 .lac = 3,
1410 },
1411 .cell_identity = 4,
1412 }
1413 },
1414 },
1415 };
1416
1417 const struct gsm0808_cell_id_list2 cgi2 = {
1418 .id_discr = CELL_IDENT_WHOLE_GLOBAL,
1419 .id_list_len = 2,
1420 .id_list = {
1421 {
1422 .global = {
1423 .lai = {
1424 .plmn = { .mcc = 1, .mnc = 2, .mnc_3_digits = true },
1425 .lac = 3,
1426 },
1427 .cell_identity = 4,
1428 }
1429 },
1430 {
1431 .global = {
1432 .lai = {
1433 .plmn = { .mcc = 5, .mnc = 6, .mnc_3_digits = true },
1434 .lac = 7,
1435 },
1436 .cell_identity = 8,
1437 }
1438 },
1439 },
1440 };
1441
1442 const struct gsm0808_cell_id_list2 cgi2a = {
1443 .id_discr = CELL_IDENT_WHOLE_GLOBAL,
1444 .id_list_len = 2,
1445 .id_list = {
1446 {
1447 .global = cgi2.id_list[0].global
1448 },
1449 {
1450 .global = {
1451 .lai = {
1452 .plmn = { .mcc = 9, .mnc = 10, .mnc_3_digits = true },
1453 .lac = 11,
1454 },
1455 .cell_identity = 12,
1456 }
1457 },
1458 },
1459 };
1460
1461 const struct gsm0808_cell_id_list2 cgi3 = {
1462 .id_discr = CELL_IDENT_WHOLE_GLOBAL,
1463 .id_list_len = 2,
1464 .id_list = {
1465 {
1466 .global = {
1467 .lai = {
1468 .plmn = { .mcc = 13, .mnc = 14, .mnc_3_digits = true },
1469 .lac = 15,
1470 },
1471 .cell_identity = 16,
1472 }
1473 },
1474 {
1475 .global = {
1476 .lai = {
1477 .plmn = { .mcc = 16, .mnc = 17, .mnc_3_digits = true },
1478 .lac = 18,
1479 },
1480 .cell_identity = 19,
1481 }
1482 },
1483 },
1484 };
1485
1486
1487 const struct gsm0808_cell_id_list2 lac1 = {
1488 .id_discr = CELL_IDENT_LAC,
1489 .id_list_len = 1,
1490 .id_list = {
1491 {
1492 .lac = 123
1493 },
1494 },
1495 };
1496
1497 const struct gsm0808_cell_id_list2 lac2 = {
1498 .id_discr = CELL_IDENT_LAC,
1499 .id_list_len = 2,
1500 .id_list = {
1501 {
1502 .lac = 456
1503 },
1504 {
1505 .lac = 789
1506 },
1507 },
1508 };
1509
1510 struct gsm0808_cell_id_list2 cil = {};
1511
1512 printf("------- %s\n", __func__);
1513
1514 print_cil(&cil);
1515
1516#define ADD_QUIET(other_cil, expect_rc) do { \
1517 int rc = gsm0808_cell_id_list_add(&cil, &other_cil); \
Neels Hofmeyra4399c82018-04-17 02:26:10 +02001518 printf("gsm0808_cell_id_list_add(&cil, &" #other_cil ") --> rc = %d\n", rc); \
Neels Hofmeyr74663d92018-03-23 01:46:42 +01001519 OSMO_ASSERT(rc == expect_rc); \
1520 } while(0)
1521
1522#define ADD(other_cil, expect_rc) ADD_QUIET(other_cil, expect_rc); print_cil(&cil)
1523
1524 ADD(lac1, 1);
1525 ADD(lac1, 0);
1526 ADD(lac2, 2);
1527 ADD(lac2, 0);
1528 ADD(cil, 0);
1529 ADD(cgi1, -EINVAL);
1530
Neels Hofmeyra4399c82018-04-17 02:26:10 +02001531 printf("* can't add to BSS list\n");
Neels Hofmeyr74663d92018-03-23 01:46:42 +01001532 cil.id_list_len = 0;
1533 cil.id_discr = CELL_IDENT_BSS;
1534 print_cil(&cil);
1535 ADD(lac1, -EINVAL);
1536
Neels Hofmeyra4399c82018-04-17 02:26:10 +02001537 printf("* other types (including NO_CELL) take on new type iff empty\n");
Neels Hofmeyr74663d92018-03-23 01:46:42 +01001538 cil.id_list_len = 0;
1539 cil.id_discr = CELL_IDENT_NO_CELL;
1540 print_cil(&cil);
1541 ADD(cgi1, 1);
1542 ADD(cgi1, 0);
1543 ADD(cgi2, 2);
1544 ADD(cgi2, 0);
1545
Neels Hofmeyra4399c82018-04-17 02:26:10 +02001546 printf("* test gsm0808_cell_id_list_name_buf()'s return val\n");
1547 zu = strlen(gsm0808_cell_id_list_name(&cil));
1548 printf(" strlen(gsm0808_cell_id_list_name(cil)) == %zu\n", zu);
1549 zu ++;
1550 while (1) {
1551 char buf[128] = "?";
1552 int rc;
1553 OSMO_ASSERT(zu < sizeof(buf));
1554 buf[zu] = '#';
1555 rc = gsm0808_cell_id_list_name_buf(buf, zu, &cil);
1556 printf(" gsm0808_cell_id_list_name_buf(buf, %zu, cil)) == %d \"%s\"\n",
1557 zu, rc, buf);
1558 OSMO_ASSERT(buf[zu] == '#');
1559 if (!zu)
1560 break;
1561 zu /= 2;
1562 }
1563
1564 printf("* list-full behavior\n");
Neels Hofmeyr74663d92018-03-23 01:46:42 +01001565 cil.id_list_len = GSM0808_CELL_ID_LIST2_MAXLEN - 1;
Neels Hofmeyra4399c82018-04-17 02:26:10 +02001566 printf("cil.id_list_len = %u\n", cil.id_list_len);
Neels Hofmeyr74663d92018-03-23 01:46:42 +01001567 ADD_QUIET(cgi2a, 1);
1568 printf("cil.id_list_len = %u\n", cil.id_list_len);
1569
1570 cil.id_list_len = GSM0808_CELL_ID_LIST2_MAXLEN - 1;
Neels Hofmeyra4399c82018-04-17 02:26:10 +02001571 printf("cil.id_list_len = %u\n", cil.id_list_len);
Neels Hofmeyr74663d92018-03-23 01:46:42 +01001572 ADD_QUIET(cgi3, -ENOSPC);
Neels Hofmeyra4399c82018-04-17 02:26:10 +02001573 printf("cil.id_list_len = %u\n", cil.id_list_len);
Neels Hofmeyr74663d92018-03-23 01:46:42 +01001574 ADD_QUIET(cgi2a, -ENOSPC);
1575 printf("cil.id_list_len = %u\n", cil.id_list_len);
1576
1577 printf("------- %s done\n", __func__);
1578}
1579
Neels Hofmeyr250e7f72018-04-13 03:30:14 +02001580static void test_gsm0808_enc_dec_cell_id_lac()
1581{
1582 struct gsm0808_cell_id enc_ci = {
1583 .id_discr = CELL_IDENT_LAC,
1584 .id.lac = 0x0124,
1585 };
1586 struct gsm0808_cell_id dec_ci;
1587 struct msgb *msg;
1588 uint8_t rc_enc;
1589 int rc_dec;
1590
1591 memset(&dec_ci, 0xa5, sizeof(dec_ci));
1592
1593 msg = msgb_alloc(1024, "output buffer");
1594 rc_enc = gsm0808_enc_cell_id(msg, &enc_ci);
1595 EXPECT_ENCODED("05 03 05 01 24");
1596
1597 rc_dec = gsm0808_dec_cell_id(&dec_ci, msg->data + 2, msg->len - 2);
1598 OSMO_ASSERT(rc_dec == 3);
1599
1600 OSMO_ASSERT(enc_ci.id_discr == dec_ci.id_discr
1601 && enc_ci.id.lac == dec_ci.id.lac);
1602
1603 msgb_free(msg);
1604}
1605
1606static void test_gsm0808_enc_dec_cell_id_bss()
1607{
1608 struct gsm0808_cell_id enc_ci = {
1609 .id_discr = CELL_IDENT_BSS,
1610 };
1611 struct gsm0808_cell_id dec_ci;
1612 struct msgb *msg;
1613 uint8_t rc_enc;
1614 int rc_dec;
1615
1616 msg = msgb_alloc(1024, "output buffer");
1617 rc_enc = gsm0808_enc_cell_id(msg, &enc_ci);
1618 EXPECT_ENCODED("05 01 06");
1619
1620 rc_dec = gsm0808_dec_cell_id(&dec_ci, msg->data + 2, msg->len - 2);
1621 OSMO_ASSERT(rc_dec == 1);
1622
1623 OSMO_ASSERT(enc_ci.id_discr == dec_ci.id_discr);
1624
1625 msgb_free(msg);
1626}
1627
1628static void test_gsm0808_enc_dec_cell_id_no_cell()
1629{
1630 struct gsm0808_cell_id enc_ci = {
1631 .id_discr = CELL_IDENT_NO_CELL,
1632 };
1633 struct gsm0808_cell_id dec_ci;
1634 struct msgb *msg;
1635 uint8_t rc_enc;
1636 int rc_dec;
1637
1638 msg = msgb_alloc(1024, "output buffer");
1639 rc_enc = gsm0808_enc_cell_id(msg, &enc_ci);
1640 EXPECT_ENCODED("05 01 03");
1641
1642 rc_dec = gsm0808_dec_cell_id(&dec_ci, msg->data + 2, msg->len - 2);
1643 OSMO_ASSERT(rc_dec == 1);
1644
1645 OSMO_ASSERT(enc_ci.id_discr == dec_ci.id_discr);
1646
1647 msgb_free(msg);
1648}
1649
1650static void test_gsm0808_enc_dec_cell_id_lai_and_lac()
1651{
1652 struct gsm0808_cell_id enc_ci = {
1653 .id_discr = CELL_IDENT_LAI_AND_LAC,
1654 .id.lai_and_lac = {
1655 .plmn = {
1656 .mcc = 123,
1657 .mnc = 456,
1658 },
1659 .lac = 0x2342,
1660 },
1661 };
1662 struct gsm0808_cell_id dec_ci;
1663 struct msgb *msg;
1664 uint8_t rc_enc;
1665 int rc_dec;
1666
1667 msg = msgb_alloc(1024, "output buffer");
1668 rc_enc = gsm0808_enc_cell_id(msg, &enc_ci);
1669 EXPECT_ENCODED("05 06 04 21 63 54 23 42");
1670
1671 memset(&dec_ci, 0xa5, sizeof(dec_ci));
1672 rc_dec = gsm0808_dec_cell_id(&dec_ci, msg->data + 2, msg->len - 2);
1673 OSMO_ASSERT(rc_dec == msg->len - 2);
1674
1675 OSMO_ASSERT(enc_ci.id_discr == dec_ci.id_discr
1676 && osmo_plmn_cmp(&enc_ci.id.lai_and_lac.plmn, &dec_ci.id.lai_and_lac.plmn) == 0
1677 && enc_ci.id.lai_and_lac.lac == dec_ci.id.lai_and_lac.lac);
1678 msgb_free(msg);
1679}
1680
1681static void test_gsm0808_enc_dec_cell_id_ci()
1682{
1683 struct gsm0808_cell_id enc_ci = {
1684 .id_discr = CELL_IDENT_CI,
1685 .id.ci = 0x423,
1686 };
1687 struct gsm0808_cell_id dec_ci;
1688 struct msgb *msg;
1689 uint8_t rc_enc;
1690 int rc_dec;
1691
1692 msg = msgb_alloc(1024, "output buffer");
1693 rc_enc = gsm0808_enc_cell_id(msg, &enc_ci);
1694 EXPECT_ENCODED("05 03 02 04 23");
1695
1696 rc_dec = gsm0808_dec_cell_id(&dec_ci, msg->data + 2, msg->len - 2);
1697 OSMO_ASSERT(rc_dec == msg->len - 2);
1698 OSMO_ASSERT(enc_ci.id_discr == dec_ci.id_discr
1699 && enc_ci.id.ci == dec_ci.id.ci);
1700
1701 msgb_free(msg);
1702}
1703
1704static void test_gsm0808_enc_dec_cell_id_lac_and_ci()
1705{
1706 struct gsm0808_cell_id enc_ci = {
1707 .id_discr = CELL_IDENT_LAC_AND_CI,
1708 .id.lac_and_ci = {
1709 .lac = 0x423,
1710 .ci = 0x235,
1711 },
1712 };
1713 struct gsm0808_cell_id dec_ci;
1714 struct msgb *msg;
1715 uint8_t rc_enc;
1716 int rc_dec;
1717
1718 msg = msgb_alloc(1024, "output buffer");
1719 rc_enc = gsm0808_enc_cell_id(msg, &enc_ci);
1720 EXPECT_ENCODED("05 05 01 04 23 02 35");
1721
1722 rc_dec = gsm0808_dec_cell_id(&dec_ci, msg->data + 2, msg->len - 2);
1723 OSMO_ASSERT(rc_dec == msg->len - 2);
1724 OSMO_ASSERT(enc_ci.id_discr == dec_ci.id_discr
1725 && enc_ci.id.lac_and_ci.lac == dec_ci.id.lac_and_ci.lac
1726 && enc_ci.id.lac_and_ci.ci == dec_ci.id.lac_and_ci.ci);
1727
1728 msgb_free(msg);
1729}
1730
1731static void test_gsm0808_enc_dec_cell_id_global()
1732{
1733 struct gsm0808_cell_id enc_ci = {
1734 .id_discr = CELL_IDENT_WHOLE_GLOBAL,
1735 .id.global = {
1736 .lai = {
1737 .plmn = { .mcc = 123, .mnc = 456 },
1738 .lac = 0x2342
1739 },
1740 .cell_identity = 0x423,
1741 }
1742 };
1743 struct gsm0808_cell_id dec_ci;
1744 struct msgb *msg;
1745 uint8_t rc_enc;
1746 int rc_dec;
1747
1748 msg = msgb_alloc(1024, "output buffer");
1749 rc_enc = gsm0808_enc_cell_id(msg, &enc_ci);
1750 EXPECT_ENCODED("05 08 00 21 63 54 23 42 04 23");
1751
1752 rc_dec = gsm0808_dec_cell_id(&dec_ci, msg->data + 2, msg->len - 2);
1753 OSMO_ASSERT(rc_dec == msg->len - 2);
1754
1755 OSMO_ASSERT(enc_ci.id_discr == dec_ci.id_discr
1756 && osmo_plmn_cmp(&enc_ci.id.global.lai.plmn,
1757 &dec_ci.id.global.lai.plmn) == 0
1758 && enc_ci.id.global.lai.lac == dec_ci.id.global.lai.lac
1759 && enc_ci.id.global.cell_identity == dec_ci.id.global.cell_identity);
1760 msgb_free(msg);
1761}
1762
Philipp Maier5f2eb152018-09-19 13:40:21 +02001763static void test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(struct gsm48_multi_rate_conf *cfg)
1764{
1765 uint16_t s15_s0;
1766
1767 printf("Input:\n");
1768 printf(" m4_75= %u smod= %u\n", cfg->m4_75, cfg->smod);
1769 printf(" m5_15= %u spare= %u\n", cfg->m5_15, cfg->spare);
1770 printf(" m5_90= %u icmi= %u\n", cfg->m5_90, cfg->icmi);
1771 printf(" m6_70= %u nscb= %u\n", cfg->m6_70, cfg->nscb);
1772 printf(" m7_40= %u ver= %u\n", cfg->m7_40, cfg->ver);
1773 printf(" m7_95= %u\n", cfg->m7_95);
1774 printf(" m10_2= %u\n", cfg->m10_2);
1775 printf(" m12_2= %u\n", cfg->m12_2);
1776
1777 s15_s0 = gsm0808_sc_cfg_from_gsm48_mr_cfg(cfg, true);
1778 printf("Result (fr):\n");
1779 printf(" S15-S0 = %04x = 0b" OSMO_BIN_SPEC OSMO_BIN_SPEC "\n", s15_s0,
1780 OSMO_BIN_PRINT(s15_s0 >> 8), OSMO_BIN_PRINT(s15_s0));
1781
1782 s15_s0 = gsm0808_sc_cfg_from_gsm48_mr_cfg(cfg, false);
1783 printf("Result (hr):\n");
1784 printf(" S15-S0 = %04x = 0b" OSMO_BIN_SPEC OSMO_BIN_SPEC "\n", s15_s0,
1785 OSMO_BIN_PRINT(s15_s0 >> 8), OSMO_BIN_PRINT(s15_s0));
1786
1787 printf("\n");
1788}
1789
1790static void test_gsm0808_sc_cfg_from_gsm48_mr_cfg(void)
1791{
1792 struct gsm48_multi_rate_conf cfg;
1793
1794 printf("Testing gsm0808_sc_cfg_from_gsm48_mr_cfg():\n");
1795
1796 memset(&cfg, 0, sizeof(cfg));
1797
1798 cfg.m4_75 = 0;
1799 cfg.m5_15 = 0;
1800 cfg.m5_90 = 0;
1801 cfg.m6_70 = 0;
1802 cfg.m7_40 = 0;
1803 cfg.m7_95 = 0;
1804 cfg.m10_2 = 0;
1805 cfg.m12_2 = 0;
1806 test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(&cfg);
1807
1808 cfg.m4_75 = 1;
1809 cfg.m5_15 = 0;
1810 cfg.m5_90 = 0;
1811 cfg.m6_70 = 0;
1812 cfg.m7_40 = 0;
1813 cfg.m7_95 = 0;
1814 cfg.m10_2 = 0;
1815 cfg.m12_2 = 0;
1816 test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(&cfg);
1817
1818 cfg.m4_75 = 0;
1819 cfg.m5_15 = 1;
1820 cfg.m5_90 = 0;
1821 cfg.m6_70 = 0;
1822 cfg.m7_40 = 0;
1823 cfg.m7_95 = 0;
1824 cfg.m10_2 = 0;
1825 cfg.m12_2 = 0;
1826 test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(&cfg);
1827
1828 cfg.m4_75 = 0;
1829 cfg.m5_15 = 0;
1830 cfg.m5_90 = 1;
1831 cfg.m6_70 = 0;
1832 cfg.m7_40 = 0;
1833 cfg.m7_95 = 0;
1834 cfg.m10_2 = 0;
1835 cfg.m12_2 = 0;
1836 test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(&cfg);
1837
1838 cfg.m4_75 = 0;
1839 cfg.m5_15 = 0;
1840 cfg.m5_90 = 0;
1841 cfg.m6_70 = 1;
1842 cfg.m7_40 = 0;
1843 cfg.m7_95 = 0;
1844 cfg.m10_2 = 0;
1845 cfg.m12_2 = 0;
1846 test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(&cfg);
1847
1848 cfg.m4_75 = 0;
1849 cfg.m5_15 = 0;
1850 cfg.m5_90 = 0;
1851 cfg.m6_70 = 0;
1852 cfg.m7_40 = 1;
1853 cfg.m7_95 = 0;
1854 cfg.m10_2 = 0;
1855 cfg.m12_2 = 0;
1856 test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(&cfg);
1857
1858 cfg.m4_75 = 0;
1859 cfg.m5_15 = 0;
1860 cfg.m5_90 = 0;
1861 cfg.m6_70 = 0;
1862 cfg.m7_40 = 0;
1863 cfg.m7_95 = 1;
1864 cfg.m10_2 = 0;
1865 cfg.m12_2 = 0;
1866 test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(&cfg);
1867
1868 cfg.m4_75 = 0;
1869 cfg.m5_15 = 0;
1870 cfg.m5_90 = 0;
1871 cfg.m6_70 = 0;
1872 cfg.m7_40 = 0;
1873 cfg.m7_95 = 0;
1874 cfg.m10_2 = 1;
1875 cfg.m12_2 = 0;
1876 test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(&cfg);
1877
1878 cfg.m4_75 = 0;
1879 cfg.m5_15 = 0;
1880 cfg.m5_90 = 0;
1881 cfg.m6_70 = 0;
1882 cfg.m7_40 = 0;
1883 cfg.m7_95 = 0;
1884 cfg.m10_2 = 0;
1885 cfg.m12_2 = 1;
1886 test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(&cfg);
1887
1888 cfg.m4_75 = 1;
1889 cfg.m5_15 = 1;
1890 cfg.m5_90 = 1;
1891 cfg.m6_70 = 1;
1892 cfg.m7_40 = 0;
1893 cfg.m7_95 = 0;
1894 cfg.m10_2 = 0;
1895 cfg.m12_2 = 0;
1896 test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(&cfg);
1897
1898 cfg.m4_75 = 0;
1899 cfg.m5_15 = 0;
1900 cfg.m5_90 = 0;
1901 cfg.m6_70 = 0;
1902 cfg.m7_40 = 1;
1903 cfg.m7_95 = 1;
1904 cfg.m10_2 = 1;
1905 cfg.m12_2 = 1;
1906 test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(&cfg);
1907
1908 cfg.m4_75 = 0;
1909 cfg.m5_15 = 0;
1910 cfg.m5_90 = 1;
1911 cfg.m6_70 = 1;
1912 cfg.m7_40 = 0;
1913 cfg.m7_95 = 0;
1914 cfg.m10_2 = 1;
1915 cfg.m12_2 = 1;
1916 test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(&cfg);
1917
1918 cfg.m4_75 = 1;
1919 cfg.m5_15 = 1;
1920 cfg.m5_90 = 0;
1921 cfg.m6_70 = 0;
1922 cfg.m7_40 = 1;
1923 cfg.m7_95 = 1;
1924 cfg.m10_2 = 0;
1925 cfg.m12_2 = 0;
1926 test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(&cfg);
1927
1928 cfg.m4_75 = 0;
1929 cfg.m5_15 = 1;
1930 cfg.m5_90 = 0;
1931 cfg.m6_70 = 1;
1932 cfg.m7_40 = 0;
1933 cfg.m7_95 = 1;
1934 cfg.m10_2 = 0;
1935 cfg.m12_2 = 1;
1936 test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(&cfg);
1937
1938 cfg.m4_75 = 1;
1939 cfg.m5_15 = 0;
1940 cfg.m5_90 = 1;
1941 cfg.m6_70 = 0;
1942 cfg.m7_40 = 1;
1943 cfg.m7_95 = 0;
1944 cfg.m10_2 = 1;
1945 cfg.m12_2 = 0;
1946 test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(&cfg);
1947
1948 cfg.m4_75 = 1;
1949 cfg.m5_15 = 1;
1950 cfg.m5_90 = 1;
1951 cfg.m6_70 = 1;
1952 cfg.m7_40 = 1;
1953 cfg.m7_95 = 1;
1954 cfg.m10_2 = 1;
1955 cfg.m12_2 = 1;
1956 test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(&cfg);
Philipp Maier94d79fd2019-03-01 10:40:48 +01001957
1958 cfg.m4_75 = 1;
1959 cfg.m5_15 = 0;
1960 cfg.m5_90 = 1;
1961 cfg.m6_70 = 0;
1962 cfg.m7_40 = 1;
1963 cfg.m7_95 = 0;
1964 cfg.m10_2 = 0;
1965 cfg.m12_2 = 1;
1966 test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(&cfg);
1967
1968 cfg.m4_75 = 1;
1969 cfg.m5_15 = 0;
1970 cfg.m5_90 = 1;
1971 cfg.m6_70 = 0;
1972 cfg.m7_40 = 1;
1973 cfg.m7_95 = 0;
1974 cfg.m10_2 = 0;
1975 cfg.m12_2 = 0;
1976 test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(&cfg);
1977
Philipp Maier5f2eb152018-09-19 13:40:21 +02001978}
1979
Philipp Maier8515d032018-09-25 15:57:49 +02001980static void test_gsm48_mr_cfg_from_gsm0808_sc_cfg_single(uint16_t s15_s0)
1981{
1982 struct gsm48_multi_rate_conf cfg;
Philipp Maier3713af82019-02-27 16:48:25 +01001983 int rc;
Philipp Maier8515d032018-09-25 15:57:49 +02001984
1985 printf("Input:\n");
1986 printf(" S15-S0 = %04x = 0b" OSMO_BIN_SPEC OSMO_BIN_SPEC "\n", s15_s0,
1987 OSMO_BIN_PRINT(s15_s0 >> 8), OSMO_BIN_PRINT(s15_s0));
1988
Philipp Maier3713af82019-02-27 16:48:25 +01001989 rc = gsm48_mr_cfg_from_gsm0808_sc_cfg(&cfg, s15_s0);
Philipp Maier8515d032018-09-25 15:57:49 +02001990
1991 printf("Output:\n");
1992 printf(" m4_75= %u smod= %u\n", cfg.m4_75, cfg.smod);
1993 printf(" m5_15= %u spare= %u\n", cfg.m5_15, cfg.spare);
1994 printf(" m5_90= %u icmi= %u\n", cfg.m5_90, cfg.icmi);
1995 printf(" m6_70= %u nscb= %u\n", cfg.m6_70, cfg.nscb);
1996 printf(" m7_40= %u ver= %u\n", cfg.m7_40, cfg.ver);
1997 printf(" m7_95= %u\n", cfg.m7_95);
1998 printf(" m10_2= %u\n", cfg.m10_2);
1999 printf(" m12_2= %u\n", cfg.m12_2);
2000
Philipp Maier3713af82019-02-27 16:48:25 +01002001 if (rc != 0)
2002 printf(" Result invalid!\n");
2003
Philipp Maier8515d032018-09-25 15:57:49 +02002004 printf("\n");
2005}
2006
2007void test_gsm48_mr_cfg_from_gsm0808_sc_cfg()
2008{
2009 printf("Testing gsm48_mr_cfg_from_gsm0808_sc_cfg():\n");
2010
Philipp Maier3713af82019-02-27 16:48:25 +01002011 /* Test with settings as defined in 3GPP TS 28.062, Table 7.11.3.1.3-2,
2012 * (up to four codecs may become selected) */
Philipp Maier8515d032018-09-25 15:57:49 +02002013 test_gsm48_mr_cfg_from_gsm0808_sc_cfg_single
2014 (GSM0808_SC_CFG_DEFAULT_AMR_4_75);
2015 test_gsm48_mr_cfg_from_gsm0808_sc_cfg_single
2016 (GSM0808_SC_CFG_DEFAULT_AMR_5_15);
2017 test_gsm48_mr_cfg_from_gsm0808_sc_cfg_single
2018 (GSM0808_SC_CFG_DEFAULT_AMR_5_90);
2019 test_gsm48_mr_cfg_from_gsm0808_sc_cfg_single
2020 (GSM0808_SC_CFG_DEFAULT_AMR_6_70);
2021 test_gsm48_mr_cfg_from_gsm0808_sc_cfg_single
2022 (GSM0808_SC_CFG_DEFAULT_AMR_7_40);
2023 test_gsm48_mr_cfg_from_gsm0808_sc_cfg_single
2024 (GSM0808_SC_CFG_DEFAULT_AMR_7_95);
2025 test_gsm48_mr_cfg_from_gsm0808_sc_cfg_single
2026 (GSM0808_SC_CFG_DEFAULT_AMR_10_2);
2027 test_gsm48_mr_cfg_from_gsm0808_sc_cfg_single
2028 (GSM0808_SC_CFG_DEFAULT_AMR_12_2);
2029
Philipp Maier3713af82019-02-27 16:48:25 +01002030 /* Test with settings as defined in 3GPP TS 28.062, Table 7.11.3.1.3-2,
2031 * but pick only one distinctive setting at a time */
2032 test_gsm48_mr_cfg_from_gsm0808_sc_cfg_single(GSM0808_SC_CFG_AMR_4_75);
Philipp Maier8515d032018-09-25 15:57:49 +02002033 test_gsm48_mr_cfg_from_gsm0808_sc_cfg_single
Philipp Maier3713af82019-02-27 16:48:25 +01002034 (GSM0808_SC_CFG_AMR_4_75_5_90_7_40_12_20);
2035 test_gsm48_mr_cfg_from_gsm0808_sc_cfg_single(GSM0808_SC_CFG_AMR_5_90);
2036 test_gsm48_mr_cfg_from_gsm0808_sc_cfg_single(GSM0808_SC_CFG_AMR_6_70);
2037 test_gsm48_mr_cfg_from_gsm0808_sc_cfg_single(GSM0808_SC_CFG_AMR_7_40);
2038 test_gsm48_mr_cfg_from_gsm0808_sc_cfg_single(GSM0808_SC_CFG_AMR_7_95);
2039 test_gsm48_mr_cfg_from_gsm0808_sc_cfg_single(GSM0808_SC_CFG_AMR_10_2);
2040 test_gsm48_mr_cfg_from_gsm0808_sc_cfg_single(GSM0808_SC_CFG_AMR_12_2);
2041
2042 /* Arbitrary, but valid combinations */
2043 test_gsm48_mr_cfg_from_gsm0808_sc_cfg_single(GSM0808_SC_CFG_AMR_7_40 |
2044 GSM0808_SC_CFG_AMR_6_70 |
2045 GSM0808_SC_CFG_AMR_10_2);
2046 test_gsm48_mr_cfg_from_gsm0808_sc_cfg_single(GSM0808_SC_CFG_AMR_7_95 |
2047 GSM0808_SC_CFG_AMR_4_75);
2048 test_gsm48_mr_cfg_from_gsm0808_sc_cfg_single(GSM0808_SC_CFG_AMR_5_90 |
2049 GSM0808_SC_CFG_AMR_12_2);
Philipp Maier8515d032018-09-25 15:57:49 +02002050 test_gsm48_mr_cfg_from_gsm0808_sc_cfg_single
Philipp Maier3713af82019-02-27 16:48:25 +01002051 (GSM0808_SC_CFG_AMR_4_75_5_90_7_40_12_20 | GSM0808_SC_CFG_AMR_5_90 |
2052 GSM0808_SC_CFG_AMR_12_2);
2053
2054 /* Invalid combinations */
Philipp Maier8515d032018-09-25 15:57:49 +02002055 test_gsm48_mr_cfg_from_gsm0808_sc_cfg_single
Philipp Maier3713af82019-02-27 16:48:25 +01002056 (GSM0808_SC_CFG_AMR_4_75_5_90_7_40_12_20 | GSM0808_SC_CFG_AMR_6_70);
2057 test_gsm48_mr_cfg_from_gsm0808_sc_cfg_single(GSM0808_SC_CFG_AMR_7_40 |
2058 GSM0808_SC_CFG_AMR_6_70 |
2059 GSM0808_SC_CFG_AMR_10_2 |
2060 GSM0808_SC_CFG_AMR_7_95 |
2061 GSM0808_SC_CFG_AMR_4_75);
2062 test_gsm48_mr_cfg_from_gsm0808_sc_cfg_single(0x0000);
2063 test_gsm48_mr_cfg_from_gsm0808_sc_cfg_single(0xffff);
Philipp Maier8515d032018-09-25 15:57:49 +02002064}
2065
Neels Hofmeyrd01ef752018-09-21 15:57:26 +02002066struct test_cell_id_matching_data {
2067 struct gsm0808_cell_id id;
2068 struct gsm0808_cell_id match_id;
2069 bool expect_match;
2070 bool expect_exact_match;
2071};
2072
2073#define lac_23 { .id_discr = CELL_IDENT_LAC, .id.lac = 23, }
2074#define lac_42 { .id_discr = CELL_IDENT_LAC, .id.lac = 42, }
2075#define ci_5 { .id_discr = CELL_IDENT_CI, .id.ci = 5, }
2076#define ci_6 { .id_discr = CELL_IDENT_CI, .id.ci = 6, }
2077#define lac_ci_23_5 { \
2078 .id_discr = CELL_IDENT_LAC_AND_CI, \
2079 .id.lac_and_ci = { .lac = 23, .ci = 5, }, \
2080 }
2081#define lac_ci_42_6 { \
2082 .id_discr = CELL_IDENT_LAC_AND_CI, \
2083 .id.lac_and_ci = { .lac = 42, .ci = 6, }, \
2084 }
2085#define lai_23_042_23 { \
2086 .id_discr = CELL_IDENT_LAI_AND_LAC, \
2087 .id.lai_and_lac = { .plmn = { .mcc = 23, .mnc = 42, .mnc_3_digits = true }, .lac = 23, }, \
2088 }
2089#define lai_23_042_42 { \
2090 .id_discr = CELL_IDENT_LAI_AND_LAC, \
2091 .id.lai_and_lac = { .plmn = { .mcc = 23, .mnc = 42, .mnc_3_digits = true }, .lac = 42, }, \
2092 }
2093#define lai_23_99_23 { \
2094 .id_discr = CELL_IDENT_LAI_AND_LAC, \
2095 .id.lai_and_lac = { .plmn = { .mcc = 23, .mnc = 99, .mnc_3_digits = false }, .lac = 23, }, \
2096 }
2097#define lai_23_42_23 { \
2098 .id_discr = CELL_IDENT_LAI_AND_LAC, \
2099 .id.lai_and_lac = { .plmn = { .mcc = 23, .mnc = 42, .mnc_3_digits = false }, .lac = 23, }, \
2100 }
2101#define cgi_23_042_23_5 { \
2102 .id_discr = CELL_IDENT_WHOLE_GLOBAL, \
2103 .id.global = { \
2104 .lai = { .plmn = { .mcc = 23, .mnc = 42, .mnc_3_digits = true }, .lac = 23, }, \
2105 .cell_identity = 5, \
2106 }, \
2107 }
2108#define cgi_23_042_42_6 { \
2109 .id_discr = CELL_IDENT_WHOLE_GLOBAL, \
2110 .id.global = { \
2111 .lai = { .plmn = { .mcc = 23, .mnc = 42, .mnc_3_digits = true }, .lac = 42, }, \
2112 .cell_identity = 6, \
2113 }, \
2114 }
2115#define cgi_23_99_23_5 { \
2116 .id_discr = CELL_IDENT_WHOLE_GLOBAL, \
2117 .id.global = { \
2118 .lai = { .plmn = { .mcc = 23, .mnc = 99, .mnc_3_digits = false }, .lac = 23, }, \
2119 .cell_identity = 5, \
2120 }, \
2121 }
2122
2123
2124static const struct test_cell_id_matching_data test_cell_id_matching_tests[] = {
2125 { .id = lac_23, .match_id = lac_23, .expect_match = true, .expect_exact_match = true },
2126 { .id = lac_23, .match_id = lac_42, .expect_match = false, .expect_exact_match = false },
2127 { .id = lac_23, .match_id = ci_5, .expect_match = true, .expect_exact_match = false },
2128 { .id = lac_23, .match_id = ci_6, .expect_match = true, .expect_exact_match = false },
2129 { .id = lac_23, .match_id = lac_ci_23_5, .expect_match = true, .expect_exact_match = false },
2130 { .id = lac_23, .match_id = lac_ci_42_6, .expect_match = false, .expect_exact_match = false },
2131 { .id = lac_23, .match_id = lai_23_042_23, .expect_match = true, .expect_exact_match = false },
2132 { .id = lac_23, .match_id = lai_23_042_42, .expect_match = false, .expect_exact_match = false },
2133 { .id = lac_23, .match_id = lai_23_99_23, .expect_match = true, .expect_exact_match = false },
2134 { .id = lac_23, .match_id = lai_23_42_23, .expect_match = true, .expect_exact_match = false },
2135 { .id = lac_23, .match_id = cgi_23_042_23_5, .expect_match = true, .expect_exact_match = false },
2136 { .id = lac_23, .match_id = cgi_23_042_42_6, .expect_match = false, .expect_exact_match = false },
2137 { .id = lac_23, .match_id = cgi_23_99_23_5, .expect_match = true, .expect_exact_match = false },
2138 { .id = ci_5, .match_id = lac_23, .expect_match = true, .expect_exact_match = false },
2139 { .id = ci_5, .match_id = lac_42, .expect_match = true, .expect_exact_match = false },
2140 { .id = ci_5, .match_id = ci_5, .expect_match = true, .expect_exact_match = true },
2141 { .id = ci_5, .match_id = ci_6, .expect_match = false, .expect_exact_match = false },
2142 { .id = ci_5, .match_id = lac_ci_23_5, .expect_match = true, .expect_exact_match = false },
2143 { .id = ci_5, .match_id = lac_ci_42_6, .expect_match = false, .expect_exact_match = false },
2144 { .id = ci_5, .match_id = lai_23_042_23, .expect_match = true, .expect_exact_match = false },
2145 { .id = ci_5, .match_id = lai_23_042_42, .expect_match = true, .expect_exact_match = false },
2146 { .id = ci_5, .match_id = lai_23_99_23, .expect_match = true, .expect_exact_match = false },
2147 { .id = ci_5, .match_id = lai_23_42_23, .expect_match = true, .expect_exact_match = false },
2148 { .id = ci_5, .match_id = cgi_23_042_23_5, .expect_match = true, .expect_exact_match = false },
2149 { .id = ci_5, .match_id = cgi_23_042_42_6, .expect_match = false, .expect_exact_match = false },
2150 { .id = ci_5, .match_id = cgi_23_99_23_5, .expect_match = true, .expect_exact_match = false },
2151 { .id = lac_ci_23_5, .match_id = lac_23, .expect_match = true, .expect_exact_match = false },
2152 { .id = lac_ci_23_5, .match_id = lac_42, .expect_match = false, .expect_exact_match = false },
2153 { .id = lac_ci_23_5, .match_id = ci_5, .expect_match = true, .expect_exact_match = false },
2154 { .id = lac_ci_23_5, .match_id = ci_6, .expect_match = false, .expect_exact_match = false },
2155 { .id = lac_ci_23_5, .match_id = lac_ci_23_5, .expect_match = true, .expect_exact_match = true },
2156 { .id = lac_ci_23_5, .match_id = lac_ci_42_6, .expect_match = false, .expect_exact_match = false },
2157 { .id = lac_ci_23_5, .match_id = lai_23_042_23, .expect_match = true, .expect_exact_match = false },
2158 { .id = lac_ci_23_5, .match_id = lai_23_042_42, .expect_match = false, .expect_exact_match = false },
2159 { .id = lac_ci_23_5, .match_id = lai_23_99_23, .expect_match = true, .expect_exact_match = false },
2160 { .id = lac_ci_23_5, .match_id = lai_23_42_23, .expect_match = true, .expect_exact_match = false },
2161 { .id = lac_ci_23_5, .match_id = cgi_23_042_23_5, .expect_match = true, .expect_exact_match = false },
2162 { .id = lac_ci_23_5, .match_id = cgi_23_042_42_6, .expect_match = false, .expect_exact_match = false },
2163 { .id = lac_ci_23_5, .match_id = cgi_23_99_23_5, .expect_match = true, .expect_exact_match = false },
2164 { .id = lai_23_042_23, .match_id = lac_23, .expect_match = true, .expect_exact_match = false },
2165 { .id = lai_23_042_23, .match_id = lac_42, .expect_match = false, .expect_exact_match = false },
2166 { .id = lai_23_042_23, .match_id = ci_5, .expect_match = true, .expect_exact_match = false },
2167 { .id = lai_23_042_23, .match_id = ci_6, .expect_match = true, .expect_exact_match = false },
2168 { .id = lai_23_042_23, .match_id = lac_ci_23_5, .expect_match = true, .expect_exact_match = false },
2169 { .id = lai_23_042_23, .match_id = lac_ci_42_6, .expect_match = false, .expect_exact_match = false },
2170 { .id = lai_23_042_23, .match_id = lai_23_042_23, .expect_match = true, .expect_exact_match = true },
2171 { .id = lai_23_042_23, .match_id = lai_23_042_42, .expect_match = false, .expect_exact_match = false },
2172 { .id = lai_23_042_23, .match_id = lai_23_99_23, .expect_match = false, .expect_exact_match = false },
2173 { .id = lai_23_042_23, .match_id = lai_23_42_23, .expect_match = false, .expect_exact_match = false },
2174 { .id = lai_23_042_23, .match_id = cgi_23_042_23_5, .expect_match = true, .expect_exact_match = false },
2175 { .id = lai_23_042_23, .match_id = cgi_23_042_42_6, .expect_match = false, .expect_exact_match = false },
2176 { .id = lai_23_042_23, .match_id = cgi_23_99_23_5, .expect_match = false, .expect_exact_match = false },
2177 { .id = cgi_23_042_23_5, .match_id = lac_23, .expect_match = true, .expect_exact_match = false },
2178 { .id = cgi_23_042_23_5, .match_id = lac_42, .expect_match = false, .expect_exact_match = false },
2179 { .id = cgi_23_042_23_5, .match_id = ci_5, .expect_match = true, .expect_exact_match = false },
2180 { .id = cgi_23_042_23_5, .match_id = ci_6, .expect_match = false, .expect_exact_match = false },
2181 { .id = cgi_23_042_23_5, .match_id = lac_ci_23_5, .expect_match = true, .expect_exact_match = false },
2182 { .id = cgi_23_042_23_5, .match_id = lac_ci_42_6, .expect_match = false, .expect_exact_match = false },
2183 { .id = cgi_23_042_23_5, .match_id = lai_23_042_23, .expect_match = true, .expect_exact_match = false },
2184 { .id = cgi_23_042_23_5, .match_id = lai_23_042_42, .expect_match = false, .expect_exact_match = false },
2185 { .id = cgi_23_042_23_5, .match_id = lai_23_99_23, .expect_match = false, .expect_exact_match = false },
2186 { .id = cgi_23_042_23_5, .match_id = lai_23_42_23, .expect_match = false, .expect_exact_match = false },
2187 { .id = cgi_23_042_23_5, .match_id = cgi_23_042_23_5, .expect_match = true, .expect_exact_match = true },
2188 { .id = cgi_23_042_23_5, .match_id = cgi_23_042_42_6, .expect_match = false, .expect_exact_match = false },
2189 { .id = cgi_23_042_23_5, .match_id = cgi_23_99_23_5, .expect_match = false, .expect_exact_match = false },
2190};
2191
2192static void test_cell_id_matching()
2193{
2194 int i;
2195 bool ok = true;
2196 printf("\n%s\n", __func__);
2197
2198 for (i = 0; i < ARRAY_SIZE(test_cell_id_matching_tests); i++) {
2199 const struct test_cell_id_matching_data *d = &test_cell_id_matching_tests[i];
2200 int exact_match;
2201
2202 for (exact_match = 0; exact_match < 2; exact_match++) {
2203 bool result;
2204 bool expect_result = exact_match ? d->expect_exact_match : d->expect_match;
2205
2206 result = gsm0808_cell_ids_match(&d->id, &d->match_id, (bool)exact_match);
2207
2208 printf("[%d] %s %s %s%s\n",
2209 i,
2210 gsm0808_cell_id_name(&d->id),
2211 gsm0808_cell_id_name2(&d->match_id),
2212 result ? "MATCH" : "don't match",
2213 exact_match ? " exactly" : "");
2214 if (result != expect_result) {
2215 printf(" ERROR: expected %s\n", d->expect_match ? "MATCH" : "no match");
2216 ok = false;
2217 }
2218 }
2219 }
2220
2221 OSMO_ASSERT(ok);
2222}
2223
2224static bool test_cell_id_list_matching_discrs(bool test_match,
2225 enum CELL_IDENT id_discr,
2226 enum CELL_IDENT list_discr)
2227{
2228 int i, j;
2229 const struct gsm0808_cell_id *id = NULL;
2230 struct gsm0808_cell_id_list2 list = {};
2231 int match_idx = -1;
2232 int result;
2233
2234 for (i = 0; i < ARRAY_SIZE(test_cell_id_matching_tests); i++) {
2235 const struct test_cell_id_matching_data *d = &test_cell_id_matching_tests[i];
2236 if (id_discr != d->id.id_discr)
2237 continue;
2238 id = &d->id;
2239 break;
2240 }
2241
2242 if (!id) {
2243 printf("Did not find any entry for %s\n", gsm0808_cell_id_discr_name(id_discr));
2244 return true;
2245 }
2246
2247 /* Collect those entries with exactly this id on the left, of type list_discr on the right.
2248 * Collect the mismatches first, for more interesting match indexes in the results. */
2249 for (j = 0; j < 2; j++) {
2250 bool collect_matches = (bool)j;
2251
2252 /* If we want to have a mismatching list, don't add any entries that match. */
2253 if (!test_match && collect_matches)
2254 continue;
2255
2256 for (i = 0; i < ARRAY_SIZE(test_cell_id_matching_tests); i++) {
2257 const struct test_cell_id_matching_data *d = &test_cell_id_matching_tests[i];
2258 struct gsm0808_cell_id_list2 add;
2259
2260 /* Ignore those with a different d->id */
2261 if (!gsm0808_cell_ids_match(&d->id, id, true))
2262 continue;
2263
2264 /* Ignore those with a different d->match_id discr */
2265 if (d->match_id.id_discr != list_discr)
2266 continue;
2267
2268 if (collect_matches != d->expect_match)
2269 continue;
2270
2271 if (match_idx < 0 && d->expect_match) {
2272 match_idx = list.id_list_len;
2273 }
2274
2275 gsm0808_cell_id_to_list(&add, &d->match_id);
2276 gsm0808_cell_id_list_add(&list, &add);
2277 }
2278 }
2279
2280 if (!list.id_list_len) {
2281 printf("%s vs. %s: No match_id entries to test %s\n",
2282 gsm0808_cell_id_name(id),
2283 gsm0808_cell_id_discr_name(list_discr),
2284 test_match ? "MATCH" : "mismatch");
2285 return true;
2286 }
2287
2288 result = gsm0808_cell_id_matches_list(id, &list, 0, false);
2289
2290 printf("%s and %s: ",
2291 gsm0808_cell_id_name(id),
2292 gsm0808_cell_id_list_name(&list));
2293 if (result >= 0)
2294 printf("MATCH at [%d]\n", result);
2295 else
2296 printf("mismatch\n");
2297
2298 if (test_match
2299 && (result < 0 || result != match_idx)) {
2300 printf(" ERROR: expected MATCH at %d\n", match_idx);
2301 return false;
2302 }
2303
2304 if (!test_match && result >= 0) {
2305 printf(" ERROR: expected mismatch\n");
2306 return false;
2307 }
2308
2309 return true;
2310}
2311
Neels Hofmeyr3a504532019-02-10 22:28:27 +01002312const enum CELL_IDENT cell_ident_discrs[] = {
2313 CELL_IDENT_LAC, CELL_IDENT_CI, CELL_IDENT_LAC_AND_CI, CELL_IDENT_LAI_AND_LAC,
2314 CELL_IDENT_WHOLE_GLOBAL,
2315};
2316
2317
Neels Hofmeyrd01ef752018-09-21 15:57:26 +02002318static void test_cell_id_list_matching(bool test_match)
2319{
2320 int i, j;
2321 bool ok = true;
2322
Neels Hofmeyrd01ef752018-09-21 15:57:26 +02002323 printf("\n%s(%s)\n", __func__, test_match ? "test match" : "test mismatch");
2324
2325 /* Autogenerate Cell ID lists from above dataset, which should match / not match. */
Neels Hofmeyr3a504532019-02-10 22:28:27 +01002326 for (i = 0; i < ARRAY_SIZE(cell_ident_discrs); i++) {
2327 for (j = 0; j < ARRAY_SIZE(cell_ident_discrs); j++)
Neels Hofmeyrd01ef752018-09-21 15:57:26 +02002328 if (!test_cell_id_list_matching_discrs(test_match,
Neels Hofmeyr3a504532019-02-10 22:28:27 +01002329 cell_ident_discrs[i], cell_ident_discrs[j]))
Neels Hofmeyrd01ef752018-09-21 15:57:26 +02002330 ok = false;
2331 }
2332
2333 OSMO_ASSERT(ok);
2334}
2335
Neels Hofmeyr3a504532019-02-10 22:28:27 +01002336
2337static const struct gsm0808_cell_id test_gsm0808_cell_id_to_from_cgi_data[] = {
2338 lac_23,
2339 lac_42,
2340 ci_5,
2341 ci_6,
2342 lac_ci_23_5,
2343 lac_ci_42_6,
2344 lai_23_042_23,
2345 lai_23_042_42,
2346 lai_23_99_23,
2347 lai_23_42_23,
2348 cgi_23_042_23_5,
2349 cgi_23_042_42_6,
2350 cgi_23_99_23_5,
2351 { .id_discr = CELL_IDENT_NO_CELL },
2352 { .id_discr = 423 },
2353};
2354
2355static void test_gsm0808_cell_id_to_from_cgi()
2356{
2357 int i;
2358 int j;
2359
2360 printf("\n%s()\n", __func__);
2361
2362 for (i = 0; i < ARRAY_SIZE(test_gsm0808_cell_id_to_from_cgi_data); i++) {
2363 const struct gsm0808_cell_id *from_cid = &test_gsm0808_cell_id_to_from_cgi_data[i];
2364 struct osmo_cell_global_id cgi = {
2365 .lai = {
2366 .plmn = {
2367 .mcc = 777,
2368 .mnc = 7,
2369 .mnc_3_digits = true,
2370 },
2371 .lac = 7777,
2372 },
2373 .cell_identity = 7777,
2374 };
2375 struct gsm0808_cell_id cid = {};
2376 int rc;
2377
2378 rc = gsm0808_cell_id_to_cgi(&cgi, from_cid);
2379 printf("cid %s -> cgi %s", gsm0808_cell_id_name(from_cid), osmo_cgi_name(&cgi));
2380
2381 if (rc & OSMO_CGI_PART_PLMN)
2382 printf(" PLMN");
2383 if (rc & OSMO_CGI_PART_LAC)
2384 printf(" LAC");
2385 if (rc & OSMO_CGI_PART_CI)
2386 printf(" CI");
2387
2388 gsm0808_cell_id_from_cgi(&cid, from_cid->id_discr, &cgi);
2389 printf(" -> cid %s\n", gsm0808_cell_id_name(&cid));
2390 if (!gsm0808_cell_ids_match(from_cid, &cid, true))
2391 printf(" MISMATCH!\n");
2392
2393 for (j = 0; j < ARRAY_SIZE(cell_ident_discrs); j++) {
2394 enum CELL_IDENT discr = cell_ident_discrs[j];
2395
2396 gsm0808_cell_id_from_cgi(&cid, discr, &cgi);
2397 printf(" --> gsm0808_cell_id{%s} = %s\n", gsm0808_cell_id_discr_name(discr), gsm0808_cell_id_name(&cid));
2398 }
2399 }
2400}
2401
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +01002402int main(int argc, char **argv)
2403{
Max969fb2e2018-12-10 11:01:10 +01002404 void *ctx = talloc_named_const(NULL, 0, "gsm0808 test");
2405 msgb_talloc_ctx_init(ctx, 0);
2406 osmo_init_logging2(ctx, NULL);
2407
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +01002408 printf("Testing generation of GSM0808 messages\n");
Philipp Maier4f4905f2018-11-30 13:36:12 +01002409 test_gsm0808_enc_cause();
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +01002410 test_create_layer3();
Philipp Maierfa896ab2017-03-27 16:55:32 +02002411 test_create_layer3_aoip();
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +01002412 test_create_reset();
Philipp Maier15596e22017-04-05 17:55:27 +02002413 test_create_reset_ack();
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +01002414 test_create_clear_command();
Harald Weltecf665fc2019-02-18 13:45:36 +01002415 test_create_clear_command2();
2416 test_create_clear_command2_csfb();
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +01002417 test_create_clear_complete();
Philipp Maierb478dd32017-03-29 15:50:05 +02002418 test_create_cipher();
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +01002419 test_create_cipher_complete();
2420 test_create_cipher_reject();
Maxed651d22018-11-07 15:25:05 +01002421 test_create_cipher_reject_ext();
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +01002422 test_create_cm_u();
2423 test_create_sapi_reject();
Philipp Maierc6144a22017-03-29 17:53:43 +02002424 test_create_ass();
Max52074322018-11-30 10:44:07 +01002425 test_create_ass2();
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +01002426 test_create_ass_compl();
Philipp Maierfa896ab2017-03-27 16:55:32 +02002427 test_create_ass_compl_aoip();
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +01002428 test_create_ass_fail();
Philipp Maierfa896ab2017-03-27 16:55:32 +02002429 test_create_ass_fail_aoip();
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +01002430 test_create_clear_rqst();
Philipp Maier3d48ec02017-03-29 17:37:55 +02002431 test_create_paging();
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +01002432 test_create_dtap();
2433 test_prepend_dtap();
Max969fb2e2018-12-10 11:01:10 +01002434
Max47022152018-12-19 18:51:00 +01002435 test_enc_dec_lcls();
Max969fb2e2018-12-10 11:01:10 +01002436
Philipp Maier22401432017-03-24 17:59:26 +01002437 test_enc_dec_aoip_trasp_addr_v4();
2438 test_enc_dec_aoip_trasp_addr_v6();
Philipp Maier6f725d62017-03-24 18:03:17 +01002439 test_gsm0808_enc_dec_speech_codec();
Philipp Maier6f725d62017-03-24 18:03:17 +01002440 test_gsm0808_enc_dec_speech_codec_ext_with_cfg();
Philipp Maierbb839662017-06-01 17:11:19 +02002441 test_gsm0808_enc_dec_speech_codec_with_cfg();
Philipp Maier6f725d62017-03-24 18:03:17 +01002442 test_gsm0808_enc_dec_speech_codec_list();
Philipp Maierf6c369f2018-10-16 15:24:47 +02002443 test_gsm0808_enc_dec_empty_speech_codec_list();
Philipp Maiere0c65302017-03-28 17:05:40 +02002444 test_gsm0808_enc_dec_channel_type();
Philipp Maier14e76b92017-03-28 18:36:52 +02002445 test_gsm0808_enc_dec_encrypt_info();
Neels Hofmeyr250e7f72018-04-13 03:30:14 +02002446
Philipp Maier783047e2017-03-29 11:35:50 +02002447 test_gsm0808_enc_dec_cell_id_list_lac();
2448 test_gsm0808_enc_dec_cell_id_list_single_lac();
Stefan Sperlinge1a86742018-03-15 18:05:02 +01002449 test_gsm0808_enc_dec_cell_id_list_multi_lac();
Philipp Maier783047e2017-03-29 11:35:50 +02002450 test_gsm0808_enc_dec_cell_id_list_bss();
Stefan Sperling23381452018-03-15 19:38:15 +01002451 test_gsm0808_enc_dec_cell_id_list_multi_lai_and_lac();
Stefan Sperling9c62fc62018-03-16 10:23:34 +01002452 test_gsm0808_enc_dec_cell_id_list_multi_ci();
Stefan Sperlinged4327c2018-03-16 11:02:59 +01002453 test_gsm0808_enc_dec_cell_id_list_multi_lac_and_ci();
Stefan Sperling483f3862018-03-16 12:21:26 +01002454 test_gsm0808_enc_dec_cell_id_list_multi_global();
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +01002455
Neels Hofmeyr74663d92018-03-23 01:46:42 +01002456 test_cell_id_list_add();
2457
Neels Hofmeyr250e7f72018-04-13 03:30:14 +02002458 test_gsm0808_enc_dec_cell_id_lac();
2459 test_gsm0808_enc_dec_cell_id_bss();
2460 test_gsm0808_enc_dec_cell_id_no_cell();
2461 test_gsm0808_enc_dec_cell_id_lai_and_lac();
2462 test_gsm0808_enc_dec_cell_id_ci();
2463 test_gsm0808_enc_dec_cell_id_lac_and_ci();
2464 test_gsm0808_enc_dec_cell_id_global();
Philipp Maier5f2eb152018-09-19 13:40:21 +02002465 test_gsm0808_sc_cfg_from_gsm48_mr_cfg();
Philipp Maier8515d032018-09-25 15:57:49 +02002466 test_gsm48_mr_cfg_from_gsm0808_sc_cfg();
Philipp Maier5f2eb152018-09-19 13:40:21 +02002467
Neels Hofmeyrd01ef752018-09-21 15:57:26 +02002468 test_cell_id_matching();
2469 test_cell_id_list_matching(true);
2470 test_cell_id_list_matching(false);
2471
Neels Hofmeyr3a504532019-02-10 22:28:27 +01002472 test_gsm0808_cell_id_to_from_cgi();
2473
Alexander Chemeris22630e62020-05-13 00:44:04 +03002474 test_dec_confusion();
2475
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +01002476 printf("Done\n");
2477 return EXIT_SUCCESS;
2478}