blob: b823a151370c1598e10144b286527f1f860c1319 [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 *
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +010015 */
16
17#include <osmocom/gsm/gsm0808.h>
Philipp Maier22401432017-03-24 17:59:26 +010018#include <osmocom/gsm/gsm0808_utils.h>
19#include <osmocom/gsm/protocol/gsm_08_08.h>
Philipp Maier3d48ec02017-03-29 17:37:55 +020020#include <osmocom/gsm/protocol/gsm_08_58.h>
Max969fb2e2018-12-10 11:01:10 +010021#include <osmocom/core/logging.h>
22#include <osmocom/core/application.h>
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +010023
24#include <stdio.h>
25#include <stdlib.h>
Philipp Maier22401432017-03-24 17:59:26 +010026#include <sys/socket.h>
27#include <netinet/in.h>
28#include <arpa/inet.h>
Neels Hofmeyr74663d92018-03-23 01:46:42 +010029#include <errno.h>
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +010030
Philipp Maier4f4905f2018-11-30 13:36:12 +010031#define EXPECT_ENCODED(hexstr) do { \
32 const char *enc_str = msgb_hexdump(msg); \
33 printf("%s: encoded: %s(rc = %u)\n", __func__, enc_str, rc_enc); \
34 OSMO_ASSERT(strcmp(enc_str, hexstr " ") == 0); \
35 OSMO_ASSERT(rc_enc == msg->len); \
36 } while(0)
37
Vadim Yanitskiycf6ee642018-12-20 05:23:00 +070038#define VERIFY(msg, data, data_len) do { \
39 if (!msgb_eq_l3_data_print(msg, data, data_len)) \
40 abort(); \
41 } while(0)
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +010042
Philipp Maierfa896ab2017-03-27 16:55:32 +020043/* Setup a fake codec list for testing */
44static void setup_codec_list(struct gsm0808_speech_codec_list *scl)
45{
46 memset(scl, 0, sizeof(*scl));
47
48 scl->codec[0].pi = true;
49 scl->codec[0].tf = true;
Philipp Maierbb839662017-06-01 17:11:19 +020050 scl->codec[0].type = GSM0808_SCT_FR3;
Philipp Maierfa896ab2017-03-27 16:55:32 +020051 scl->codec[0].cfg = 0xcdef;
52
53 scl->codec[1].fi = true;
54 scl->codec[1].pt = true;
Philipp Maierbb839662017-06-01 17:11:19 +020055 scl->codec[1].type = GSM0808_SCT_FR2;
Philipp Maierfa896ab2017-03-27 16:55:32 +020056
57 scl->codec[2].fi = true;
58 scl->codec[2].tf = true;
Philipp Maierbb839662017-06-01 17:11:19 +020059 scl->codec[2].type = GSM0808_SCT_CSD;
60 scl->codec[2].cfg = 0xc0;
Philipp Maierfa896ab2017-03-27 16:55:32 +020061
62 scl->len = 3;
63}
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +010064
Philipp Maier4f4905f2018-11-30 13:36:12 +010065void test_gsm0808_enc_cause(void)
66{
67 /* NOTE: This must be tested early because many of the following tests
68 * rely on the generation of a proper cause code. */
69
70 uint8_t rc_enc;
71 struct msgb *msg;
72
73 /* Test with a single byte cause code */
74 msg = msgb_alloc(1024, "output buffer");
75 rc_enc = gsm0808_enc_cause(msg, 0x41);
76 EXPECT_ENCODED("04 01 41");
77 msgb_free(msg);
78
79 /* Test with an extended (two byte) cause code */
80 msg = msgb_alloc(1024, "output buffer");
81 rc_enc = gsm0808_enc_cause(msg, 0x8041);
82 EXPECT_ENCODED("04 02 80 41");
83 msgb_free(msg);
84}
85
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +010086static void test_create_layer3(void)
87{
88 static const uint8_t res[] = {
89 0x00, 0x0e, 0x57, 0x05, 0x08, 0x00, 0x77, 0x62,
90 0x83, 0x33, 0x66, 0x44, 0x88, 0x17, 0x01, 0x23 };
91 struct msgb *msg, *in_msg;
Neels Hofmeyr178bf7a2018-04-20 12:23:45 +020092 struct osmo_cell_global_id cgi = {
93 .lai = {
94 .plmn = {
95 .mcc = 0x2244,
96 .mnc = 0x1122,
97 },
98 .lac = 0x3366,
99 },
100 .cell_identity = 0x4488,
101 };
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +0100102 printf("Testing creating Layer3\n");
103
104 in_msg = msgb_alloc_headroom(512, 128, "foo");
105 in_msg->l3h = in_msg->data;
106 msgb_v_put(in_msg, 0x23);
107
Neels Hofmeyr178bf7a2018-04-20 12:23:45 +0200108 msg = gsm0808_create_layer3_2(in_msg, &cgi, NULL);
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +0100109 VERIFY(msg, res, ARRAY_SIZE(res));
110 msgb_free(msg);
111 msgb_free(in_msg);
112}
113
Philipp Maierfa896ab2017-03-27 16:55:32 +0200114static void test_create_layer3_aoip()
115{
116 static const uint8_t res[] = {
117 0x00, 0x17, 0x57, 0x05, 0x08, 0x00, 0x77, 0x62,
118 0x83, 0x33, 0x66, 0x44, 0x88, 0x17, 0x01, 0x23,
Philipp Maierbb839662017-06-01 17:11:19 +0200119 GSM0808_IE_SPEECH_CODEC_LIST, 0x07, GSM0808_SCT_FR3 | 0x50,
Philipp Maier7e27b142018-03-22 17:26:46 +0100120 0xef, 0xcd, GSM0808_SCT_FR2 | 0xa0, 0x9f,
Philipp Maierbb839662017-06-01 17:11:19 +0200121 GSM0808_SCT_CSD | 0x90, 0xc0
Philipp Maierfa896ab2017-03-27 16:55:32 +0200122 };
Maxfa3b4822018-11-05 14:59:54 +0100123 struct osmo_cell_global_id cgi = {
124 .lai = {
125 .plmn = {
126 .mcc = 0x2244,
127 .mnc = 0x1122,
128 },
129 .lac = 0x3366,
130 },
131 .cell_identity = 0x4488,
132 };
Philipp Maierfa896ab2017-03-27 16:55:32 +0200133 struct msgb *msg, *in_msg;
134 struct gsm0808_speech_codec_list sc_list;
135 printf("Testing creating Layer3 (AoIP)\n");
136
137 setup_codec_list(&sc_list);
138
139 in_msg = msgb_alloc_headroom(512, 128, "foo");
140 in_msg->l3h = in_msg->data;
141 msgb_v_put(in_msg, 0x23);
142
Maxfa3b4822018-11-05 14:59:54 +0100143 msg = gsm0808_create_layer3_2(in_msg, &cgi, &sc_list);
144
Philipp Maierfa896ab2017-03-27 16:55:32 +0200145 VERIFY(msg, res, ARRAY_SIZE(res));
146
147 msgb_free(msg);
148 msgb_free(in_msg);
149}
150
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +0100151static void test_create_reset()
152{
153 static const uint8_t res[] = { 0x00, 0x04, 0x30, 0x04, 0x01, 0x20 };
154 struct msgb *msg;
155
156 printf("Testing creating Reset\n");
157 msg = gsm0808_create_reset();
158 VERIFY(msg, res, ARRAY_SIZE(res));
159 msgb_free(msg);
160}
161
Philipp Maier15596e22017-04-05 17:55:27 +0200162static void test_create_reset_ack()
163{
164 static const uint8_t res[] = { 0x00, 0x01, 0x31 };
165 struct msgb *msg;
166
167 printf("Testing creating Reset Ack\n");
168 msg = gsm0808_create_reset_ack();
169 VERIFY(msg, res, ARRAY_SIZE(res));
170 msgb_free(msg);
171}
172
173
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +0100174static void test_create_clear_command()
175{
176 static const uint8_t res[] = { 0x20, 0x04, 0x01, 0x23 };
177 struct msgb *msg;
178
179 printf("Testing creating Clear Command\n");
180 msg = gsm0808_create_clear_command(0x23);
181 VERIFY(msg, res, ARRAY_SIZE(res));
182 msgb_free(msg);
183}
184
Harald Weltecf665fc2019-02-18 13:45:36 +0100185static void test_create_clear_command2()
186{
187 static const uint8_t res[] = { 0x00, 0x04, 0x20, 0x04, 0x01, 0x23 };
188 struct msgb *msg;
189
190 printf("Testing creating Clear Command 2\n");
191 msg = gsm0808_create_clear_command2(0x23, false);
192 VERIFY(msg, res, ARRAY_SIZE(res));
193 msgb_free(msg);
194}
195
196static void test_create_clear_command2_csfb()
197{
198 static const uint8_t res[] = { 0x00, 0x05, 0x20, 0x04, 0x01, 0x23, 0x8F };
199 struct msgb *msg;
200
201 printf("Testing creating Clear Command 2 (CSFB)\n");
202 msg = gsm0808_create_clear_command2(0x23, true);
203 VERIFY(msg, res, ARRAY_SIZE(res));
204 msgb_free(msg);
205}
206
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +0100207static void test_create_clear_complete()
208{
209 static const uint8_t res[] = { 0x00, 0x01, 0x21 };
210 struct msgb *msg;
211
212 printf("Testing creating Clear Complete\n");
213 msg = gsm0808_create_clear_complete();
214 VERIFY(msg, res, ARRAY_SIZE(res));
215 msgb_free(msg);
216}
217
Philipp Maierb478dd32017-03-29 15:50:05 +0200218static void test_create_cipher()
219{
220 static const uint8_t res[] =
221 { 0x00, 0x0c, 0x53, 0x0a, 0x09, 0x03, 0xaa,
222 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x23, 0x42 };
223 static const uint8_t res2[] =
224 { 0x00, 0x0e, 0x53, 0x0a, 0x09, 0x03, 0xaa,
225 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x23, 0x42,
226 GSM0808_IE_CIPHER_RESPONSE_MODE, 0x01 };
227 struct msgb *msg;
228 struct gsm0808_encrypt_info ei;
229 uint8_t include_imeisv;
230
231 memset(&ei, 0, sizeof(ei));
232 ei.perm_algo[0] = GSM0808_ALG_ID_A5_0;
233 ei.perm_algo[1] = GSM0808_ALG_ID_A5_1;
234 ei.perm_algo_len = 2;
235 ei.key[0] = 0xaa;
236 ei.key[1] = 0xbb;
237 ei.key[2] = 0xcc;
238 ei.key[3] = 0xdd;
239 ei.key[4] = 0xee;
240 ei.key[5] = 0xff;
241 ei.key[6] = 0x23;
242 ei.key[7] = 0x42;
243 ei.key_len = 8;
244 include_imeisv = 1;
245
246 printf("Testing creating Chipher Mode Command\n");
247 msg = gsm0808_create_cipher(&ei, NULL);
248 OSMO_ASSERT(msg);
249 VERIFY(msg, res, ARRAY_SIZE(res));
250 msgb_free(msg);
251
252 msg = gsm0808_create_cipher(&ei, &include_imeisv);
253 OSMO_ASSERT(msg);
254 VERIFY(msg, res2, ARRAY_SIZE(res2));
255 msgb_free(msg);
256}
257
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +0100258static void test_create_cipher_complete()
259{
260 static const uint8_t res1[] = {
261 0x00, 0x08, 0x55, 0x20, 0x03, 0x23, 0x42, 0x21, 0x2c, 0x04 };
262 static const uint8_t res2[] = { 0x00, 0x03, 0x55, 0x2c, 0x04};
263 struct msgb *l3, *msg;
264
265 printf("Testing creating Cipher Complete\n");
266 l3 = msgb_alloc_headroom(512, 128, "l3h");
267 l3->l3h = l3->data;
268 msgb_v_put(l3, 0x23);
269 msgb_v_put(l3, 0x42);
270 msgb_v_put(l3, 0x21);
271
272 /* with l3 data */
273 msg = gsm0808_create_cipher_complete(l3, 4);
274 VERIFY(msg, res1, ARRAY_SIZE(res1));
275 msgb_free(msg);
276
277 /* with l3 data but short */
278 l3->len -= 1;
279 l3->tail -= 1;
280 msg = gsm0808_create_cipher_complete(l3, 4);
281 VERIFY(msg, res2, ARRAY_SIZE(res2));
282 msgb_free(msg);
283
284 /* without l3 data */
285 msg = gsm0808_create_cipher_complete(NULL, 4);
286 VERIFY(msg, res2, ARRAY_SIZE(res2));
287 msgb_free(msg);
288
289
290 msgb_free(l3);
291}
292
Maxed651d22018-11-07 15:25:05 +0100293static inline void parse_cipher_reject(struct msgb *msg, uint8_t exp)
294{
295 struct tlv_parsed tp;
296 int rc;
297
298 /* skip header and message type so we can parse Cause IE directly */
299 msg->l2h = msgb_data(msg) + sizeof(struct bssmap_header) + 1;
300
301 rc = osmo_bssap_tlv_parse(&tp, msg->l2h, msgb_l2len(msg));
302 if (rc < 0)
303 printf("FIXME: failed (%d) to parse created message %s\n", rc, msgb_hexdump(msg));
304
Alexander Chemerisfdfe25b2020-05-12 23:21:56 +0300305 rc = gsm0808_get_cause(&tp);
Maxed651d22018-11-07 15:25:05 +0100306 if (rc < 0)
307 printf("FIXME: failed (%s) to extract Cause from created message %s\n",
308 strerror(-rc), msgb_hexdump(msg));
309
310 if (exp != (enum gsm0808_cause)rc)
311 printf("FIXME: wrong Cause %d != %u (" OSMO_BIN_SPEC ") extracted from created message %s\n",
312 rc, exp, OSMO_BIT_PRINT(exp), msgb_hexdump(msg));
313}
314
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +0100315static void test_create_cipher_reject()
316{
Harald Welte62e40852017-12-17 20:50:34 +0100317 static const uint8_t res[] = { 0x00, 0x04, 0x59, 0x04, 0x01, 0x23 };
Maxed651d22018-11-07 15:25:05 +0100318 enum gsm0808_cause cause = GSM0808_CAUSE_CCCH_OVERLOAD;
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +0100319 struct msgb *msg;
320
321 printf("Testing creating Cipher Reject\n");
Maxed651d22018-11-07 15:25:05 +0100322 msg = gsm0808_create_cipher_reject(cause);
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +0100323 VERIFY(msg, res, ARRAY_SIZE(res));
Maxed651d22018-11-07 15:25:05 +0100324
325 parse_cipher_reject(msg, cause);
326
327 msgb_free(msg);
328}
329
330static void test_create_cipher_reject_ext()
331{
332 static const uint8_t res[] = { 0x00, 0x05, 0x59, 0x04, 0x02, 0xd0, 0xFA };
333 uint8_t cause = 0xFA;
334 struct msgb *msg;
335
336 printf("Testing creating Cipher Reject (extended)\n");
337 msg = gsm0808_create_cipher_reject_ext(GSM0808_CAUSE_CLASS_INVAL, cause);
338 VERIFY(msg, res, ARRAY_SIZE(res));
339
340 parse_cipher_reject(msg, cause);
341
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +0100342 msgb_free(msg);
343}
344
345static void test_create_cm_u()
346{
Harald Welte07b625d2012-01-23 10:02:58 +0100347 static const uint8_t res[] = {
348 0x00, 0x07, 0x54, 0x12, 0x01, 0x23, 0x13, 0x01, 0x42 };
349 static const uint8_t res2o[] = {
350 0x00, 0x04, 0x54, 0x12, 0x01, 0x23 };
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +0100351 struct msgb *msg;
Harald Welte07b625d2012-01-23 10:02:58 +0100352 const uint8_t cm2 = 0x23;
353 const uint8_t cm3 = 0x42;
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +0100354
355 printf("Testing creating CM U\n");
Harald Welte07b625d2012-01-23 10:02:58 +0100356 msg = gsm0808_create_classmark_update(&cm2, 1, &cm3, 1);
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +0100357 VERIFY(msg, res, ARRAY_SIZE(res));
Harald Welte07b625d2012-01-23 10:02:58 +0100358
Neels Hofmeyr9a938ae2017-11-16 17:34:07 +0100359 msgb_free(msg);
360
Harald Welte07b625d2012-01-23 10:02:58 +0100361 msg = gsm0808_create_classmark_update(&cm2, 1, NULL, 0);
362 VERIFY(msg, res2o, ARRAY_SIZE(res2o));
363
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +0100364 msgb_free(msg);
365}
366
367static void test_create_sapi_reject()
368{
Alexander Chemerisa5b1b862020-05-12 01:03:08 +0300369 static const uint8_t res[] = { 0x00, 0x06, 0x25, 0x18, 0x03, 0x04, 0x01, 0x25 };
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +0100370 struct msgb *msg;
371
372 printf("Testing creating SAPI Reject\n");
Vadim Yanitskiyfa6cd882020-08-26 18:03:59 +0700373 msg = gsm0808_create_sapi_reject_cause(3, GSM0808_CAUSE_BSS_NOT_EQUIPPED);
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +0100374 VERIFY(msg, res, ARRAY_SIZE(res));
375 msgb_free(msg);
376}
377
Alexander Chemeris22630e62020-05-13 00:44:04 +0300378static void test_dec_confusion()
379{
380 static const uint8_t hex[] =
381 { 0x26, 0x04, 0x01, 0x52, 0x1f, 0x07, 0x00, 0xff, 0x00, 0x03, 0x25, 0x03, 0x25 };
382 struct tlv_parsed tp;
383 int diag_len;
384 enum gsm0808_cause cause;
385 enum gsm0808_cause_class cause_class;
386 struct gsm0808_diagnostics *diag;
387
388 printf("Testing decoding CONFUSION\n");
389
390 tlv_parse(&tp, gsm0808_att_tlvdef(), hex+1, sizeof(hex)-1, 0, 0);
391
392 /* Check for the Cause and Diagnostic mandatory elements */
393 if (!TLVP_PRESENT(&tp, GSM0808_IE_CAUSE) || !TLVP_PRESENT(&tp, GSM0808_IE_DIAGNOSTIC)) {
394 printf("Either Cause or Diagnostic mandatory IE are not detected\n");
395 return;
396 }
397
398 diag_len = TLVP_LEN(&tp, GSM0808_IE_DIAGNOSTIC);
399 if (diag_len < 5) {
400 printf("Diagnostic length is too short: %d (expected > 5)\n",
401 diag_len);
402 return;
403 }
404
405 cause = gsm0808_get_cause(&tp);
406 if ((int)cause < 0) {
407 printf("ERROR: failed (%s) to extract Cause, aborting\n", strerror(-(int)cause));
408 return;
409 }
410 cause_class = gsm0808_cause_class(cause);
411 printf(" Cause class %d/0x%x (%s)\n",
412 cause_class, cause_class, gsm0808_cause_class_name(cause_class));
413 printf(" Cause %d/0x%x (%s)\n",
414 cause, cause, gsm0808_cause_name(cause));
415
416 diag = (struct gsm0808_diagnostics *)TLVP_VAL(&tp, GSM0808_IE_DIAGNOSTIC);
417 printf(" Diagnostics error octet location %d (%s)\n",
418 diag->error_pointer_octet,
419 gsm0808_diagnostics_octet_location_str(diag->error_pointer_octet));
420 printf(" Diagnostics error bit location %d (%s)\n",
421 diag->error_pointer_bit,
422 gsm0808_diagnostics_bit_location_str(diag->error_pointer_bit));
423 printf(" Diagnostics message that provoked the error: %s\n",
424 osmo_hexdump(diag->msg, diag_len-2));
425}
426
Philipp Maierc6144a22017-03-29 17:53:43 +0200427static void test_create_ass()
428{
429 static const uint8_t res1[] =
430 { 0x00, 0x0a, 0x01, 0x0b, 0x04, 0x01, 0x0b, 0xa1, 0x25, 0x01, 0x00,
431 0x04 };
432 static const uint8_t res2[] =
433 { 0x00, 0x20, 0x01, 0x0b, 0x04, 0x01, 0x0b, 0xa1, 0x25, 0x01, 0x00,
434 0x04, GSM0808_IE_AOIP_TRASP_ADDR, 0x06, 0xc0, 0xa8, 0x64, 0x17,
Philipp Maierbb839662017-06-01 17:11:19 +0200435 0x04, 0xd2, GSM0808_IE_SPEECH_CODEC_LIST, 0x07,
Philipp Maier7e27b142018-03-22 17:26:46 +0100436 GSM0808_SCT_FR3 | 0x50, 0xef, 0xcd, GSM0808_SCT_FR2 | 0xa0, 0x9f,
Philipp Maier2908dbf2020-06-05 14:16:11 +0200437 GSM0808_SCT_CSD | 0x90, 0xc0, GSM0808_IE_CALL_ID, 0xdd, 0xcc,
438 0xbb, 0xaa };
Philipp Maierc6144a22017-03-29 17:53:43 +0200439
440 struct msgb *msg;
441 struct gsm0808_channel_type ct;
442 uint16_t cic = 0004;
443 struct sockaddr_storage ss;
444 struct sockaddr_in sin;
445 struct gsm0808_speech_codec_list sc_list;
446 uint32_t call_id = 0xAABBCCDD;
447
448 memset(&ct, 0, sizeof(ct));
449 ct.ch_indctr = GSM0808_CHAN_SPEECH;
450 ct.ch_rate_type = GSM0808_SPEECH_HALF_PREF;
451 ct.perm_spch[0] = GSM0808_PERM_FR3;
452 ct.perm_spch[1] = GSM0808_PERM_HR3;
453 ct.perm_spch_len = 2;
454
455 memset(&sin, 0, sizeof(sin));
456 sin.sin_family = AF_INET;
457 sin.sin_port = htons(1234);
458 inet_aton("192.168.100.23", &sin.sin_addr);
459
460 memset(&ss, 0, sizeof(ss));
461 memcpy(&ss, &sin, sizeof(sin));
462
463 setup_codec_list(&sc_list);
464
465 printf("Testing creating Assignment Request\n");
466 msg = gsm0808_create_ass(&ct, &cic, NULL, NULL, NULL);
467 OSMO_ASSERT(msg);
468 VERIFY(msg, res1, ARRAY_SIZE(res1));
469 msgb_free(msg);
470
471 msg = gsm0808_create_ass(&ct, &cic, &ss, &sc_list, &call_id);
472 OSMO_ASSERT(msg);
473 VERIFY(msg, res2, ARRAY_SIZE(res2));
474 msgb_free(msg);
475}
476
Max52074322018-11-30 10:44:07 +0100477static void test_create_ass2()
478{
479 static const uint8_t res[] = {
480 BSSAP_MSG_BSS_MANAGEMENT,
481 0x45,
482 BSS_MAP_MSG_ASSIGMENT_RQST,
483 GSM0808_IE_CHANNEL_TYPE,
484 0x04, 0x01, 0x0b, 0x91, 0x15, 0x01, 0x00, 0x04,
485 GSM0808_IE_AOIP_TRASP_ADDR,
486 0x06,
487 0xac, 0x0c, 0x65, 0x0d, /* IPv4 */
488 0x02, 0x9a,
489 GSM0808_IE_SPEECH_CODEC_LIST,
490 0x07,
491 GSM0808_SCT_FR3 | 0x50,
492 0xef, 0xcd,
493 GSM0808_SCT_FR2 | 0xa0,
494 0x9f,
495 GSM0808_SCT_CSD | 0x90,
496 0xc0,
497 GSM0808_IE_CALL_ID,
Pau Espin Pedrol1bd495a2021-02-15 16:15:59 +0100498 0xce, 0xfa, 0xad, 0xde, /* CallID */
Max52074322018-11-30 10:44:07 +0100499 0x83, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, /* Kc */
500 GSM0808_IE_GLOBAL_CALL_REF, 0x0d, /* GCR, length */
501 0x03, 0x44, 0x44, 0x44, /* GCR, Net ID */
502 0x02, 0xfe, 0xed, /* GCR, Node ID */
503 0x05, 0x41, 0x41, 0x41, 0x41, 0x41, /* GCR, Call ref. ID */
504 GSM0808_IE_LCLS_CONFIG, GSM0808_LCLS_CFG_BOTH_WAY,
505 GSM0808_IE_LCLS_CONN_STATUS_CTRL, GSM0808_LCLS_CSC_CONNECT,
506 GSM0808_IE_LCLS_CORR_NOT_NEEDED,
507 };
508 struct msgb *msg;
509 struct gsm0808_channel_type ct;
510 uint16_t cic = 4;
511 struct sockaddr_storage ss;
512 struct sockaddr_in sin;
513 struct gsm0808_speech_codec_list sc_list;
514 uint32_t call_id = 0xDEADFACE;
Max52074322018-11-30 10:44:07 +0100515 uint8_t Kc[16];
516 struct osmo_lcls lcls = {
517 .config = GSM0808_LCLS_CFG_BOTH_WAY,
518 .control = GSM0808_LCLS_CSC_CONNECT,
Max3b901252019-01-15 14:15:11 +0100519 .gcr = { .net_len = 3, .node = 0xFEED },
520 .gcr_available = true,
Max52074322018-11-30 10:44:07 +0100521 .corr_needed = false
522 };
523
Max3b901252019-01-15 14:15:11 +0100524 memset(lcls.gcr.cr, 'A', 5);
525 memset(lcls.gcr.net, 'D', lcls.gcr.net_len);
Max52074322018-11-30 10:44:07 +0100526 memset(Kc, 'E', 16);
527
528 memset(&ct, 0, sizeof(ct));
529 ct.ch_indctr = GSM0808_CHAN_SPEECH;
530 ct.ch_rate_type = GSM0808_SPEECH_HALF_PREF;
531 ct.perm_spch[0] = GSM0808_PERM_FR2;
532 ct.perm_spch[1] = GSM0808_PERM_HR2;
533 ct.perm_spch_len = 2;
534
535 memset(&sin, 0, sizeof(sin));
536 sin.sin_family = AF_INET;
537 sin.sin_port = htons(666);
538 inet_aton("172.12.101.13", &sin.sin_addr); /* IPv4 */
539
540 memset(&ss, 0, sizeof(ss));
541 memcpy(&ss, &sin, sizeof(sin));
542
543 setup_codec_list(&sc_list);
544
545 printf("Testing creating Assignment Request with Kc and LCLS\n");
546
547 msg = gsm0808_create_ass2(&ct, &cic, &ss, &sc_list, &call_id, Kc, &lcls);
548 if (!msgb_eq_l3_data_print(msg, res, ARRAY_SIZE(res)))
549 abort();
550
551 msgb_free(msg);
552}
553
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +0100554static void test_create_ass_compl()
555{
556 static const uint8_t res1[] = {
557 0x00, 0x09, 0x02, 0x15, 0x23, 0x21, 0x42, 0x2c,
558 0x11, 0x40, 0x22 };
559 static const uint8_t res2[] = {
560 0x00, 0x07, 0x02, 0x15, 0x23, 0x21, 0x42, 0x2c, 0x11};
561 struct msgb *msg;
562
563 printf("Testing creating Assignment Complete\n");
564 msg = gsm0808_create_assignment_completed(0x23, 0x42, 0x11, 0x22);
565 VERIFY(msg, res1, ARRAY_SIZE(res1));
566 msgb_free(msg);
567
568 msg = gsm0808_create_assignment_completed(0x23, 0x42, 0x11, 0);
569 VERIFY(msg, res2, ARRAY_SIZE(res2));
570 msgb_free(msg);
571}
572
Philipp Maierfa896ab2017-03-27 16:55:32 +0200573static void test_create_ass_compl_aoip()
574{
575 struct sockaddr_storage ss;
576 struct sockaddr_in sin;
577 struct gsm0808_speech_codec sc;
578 struct gsm0808_speech_codec_list sc_list;
579 static const uint8_t res[] =
Max414c8f52019-01-08 14:44:24 +0100580 { 0x00, 0x1f, 0x02, 0x15, 0x23, 0x21, 0x42, 0x2c, 0x11, 0x40, 0x22,
Philipp Maierfa896ab2017-03-27 16:55:32 +0200581 GSM0808_IE_AOIP_TRASP_ADDR, 0x06, 0xc0, 0xa8, 0x64, 0x17, 0x04,
Philipp Maierbb839662017-06-01 17:11:19 +0200582 0xd2, GSM0808_IE_SPEECH_CODEC, 0x01, GSM0808_SCT_HR1 | 0x90,
Philipp Maier7e27b142018-03-22 17:26:46 +0100583 GSM0808_IE_SPEECH_CODEC_LIST, 0x07, GSM0808_SCT_FR3 | 0x50, 0xef,
Max414c8f52019-01-08 14:44:24 +0100584 0xcd, GSM0808_SCT_FR2 | 0xa0, 0x9f, GSM0808_SCT_CSD | 0x90, 0xc0,
585 GSM0808_IE_LCLS_BSS_STATUS, GSM0808_LCLS_STS_LOCALLY_SWITCHED };
Philipp Maierfa896ab2017-03-27 16:55:32 +0200586 struct msgb *msg;
587
588 memset(&sin, 0, sizeof(sin));
589 sin.sin_family = AF_INET;
590 sin.sin_port = htons(1234);
591 inet_aton("192.168.100.23", &sin.sin_addr);
592
593 memset(&ss, 0, sizeof(ss));
594 memcpy(&ss, &sin, sizeof(sin));
595
596 memset(&sc, 0, sizeof(sc));
597 sc.fi = true;
598 sc.tf = true;
Philipp Maierbb839662017-06-01 17:11:19 +0200599 sc.type = GSM0808_SCT_HR1;
Philipp Maierfa896ab2017-03-27 16:55:32 +0200600
601 setup_codec_list(&sc_list);
602
603 printf("Testing creating Assignment Complete (AoIP)\n");
Max414c8f52019-01-08 14:44:24 +0100604 msg = gsm0808_create_ass_compl2(0x23, 0x42, 0x11, 0x22,
605 &ss, &sc, &sc_list, GSM0808_LCLS_STS_LOCALLY_SWITCHED);
Philipp Maierfa896ab2017-03-27 16:55:32 +0200606 VERIFY(msg, res, ARRAY_SIZE(res));
607 msgb_free(msg);
608}
609
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +0100610static void test_create_ass_fail()
611{
612 static const uint8_t res1[] = { 0x00, 0x04, 0x03, 0x04, 0x01, 0x23 };
613 static const uint8_t res2[] = {
614 0x00, 0x06, 0x03, 0x04, 0x01, 0x23, 0x15, 0x02};
615 uint8_t rr_res = 2;
616 struct msgb *msg;
617
618 printf("Testing creating Assignment Failure\n");
619 msg = gsm0808_create_assignment_failure(0x23, NULL);
620 VERIFY(msg, res1, ARRAY_SIZE(res1));
621 msgb_free(msg);
622
623 msg = gsm0808_create_assignment_failure(0x23, &rr_res);
624 VERIFY(msg, res2, ARRAY_SIZE(res2));
625 msgb_free(msg);
626}
627
Philipp Maierfa896ab2017-03-27 16:55:32 +0200628static void test_create_ass_fail_aoip()
629{
630 static const uint8_t res1[] =
631 { 0x00, 0x0d, 0x03, 0x04, 0x01, 0x23, GSM0808_IE_SPEECH_CODEC_LIST,
Philipp Maier7e27b142018-03-22 17:26:46 +0100632 0x07, GSM0808_SCT_FR3 | 0x50, 0xef, 0xcd, GSM0808_SCT_FR2 | 0xa0,
Philipp Maierbb839662017-06-01 17:11:19 +0200633 0x9f, GSM0808_SCT_CSD | 0x90, 0xc0 };
Philipp Maierfa896ab2017-03-27 16:55:32 +0200634 static const uint8_t res2[] =
635 { 0x00, 0x0f, 0x03, 0x04, 0x01, 0x23, 0x15, 0x02,
Philipp Maier7e27b142018-03-22 17:26:46 +0100636 GSM0808_IE_SPEECH_CODEC_LIST, 0x07, GSM0808_SCT_FR3 | 0x50, 0xef,
637 0xcd, GSM0808_SCT_FR2 | 0xa0, 0x9f, GSM0808_SCT_CSD | 0x90, 0xc0 };
Philipp Maierfa896ab2017-03-27 16:55:32 +0200638 uint8_t rr_res = 2;
639 struct msgb *msg;
640 struct gsm0808_speech_codec_list sc_list;
641
642 setup_codec_list(&sc_list);
643
644 printf("Testing creating Assignment Failure (AoIP)\n");
645 msg = gsm0808_create_ass_fail(0x23, NULL, &sc_list);
646 VERIFY(msg, res1, ARRAY_SIZE(res1));
647 msgb_free(msg);
648
649 msg = gsm0808_create_ass_fail(0x23, &rr_res, &sc_list);
650 VERIFY(msg, res2, ARRAY_SIZE(res2));
651 msgb_free(msg);
652}
653
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +0100654static void test_create_clear_rqst()
655{
656 static const uint8_t res[] = { 0x00, 0x04, 0x22, 0x04, 0x01, 0x23 };
657 struct msgb *msg;
658
659 printf("Testing creating Clear Request\n");
660 msg = gsm0808_create_clear_rqst(0x23);
661 VERIFY(msg, res, ARRAY_SIZE(res));
662 msgb_free(msg);
663}
664
Philipp Maier3d48ec02017-03-29 17:37:55 +0200665static void test_create_paging()
666{
667 static const uint8_t res[] =
668 { 0x00, 0x10, 0x52, 0x08, 0x08, 0x09, 0x10, 0x10, 0x00, 0x00, 0x00,
669 0x21, 0x43, 0x1a, 0x03, 0x05, 0x23, 0x42 };
670 static const uint8_t res2[] =
671 { 0x00, 0x16, 0x52, 0x08, 0x08, 0x09, 0x10, 0x10, 0x00, 0x00, 0x00,
672 0x21, 0x43, GSM0808_IE_TMSI, 0x04, 0x12, 0x34, 0x56, 0x78, 0x1a,
673 0x03, 0x05, 0x23, 0x42 };
674 static const uint8_t res3[] =
675 { 0x00, 0x18, 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, GSM0808_IE_CHANNEL_NEEDED,
678 RSL_CHANNEED_TCH_ForH };
679
680 struct msgb *msg;
Stefan Sperling11a4d9d2018-02-15 18:28:04 +0100681 struct gsm0808_cell_id_list2 cil;
Philipp Maier3d48ec02017-03-29 17:37:55 +0200682 uint32_t tmsi = 0x12345678;
683 uint8_t chan_needed = RSL_CHANNEED_TCH_ForH;
684
685 char imsi[] = "001010000001234";
686
687 cil.id_discr = CELL_IDENT_LAC;
Stefan Sperling11a4d9d2018-02-15 18:28:04 +0100688 cil.id_list[0].lac = 0x2342;
Philipp Maier3d48ec02017-03-29 17:37:55 +0200689 cil.id_list_len = 1;
690
691 printf("Testing creating Paging Request\n");
Stefan Sperling11a4d9d2018-02-15 18:28:04 +0100692 msg = gsm0808_create_paging2(imsi, NULL, &cil, NULL);
Philipp Maier3d48ec02017-03-29 17:37:55 +0200693 VERIFY(msg, res, ARRAY_SIZE(res));
694 msgb_free(msg);
695
Stefan Sperling11a4d9d2018-02-15 18:28:04 +0100696 msg = gsm0808_create_paging2(imsi, &tmsi, &cil, NULL);
Philipp Maier3d48ec02017-03-29 17:37:55 +0200697 VERIFY(msg, res2, ARRAY_SIZE(res2));
698 msgb_free(msg);
699
Stefan Sperling11a4d9d2018-02-15 18:28:04 +0100700 msg = gsm0808_create_paging2(imsi, &tmsi, &cil, &chan_needed);
Philipp Maier3d48ec02017-03-29 17:37:55 +0200701 VERIFY(msg, res3, ARRAY_SIZE(res3));
702 msgb_free(msg);
703}
704
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +0100705static void test_create_dtap()
706{
707 static const uint8_t res[] = { 0x01, 0x03, 0x02, 0x23, 0x42 };
708 struct msgb *msg, *l3;
709
710 printf("Testing creating DTAP\n");
711 l3 = msgb_alloc_headroom(512, 128, "test");
712 l3->l3h = l3->data;
713 msgb_v_put(l3, 0x23);
714 msgb_v_put(l3, 0x42);
715
716 msg = gsm0808_create_dtap(l3, 0x3);
717 VERIFY(msg, res, ARRAY_SIZE(res));
718 msgb_free(msg);
719 msgb_free(l3);
720}
721
722static void test_prepend_dtap()
723{
724 static const uint8_t res[] = { 0x01, 0x03, 0x02, 0x23, 0x42 };
725 struct msgb *in_msg;
726
727 printf("Testing prepend DTAP\n");
728
729 in_msg = msgb_alloc_headroom(512, 128, "test");
730 msgb_v_put(in_msg, 0x23);
731 msgb_v_put(in_msg, 0x42);
732
733 gsm0808_prepend_dtap_header(in_msg, 0x3);
734 in_msg->l3h = in_msg->data;
735 VERIFY(in_msg, res, ARRAY_SIZE(res));
736 msgb_free(in_msg);
737}
738
Max47022152018-12-19 18:51:00 +0100739static void test_enc_dec_lcls()
Max969fb2e2018-12-10 11:01:10 +0100740{
741 static const uint8_t res[] = {
742 GSM0808_IE_GLOBAL_CALL_REF,
743 0x0d, /* GCR length */
744 0x03, /* .net_len */
745 0xf1, 0xf2, 0xf3, /* .net */
746 0x02, /* .node length */
747 0xde, 0xad, /* .node */
748 0x05, /* length of Call. Ref. */
749 0x41, 0x42, 0x43, 0x44, 0x45 /* .cr - Call. Ref. */
750 };
751 uint8_t len;
752 struct msgb *msg;
Max969fb2e2018-12-10 11:01:10 +0100753 int rc;
754 struct tlv_parsed tp;
Max3b901252019-01-15 14:15:11 +0100755 struct osmo_lcls *lcls_out, lcls_in = {
756 .gcr = {
757 .net_len = 3,
758 .net = { 0xf1, 0xf2, 0xf3 },
759 .node = 0xDEAD,
760 .cr = { 0x41, 0x42, 0x43, 0x44, 0x45 },
761 },
762 .gcr_available = true,
Max47022152018-12-19 18:51:00 +0100763 .config = GSM0808_LCLS_CFG_NA,
764 .control = GSM0808_LCLS_CSC_NA,
765 .corr_needed = true,
766 };
767
768 msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM, "LCLS IE");
Max969fb2e2018-12-10 11:01:10 +0100769 if (!msg)
770 return;
771
Max3b901252019-01-15 14:15:11 +0100772 lcls_out = talloc_zero(msg, struct osmo_lcls);
773 if (!lcls_out)
774 return;
775
Max47022152018-12-19 18:51:00 +0100776 len = gsm0808_enc_lcls(msg, &lcls_in);
Max969fb2e2018-12-10 11:01:10 +0100777 printf("Testing Global Call Reference IE encoder...\n\t%d bytes added: %s\n",
778 len, len == ARRAY_SIZE(res) ? "OK" : "FAIL");
779
780 if (!msgb_eq_data_print(msg, res, ARRAY_SIZE(res)))
781 abort();
782
783 rc = osmo_bssap_tlv_parse(&tp, msgb_data(msg), msgb_length(msg));
784 if (rc < 0) {
785 printf("parsing failed: %s [%s]\n", strerror(-rc), msgb_hexdump(msg));
786 abort();
787 }
788
Max3b901252019-01-15 14:15:11 +0100789 rc = gsm0808_dec_lcls(lcls_out, &tp);
Max969fb2e2018-12-10 11:01:10 +0100790 if (rc < 0) {
791 printf("decoding failed: %s [%s]\n", strerror(-rc), msgb_hexdump(msg));
792 abort();
793 }
794
Max3b901252019-01-15 14:15:11 +0100795 if (lcls_out->config != lcls_in.config) {
Max4fd64e52019-01-14 19:27:44 +0100796 printf("LCLS Config parsed wrong: %s != %s\n",
Max3b901252019-01-15 14:15:11 +0100797 gsm0808_lcls_config_name(lcls_out->config), gsm0808_lcls_config_name(lcls_in.config));
Max4fd64e52019-01-14 19:27:44 +0100798 abort();
799 }
800
Max3b901252019-01-15 14:15:11 +0100801 if (lcls_out->control != lcls_in.control) {
Max4fd64e52019-01-14 19:27:44 +0100802 printf("LCLS Control parsed wrong: %s != %s\n",
Max3b901252019-01-15 14:15:11 +0100803 gsm0808_lcls_control_name(lcls_out->control), gsm0808_lcls_control_name(lcls_in.control));
Max4fd64e52019-01-14 19:27:44 +0100804 abort();
805 }
806
Max3b901252019-01-15 14:15:11 +0100807 if (!osmo_gcr_eq(&lcls_out->gcr, &lcls_in.gcr)) {
Max5ec0cf52019-01-15 16:37:09 +0100808 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 +0100809 abort();
810 }
Max969fb2e2018-12-10 11:01:10 +0100811
Max5ec0cf52019-01-15 16:37:09 +0100812 printf("\tdecoded %d bytes: %s:\n%s\n", rc, rc == len ? "OK" : "FAIL", osmo_lcls_dump(lcls_out));
813 printf("\t%s\n", osmo_gcr_dump(lcls_out));
Max969fb2e2018-12-10 11:01:10 +0100814 msgb_free(msg);
815}
816
Philipp Maier22401432017-03-24 17:59:26 +0100817static void test_enc_dec_aoip_trasp_addr_v4()
818{
819 struct sockaddr_storage enc_addr;
820 struct sockaddr_storage dec_addr;
821 struct sockaddr_in enc_addr_in;
822 struct msgb *msg;
823 uint8_t rc_enc;
824 int rc_dec;
825
826 memset(&enc_addr_in, 0, sizeof(enc_addr_in));
827 enc_addr_in.sin_family = AF_INET;
828 enc_addr_in.sin_port = htons(1234);
829 inet_aton("255.0.255.255", &enc_addr_in.sin_addr);
830
831 memset(&enc_addr, 0, sizeof(enc_addr));
832 memcpy(&enc_addr, &enc_addr_in, sizeof(enc_addr_in));
833
834 msg = msgb_alloc(1024, "output buffer");
835 rc_enc = gsm0808_enc_aoip_trasp_addr(msg, &enc_addr);
836 OSMO_ASSERT(rc_enc == 8);
837 rc_dec =
838 gsm0808_dec_aoip_trasp_addr(&dec_addr, msg->data + 2, msg->len - 2);
839 OSMO_ASSERT(rc_dec == 6);
840 OSMO_ASSERT(memcmp(&enc_addr, &dec_addr, sizeof(enc_addr)) == 0);
841
842 msgb_free(msg);
843}
844
845static void test_enc_dec_aoip_trasp_addr_v6()
846{
847 struct sockaddr_storage enc_addr;
848 struct sockaddr_storage dec_addr;
849 struct sockaddr_in6 enc_addr_in;
850 struct msgb *msg;
851 uint8_t rc_enc;
852 int rc_dec;
853
854 memset(&enc_addr_in, 0, sizeof(enc_addr_in));
855 enc_addr_in.sin6_family = AF_INET6;
856 enc_addr_in.sin6_port = htons(4567);
857 inet_pton(AF_INET6, "2001:0db8:85a3:08d3:1319:8a2e:0370:7344",
858 &enc_addr_in.sin6_addr);
859
860 memset(&enc_addr, 0, sizeof(enc_addr));
861 memcpy(&enc_addr, &enc_addr_in, sizeof(enc_addr_in));
862
863 msg = msgb_alloc(1024, "output buffer");
864 rc_enc = gsm0808_enc_aoip_trasp_addr(msg, &enc_addr);
865 OSMO_ASSERT(rc_enc == 20);
866 rc_dec =
867 gsm0808_dec_aoip_trasp_addr(&dec_addr, msg->data + 2, msg->len - 2);
868 OSMO_ASSERT(rc_dec == 18);
869 OSMO_ASSERT(memcmp(&enc_addr, &dec_addr, sizeof(enc_addr)) == 0);
870
871 msgb_free(msg);
872}
873
Philipp Maier6f725d62017-03-24 18:03:17 +0100874static void test_gsm0808_enc_dec_speech_codec()
875{
Neels Hofmeyr9a4286b2018-04-20 12:27:52 +0200876 struct gsm0808_speech_codec enc_sc = {
877 .pi = true,
878 .tf = true,
879 .type = GSM0808_SCT_FR2,
880 };
881 struct gsm0808_speech_codec dec_sc = {};
Philipp Maier6f725d62017-03-24 18:03:17 +0100882 struct msgb *msg;
883 uint8_t rc_enc;
884 int rc_dec;
885
Philipp Maier6f725d62017-03-24 18:03:17 +0100886 msg = msgb_alloc(1024, "output buffer");
887 rc_enc = gsm0808_enc_speech_codec(msg, &enc_sc);
888 OSMO_ASSERT(rc_enc == 3);
889
890 rc_dec = gsm0808_dec_speech_codec(&dec_sc, msg->data + 2, msg->len - 2);
891 OSMO_ASSERT(rc_dec == 1);
892
893 OSMO_ASSERT(memcmp(&enc_sc, &dec_sc, sizeof(enc_sc)) == 0);
894
895 msgb_free(msg);
896}
897
898
Philipp Maierbb839662017-06-01 17:11:19 +0200899static void test_gsm0808_enc_dec_speech_codec_with_cfg()
900{
Neels Hofmeyrc62c9342018-04-15 23:31:47 +0200901 struct gsm0808_speech_codec enc_sc = {
902 .pi = true,
903 .tf = true,
904 .type = GSM0808_SCT_FR3,
905 .cfg = 0xabcd,
906 };
907 struct gsm0808_speech_codec dec_sc = {};
Philipp Maierbb839662017-06-01 17:11:19 +0200908 struct msgb *msg;
909 uint8_t rc_enc;
910 int rc_dec;
911
Philipp Maierbb839662017-06-01 17:11:19 +0200912 msg = msgb_alloc(1024, "output buffer");
913 rc_enc = gsm0808_enc_speech_codec(msg, &enc_sc);
914 OSMO_ASSERT(rc_enc == 5);
915
916 rc_dec = gsm0808_dec_speech_codec(&dec_sc, msg->data + 2, msg->len - 2);
917 OSMO_ASSERT(rc_dec == 3);
918
919 OSMO_ASSERT(memcmp(&enc_sc, &dec_sc, sizeof(enc_sc)) == 0);
920
921 msgb_free(msg);
922}
923
Philipp Maier6f725d62017-03-24 18:03:17 +0100924static void test_gsm0808_enc_dec_speech_codec_ext_with_cfg()
925{
Neels Hofmeyr9a4286b2018-04-20 12:27:52 +0200926 struct gsm0808_speech_codec enc_sc = {
927 .pi = true,
928 .tf = true,
929 .type = GSM0808_SCT_CSD,
930 .cfg = 0xc0,
931 };
932 struct gsm0808_speech_codec dec_sc = {};
Philipp Maier6f725d62017-03-24 18:03:17 +0100933 struct msgb *msg;
934 uint8_t rc_enc;
935 int rc_dec;
936
Philipp Maier6f725d62017-03-24 18:03:17 +0100937 msg = msgb_alloc(1024, "output buffer");
938 rc_enc = gsm0808_enc_speech_codec(msg, &enc_sc);
Philipp Maierbb839662017-06-01 17:11:19 +0200939 OSMO_ASSERT(rc_enc == 5);
Philipp Maier6f725d62017-03-24 18:03:17 +0100940
941 rc_dec = gsm0808_dec_speech_codec(&dec_sc, msg->data + 2, msg->len - 2);
Philipp Maierbb839662017-06-01 17:11:19 +0200942 OSMO_ASSERT(rc_dec == 3);
Philipp Maier6f725d62017-03-24 18:03:17 +0100943
944 OSMO_ASSERT(memcmp(&enc_sc, &dec_sc, sizeof(enc_sc)) == 0);
945
946 msgb_free(msg);
947}
948
949static void test_gsm0808_enc_dec_speech_codec_list()
950{
Neels Hofmeyr9a4286b2018-04-20 12:27:52 +0200951 struct gsm0808_speech_codec_list enc_scl = {
952 .codec = {
953 {
954 .pi = true,
955 .tf = true,
956 .type = GSM0808_SCT_FR3,
957 .cfg = 0xcdef,
958 },
959
960 {
961 .fi = true,
962 .pt = true,
963 .type = GSM0808_SCT_FR2,
964 },
965
966 {
967 .fi = true,
968 .tf = true,
969 .type = GSM0808_SCT_CSD,
970 .cfg = 0xc0,
971 },
972 },
973 .len = 3,
974 };
975 struct gsm0808_speech_codec_list dec_scl = {};
Philipp Maier6f725d62017-03-24 18:03:17 +0100976 struct msgb *msg;
977 uint8_t rc_enc;
978 int rc_dec;
979
Philipp Maier6f725d62017-03-24 18:03:17 +0100980 msg = msgb_alloc(1024, "output buffer");
981 rc_enc = gsm0808_enc_speech_codec_list(msg, &enc_scl);
982 OSMO_ASSERT(rc_enc == 9);
983
984 rc_dec = gsm0808_dec_speech_codec_list(&dec_scl, msg->data + 2, msg->len - 2);
985 OSMO_ASSERT(rc_dec == 7);
986
987 OSMO_ASSERT(memcmp(&enc_scl, &dec_scl, sizeof(enc_scl)) == 0);
988
989 msgb_free(msg);
990}
991
Philipp Maierf6c369f2018-10-16 15:24:47 +0200992static void test_gsm0808_enc_dec_empty_speech_codec_list()
993{
994 struct gsm0808_speech_codec_list enc_scl = {
995 .len = 0,
996 };
997 struct gsm0808_speech_codec_list dec_scl = {};
998 struct msgb *msg;
999 uint8_t rc_enc;
1000 int rc_dec;
1001
1002 msg = msgb_alloc(1024, "output buffer");
1003 rc_enc = gsm0808_enc_speech_codec_list(msg, &enc_scl);
1004 OSMO_ASSERT(rc_enc == 2);
1005
1006 rc_dec = gsm0808_dec_speech_codec_list(&dec_scl, msg->data + 2, msg->len - 2);
1007 OSMO_ASSERT(rc_dec == 0);
1008
1009 OSMO_ASSERT(memcmp(&enc_scl, &dec_scl, sizeof(enc_scl)) == 0);
1010
1011 msgb_free(msg);
1012}
1013
Philipp Maiere0c65302017-03-28 17:05:40 +02001014static void test_gsm0808_enc_dec_channel_type()
1015{
Neels Hofmeyr9a4286b2018-04-20 12:27:52 +02001016 struct gsm0808_channel_type enc_ct = {
1017 .ch_indctr = GSM0808_CHAN_SPEECH,
1018 .ch_rate_type = GSM0808_SPEECH_HALF_PREF,
1019 .perm_spch = { GSM0808_PERM_FR3, GSM0808_PERM_HR3 },
1020 .perm_spch_len = 2,
1021 };
1022 struct gsm0808_channel_type dec_ct = {};
Philipp Maiere0c65302017-03-28 17:05:40 +02001023 struct msgb *msg;
1024 uint8_t ct_enc_expected[] = { GSM0808_IE_CHANNEL_TYPE,
1025 0x04, 0x01, 0x0b, 0xa1, 0x25
1026 };
1027 uint8_t rc_enc;
1028 int rc_dec;
1029
Philipp Maiere0c65302017-03-28 17:05:40 +02001030 msg = msgb_alloc(1024, "output buffer");
1031 rc_enc = gsm0808_enc_channel_type(msg, &enc_ct);
1032 OSMO_ASSERT(rc_enc == 6);
1033 OSMO_ASSERT(memcmp(ct_enc_expected, msg->data, msg->len) == 0);
1034
1035 rc_dec = gsm0808_dec_channel_type(&dec_ct, msg->data + 2, msg->len - 2);
1036 OSMO_ASSERT(rc_dec == 4);
Pau Espin Pedrol2605ffc2019-07-29 16:44:22 +02001037 OSMO_ASSERT(enc_ct.ch_indctr == dec_ct.ch_indctr);
1038 OSMO_ASSERT(enc_ct.ch_rate_type == dec_ct.ch_rate_type);
1039 OSMO_ASSERT(enc_ct.perm_spch_len == dec_ct.perm_spch_len);
1040 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 +02001041
1042 msgb_free(msg);
1043}
1044
Philipp Maier14e76b92017-03-28 18:36:52 +02001045static void test_gsm0808_enc_dec_encrypt_info()
1046{
Neels Hofmeyr9a4286b2018-04-20 12:27:52 +02001047 struct gsm0808_encrypt_info enc_ei = {
1048 .perm_algo = { GSM0808_ALG_ID_A5_0, GSM0808_ALG_ID_A5_1 },
1049 .perm_algo_len = 2,
1050 .key = { 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x23, 0x42, },
1051 .key_len = 8,
1052 };
1053 struct gsm0808_encrypt_info dec_ei = {};
Philipp Maier14e76b92017-03-28 18:36:52 +02001054 struct msgb *msg;
1055 uint8_t ei_enc_expected[] =
1056 { GSM0808_IE_ENCRYPTION_INFORMATION, 0x09, 0x03, 0xaa, 0xbb,
1057 0xcc, 0xdd, 0xee, 0xff, 0x23, 0x42
1058 };
1059 uint8_t rc_enc;
1060 int rc_dec;
1061
Philipp Maier14e76b92017-03-28 18:36:52 +02001062 msg = msgb_alloc(1024, "output buffer");
1063 rc_enc = gsm0808_enc_encrypt_info(msg, &enc_ei);
1064 OSMO_ASSERT(rc_enc == 11);
1065 OSMO_ASSERT(memcmp(ei_enc_expected, msg->data, msg->len) == 0);
1066
1067 rc_dec = gsm0808_dec_encrypt_info(&dec_ei, msg->data + 2, msg->len - 2);
1068 OSMO_ASSERT(rc_dec == 9);
1069
1070 OSMO_ASSERT(memcmp(&enc_ei, &dec_ei, sizeof(enc_ei)) == 0);
1071
1072 msgb_free(msg);
1073}
1074
Harald Weltea87526d2022-02-15 20:06:16 +01001075static void test_gsm0808_dec_cell_id_list_srvcc()
1076{
1077 /* taken from a pcap file of a real-world 3rd party MSC (SYS#5838) */
1078 const uint8_t enc_cil[] = { 0x0b, 0x2, 0xf2, 0x10, 0x4e, 0x20, 0x15, 0xbe};
1079 struct gsm0808_cell_id_list2 dec_cil;
1080 int rc;
1081
1082 rc = gsm0808_dec_cell_id_list2(&dec_cil, enc_cil, sizeof(enc_cil));
Pau Espin Pedrolb5551ee2022-02-16 13:09:32 +01001083 OSMO_ASSERT(rc == sizeof(enc_cil));
1084 OSMO_ASSERT(dec_cil.id_discr = CELL_IDENT_SAI);
1085 OSMO_ASSERT(dec_cil.id_list_len = 1);
Harald Weltea87526d2022-02-15 20:06:16 +01001086}
1087
Philipp Maier783047e2017-03-29 11:35:50 +02001088static void test_gsm0808_enc_dec_cell_id_list_lac()
1089{
Stefan Sperling11a4d9d2018-02-15 18:28:04 +01001090 struct gsm0808_cell_id_list2 enc_cil;
1091 struct gsm0808_cell_id_list2 dec_cil;
Philipp Maier783047e2017-03-29 11:35:50 +02001092 struct msgb *msg;
1093 uint8_t rc_enc;
1094 int rc_dec;
1095
1096 memset(&enc_cil, 0, sizeof(enc_cil));
1097 enc_cil.id_discr = CELL_IDENT_LAC;
Stefan Sperling11a4d9d2018-02-15 18:28:04 +01001098 enc_cil.id_list[0].lac = 0x0124;
Neels Hofmeyrdb2fa4e2018-04-13 04:11:20 +02001099 enc_cil.id_list[1].lac = 0xABCD;
1100 enc_cil.id_list[2].lac = 0x5678;
Philipp Maier783047e2017-03-29 11:35:50 +02001101 enc_cil.id_list_len = 3;
1102
1103 msg = msgb_alloc(1024, "output buffer");
Stefan Sperling11a4d9d2018-02-15 18:28:04 +01001104 rc_enc = gsm0808_enc_cell_id_list2(msg, &enc_cil);
Neels Hofmeyrdb2fa4e2018-04-13 04:11:20 +02001105 EXPECT_ENCODED("1a 07 05 01 24 ab cd 56 78");
Philipp Maier783047e2017-03-29 11:35:50 +02001106
Stefan Sperling11a4d9d2018-02-15 18:28:04 +01001107 rc_dec = gsm0808_dec_cell_id_list2(&dec_cil, msg->data + 2, msg->len - 2);
Philipp Maier783047e2017-03-29 11:35:50 +02001108 OSMO_ASSERT(rc_dec == 7);
1109
1110 OSMO_ASSERT(memcmp(&enc_cil, &dec_cil, sizeof(enc_cil)) == 0);
1111
1112 msgb_free(msg);
1113}
1114
1115static void test_gsm0808_enc_dec_cell_id_list_single_lac()
1116{
Stefan Sperling11a4d9d2018-02-15 18:28:04 +01001117 struct gsm0808_cell_id_list2 enc_cil;
1118 struct gsm0808_cell_id_list2 dec_cil;
Philipp Maier783047e2017-03-29 11:35:50 +02001119 struct msgb *msg;
1120 uint8_t cil_enc_expected[] = { GSM0808_IE_CELL_IDENTIFIER_LIST, 0x03,
1121 0x05, 0x23, 0x42
1122 };
1123 uint8_t rc_enc;
1124 int rc_dec;
1125
1126 memset(&enc_cil, 0, sizeof(enc_cil));
1127 enc_cil.id_discr = CELL_IDENT_LAC;
Stefan Sperling11a4d9d2018-02-15 18:28:04 +01001128 enc_cil.id_list[0].lac = 0x2342;
Philipp Maier783047e2017-03-29 11:35:50 +02001129 enc_cil.id_list_len = 1;
1130
1131 msg = msgb_alloc(1024, "output buffer");
Stefan Sperling11a4d9d2018-02-15 18:28:04 +01001132 rc_enc = gsm0808_enc_cell_id_list2(msg, &enc_cil);
Philipp Maier783047e2017-03-29 11:35:50 +02001133 OSMO_ASSERT(rc_enc == 5);
1134 OSMO_ASSERT(memcmp(cil_enc_expected, msg->data, msg->len) == 0);
1135
Stefan Sperling11a4d9d2018-02-15 18:28:04 +01001136 rc_dec = gsm0808_dec_cell_id_list2(&dec_cil, msg->data + 2, msg->len - 2);
Philipp Maier783047e2017-03-29 11:35:50 +02001137 OSMO_ASSERT(rc_dec == 3);
1138
1139 OSMO_ASSERT(memcmp(&enc_cil, &dec_cil, sizeof(enc_cil)) == 0);
1140
1141 msgb_free(msg);
1142}
1143
Stefan Sperlinge1a86742018-03-15 18:05:02 +01001144static void test_gsm0808_enc_dec_cell_id_list_multi_lac()
1145{
1146 struct gsm0808_cell_id_list2 enc_cil;
1147 struct gsm0808_cell_id_list2 dec_cil;
1148 struct msgb *msg;
1149 uint8_t cil_enc_expected[] = { GSM0808_IE_CELL_IDENTIFIER_LIST, 0x0b, 0x05,
1150 0x23, 0x42,
1151 0x24, 0x43,
1152 0x25, 0x44,
1153 0x26, 0x45,
1154 0x27, 0x46
1155 };
1156 uint8_t rc_enc;
1157 int rc_dec;
1158
1159 memset(&enc_cil, 0, sizeof(enc_cil));
1160 enc_cil.id_discr = CELL_IDENT_LAC;
1161 enc_cil.id_list[0].lac = 0x2342;
1162 enc_cil.id_list[1].lac = 0x2443;
1163 enc_cil.id_list[2].lac = 0x2544;
1164 enc_cil.id_list[3].lac = 0x2645;
1165 enc_cil.id_list[4].lac = 0x2746;
1166 enc_cil.id_list_len = 5;
1167
1168 msg = msgb_alloc(1024, "output buffer");
1169 rc_enc = gsm0808_enc_cell_id_list2(msg, &enc_cil);
1170 OSMO_ASSERT(rc_enc == sizeof(cil_enc_expected));
1171 OSMO_ASSERT(memcmp(cil_enc_expected, msg->data, msg->len) == 0);
1172
1173 rc_dec = gsm0808_dec_cell_id_list2(&dec_cil, msg->data + 2, msg->len - 2);
1174 OSMO_ASSERT(rc_dec == msg->len - 2);
1175 OSMO_ASSERT(memcmp(&enc_cil, &dec_cil, sizeof(enc_cil)) == 0);
1176
1177 msgb_free(msg);
1178}
1179
Philipp Maier783047e2017-03-29 11:35:50 +02001180static void test_gsm0808_enc_dec_cell_id_list_bss()
1181{
Stefan Sperling11a4d9d2018-02-15 18:28:04 +01001182 struct gsm0808_cell_id_list2 enc_cil;
1183 struct gsm0808_cell_id_list2 dec_cil;
Philipp Maier783047e2017-03-29 11:35:50 +02001184 struct msgb *msg;
1185 uint8_t rc_enc;
1186 int rc_dec;
1187
1188 memset(&enc_cil, 0, sizeof(enc_cil));
Stefan Sperling11a4d9d2018-02-15 18:28:04 +01001189 enc_cil.id_discr = CELL_IDENT_BSS;
Philipp Maier783047e2017-03-29 11:35:50 +02001190
1191 msg = msgb_alloc(1024, "output buffer");
Stefan Sperling11a4d9d2018-02-15 18:28:04 +01001192 rc_enc = gsm0808_enc_cell_id_list2(msg, &enc_cil);
Philipp Maier783047e2017-03-29 11:35:50 +02001193 OSMO_ASSERT(rc_enc == 3);
1194
Stefan Sperling11a4d9d2018-02-15 18:28:04 +01001195 rc_dec = gsm0808_dec_cell_id_list2(&dec_cil, msg->data + 2, msg->len - 2);
Philipp Maier783047e2017-03-29 11:35:50 +02001196 OSMO_ASSERT(rc_dec == 1);
1197
1198 OSMO_ASSERT(memcmp(&enc_cil, &dec_cil, sizeof(enc_cil)) == 0);
1199
1200 msgb_free(msg);
1201}
1202
Stefan Sperling23381452018-03-15 19:38:15 +01001203static void test_gsm0808_enc_dec_cell_id_list_multi_lai_and_lac()
1204{
1205 struct gsm0808_cell_id_list2 enc_cil;
1206 struct gsm0808_cell_id_list2 dec_cil;
1207 struct osmo_location_area_id id;
1208 struct msgb *msg;
1209 uint8_t cil_enc_expected[] = { GSM0808_IE_CELL_IDENTIFIER_LIST, 0x10, 0x04,
1210 0x92, 0x61, 0x54, 0x23, 0x42,
1211 0x92, 0x72, 0x54, 0x24, 0x43,
1212 0x92, 0x83, 0x54, 0x25, 0x44
1213 };
1214 uint8_t rc_enc;
1215 int rc_dec, i;
1216
1217 memset(&enc_cil, 0, sizeof(enc_cil));
1218 enc_cil.id_discr = CELL_IDENT_LAI_AND_LAC;
1219
1220 id.plmn.mcc = 0x123;
1221 osmo_mnc_from_str("456", &id.plmn.mnc, &id.plmn.mnc_3_digits);
1222 id.lac = 0x2342;
1223 memcpy(&enc_cil.id_list[0].lai_and_lac, &id, sizeof(id));
1224
1225 id.plmn.mcc = 0x124;
1226 osmo_mnc_from_str("457", &id.plmn.mnc, &id.plmn.mnc_3_digits);
1227 id.lac = 0x2443;
1228 memcpy(&enc_cil.id_list[1].lai_and_lac, &id, sizeof(id));
1229
1230 id.plmn.mcc = 0x125;
1231 osmo_mnc_from_str("458", &id.plmn.mnc, &id.plmn.mnc_3_digits);
1232 id.lac = 0x2544;
1233 memcpy(&enc_cil.id_list[2].lai_and_lac, &id, sizeof(id));
1234
1235 enc_cil.id_list_len = 3;
1236
1237 msg = msgb_alloc(1024, "output buffer");
1238 rc_enc = gsm0808_enc_cell_id_list2(msg, &enc_cil);
1239 OSMO_ASSERT(rc_enc == sizeof(cil_enc_expected));
1240 OSMO_ASSERT(memcmp(cil_enc_expected, msg->data, msg->len) == 0);
1241
1242 rc_dec = gsm0808_dec_cell_id_list2(&dec_cil, msg->data + 2, msg->len - 2);
1243 OSMO_ASSERT(rc_dec == msg->len - 2);
1244
1245 OSMO_ASSERT(dec_cil.id_list_len == 3);
1246 /* Check MAXLEN elements to ensure everything has been initialized. */
1247 for (i = 0; i < GSM0808_CELL_ID_LIST2_MAXLEN; i++) {
1248 struct osmo_location_area_id *enc_id;
1249 struct osmo_location_area_id *dec_id;
1250 enc_id = &enc_cil.id_list[i].lai_and_lac;
1251 dec_id = &dec_cil.id_list[i].lai_and_lac;
1252 OSMO_ASSERT(osmo_plmn_cmp(&enc_id->plmn, &dec_id->plmn) == 0);
1253 OSMO_ASSERT(enc_id->lac == dec_id->lac);
1254 }
1255
1256 msgb_free(msg);
1257}
1258
Stefan Sperling9c62fc62018-03-16 10:23:34 +01001259static void test_gsm0808_enc_dec_cell_id_list_multi_ci()
1260{
1261 struct gsm0808_cell_id_list2 enc_cil;
1262 struct gsm0808_cell_id_list2 dec_cil;
1263 struct msgb *msg;
1264 uint8_t cil_enc_expected[] = { GSM0808_IE_CELL_IDENTIFIER_LIST, 0x09, 0x02,
1265 0x00, 0x01,
1266 0x00, 0x02,
1267 0x00, 0x77,
1268 0x01, 0xff,
1269 };
1270 uint8_t rc_enc;
1271 int rc_dec;
1272
1273 memset(&enc_cil, 0, sizeof(enc_cil));
1274 enc_cil.id_discr = CELL_IDENT_CI;
1275 enc_cil.id_list[0].ci = 1;
1276 enc_cil.id_list[1].ci = 2;
1277 enc_cil.id_list[2].ci = 119;
1278 enc_cil.id_list[3].ci = 511;
1279 enc_cil.id_list_len = 4;
1280
1281 msg = msgb_alloc(1024, "output buffer");
1282 rc_enc = gsm0808_enc_cell_id_list2(msg, &enc_cil);
1283 OSMO_ASSERT(rc_enc == sizeof(cil_enc_expected));
1284 OSMO_ASSERT(memcmp(cil_enc_expected, msg->data, msg->len) == 0);
1285
1286 rc_dec = gsm0808_dec_cell_id_list2(&dec_cil, msg->data + 2, msg->len - 2);
1287 OSMO_ASSERT(rc_dec == msg->len - 2);
1288 OSMO_ASSERT(memcmp(&enc_cil, &dec_cil, sizeof(enc_cil)) == 0);
1289
1290 msgb_free(msg);
1291}
1292
Stefan Sperlinged4327c2018-03-16 11:02:59 +01001293static void test_gsm0808_enc_dec_cell_id_list_multi_lac_and_ci()
1294{
1295 struct gsm0808_cell_id_list2 enc_cil;
1296 struct gsm0808_cell_id_list2 dec_cil;
1297 struct msgb *msg;
1298 uint8_t cil_enc_expected[] = { GSM0808_IE_CELL_IDENTIFIER_LIST, 0x15, 0x01,
1299 0x23, 0x42, 0x00, 0x01,
1300 0x24, 0x43, 0x00, 0x02,
1301 0x25, 0x44, 0x00, 0x77,
1302 0x26, 0x45, 0x01, 0xff,
1303 0x27, 0x46, 0x02, 0xfe,
1304 };
1305 uint8_t rc_enc;
1306 int rc_dec;
1307
1308 memset(&enc_cil, 0, sizeof(enc_cil));
1309 enc_cil.id_discr = CELL_IDENT_LAC_AND_CI;
1310 enc_cil.id_list[0].lac_and_ci.lac = 0x2342;
1311 enc_cil.id_list[0].lac_and_ci.ci = 1;
1312 enc_cil.id_list[1].lac_and_ci.lac = 0x2443;
1313 enc_cil.id_list[1].lac_and_ci.ci = 2;
1314 enc_cil.id_list[2].lac_and_ci.lac = 0x2544;
1315 enc_cil.id_list[2].lac_and_ci.ci = 119;
1316 enc_cil.id_list[3].lac_and_ci.lac = 0x2645;
1317 enc_cil.id_list[3].lac_and_ci.ci = 511;
1318 enc_cil.id_list[4].lac_and_ci.lac = 0x2746;
1319 enc_cil.id_list[4].lac_and_ci.ci = 766;
1320 enc_cil.id_list_len = 5;
1321
1322 msg = msgb_alloc(1024, "output buffer");
1323 rc_enc = gsm0808_enc_cell_id_list2(msg, &enc_cil);
1324 OSMO_ASSERT(rc_enc == sizeof(cil_enc_expected));
1325 OSMO_ASSERT(memcmp(cil_enc_expected, msg->data, msg->len) == 0);
1326
1327 rc_dec = gsm0808_dec_cell_id_list2(&dec_cil, msg->data + 2, msg->len - 2);
1328 OSMO_ASSERT(rc_dec == msg->len - 2);
1329 OSMO_ASSERT(memcmp(&enc_cil, &dec_cil, sizeof(enc_cil)) == 0);
1330
1331 msgb_free(msg);
1332}
1333
Stefan Sperling483f3862018-03-16 12:21:26 +01001334static void test_gsm0808_enc_dec_cell_id_list_multi_global()
1335{
1336 struct gsm0808_cell_id_list2 enc_cil;
1337 struct gsm0808_cell_id_list2 dec_cil;
1338 struct msgb *msg;
1339 uint8_t cil_enc_expected[] = { GSM0808_IE_CELL_IDENTIFIER_LIST, 0x16, 0x00,
Neels Hofmeyr473485c2018-03-23 02:04:18 +01001340 0x21, 0x63, 0x54, 0x23, 0x42, 0x00, 0x1,
Neels Hofmeyrc44fc232018-03-23 02:15:12 +01001341 0x21, 0xf4, 0x75, 0x24, 0x43, 0x00, 0x2,
Neels Hofmeyr8b8cd932018-03-23 01:47:37 +01001342 0x21, 0x75, 0x00, 0x25, 0x44, 0x00, 0x77
Stefan Sperling483f3862018-03-16 12:21:26 +01001343 };
Stefan Sperling483f3862018-03-16 12:21:26 +01001344 uint8_t rc_enc;
1345 int rc_dec, i;
1346
Neels Hofmeyrc1991df2018-03-23 02:00:00 +01001347 enc_cil = (struct gsm0808_cell_id_list2){
1348 .id_discr = CELL_IDENT_WHOLE_GLOBAL,
1349 .id_list_len = 3,
1350 .id_list = {
1351 {
1352 .global = {
Neels Hofmeyr473485c2018-03-23 02:04:18 +01001353 .lai = { .plmn = { .mcc = 123, .mnc = 456 },
Neels Hofmeyrc1991df2018-03-23 02:00:00 +01001354 .lac = 0x2342 },
1355 .cell_identity = 1,
1356 }
1357 },
1358 {
1359 .global = {
Neels Hofmeyrc44fc232018-03-23 02:15:12 +01001360 .lai = { .plmn = { .mcc = 124, .mnc = 57 },
Neels Hofmeyrc1991df2018-03-23 02:00:00 +01001361 .lac = 0x2443 },
1362 .cell_identity = 2,
1363 }
1364 },
1365 {
1366 .global = {
Neels Hofmeyrc44fc232018-03-23 02:15:12 +01001367 .lai = { .plmn = { .mcc = 125, .mnc = 7,
1368 .mnc_3_digits = true },
Neels Hofmeyrc1991df2018-03-23 02:00:00 +01001369 .lac = 0x2544 },
1370 .cell_identity = 119,
1371 }
1372 },
1373 }
1374 };
Stefan Sperling483f3862018-03-16 12:21:26 +01001375
1376 msg = msgb_alloc(1024, "output buffer");
1377 rc_enc = gsm0808_enc_cell_id_list2(msg, &enc_cil);
1378 OSMO_ASSERT(rc_enc == sizeof(cil_enc_expected));
Neels Hofmeyrc1991df2018-03-23 02:00:00 +01001379 if (memcmp(cil_enc_expected, msg->data, msg->len)) {
1380 printf(" got: %s\n", osmo_hexdump(msg->data, msg->len));
1381 printf("expect: %s\n", osmo_hexdump(cil_enc_expected, sizeof(cil_enc_expected)));
1382 OSMO_ASSERT(false);
1383 }
Stefan Sperling483f3862018-03-16 12:21:26 +01001384
1385 rc_dec = gsm0808_dec_cell_id_list2(&dec_cil, msg->data + 2, msg->len - 2);
1386 OSMO_ASSERT(rc_dec == msg->len - 2);
1387
1388 /* Check MAXLEN elements to ensure everything has been initialized. */
1389 for (i = 0; i < GSM0808_CELL_ID_LIST2_MAXLEN; i++) {
1390 struct osmo_cell_global_id *enc_id;
1391 struct osmo_cell_global_id *dec_id;
1392 enc_id = &enc_cil.id_list[i].global;
1393 dec_id = &dec_cil.id_list[i].global;
1394 OSMO_ASSERT(osmo_plmn_cmp(&enc_id->lai.plmn, &dec_id->lai.plmn) == 0);
1395 OSMO_ASSERT(enc_id->lai.lac == dec_id->lai.lac);
1396 OSMO_ASSERT(enc_id->cell_identity == dec_id->cell_identity);
1397 }
1398
1399 msgb_free(msg);
1400}
1401
Neels Hofmeyr74663d92018-03-23 01:46:42 +01001402static void print_cil(const struct gsm0808_cell_id_list2 *cil)
1403{
Neels Hofmeyra4399c82018-04-17 02:26:10 +02001404 printf(" cell_id_list == %s\n", gsm0808_cell_id_list_name(cil));
Neels Hofmeyr74663d92018-03-23 01:46:42 +01001405}
1406
1407void test_cell_id_list_add() {
Neels Hofmeyra4399c82018-04-17 02:26:10 +02001408 size_t zu;
1409
Neels Hofmeyr74663d92018-03-23 01:46:42 +01001410 const struct gsm0808_cell_id_list2 cgi1 = {
1411 .id_discr = CELL_IDENT_WHOLE_GLOBAL,
1412 .id_list_len = 1,
1413 .id_list = {
1414 {
1415 .global = {
1416 .lai = {
1417 .plmn = { .mcc = 1, .mnc = 2, .mnc_3_digits = false },
1418 .lac = 3,
1419 },
1420 .cell_identity = 4,
1421 }
1422 },
1423 },
1424 };
1425
1426 const struct gsm0808_cell_id_list2 cgi2 = {
1427 .id_discr = CELL_IDENT_WHOLE_GLOBAL,
1428 .id_list_len = 2,
1429 .id_list = {
1430 {
1431 .global = {
1432 .lai = {
1433 .plmn = { .mcc = 1, .mnc = 2, .mnc_3_digits = true },
1434 .lac = 3,
1435 },
1436 .cell_identity = 4,
1437 }
1438 },
1439 {
1440 .global = {
1441 .lai = {
1442 .plmn = { .mcc = 5, .mnc = 6, .mnc_3_digits = true },
1443 .lac = 7,
1444 },
1445 .cell_identity = 8,
1446 }
1447 },
1448 },
1449 };
1450
1451 const struct gsm0808_cell_id_list2 cgi2a = {
1452 .id_discr = CELL_IDENT_WHOLE_GLOBAL,
1453 .id_list_len = 2,
1454 .id_list = {
1455 {
1456 .global = cgi2.id_list[0].global
1457 },
1458 {
1459 .global = {
1460 .lai = {
1461 .plmn = { .mcc = 9, .mnc = 10, .mnc_3_digits = true },
1462 .lac = 11,
1463 },
1464 .cell_identity = 12,
1465 }
1466 },
1467 },
1468 };
1469
1470 const struct gsm0808_cell_id_list2 cgi3 = {
1471 .id_discr = CELL_IDENT_WHOLE_GLOBAL,
1472 .id_list_len = 2,
1473 .id_list = {
1474 {
1475 .global = {
1476 .lai = {
1477 .plmn = { .mcc = 13, .mnc = 14, .mnc_3_digits = true },
1478 .lac = 15,
1479 },
1480 .cell_identity = 16,
1481 }
1482 },
1483 {
1484 .global = {
1485 .lai = {
1486 .plmn = { .mcc = 16, .mnc = 17, .mnc_3_digits = true },
1487 .lac = 18,
1488 },
1489 .cell_identity = 19,
1490 }
1491 },
1492 },
1493 };
1494
1495
1496 const struct gsm0808_cell_id_list2 lac1 = {
1497 .id_discr = CELL_IDENT_LAC,
1498 .id_list_len = 1,
1499 .id_list = {
1500 {
1501 .lac = 123
1502 },
1503 },
1504 };
1505
1506 const struct gsm0808_cell_id_list2 lac2 = {
1507 .id_discr = CELL_IDENT_LAC,
1508 .id_list_len = 2,
1509 .id_list = {
1510 {
1511 .lac = 456
1512 },
1513 {
1514 .lac = 789
1515 },
1516 },
1517 };
1518
1519 struct gsm0808_cell_id_list2 cil = {};
1520
1521 printf("------- %s\n", __func__);
1522
1523 print_cil(&cil);
1524
1525#define ADD_QUIET(other_cil, expect_rc) do { \
1526 int rc = gsm0808_cell_id_list_add(&cil, &other_cil); \
Neels Hofmeyra4399c82018-04-17 02:26:10 +02001527 printf("gsm0808_cell_id_list_add(&cil, &" #other_cil ") --> rc = %d\n", rc); \
Neels Hofmeyr74663d92018-03-23 01:46:42 +01001528 OSMO_ASSERT(rc == expect_rc); \
1529 } while(0)
1530
1531#define ADD(other_cil, expect_rc) ADD_QUIET(other_cil, expect_rc); print_cil(&cil)
1532
1533 ADD(lac1, 1);
1534 ADD(lac1, 0);
1535 ADD(lac2, 2);
1536 ADD(lac2, 0);
1537 ADD(cil, 0);
1538 ADD(cgi1, -EINVAL);
1539
Neels Hofmeyra4399c82018-04-17 02:26:10 +02001540 printf("* can't add to BSS list\n");
Neels Hofmeyr74663d92018-03-23 01:46:42 +01001541 cil.id_list_len = 0;
1542 cil.id_discr = CELL_IDENT_BSS;
1543 print_cil(&cil);
1544 ADD(lac1, -EINVAL);
1545
Neels Hofmeyra4399c82018-04-17 02:26:10 +02001546 printf("* other types (including NO_CELL) take on new type iff empty\n");
Neels Hofmeyr74663d92018-03-23 01:46:42 +01001547 cil.id_list_len = 0;
1548 cil.id_discr = CELL_IDENT_NO_CELL;
1549 print_cil(&cil);
1550 ADD(cgi1, 1);
1551 ADD(cgi1, 0);
1552 ADD(cgi2, 2);
1553 ADD(cgi2, 0);
1554
Neels Hofmeyra4399c82018-04-17 02:26:10 +02001555 printf("* test gsm0808_cell_id_list_name_buf()'s return val\n");
1556 zu = strlen(gsm0808_cell_id_list_name(&cil));
1557 printf(" strlen(gsm0808_cell_id_list_name(cil)) == %zu\n", zu);
1558 zu ++;
1559 while (1) {
1560 char buf[128] = "?";
1561 int rc;
1562 OSMO_ASSERT(zu < sizeof(buf));
1563 buf[zu] = '#';
1564 rc = gsm0808_cell_id_list_name_buf(buf, zu, &cil);
1565 printf(" gsm0808_cell_id_list_name_buf(buf, %zu, cil)) == %d \"%s\"\n",
1566 zu, rc, buf);
1567 OSMO_ASSERT(buf[zu] == '#');
1568 if (!zu)
1569 break;
1570 zu /= 2;
1571 }
1572
1573 printf("* list-full behavior\n");
Neels Hofmeyr74663d92018-03-23 01:46:42 +01001574 cil.id_list_len = GSM0808_CELL_ID_LIST2_MAXLEN - 1;
Neels Hofmeyra4399c82018-04-17 02:26:10 +02001575 printf("cil.id_list_len = %u\n", cil.id_list_len);
Neels Hofmeyr74663d92018-03-23 01:46:42 +01001576 ADD_QUIET(cgi2a, 1);
1577 printf("cil.id_list_len = %u\n", cil.id_list_len);
1578
1579 cil.id_list_len = GSM0808_CELL_ID_LIST2_MAXLEN - 1;
Neels Hofmeyra4399c82018-04-17 02:26:10 +02001580 printf("cil.id_list_len = %u\n", cil.id_list_len);
Neels Hofmeyr74663d92018-03-23 01:46:42 +01001581 ADD_QUIET(cgi3, -ENOSPC);
Neels Hofmeyra4399c82018-04-17 02:26:10 +02001582 printf("cil.id_list_len = %u\n", cil.id_list_len);
Neels Hofmeyr74663d92018-03-23 01:46:42 +01001583 ADD_QUIET(cgi2a, -ENOSPC);
1584 printf("cil.id_list_len = %u\n", cil.id_list_len);
1585
1586 printf("------- %s done\n", __func__);
1587}
1588
Neels Hofmeyr250e7f72018-04-13 03:30:14 +02001589static void test_gsm0808_enc_dec_cell_id_lac()
1590{
1591 struct gsm0808_cell_id enc_ci = {
1592 .id_discr = CELL_IDENT_LAC,
1593 .id.lac = 0x0124,
1594 };
1595 struct gsm0808_cell_id dec_ci;
1596 struct msgb *msg;
1597 uint8_t rc_enc;
1598 int rc_dec;
1599
1600 memset(&dec_ci, 0xa5, sizeof(dec_ci));
1601
1602 msg = msgb_alloc(1024, "output buffer");
1603 rc_enc = gsm0808_enc_cell_id(msg, &enc_ci);
1604 EXPECT_ENCODED("05 03 05 01 24");
1605
1606 rc_dec = gsm0808_dec_cell_id(&dec_ci, msg->data + 2, msg->len - 2);
1607 OSMO_ASSERT(rc_dec == 3);
1608
1609 OSMO_ASSERT(enc_ci.id_discr == dec_ci.id_discr
1610 && enc_ci.id.lac == dec_ci.id.lac);
1611
1612 msgb_free(msg);
1613}
1614
1615static void test_gsm0808_enc_dec_cell_id_bss()
1616{
1617 struct gsm0808_cell_id enc_ci = {
1618 .id_discr = CELL_IDENT_BSS,
1619 };
1620 struct gsm0808_cell_id dec_ci;
1621 struct msgb *msg;
1622 uint8_t rc_enc;
1623 int rc_dec;
1624
1625 msg = msgb_alloc(1024, "output buffer");
1626 rc_enc = gsm0808_enc_cell_id(msg, &enc_ci);
1627 EXPECT_ENCODED("05 01 06");
1628
1629 rc_dec = gsm0808_dec_cell_id(&dec_ci, msg->data + 2, msg->len - 2);
1630 OSMO_ASSERT(rc_dec == 1);
1631
1632 OSMO_ASSERT(enc_ci.id_discr == dec_ci.id_discr);
1633
1634 msgb_free(msg);
1635}
1636
1637static void test_gsm0808_enc_dec_cell_id_no_cell()
1638{
1639 struct gsm0808_cell_id enc_ci = {
1640 .id_discr = CELL_IDENT_NO_CELL,
1641 };
1642 struct gsm0808_cell_id dec_ci;
1643 struct msgb *msg;
1644 uint8_t rc_enc;
1645 int rc_dec;
1646
1647 msg = msgb_alloc(1024, "output buffer");
1648 rc_enc = gsm0808_enc_cell_id(msg, &enc_ci);
1649 EXPECT_ENCODED("05 01 03");
1650
1651 rc_dec = gsm0808_dec_cell_id(&dec_ci, msg->data + 2, msg->len - 2);
1652 OSMO_ASSERT(rc_dec == 1);
1653
1654 OSMO_ASSERT(enc_ci.id_discr == dec_ci.id_discr);
1655
1656 msgb_free(msg);
1657}
1658
1659static void test_gsm0808_enc_dec_cell_id_lai_and_lac()
1660{
1661 struct gsm0808_cell_id enc_ci = {
1662 .id_discr = CELL_IDENT_LAI_AND_LAC,
1663 .id.lai_and_lac = {
1664 .plmn = {
1665 .mcc = 123,
1666 .mnc = 456,
1667 },
1668 .lac = 0x2342,
1669 },
1670 };
1671 struct gsm0808_cell_id dec_ci;
1672 struct msgb *msg;
1673 uint8_t rc_enc;
1674 int rc_dec;
1675
1676 msg = msgb_alloc(1024, "output buffer");
1677 rc_enc = gsm0808_enc_cell_id(msg, &enc_ci);
1678 EXPECT_ENCODED("05 06 04 21 63 54 23 42");
1679
1680 memset(&dec_ci, 0xa5, sizeof(dec_ci));
1681 rc_dec = gsm0808_dec_cell_id(&dec_ci, msg->data + 2, msg->len - 2);
1682 OSMO_ASSERT(rc_dec == msg->len - 2);
1683
1684 OSMO_ASSERT(enc_ci.id_discr == dec_ci.id_discr
1685 && osmo_plmn_cmp(&enc_ci.id.lai_and_lac.plmn, &dec_ci.id.lai_and_lac.plmn) == 0
1686 && enc_ci.id.lai_and_lac.lac == dec_ci.id.lai_and_lac.lac);
1687 msgb_free(msg);
1688}
1689
1690static void test_gsm0808_enc_dec_cell_id_ci()
1691{
1692 struct gsm0808_cell_id enc_ci = {
1693 .id_discr = CELL_IDENT_CI,
1694 .id.ci = 0x423,
1695 };
1696 struct gsm0808_cell_id dec_ci;
1697 struct msgb *msg;
1698 uint8_t rc_enc;
1699 int rc_dec;
1700
1701 msg = msgb_alloc(1024, "output buffer");
1702 rc_enc = gsm0808_enc_cell_id(msg, &enc_ci);
1703 EXPECT_ENCODED("05 03 02 04 23");
1704
1705 rc_dec = gsm0808_dec_cell_id(&dec_ci, msg->data + 2, msg->len - 2);
1706 OSMO_ASSERT(rc_dec == msg->len - 2);
1707 OSMO_ASSERT(enc_ci.id_discr == dec_ci.id_discr
1708 && enc_ci.id.ci == dec_ci.id.ci);
1709
1710 msgb_free(msg);
1711}
1712
1713static void test_gsm0808_enc_dec_cell_id_lac_and_ci()
1714{
1715 struct gsm0808_cell_id enc_ci = {
1716 .id_discr = CELL_IDENT_LAC_AND_CI,
1717 .id.lac_and_ci = {
1718 .lac = 0x423,
1719 .ci = 0x235,
1720 },
1721 };
1722 struct gsm0808_cell_id dec_ci;
1723 struct msgb *msg;
1724 uint8_t rc_enc;
1725 int rc_dec;
1726
1727 msg = msgb_alloc(1024, "output buffer");
1728 rc_enc = gsm0808_enc_cell_id(msg, &enc_ci);
1729 EXPECT_ENCODED("05 05 01 04 23 02 35");
1730
1731 rc_dec = gsm0808_dec_cell_id(&dec_ci, msg->data + 2, msg->len - 2);
1732 OSMO_ASSERT(rc_dec == msg->len - 2);
1733 OSMO_ASSERT(enc_ci.id_discr == dec_ci.id_discr
1734 && enc_ci.id.lac_and_ci.lac == dec_ci.id.lac_and_ci.lac
1735 && enc_ci.id.lac_and_ci.ci == dec_ci.id.lac_and_ci.ci);
1736
1737 msgb_free(msg);
1738}
1739
1740static void test_gsm0808_enc_dec_cell_id_global()
1741{
1742 struct gsm0808_cell_id enc_ci = {
1743 .id_discr = CELL_IDENT_WHOLE_GLOBAL,
1744 .id.global = {
1745 .lai = {
1746 .plmn = { .mcc = 123, .mnc = 456 },
1747 .lac = 0x2342
1748 },
1749 .cell_identity = 0x423,
1750 }
1751 };
1752 struct gsm0808_cell_id dec_ci;
1753 struct msgb *msg;
1754 uint8_t rc_enc;
1755 int rc_dec;
1756
1757 msg = msgb_alloc(1024, "output buffer");
1758 rc_enc = gsm0808_enc_cell_id(msg, &enc_ci);
1759 EXPECT_ENCODED("05 08 00 21 63 54 23 42 04 23");
1760
1761 rc_dec = gsm0808_dec_cell_id(&dec_ci, msg->data + 2, msg->len - 2);
1762 OSMO_ASSERT(rc_dec == msg->len - 2);
1763
1764 OSMO_ASSERT(enc_ci.id_discr == dec_ci.id_discr
1765 && osmo_plmn_cmp(&enc_ci.id.global.lai.plmn,
1766 &dec_ci.id.global.lai.plmn) == 0
1767 && enc_ci.id.global.lai.lac == dec_ci.id.global.lai.lac
1768 && enc_ci.id.global.cell_identity == dec_ci.id.global.cell_identity);
1769 msgb_free(msg);
1770}
1771
Pau Espin Pedrol52489852021-02-15 16:26:37 +01001772static void test_gsm0808_enc_dec_cell_id_global_ps()
1773{
1774 struct gsm0808_cell_id enc_cgi = {
1775 .id_discr = CELL_IDENT_WHOLE_GLOBAL,
1776 .id.global = {
1777 .lai = {
1778 .plmn = { .mcc = 123, .mnc = 456 },
1779 .lac = 0x2342
1780 },
1781 .cell_identity = 0x423,
1782 }
1783 };
1784 struct gsm0808_cell_id enc_cgi_ps = {
1785 .id_discr = CELL_IDENT_WHOLE_GLOBAL_PS,
1786 .id.global_ps = {
1787 .rai = {
1788 .lac = {
1789 .plmn = { .mcc = 123, .mnc = 456 },
1790 .lac = 0x2342
1791 },
1792 .rac = 0xcc,
1793 },
1794 .cell_identity = 0x423,
1795 }
1796 };
1797 struct msgb *msg_cgi, *msg_cgi_ps;
1798 uint8_t rc_enc;
1799
1800 msg_cgi = msgb_alloc(1024, "output buffer (CGI)");
1801 rc_enc = gsm0808_enc_cell_id(msg_cgi, &enc_cgi);
1802 OSMO_ASSERT(rc_enc > 0);
1803
1804 msg_cgi_ps = msgb_alloc(1024, "output buffer (CGI-PS)");
1805 rc_enc = gsm0808_enc_cell_id(msg_cgi_ps, &enc_cgi_ps);
1806 OSMO_ASSERT(rc_enc > 0);
1807
1808 OSMO_ASSERT(msgb_eq(msg_cgi, msg_cgi_ps));
1809
1810 msgb_free(msg_cgi);
1811 msgb_free(msg_cgi_ps);
1812}
1813
Philipp Maier5f2eb152018-09-19 13:40:21 +02001814static void test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(struct gsm48_multi_rate_conf *cfg)
1815{
1816 uint16_t s15_s0;
1817
1818 printf("Input:\n");
1819 printf(" m4_75= %u smod= %u\n", cfg->m4_75, cfg->smod);
1820 printf(" m5_15= %u spare= %u\n", cfg->m5_15, cfg->spare);
1821 printf(" m5_90= %u icmi= %u\n", cfg->m5_90, cfg->icmi);
1822 printf(" m6_70= %u nscb= %u\n", cfg->m6_70, cfg->nscb);
1823 printf(" m7_40= %u ver= %u\n", cfg->m7_40, cfg->ver);
1824 printf(" m7_95= %u\n", cfg->m7_95);
1825 printf(" m10_2= %u\n", cfg->m10_2);
1826 printf(" m12_2= %u\n", cfg->m12_2);
1827
1828 s15_s0 = gsm0808_sc_cfg_from_gsm48_mr_cfg(cfg, true);
1829 printf("Result (fr):\n");
1830 printf(" S15-S0 = %04x = 0b" OSMO_BIN_SPEC OSMO_BIN_SPEC "\n", s15_s0,
1831 OSMO_BIN_PRINT(s15_s0 >> 8), OSMO_BIN_PRINT(s15_s0));
1832
1833 s15_s0 = gsm0808_sc_cfg_from_gsm48_mr_cfg(cfg, false);
1834 printf("Result (hr):\n");
1835 printf(" S15-S0 = %04x = 0b" OSMO_BIN_SPEC OSMO_BIN_SPEC "\n", s15_s0,
1836 OSMO_BIN_PRINT(s15_s0 >> 8), OSMO_BIN_PRINT(s15_s0));
1837
1838 printf("\n");
1839}
1840
1841static void test_gsm0808_sc_cfg_from_gsm48_mr_cfg(void)
1842{
1843 struct gsm48_multi_rate_conf cfg;
1844
1845 printf("Testing gsm0808_sc_cfg_from_gsm48_mr_cfg():\n");
1846
1847 memset(&cfg, 0, sizeof(cfg));
1848
1849 cfg.m4_75 = 0;
1850 cfg.m5_15 = 0;
1851 cfg.m5_90 = 0;
1852 cfg.m6_70 = 0;
1853 cfg.m7_40 = 0;
1854 cfg.m7_95 = 0;
1855 cfg.m10_2 = 0;
1856 cfg.m12_2 = 0;
1857 test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(&cfg);
1858
1859 cfg.m4_75 = 1;
1860 cfg.m5_15 = 0;
1861 cfg.m5_90 = 0;
1862 cfg.m6_70 = 0;
1863 cfg.m7_40 = 0;
1864 cfg.m7_95 = 0;
1865 cfg.m10_2 = 0;
1866 cfg.m12_2 = 0;
1867 test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(&cfg);
1868
1869 cfg.m4_75 = 0;
1870 cfg.m5_15 = 1;
1871 cfg.m5_90 = 0;
1872 cfg.m6_70 = 0;
1873 cfg.m7_40 = 0;
1874 cfg.m7_95 = 0;
1875 cfg.m10_2 = 0;
1876 cfg.m12_2 = 0;
1877 test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(&cfg);
1878
1879 cfg.m4_75 = 0;
1880 cfg.m5_15 = 0;
1881 cfg.m5_90 = 1;
1882 cfg.m6_70 = 0;
1883 cfg.m7_40 = 0;
1884 cfg.m7_95 = 0;
1885 cfg.m10_2 = 0;
1886 cfg.m12_2 = 0;
1887 test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(&cfg);
1888
1889 cfg.m4_75 = 0;
1890 cfg.m5_15 = 0;
1891 cfg.m5_90 = 0;
1892 cfg.m6_70 = 1;
1893 cfg.m7_40 = 0;
1894 cfg.m7_95 = 0;
1895 cfg.m10_2 = 0;
1896 cfg.m12_2 = 0;
1897 test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(&cfg);
1898
1899 cfg.m4_75 = 0;
1900 cfg.m5_15 = 0;
1901 cfg.m5_90 = 0;
1902 cfg.m6_70 = 0;
1903 cfg.m7_40 = 1;
1904 cfg.m7_95 = 0;
1905 cfg.m10_2 = 0;
1906 cfg.m12_2 = 0;
1907 test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(&cfg);
1908
1909 cfg.m4_75 = 0;
1910 cfg.m5_15 = 0;
1911 cfg.m5_90 = 0;
1912 cfg.m6_70 = 0;
1913 cfg.m7_40 = 0;
1914 cfg.m7_95 = 1;
1915 cfg.m10_2 = 0;
1916 cfg.m12_2 = 0;
1917 test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(&cfg);
1918
1919 cfg.m4_75 = 0;
1920 cfg.m5_15 = 0;
1921 cfg.m5_90 = 0;
1922 cfg.m6_70 = 0;
1923 cfg.m7_40 = 0;
1924 cfg.m7_95 = 0;
1925 cfg.m10_2 = 1;
1926 cfg.m12_2 = 0;
1927 test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(&cfg);
1928
1929 cfg.m4_75 = 0;
1930 cfg.m5_15 = 0;
1931 cfg.m5_90 = 0;
1932 cfg.m6_70 = 0;
1933 cfg.m7_40 = 0;
1934 cfg.m7_95 = 0;
1935 cfg.m10_2 = 0;
1936 cfg.m12_2 = 1;
1937 test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(&cfg);
1938
1939 cfg.m4_75 = 1;
1940 cfg.m5_15 = 1;
1941 cfg.m5_90 = 1;
1942 cfg.m6_70 = 1;
1943 cfg.m7_40 = 0;
1944 cfg.m7_95 = 0;
1945 cfg.m10_2 = 0;
1946 cfg.m12_2 = 0;
1947 test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(&cfg);
1948
1949 cfg.m4_75 = 0;
1950 cfg.m5_15 = 0;
1951 cfg.m5_90 = 0;
1952 cfg.m6_70 = 0;
1953 cfg.m7_40 = 1;
1954 cfg.m7_95 = 1;
1955 cfg.m10_2 = 1;
1956 cfg.m12_2 = 1;
1957 test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(&cfg);
1958
1959 cfg.m4_75 = 0;
1960 cfg.m5_15 = 0;
1961 cfg.m5_90 = 1;
1962 cfg.m6_70 = 1;
1963 cfg.m7_40 = 0;
1964 cfg.m7_95 = 0;
1965 cfg.m10_2 = 1;
1966 cfg.m12_2 = 1;
1967 test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(&cfg);
1968
1969 cfg.m4_75 = 1;
1970 cfg.m5_15 = 1;
1971 cfg.m5_90 = 0;
1972 cfg.m6_70 = 0;
1973 cfg.m7_40 = 1;
1974 cfg.m7_95 = 1;
1975 cfg.m10_2 = 0;
1976 cfg.m12_2 = 0;
1977 test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(&cfg);
1978
1979 cfg.m4_75 = 0;
1980 cfg.m5_15 = 1;
1981 cfg.m5_90 = 0;
1982 cfg.m6_70 = 1;
1983 cfg.m7_40 = 0;
1984 cfg.m7_95 = 1;
1985 cfg.m10_2 = 0;
1986 cfg.m12_2 = 1;
1987 test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(&cfg);
1988
1989 cfg.m4_75 = 1;
1990 cfg.m5_15 = 0;
1991 cfg.m5_90 = 1;
1992 cfg.m6_70 = 0;
1993 cfg.m7_40 = 1;
1994 cfg.m7_95 = 0;
1995 cfg.m10_2 = 1;
1996 cfg.m12_2 = 0;
1997 test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(&cfg);
1998
1999 cfg.m4_75 = 1;
2000 cfg.m5_15 = 1;
2001 cfg.m5_90 = 1;
2002 cfg.m6_70 = 1;
2003 cfg.m7_40 = 1;
2004 cfg.m7_95 = 1;
2005 cfg.m10_2 = 1;
2006 cfg.m12_2 = 1;
2007 test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(&cfg);
Philipp Maier94d79fd2019-03-01 10:40:48 +01002008
2009 cfg.m4_75 = 1;
2010 cfg.m5_15 = 0;
2011 cfg.m5_90 = 1;
2012 cfg.m6_70 = 0;
2013 cfg.m7_40 = 1;
2014 cfg.m7_95 = 0;
2015 cfg.m10_2 = 0;
2016 cfg.m12_2 = 1;
2017 test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(&cfg);
2018
2019 cfg.m4_75 = 1;
2020 cfg.m5_15 = 0;
2021 cfg.m5_90 = 1;
2022 cfg.m6_70 = 0;
2023 cfg.m7_40 = 1;
2024 cfg.m7_95 = 0;
2025 cfg.m10_2 = 0;
2026 cfg.m12_2 = 0;
2027 test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(&cfg);
Pau Espin Pedrol1bd495a2021-02-15 16:15:59 +01002028
Philipp Maier5f2eb152018-09-19 13:40:21 +02002029}
2030
Philipp Maier8515d032018-09-25 15:57:49 +02002031static void test_gsm48_mr_cfg_from_gsm0808_sc_cfg_single(uint16_t s15_s0)
2032{
2033 struct gsm48_multi_rate_conf cfg;
Philipp Maier3713af82019-02-27 16:48:25 +01002034 int rc;
Philipp Maier8515d032018-09-25 15:57:49 +02002035
2036 printf("Input:\n");
2037 printf(" S15-S0 = %04x = 0b" OSMO_BIN_SPEC OSMO_BIN_SPEC "\n", s15_s0,
2038 OSMO_BIN_PRINT(s15_s0 >> 8), OSMO_BIN_PRINT(s15_s0));
2039
Philipp Maier3713af82019-02-27 16:48:25 +01002040 rc = gsm48_mr_cfg_from_gsm0808_sc_cfg(&cfg, s15_s0);
Philipp Maier8515d032018-09-25 15:57:49 +02002041
2042 printf("Output:\n");
2043 printf(" m4_75= %u smod= %u\n", cfg.m4_75, cfg.smod);
2044 printf(" m5_15= %u spare= %u\n", cfg.m5_15, cfg.spare);
2045 printf(" m5_90= %u icmi= %u\n", cfg.m5_90, cfg.icmi);
2046 printf(" m6_70= %u nscb= %u\n", cfg.m6_70, cfg.nscb);
2047 printf(" m7_40= %u ver= %u\n", cfg.m7_40, cfg.ver);
2048 printf(" m7_95= %u\n", cfg.m7_95);
2049 printf(" m10_2= %u\n", cfg.m10_2);
2050 printf(" m12_2= %u\n", cfg.m12_2);
2051
Philipp Maier3713af82019-02-27 16:48:25 +01002052 if (rc != 0)
2053 printf(" Result invalid!\n");
2054
Philipp Maier8515d032018-09-25 15:57:49 +02002055 printf("\n");
2056}
2057
2058void test_gsm48_mr_cfg_from_gsm0808_sc_cfg()
2059{
2060 printf("Testing gsm48_mr_cfg_from_gsm0808_sc_cfg():\n");
2061
Philipp Maier3713af82019-02-27 16:48:25 +01002062 /* Test with settings as defined in 3GPP TS 28.062, Table 7.11.3.1.3-2,
2063 * (up to four codecs may become selected) */
Philipp Maier8515d032018-09-25 15:57:49 +02002064 test_gsm48_mr_cfg_from_gsm0808_sc_cfg_single
2065 (GSM0808_SC_CFG_DEFAULT_AMR_4_75);
2066 test_gsm48_mr_cfg_from_gsm0808_sc_cfg_single
2067 (GSM0808_SC_CFG_DEFAULT_AMR_5_15);
2068 test_gsm48_mr_cfg_from_gsm0808_sc_cfg_single
2069 (GSM0808_SC_CFG_DEFAULT_AMR_5_90);
2070 test_gsm48_mr_cfg_from_gsm0808_sc_cfg_single
2071 (GSM0808_SC_CFG_DEFAULT_AMR_6_70);
2072 test_gsm48_mr_cfg_from_gsm0808_sc_cfg_single
2073 (GSM0808_SC_CFG_DEFAULT_AMR_7_40);
2074 test_gsm48_mr_cfg_from_gsm0808_sc_cfg_single
2075 (GSM0808_SC_CFG_DEFAULT_AMR_7_95);
2076 test_gsm48_mr_cfg_from_gsm0808_sc_cfg_single
2077 (GSM0808_SC_CFG_DEFAULT_AMR_10_2);
2078 test_gsm48_mr_cfg_from_gsm0808_sc_cfg_single
2079 (GSM0808_SC_CFG_DEFAULT_AMR_12_2);
2080
Philipp Maier3713af82019-02-27 16:48:25 +01002081 /* Test with settings as defined in 3GPP TS 28.062, Table 7.11.3.1.3-2,
2082 * but pick only one distinctive setting at a time */
2083 test_gsm48_mr_cfg_from_gsm0808_sc_cfg_single(GSM0808_SC_CFG_AMR_4_75);
Philipp Maier8515d032018-09-25 15:57:49 +02002084 test_gsm48_mr_cfg_from_gsm0808_sc_cfg_single
Philipp Maier3713af82019-02-27 16:48:25 +01002085 (GSM0808_SC_CFG_AMR_4_75_5_90_7_40_12_20);
2086 test_gsm48_mr_cfg_from_gsm0808_sc_cfg_single(GSM0808_SC_CFG_AMR_5_90);
2087 test_gsm48_mr_cfg_from_gsm0808_sc_cfg_single(GSM0808_SC_CFG_AMR_6_70);
2088 test_gsm48_mr_cfg_from_gsm0808_sc_cfg_single(GSM0808_SC_CFG_AMR_7_40);
2089 test_gsm48_mr_cfg_from_gsm0808_sc_cfg_single(GSM0808_SC_CFG_AMR_7_95);
2090 test_gsm48_mr_cfg_from_gsm0808_sc_cfg_single(GSM0808_SC_CFG_AMR_10_2);
2091 test_gsm48_mr_cfg_from_gsm0808_sc_cfg_single(GSM0808_SC_CFG_AMR_12_2);
2092
2093 /* Arbitrary, but valid combinations */
2094 test_gsm48_mr_cfg_from_gsm0808_sc_cfg_single(GSM0808_SC_CFG_AMR_7_40 |
2095 GSM0808_SC_CFG_AMR_6_70 |
2096 GSM0808_SC_CFG_AMR_10_2);
2097 test_gsm48_mr_cfg_from_gsm0808_sc_cfg_single(GSM0808_SC_CFG_AMR_7_95 |
2098 GSM0808_SC_CFG_AMR_4_75);
2099 test_gsm48_mr_cfg_from_gsm0808_sc_cfg_single(GSM0808_SC_CFG_AMR_5_90 |
2100 GSM0808_SC_CFG_AMR_12_2);
Philipp Maier8515d032018-09-25 15:57:49 +02002101 test_gsm48_mr_cfg_from_gsm0808_sc_cfg_single
Philipp Maier3713af82019-02-27 16:48:25 +01002102 (GSM0808_SC_CFG_AMR_4_75_5_90_7_40_12_20 | GSM0808_SC_CFG_AMR_5_90 |
2103 GSM0808_SC_CFG_AMR_12_2);
2104
2105 /* Invalid combinations */
Philipp Maier8515d032018-09-25 15:57:49 +02002106 test_gsm48_mr_cfg_from_gsm0808_sc_cfg_single
Philipp Maier3713af82019-02-27 16:48:25 +01002107 (GSM0808_SC_CFG_AMR_4_75_5_90_7_40_12_20 | GSM0808_SC_CFG_AMR_6_70);
2108 test_gsm48_mr_cfg_from_gsm0808_sc_cfg_single(GSM0808_SC_CFG_AMR_7_40 |
2109 GSM0808_SC_CFG_AMR_6_70 |
2110 GSM0808_SC_CFG_AMR_10_2 |
2111 GSM0808_SC_CFG_AMR_7_95 |
2112 GSM0808_SC_CFG_AMR_4_75);
2113 test_gsm48_mr_cfg_from_gsm0808_sc_cfg_single(0x0000);
2114 test_gsm48_mr_cfg_from_gsm0808_sc_cfg_single(0xffff);
Philipp Maier8515d032018-09-25 15:57:49 +02002115}
2116
Neels Hofmeyrd01ef752018-09-21 15:57:26 +02002117struct test_cell_id_matching_data {
2118 struct gsm0808_cell_id id;
2119 struct gsm0808_cell_id match_id;
2120 bool expect_match;
2121 bool expect_exact_match;
2122};
2123
2124#define lac_23 { .id_discr = CELL_IDENT_LAC, .id.lac = 23, }
2125#define lac_42 { .id_discr = CELL_IDENT_LAC, .id.lac = 42, }
2126#define ci_5 { .id_discr = CELL_IDENT_CI, .id.ci = 5, }
2127#define ci_6 { .id_discr = CELL_IDENT_CI, .id.ci = 6, }
2128#define lac_ci_23_5 { \
2129 .id_discr = CELL_IDENT_LAC_AND_CI, \
2130 .id.lac_and_ci = { .lac = 23, .ci = 5, }, \
2131 }
2132#define lac_ci_42_6 { \
2133 .id_discr = CELL_IDENT_LAC_AND_CI, \
2134 .id.lac_and_ci = { .lac = 42, .ci = 6, }, \
2135 }
2136#define lai_23_042_23 { \
2137 .id_discr = CELL_IDENT_LAI_AND_LAC, \
2138 .id.lai_and_lac = { .plmn = { .mcc = 23, .mnc = 42, .mnc_3_digits = true }, .lac = 23, }, \
2139 }
2140#define lai_23_042_42 { \
2141 .id_discr = CELL_IDENT_LAI_AND_LAC, \
2142 .id.lai_and_lac = { .plmn = { .mcc = 23, .mnc = 42, .mnc_3_digits = true }, .lac = 42, }, \
2143 }
2144#define lai_23_99_23 { \
2145 .id_discr = CELL_IDENT_LAI_AND_LAC, \
2146 .id.lai_and_lac = { .plmn = { .mcc = 23, .mnc = 99, .mnc_3_digits = false }, .lac = 23, }, \
2147 }
2148#define lai_23_42_23 { \
2149 .id_discr = CELL_IDENT_LAI_AND_LAC, \
2150 .id.lai_and_lac = { .plmn = { .mcc = 23, .mnc = 42, .mnc_3_digits = false }, .lac = 23, }, \
2151 }
2152#define cgi_23_042_23_5 { \
2153 .id_discr = CELL_IDENT_WHOLE_GLOBAL, \
2154 .id.global = { \
2155 .lai = { .plmn = { .mcc = 23, .mnc = 42, .mnc_3_digits = true }, .lac = 23, }, \
2156 .cell_identity = 5, \
2157 }, \
2158 }
2159#define cgi_23_042_42_6 { \
2160 .id_discr = CELL_IDENT_WHOLE_GLOBAL, \
2161 .id.global = { \
2162 .lai = { .plmn = { .mcc = 23, .mnc = 42, .mnc_3_digits = true }, .lac = 42, }, \
2163 .cell_identity = 6, \
2164 }, \
2165 }
2166#define cgi_23_99_23_5 { \
2167 .id_discr = CELL_IDENT_WHOLE_GLOBAL, \
2168 .id.global = { \
2169 .lai = { .plmn = { .mcc = 23, .mnc = 99, .mnc_3_digits = false }, .lac = 23, }, \
2170 .cell_identity = 5, \
2171 }, \
2172 }
2173
2174
2175static const struct test_cell_id_matching_data test_cell_id_matching_tests[] = {
2176 { .id = lac_23, .match_id = lac_23, .expect_match = true, .expect_exact_match = true },
2177 { .id = lac_23, .match_id = lac_42, .expect_match = false, .expect_exact_match = false },
2178 { .id = lac_23, .match_id = ci_5, .expect_match = true, .expect_exact_match = false },
2179 { .id = lac_23, .match_id = ci_6, .expect_match = true, .expect_exact_match = false },
2180 { .id = lac_23, .match_id = lac_ci_23_5, .expect_match = true, .expect_exact_match = false },
2181 { .id = lac_23, .match_id = lac_ci_42_6, .expect_match = false, .expect_exact_match = false },
2182 { .id = lac_23, .match_id = lai_23_042_23, .expect_match = true, .expect_exact_match = false },
2183 { .id = lac_23, .match_id = lai_23_042_42, .expect_match = false, .expect_exact_match = false },
2184 { .id = lac_23, .match_id = lai_23_99_23, .expect_match = true, .expect_exact_match = false },
2185 { .id = lac_23, .match_id = lai_23_42_23, .expect_match = true, .expect_exact_match = false },
2186 { .id = lac_23, .match_id = cgi_23_042_23_5, .expect_match = true, .expect_exact_match = false },
2187 { .id = lac_23, .match_id = cgi_23_042_42_6, .expect_match = false, .expect_exact_match = false },
2188 { .id = lac_23, .match_id = cgi_23_99_23_5, .expect_match = true, .expect_exact_match = false },
2189 { .id = ci_5, .match_id = lac_23, .expect_match = true, .expect_exact_match = false },
2190 { .id = ci_5, .match_id = lac_42, .expect_match = true, .expect_exact_match = false },
2191 { .id = ci_5, .match_id = ci_5, .expect_match = true, .expect_exact_match = true },
2192 { .id = ci_5, .match_id = ci_6, .expect_match = false, .expect_exact_match = false },
2193 { .id = ci_5, .match_id = lac_ci_23_5, .expect_match = true, .expect_exact_match = false },
2194 { .id = ci_5, .match_id = lac_ci_42_6, .expect_match = false, .expect_exact_match = false },
2195 { .id = ci_5, .match_id = lai_23_042_23, .expect_match = true, .expect_exact_match = false },
2196 { .id = ci_5, .match_id = lai_23_042_42, .expect_match = true, .expect_exact_match = false },
2197 { .id = ci_5, .match_id = lai_23_99_23, .expect_match = true, .expect_exact_match = false },
2198 { .id = ci_5, .match_id = lai_23_42_23, .expect_match = true, .expect_exact_match = false },
2199 { .id = ci_5, .match_id = cgi_23_042_23_5, .expect_match = true, .expect_exact_match = false },
2200 { .id = ci_5, .match_id = cgi_23_042_42_6, .expect_match = false, .expect_exact_match = false },
2201 { .id = ci_5, .match_id = cgi_23_99_23_5, .expect_match = true, .expect_exact_match = false },
2202 { .id = lac_ci_23_5, .match_id = lac_23, .expect_match = true, .expect_exact_match = false },
2203 { .id = lac_ci_23_5, .match_id = lac_42, .expect_match = false, .expect_exact_match = false },
2204 { .id = lac_ci_23_5, .match_id = ci_5, .expect_match = true, .expect_exact_match = false },
2205 { .id = lac_ci_23_5, .match_id = ci_6, .expect_match = false, .expect_exact_match = false },
2206 { .id = lac_ci_23_5, .match_id = lac_ci_23_5, .expect_match = true, .expect_exact_match = true },
2207 { .id = lac_ci_23_5, .match_id = lac_ci_42_6, .expect_match = false, .expect_exact_match = false },
2208 { .id = lac_ci_23_5, .match_id = lai_23_042_23, .expect_match = true, .expect_exact_match = false },
2209 { .id = lac_ci_23_5, .match_id = lai_23_042_42, .expect_match = false, .expect_exact_match = false },
2210 { .id = lac_ci_23_5, .match_id = lai_23_99_23, .expect_match = true, .expect_exact_match = false },
2211 { .id = lac_ci_23_5, .match_id = lai_23_42_23, .expect_match = true, .expect_exact_match = false },
2212 { .id = lac_ci_23_5, .match_id = cgi_23_042_23_5, .expect_match = true, .expect_exact_match = false },
2213 { .id = lac_ci_23_5, .match_id = cgi_23_042_42_6, .expect_match = false, .expect_exact_match = false },
2214 { .id = lac_ci_23_5, .match_id = cgi_23_99_23_5, .expect_match = true, .expect_exact_match = false },
2215 { .id = lai_23_042_23, .match_id = lac_23, .expect_match = true, .expect_exact_match = false },
2216 { .id = lai_23_042_23, .match_id = lac_42, .expect_match = false, .expect_exact_match = false },
2217 { .id = lai_23_042_23, .match_id = ci_5, .expect_match = true, .expect_exact_match = false },
2218 { .id = lai_23_042_23, .match_id = ci_6, .expect_match = true, .expect_exact_match = false },
2219 { .id = lai_23_042_23, .match_id = lac_ci_23_5, .expect_match = true, .expect_exact_match = false },
2220 { .id = lai_23_042_23, .match_id = lac_ci_42_6, .expect_match = false, .expect_exact_match = false },
2221 { .id = lai_23_042_23, .match_id = lai_23_042_23, .expect_match = true, .expect_exact_match = true },
2222 { .id = lai_23_042_23, .match_id = lai_23_042_42, .expect_match = false, .expect_exact_match = false },
2223 { .id = lai_23_042_23, .match_id = lai_23_99_23, .expect_match = false, .expect_exact_match = false },
2224 { .id = lai_23_042_23, .match_id = lai_23_42_23, .expect_match = false, .expect_exact_match = false },
2225 { .id = lai_23_042_23, .match_id = cgi_23_042_23_5, .expect_match = true, .expect_exact_match = false },
2226 { .id = lai_23_042_23, .match_id = cgi_23_042_42_6, .expect_match = false, .expect_exact_match = false },
2227 { .id = lai_23_042_23, .match_id = cgi_23_99_23_5, .expect_match = false, .expect_exact_match = false },
2228 { .id = cgi_23_042_23_5, .match_id = lac_23, .expect_match = true, .expect_exact_match = false },
2229 { .id = cgi_23_042_23_5, .match_id = lac_42, .expect_match = false, .expect_exact_match = false },
2230 { .id = cgi_23_042_23_5, .match_id = ci_5, .expect_match = true, .expect_exact_match = false },
2231 { .id = cgi_23_042_23_5, .match_id = ci_6, .expect_match = false, .expect_exact_match = false },
2232 { .id = cgi_23_042_23_5, .match_id = lac_ci_23_5, .expect_match = true, .expect_exact_match = false },
2233 { .id = cgi_23_042_23_5, .match_id = lac_ci_42_6, .expect_match = false, .expect_exact_match = false },
2234 { .id = cgi_23_042_23_5, .match_id = lai_23_042_23, .expect_match = true, .expect_exact_match = false },
2235 { .id = cgi_23_042_23_5, .match_id = lai_23_042_42, .expect_match = false, .expect_exact_match = false },
2236 { .id = cgi_23_042_23_5, .match_id = lai_23_99_23, .expect_match = false, .expect_exact_match = false },
2237 { .id = cgi_23_042_23_5, .match_id = lai_23_42_23, .expect_match = false, .expect_exact_match = false },
2238 { .id = cgi_23_042_23_5, .match_id = cgi_23_042_23_5, .expect_match = true, .expect_exact_match = true },
2239 { .id = cgi_23_042_23_5, .match_id = cgi_23_042_42_6, .expect_match = false, .expect_exact_match = false },
2240 { .id = cgi_23_042_23_5, .match_id = cgi_23_99_23_5, .expect_match = false, .expect_exact_match = false },
2241};
2242
2243static void test_cell_id_matching()
2244{
2245 int i;
2246 bool ok = true;
2247 printf("\n%s\n", __func__);
2248
2249 for (i = 0; i < ARRAY_SIZE(test_cell_id_matching_tests); i++) {
2250 const struct test_cell_id_matching_data *d = &test_cell_id_matching_tests[i];
2251 int exact_match;
2252
2253 for (exact_match = 0; exact_match < 2; exact_match++) {
2254 bool result;
2255 bool expect_result = exact_match ? d->expect_exact_match : d->expect_match;
2256
2257 result = gsm0808_cell_ids_match(&d->id, &d->match_id, (bool)exact_match);
2258
2259 printf("[%d] %s %s %s%s\n",
2260 i,
2261 gsm0808_cell_id_name(&d->id),
2262 gsm0808_cell_id_name2(&d->match_id),
2263 result ? "MATCH" : "don't match",
2264 exact_match ? " exactly" : "");
2265 if (result != expect_result) {
2266 printf(" ERROR: expected %s\n", d->expect_match ? "MATCH" : "no match");
2267 ok = false;
2268 }
2269 }
2270 }
2271
2272 OSMO_ASSERT(ok);
2273}
2274
2275static bool test_cell_id_list_matching_discrs(bool test_match,
2276 enum CELL_IDENT id_discr,
2277 enum CELL_IDENT list_discr)
2278{
2279 int i, j;
2280 const struct gsm0808_cell_id *id = NULL;
2281 struct gsm0808_cell_id_list2 list = {};
2282 int match_idx = -1;
2283 int result;
2284
2285 for (i = 0; i < ARRAY_SIZE(test_cell_id_matching_tests); i++) {
2286 const struct test_cell_id_matching_data *d = &test_cell_id_matching_tests[i];
2287 if (id_discr != d->id.id_discr)
2288 continue;
2289 id = &d->id;
2290 break;
2291 }
2292
2293 if (!id) {
2294 printf("Did not find any entry for %s\n", gsm0808_cell_id_discr_name(id_discr));
2295 return true;
2296 }
2297
2298 /* Collect those entries with exactly this id on the left, of type list_discr on the right.
2299 * Collect the mismatches first, for more interesting match indexes in the results. */
2300 for (j = 0; j < 2; j++) {
2301 bool collect_matches = (bool)j;
2302
2303 /* If we want to have a mismatching list, don't add any entries that match. */
2304 if (!test_match && collect_matches)
2305 continue;
2306
2307 for (i = 0; i < ARRAY_SIZE(test_cell_id_matching_tests); i++) {
2308 const struct test_cell_id_matching_data *d = &test_cell_id_matching_tests[i];
2309 struct gsm0808_cell_id_list2 add;
2310
2311 /* Ignore those with a different d->id */
2312 if (!gsm0808_cell_ids_match(&d->id, id, true))
2313 continue;
2314
2315 /* Ignore those with a different d->match_id discr */
2316 if (d->match_id.id_discr != list_discr)
2317 continue;
2318
2319 if (collect_matches != d->expect_match)
2320 continue;
2321
2322 if (match_idx < 0 && d->expect_match) {
2323 match_idx = list.id_list_len;
2324 }
2325
2326 gsm0808_cell_id_to_list(&add, &d->match_id);
2327 gsm0808_cell_id_list_add(&list, &add);
2328 }
2329 }
2330
2331 if (!list.id_list_len) {
2332 printf("%s vs. %s: No match_id entries to test %s\n",
2333 gsm0808_cell_id_name(id),
2334 gsm0808_cell_id_discr_name(list_discr),
2335 test_match ? "MATCH" : "mismatch");
2336 return true;
2337 }
2338
2339 result = gsm0808_cell_id_matches_list(id, &list, 0, false);
2340
2341 printf("%s and %s: ",
2342 gsm0808_cell_id_name(id),
2343 gsm0808_cell_id_list_name(&list));
2344 if (result >= 0)
2345 printf("MATCH at [%d]\n", result);
2346 else
2347 printf("mismatch\n");
2348
2349 if (test_match
2350 && (result < 0 || result != match_idx)) {
2351 printf(" ERROR: expected MATCH at %d\n", match_idx);
2352 return false;
2353 }
2354
2355 if (!test_match && result >= 0) {
2356 printf(" ERROR: expected mismatch\n");
2357 return false;
2358 }
2359
2360 return true;
2361}
2362
Neels Hofmeyr3a504532019-02-10 22:28:27 +01002363const enum CELL_IDENT cell_ident_discrs[] = {
2364 CELL_IDENT_LAC, CELL_IDENT_CI, CELL_IDENT_LAC_AND_CI, CELL_IDENT_LAI_AND_LAC,
2365 CELL_IDENT_WHOLE_GLOBAL,
2366};
2367
2368
Neels Hofmeyrd01ef752018-09-21 15:57:26 +02002369static void test_cell_id_list_matching(bool test_match)
2370{
2371 int i, j;
2372 bool ok = true;
2373
Neels Hofmeyrd01ef752018-09-21 15:57:26 +02002374 printf("\n%s(%s)\n", __func__, test_match ? "test match" : "test mismatch");
2375
2376 /* Autogenerate Cell ID lists from above dataset, which should match / not match. */
Neels Hofmeyr3a504532019-02-10 22:28:27 +01002377 for (i = 0; i < ARRAY_SIZE(cell_ident_discrs); i++) {
2378 for (j = 0; j < ARRAY_SIZE(cell_ident_discrs); j++)
Neels Hofmeyrd01ef752018-09-21 15:57:26 +02002379 if (!test_cell_id_list_matching_discrs(test_match,
Neels Hofmeyr3a504532019-02-10 22:28:27 +01002380 cell_ident_discrs[i], cell_ident_discrs[j]))
Neels Hofmeyrd01ef752018-09-21 15:57:26 +02002381 ok = false;
2382 }
2383
2384 OSMO_ASSERT(ok);
2385}
2386
Neels Hofmeyr3a504532019-02-10 22:28:27 +01002387
2388static const struct gsm0808_cell_id test_gsm0808_cell_id_to_from_cgi_data[] = {
2389 lac_23,
2390 lac_42,
2391 ci_5,
2392 ci_6,
2393 lac_ci_23_5,
2394 lac_ci_42_6,
2395 lai_23_042_23,
2396 lai_23_042_42,
2397 lai_23_99_23,
2398 lai_23_42_23,
2399 cgi_23_042_23_5,
2400 cgi_23_042_42_6,
2401 cgi_23_99_23_5,
2402 { .id_discr = CELL_IDENT_NO_CELL },
2403 { .id_discr = 423 },
2404};
2405
2406static void test_gsm0808_cell_id_to_from_cgi()
2407{
2408 int i;
2409 int j;
2410
2411 printf("\n%s()\n", __func__);
2412
2413 for (i = 0; i < ARRAY_SIZE(test_gsm0808_cell_id_to_from_cgi_data); i++) {
2414 const struct gsm0808_cell_id *from_cid = &test_gsm0808_cell_id_to_from_cgi_data[i];
2415 struct osmo_cell_global_id cgi = {
2416 .lai = {
2417 .plmn = {
2418 .mcc = 777,
2419 .mnc = 7,
2420 .mnc_3_digits = true,
2421 },
2422 .lac = 7777,
2423 },
2424 .cell_identity = 7777,
2425 };
2426 struct gsm0808_cell_id cid = {};
2427 int rc;
2428
2429 rc = gsm0808_cell_id_to_cgi(&cgi, from_cid);
2430 printf("cid %s -> cgi %s", gsm0808_cell_id_name(from_cid), osmo_cgi_name(&cgi));
2431
2432 if (rc & OSMO_CGI_PART_PLMN)
2433 printf(" PLMN");
2434 if (rc & OSMO_CGI_PART_LAC)
2435 printf(" LAC");
2436 if (rc & OSMO_CGI_PART_CI)
2437 printf(" CI");
2438
2439 gsm0808_cell_id_from_cgi(&cid, from_cid->id_discr, &cgi);
2440 printf(" -> cid %s\n", gsm0808_cell_id_name(&cid));
2441 if (!gsm0808_cell_ids_match(from_cid, &cid, true))
2442 printf(" MISMATCH!\n");
2443
2444 for (j = 0; j < ARRAY_SIZE(cell_ident_discrs); j++) {
2445 enum CELL_IDENT discr = cell_ident_discrs[j];
2446
2447 gsm0808_cell_id_from_cgi(&cid, discr, &cgi);
2448 printf(" --> gsm0808_cell_id{%s} = %s\n", gsm0808_cell_id_discr_name(discr), gsm0808_cell_id_name(&cid));
2449 }
2450 }
2451}
2452
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +01002453int main(int argc, char **argv)
2454{
Max969fb2e2018-12-10 11:01:10 +01002455 void *ctx = talloc_named_const(NULL, 0, "gsm0808 test");
2456 msgb_talloc_ctx_init(ctx, 0);
2457 osmo_init_logging2(ctx, NULL);
2458
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +01002459 printf("Testing generation of GSM0808 messages\n");
Philipp Maier4f4905f2018-11-30 13:36:12 +01002460 test_gsm0808_enc_cause();
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +01002461 test_create_layer3();
Philipp Maierfa896ab2017-03-27 16:55:32 +02002462 test_create_layer3_aoip();
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +01002463 test_create_reset();
Philipp Maier15596e22017-04-05 17:55:27 +02002464 test_create_reset_ack();
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +01002465 test_create_clear_command();
Harald Weltecf665fc2019-02-18 13:45:36 +01002466 test_create_clear_command2();
2467 test_create_clear_command2_csfb();
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +01002468 test_create_clear_complete();
Philipp Maierb478dd32017-03-29 15:50:05 +02002469 test_create_cipher();
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +01002470 test_create_cipher_complete();
2471 test_create_cipher_reject();
Maxed651d22018-11-07 15:25:05 +01002472 test_create_cipher_reject_ext();
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +01002473 test_create_cm_u();
2474 test_create_sapi_reject();
Philipp Maierc6144a22017-03-29 17:53:43 +02002475 test_create_ass();
Max52074322018-11-30 10:44:07 +01002476 test_create_ass2();
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +01002477 test_create_ass_compl();
Philipp Maierfa896ab2017-03-27 16:55:32 +02002478 test_create_ass_compl_aoip();
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +01002479 test_create_ass_fail();
Philipp Maierfa896ab2017-03-27 16:55:32 +02002480 test_create_ass_fail_aoip();
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +01002481 test_create_clear_rqst();
Philipp Maier3d48ec02017-03-29 17:37:55 +02002482 test_create_paging();
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +01002483 test_create_dtap();
2484 test_prepend_dtap();
Max969fb2e2018-12-10 11:01:10 +01002485
Max47022152018-12-19 18:51:00 +01002486 test_enc_dec_lcls();
Max969fb2e2018-12-10 11:01:10 +01002487
Philipp Maier22401432017-03-24 17:59:26 +01002488 test_enc_dec_aoip_trasp_addr_v4();
2489 test_enc_dec_aoip_trasp_addr_v6();
Philipp Maier6f725d62017-03-24 18:03:17 +01002490 test_gsm0808_enc_dec_speech_codec();
Philipp Maier6f725d62017-03-24 18:03:17 +01002491 test_gsm0808_enc_dec_speech_codec_ext_with_cfg();
Philipp Maierbb839662017-06-01 17:11:19 +02002492 test_gsm0808_enc_dec_speech_codec_with_cfg();
Philipp Maier6f725d62017-03-24 18:03:17 +01002493 test_gsm0808_enc_dec_speech_codec_list();
Philipp Maierf6c369f2018-10-16 15:24:47 +02002494 test_gsm0808_enc_dec_empty_speech_codec_list();
Philipp Maiere0c65302017-03-28 17:05:40 +02002495 test_gsm0808_enc_dec_channel_type();
Philipp Maier14e76b92017-03-28 18:36:52 +02002496 test_gsm0808_enc_dec_encrypt_info();
Neels Hofmeyr250e7f72018-04-13 03:30:14 +02002497
Philipp Maier783047e2017-03-29 11:35:50 +02002498 test_gsm0808_enc_dec_cell_id_list_lac();
2499 test_gsm0808_enc_dec_cell_id_list_single_lac();
Stefan Sperlinge1a86742018-03-15 18:05:02 +01002500 test_gsm0808_enc_dec_cell_id_list_multi_lac();
Philipp Maier783047e2017-03-29 11:35:50 +02002501 test_gsm0808_enc_dec_cell_id_list_bss();
Stefan Sperling23381452018-03-15 19:38:15 +01002502 test_gsm0808_enc_dec_cell_id_list_multi_lai_and_lac();
Stefan Sperling9c62fc62018-03-16 10:23:34 +01002503 test_gsm0808_enc_dec_cell_id_list_multi_ci();
Stefan Sperlinged4327c2018-03-16 11:02:59 +01002504 test_gsm0808_enc_dec_cell_id_list_multi_lac_and_ci();
Stefan Sperling483f3862018-03-16 12:21:26 +01002505 test_gsm0808_enc_dec_cell_id_list_multi_global();
Harald Weltea87526d2022-02-15 20:06:16 +01002506 test_gsm0808_dec_cell_id_list_srvcc();
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +01002507
Neels Hofmeyr74663d92018-03-23 01:46:42 +01002508 test_cell_id_list_add();
2509
Neels Hofmeyr250e7f72018-04-13 03:30:14 +02002510 test_gsm0808_enc_dec_cell_id_lac();
2511 test_gsm0808_enc_dec_cell_id_bss();
2512 test_gsm0808_enc_dec_cell_id_no_cell();
2513 test_gsm0808_enc_dec_cell_id_lai_and_lac();
2514 test_gsm0808_enc_dec_cell_id_ci();
2515 test_gsm0808_enc_dec_cell_id_lac_and_ci();
2516 test_gsm0808_enc_dec_cell_id_global();
Pau Espin Pedrol52489852021-02-15 16:26:37 +01002517 test_gsm0808_enc_dec_cell_id_global_ps();
Philipp Maier5f2eb152018-09-19 13:40:21 +02002518 test_gsm0808_sc_cfg_from_gsm48_mr_cfg();
Philipp Maier8515d032018-09-25 15:57:49 +02002519 test_gsm48_mr_cfg_from_gsm0808_sc_cfg();
Philipp Maier5f2eb152018-09-19 13:40:21 +02002520
Neels Hofmeyrd01ef752018-09-21 15:57:26 +02002521 test_cell_id_matching();
2522 test_cell_id_list_matching(true);
2523 test_cell_id_list_matching(false);
2524
Neels Hofmeyr3a504532019-02-10 22:28:27 +01002525 test_gsm0808_cell_id_to_from_cgi();
2526
Alexander Chemeris22630e62020-05-13 00:44:04 +03002527 test_dec_confusion();
2528
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +01002529 printf("Done\n");
2530 return EXIT_SUCCESS;
2531}