blob: ed99245cd1d88e9a61a50d5791b3b82138624899 [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
Harald Weltee61d4592022-11-03 11:05:58 +0100114static void test_create_layer3_aoip(void)
Philipp Maierfa896ab2017-03-27 16:55:32 +0200115{
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
Harald Weltee61d4592022-11-03 11:05:58 +0100151static void test_create_reset(void)
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +0100152{
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
Harald Weltee61d4592022-11-03 11:05:58 +0100162static void test_create_reset_ack(void)
Philipp Maier15596e22017-04-05 17:55:27 +0200163{
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
Harald Weltee61d4592022-11-03 11:05:58 +0100174static void test_create_clear_command(void)
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +0100175{
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 Weltee61d4592022-11-03 11:05:58 +0100185static void test_create_clear_command2(void)
Harald Weltecf665fc2019-02-18 13:45:36 +0100186{
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
Harald Weltee61d4592022-11-03 11:05:58 +0100196static void test_create_clear_command2_csfb(void)
Harald Weltecf665fc2019-02-18 13:45:36 +0100197{
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
Harald Weltee61d4592022-11-03 11:05:58 +0100207static void test_create_clear_complete(void)
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +0100208{
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
Harald Weltee61d4592022-11-03 11:05:58 +0100218static void test_create_cipher(void)
Philipp Maierb478dd32017-03-29 15:50:05 +0200219{
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
Harald Weltee61d4592022-11-03 11:05:58 +0100258static void test_create_cipher_complete(void)
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +0100259{
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
Harald Weltee61d4592022-11-03 11:05:58 +0100315static void test_create_cipher_reject(void)
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +0100316{
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
Harald Weltee61d4592022-11-03 11:05:58 +0100330static void test_create_cipher_reject_ext(void)
Maxed651d22018-11-07 15:25:05 +0100331{
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
Harald Weltee61d4592022-11-03 11:05:58 +0100345static void test_create_cm_u(void)
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +0100346{
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
Harald Weltee61d4592022-11-03 11:05:58 +0100367static void test_create_sapi_reject(void)
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +0100368{
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
Harald Weltee61d4592022-11-03 11:05:58 +0100378static void test_dec_confusion(void)
Alexander Chemeris22630e62020-05-13 00:44:04 +0300379{
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
Pau Espin Pedrola3987fc2022-03-18 13:17:28 +0100427/* Test Perform Location Report SYS#5891 */
Harald Weltee61d4592022-11-03 11:05:58 +0100428static void test_dec_perform_location_report_sys5891(void)
Pau Espin Pedrola3987fc2022-03-18 13:17:28 +0100429{
430/* Message Type Perform Location Request
431 Location Type
432 Element ID: 0x44
433 Length: 1
434 Location Information: current geographic location (0x00)
435 Cell Identifier/CI (25911)
436 Element ID: 0x05
437 Length: 8
438 0000 .... = Spare bit(s): 0x00
439 .... 0000 = Cell identification discriminator: The whole Cell Global Identification, CGI, is used to identify the cells. (0)
440 Mobile Country Code (MCC): (removed))
441 Mobile Network Code (MNC): (removed))
442 Cell LAC: 0x001e (30)
443 Cell CI: 0x6537 (25911)
444 LCS Client Type
445 Element ID: 0x48
446 Length: 1
447 0011 .... = Client Category: Emergency Services (0x03)
448 .... 0000 = Client Subtype: unspecified (0x00)
449 LCS Priority
450 Element ID: 0x43
451 Length: 1
452 Periodicity: highest (0)
453 LCS QoS
454 Element ID: 0x3e
455 Length: 4
456 0000 00.. = Spare: 0x00
457 .... ..0. = Velocity Requested: do not report velocity (0x00)
458 .... ...0 = Vertical Coordinate Indicator: vertical coordinate not requested (0x00)
459 1... .... = Horizontal Accuracy Indicator: horizontal accuracy is specified (0x01)
460 .001 0010 = Horizontal Accuracy: 0x12
461 0... .... = Vertical Accuracy Indicator: vertical accuracy is not specified (0x00)
462 .000 0000 = Spare: 0x00
463 00.. .... = Response Time Category: Response Time is not specified (0x00)
464*/
465 const uint8_t hex[] = {
466 0x2b, 0x44, 0x01, 0x00, 0x05, 0x08, 0x00, 0xab, 0xbc, 0xcd, 0x00, 0x1e,
467 0x65, 0x37, 0x48, 0x01, 0x30, 0x43, 0x01, 0x00, 0x3e, 0x04, 0x00, 0x92,
468 0x00, 0x00
469 };
470
471 struct tlv_parsed tp;
472 int rc;
473
474 printf("Testing decoding Perform Location Report SYS#5891\n");
475
476 rc = tlv_parse(&tp, gsm0808_att_tlvdef(), hex+1, sizeof(hex)-1, 0, 0);
Pau Espin Pedrolfffd7c32022-03-18 13:45:42 +0100477 OSMO_ASSERT(rc == 5);
Pau Espin Pedrola3987fc2022-03-18 13:17:28 +0100478}
479
Harald Weltee61d4592022-11-03 11:05:58 +0100480static void test_create_ass(void)
Philipp Maierc6144a22017-03-29 17:53:43 +0200481{
482 static const uint8_t res1[] =
483 { 0x00, 0x0a, 0x01, 0x0b, 0x04, 0x01, 0x0b, 0xa1, 0x25, 0x01, 0x00,
484 0x04 };
485 static const uint8_t res2[] =
486 { 0x00, 0x20, 0x01, 0x0b, 0x04, 0x01, 0x0b, 0xa1, 0x25, 0x01, 0x00,
487 0x04, GSM0808_IE_AOIP_TRASP_ADDR, 0x06, 0xc0, 0xa8, 0x64, 0x17,
Philipp Maierbb839662017-06-01 17:11:19 +0200488 0x04, 0xd2, GSM0808_IE_SPEECH_CODEC_LIST, 0x07,
Philipp Maier7e27b142018-03-22 17:26:46 +0100489 GSM0808_SCT_FR3 | 0x50, 0xef, 0xcd, GSM0808_SCT_FR2 | 0xa0, 0x9f,
Philipp Maier2908dbf2020-06-05 14:16:11 +0200490 GSM0808_SCT_CSD | 0x90, 0xc0, GSM0808_IE_CALL_ID, 0xdd, 0xcc,
491 0xbb, 0xaa };
Philipp Maierc6144a22017-03-29 17:53:43 +0200492
493 struct msgb *msg;
494 struct gsm0808_channel_type ct;
495 uint16_t cic = 0004;
496 struct sockaddr_storage ss;
497 struct sockaddr_in sin;
498 struct gsm0808_speech_codec_list sc_list;
499 uint32_t call_id = 0xAABBCCDD;
500
501 memset(&ct, 0, sizeof(ct));
502 ct.ch_indctr = GSM0808_CHAN_SPEECH;
503 ct.ch_rate_type = GSM0808_SPEECH_HALF_PREF;
504 ct.perm_spch[0] = GSM0808_PERM_FR3;
505 ct.perm_spch[1] = GSM0808_PERM_HR3;
506 ct.perm_spch_len = 2;
507
508 memset(&sin, 0, sizeof(sin));
509 sin.sin_family = AF_INET;
510 sin.sin_port = htons(1234);
511 inet_aton("192.168.100.23", &sin.sin_addr);
512
513 memset(&ss, 0, sizeof(ss));
514 memcpy(&ss, &sin, sizeof(sin));
515
516 setup_codec_list(&sc_list);
517
518 printf("Testing creating Assignment Request\n");
519 msg = gsm0808_create_ass(&ct, &cic, NULL, NULL, NULL);
520 OSMO_ASSERT(msg);
521 VERIFY(msg, res1, ARRAY_SIZE(res1));
522 msgb_free(msg);
523
524 msg = gsm0808_create_ass(&ct, &cic, &ss, &sc_list, &call_id);
525 OSMO_ASSERT(msg);
526 VERIFY(msg, res2, ARRAY_SIZE(res2));
527 msgb_free(msg);
528}
529
Harald Weltee61d4592022-11-03 11:05:58 +0100530static void test_create_ass2(void)
Max52074322018-11-30 10:44:07 +0100531{
532 static const uint8_t res[] = {
533 BSSAP_MSG_BSS_MANAGEMENT,
534 0x45,
535 BSS_MAP_MSG_ASSIGMENT_RQST,
536 GSM0808_IE_CHANNEL_TYPE,
537 0x04, 0x01, 0x0b, 0x91, 0x15, 0x01, 0x00, 0x04,
538 GSM0808_IE_AOIP_TRASP_ADDR,
539 0x06,
540 0xac, 0x0c, 0x65, 0x0d, /* IPv4 */
541 0x02, 0x9a,
542 GSM0808_IE_SPEECH_CODEC_LIST,
543 0x07,
544 GSM0808_SCT_FR3 | 0x50,
545 0xef, 0xcd,
546 GSM0808_SCT_FR2 | 0xa0,
547 0x9f,
548 GSM0808_SCT_CSD | 0x90,
549 0xc0,
550 GSM0808_IE_CALL_ID,
Pau Espin Pedrol1bd495a2021-02-15 16:15:59 +0100551 0xce, 0xfa, 0xad, 0xde, /* CallID */
Max52074322018-11-30 10:44:07 +0100552 0x83, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, /* Kc */
553 GSM0808_IE_GLOBAL_CALL_REF, 0x0d, /* GCR, length */
554 0x03, 0x44, 0x44, 0x44, /* GCR, Net ID */
555 0x02, 0xfe, 0xed, /* GCR, Node ID */
556 0x05, 0x41, 0x41, 0x41, 0x41, 0x41, /* GCR, Call ref. ID */
557 GSM0808_IE_LCLS_CONFIG, GSM0808_LCLS_CFG_BOTH_WAY,
558 GSM0808_IE_LCLS_CONN_STATUS_CTRL, GSM0808_LCLS_CSC_CONNECT,
559 GSM0808_IE_LCLS_CORR_NOT_NEEDED,
560 };
561 struct msgb *msg;
562 struct gsm0808_channel_type ct;
563 uint16_t cic = 4;
564 struct sockaddr_storage ss;
565 struct sockaddr_in sin;
566 struct gsm0808_speech_codec_list sc_list;
567 uint32_t call_id = 0xDEADFACE;
Max52074322018-11-30 10:44:07 +0100568 uint8_t Kc[16];
569 struct osmo_lcls lcls = {
570 .config = GSM0808_LCLS_CFG_BOTH_WAY,
571 .control = GSM0808_LCLS_CSC_CONNECT,
Max3b901252019-01-15 14:15:11 +0100572 .gcr = { .net_len = 3, .node = 0xFEED },
573 .gcr_available = true,
Max52074322018-11-30 10:44:07 +0100574 .corr_needed = false
575 };
576
Max3b901252019-01-15 14:15:11 +0100577 memset(lcls.gcr.cr, 'A', 5);
578 memset(lcls.gcr.net, 'D', lcls.gcr.net_len);
Max52074322018-11-30 10:44:07 +0100579 memset(Kc, 'E', 16);
580
581 memset(&ct, 0, sizeof(ct));
582 ct.ch_indctr = GSM0808_CHAN_SPEECH;
583 ct.ch_rate_type = GSM0808_SPEECH_HALF_PREF;
584 ct.perm_spch[0] = GSM0808_PERM_FR2;
585 ct.perm_spch[1] = GSM0808_PERM_HR2;
586 ct.perm_spch_len = 2;
587
588 memset(&sin, 0, sizeof(sin));
589 sin.sin_family = AF_INET;
590 sin.sin_port = htons(666);
591 inet_aton("172.12.101.13", &sin.sin_addr); /* IPv4 */
592
593 memset(&ss, 0, sizeof(ss));
594 memcpy(&ss, &sin, sizeof(sin));
595
596 setup_codec_list(&sc_list);
597
598 printf("Testing creating Assignment Request with Kc and LCLS\n");
599
600 msg = gsm0808_create_ass2(&ct, &cic, &ss, &sc_list, &call_id, Kc, &lcls);
601 if (!msgb_eq_l3_data_print(msg, res, ARRAY_SIZE(res)))
602 abort();
603
604 msgb_free(msg);
605}
606
Harald Weltee61d4592022-11-03 11:05:58 +0100607static void test_create_ass_compl(void)
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +0100608{
609 static const uint8_t res1[] = {
610 0x00, 0x09, 0x02, 0x15, 0x23, 0x21, 0x42, 0x2c,
611 0x11, 0x40, 0x22 };
612 static const uint8_t res2[] = {
613 0x00, 0x07, 0x02, 0x15, 0x23, 0x21, 0x42, 0x2c, 0x11};
614 struct msgb *msg;
615
616 printf("Testing creating Assignment Complete\n");
617 msg = gsm0808_create_assignment_completed(0x23, 0x42, 0x11, 0x22);
618 VERIFY(msg, res1, ARRAY_SIZE(res1));
619 msgb_free(msg);
620
621 msg = gsm0808_create_assignment_completed(0x23, 0x42, 0x11, 0);
622 VERIFY(msg, res2, ARRAY_SIZE(res2));
623 msgb_free(msg);
624}
625
Harald Weltee61d4592022-11-03 11:05:58 +0100626static void test_create_ass_compl_aoip(void)
Philipp Maierfa896ab2017-03-27 16:55:32 +0200627{
628 struct sockaddr_storage ss;
629 struct sockaddr_in sin;
630 struct gsm0808_speech_codec sc;
631 struct gsm0808_speech_codec_list sc_list;
632 static const uint8_t res[] =
Max414c8f52019-01-08 14:44:24 +0100633 { 0x00, 0x1f, 0x02, 0x15, 0x23, 0x21, 0x42, 0x2c, 0x11, 0x40, 0x22,
Philipp Maierfa896ab2017-03-27 16:55:32 +0200634 GSM0808_IE_AOIP_TRASP_ADDR, 0x06, 0xc0, 0xa8, 0x64, 0x17, 0x04,
Philipp Maierbb839662017-06-01 17:11:19 +0200635 0xd2, GSM0808_IE_SPEECH_CODEC, 0x01, GSM0808_SCT_HR1 | 0x90,
Philipp Maier7e27b142018-03-22 17:26:46 +0100636 GSM0808_IE_SPEECH_CODEC_LIST, 0x07, GSM0808_SCT_FR3 | 0x50, 0xef,
Max414c8f52019-01-08 14:44:24 +0100637 0xcd, GSM0808_SCT_FR2 | 0xa0, 0x9f, GSM0808_SCT_CSD | 0x90, 0xc0,
638 GSM0808_IE_LCLS_BSS_STATUS, GSM0808_LCLS_STS_LOCALLY_SWITCHED };
Philipp Maierfa896ab2017-03-27 16:55:32 +0200639 struct msgb *msg;
640
641 memset(&sin, 0, sizeof(sin));
642 sin.sin_family = AF_INET;
643 sin.sin_port = htons(1234);
644 inet_aton("192.168.100.23", &sin.sin_addr);
645
646 memset(&ss, 0, sizeof(ss));
647 memcpy(&ss, &sin, sizeof(sin));
648
649 memset(&sc, 0, sizeof(sc));
650 sc.fi = true;
651 sc.tf = true;
Philipp Maierbb839662017-06-01 17:11:19 +0200652 sc.type = GSM0808_SCT_HR1;
Philipp Maierfa896ab2017-03-27 16:55:32 +0200653
654 setup_codec_list(&sc_list);
655
656 printf("Testing creating Assignment Complete (AoIP)\n");
Max414c8f52019-01-08 14:44:24 +0100657 msg = gsm0808_create_ass_compl2(0x23, 0x42, 0x11, 0x22,
658 &ss, &sc, &sc_list, GSM0808_LCLS_STS_LOCALLY_SWITCHED);
Philipp Maierfa896ab2017-03-27 16:55:32 +0200659 VERIFY(msg, res, ARRAY_SIZE(res));
660 msgb_free(msg);
661}
662
Harald Weltee61d4592022-11-03 11:05:58 +0100663static void test_create_ass_fail(void)
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +0100664{
665 static const uint8_t res1[] = { 0x00, 0x04, 0x03, 0x04, 0x01, 0x23 };
666 static const uint8_t res2[] = {
667 0x00, 0x06, 0x03, 0x04, 0x01, 0x23, 0x15, 0x02};
668 uint8_t rr_res = 2;
669 struct msgb *msg;
670
671 printf("Testing creating Assignment Failure\n");
672 msg = gsm0808_create_assignment_failure(0x23, NULL);
673 VERIFY(msg, res1, ARRAY_SIZE(res1));
674 msgb_free(msg);
675
676 msg = gsm0808_create_assignment_failure(0x23, &rr_res);
677 VERIFY(msg, res2, ARRAY_SIZE(res2));
678 msgb_free(msg);
679}
680
Harald Weltee61d4592022-11-03 11:05:58 +0100681static void test_create_ass_fail_aoip(void)
Philipp Maierfa896ab2017-03-27 16:55:32 +0200682{
683 static const uint8_t res1[] =
684 { 0x00, 0x0d, 0x03, 0x04, 0x01, 0x23, GSM0808_IE_SPEECH_CODEC_LIST,
Philipp Maier7e27b142018-03-22 17:26:46 +0100685 0x07, GSM0808_SCT_FR3 | 0x50, 0xef, 0xcd, GSM0808_SCT_FR2 | 0xa0,
Philipp Maierbb839662017-06-01 17:11:19 +0200686 0x9f, GSM0808_SCT_CSD | 0x90, 0xc0 };
Philipp Maierfa896ab2017-03-27 16:55:32 +0200687 static const uint8_t res2[] =
688 { 0x00, 0x0f, 0x03, 0x04, 0x01, 0x23, 0x15, 0x02,
Philipp Maier7e27b142018-03-22 17:26:46 +0100689 GSM0808_IE_SPEECH_CODEC_LIST, 0x07, GSM0808_SCT_FR3 | 0x50, 0xef,
690 0xcd, GSM0808_SCT_FR2 | 0xa0, 0x9f, GSM0808_SCT_CSD | 0x90, 0xc0 };
Philipp Maierfa896ab2017-03-27 16:55:32 +0200691 uint8_t rr_res = 2;
692 struct msgb *msg;
693 struct gsm0808_speech_codec_list sc_list;
694
695 setup_codec_list(&sc_list);
696
697 printf("Testing creating Assignment Failure (AoIP)\n");
698 msg = gsm0808_create_ass_fail(0x23, NULL, &sc_list);
699 VERIFY(msg, res1, ARRAY_SIZE(res1));
700 msgb_free(msg);
701
702 msg = gsm0808_create_ass_fail(0x23, &rr_res, &sc_list);
703 VERIFY(msg, res2, ARRAY_SIZE(res2));
704 msgb_free(msg);
705}
706
Harald Weltee61d4592022-11-03 11:05:58 +0100707static void test_create_clear_rqst(void)
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +0100708{
709 static const uint8_t res[] = { 0x00, 0x04, 0x22, 0x04, 0x01, 0x23 };
710 struct msgb *msg;
711
712 printf("Testing creating Clear Request\n");
713 msg = gsm0808_create_clear_rqst(0x23);
714 VERIFY(msg, res, ARRAY_SIZE(res));
715 msgb_free(msg);
716}
717
Harald Weltee61d4592022-11-03 11:05:58 +0100718static void test_create_paging(void)
Philipp Maier3d48ec02017-03-29 17:37:55 +0200719{
720 static const uint8_t res[] =
721 { 0x00, 0x10, 0x52, 0x08, 0x08, 0x09, 0x10, 0x10, 0x00, 0x00, 0x00,
722 0x21, 0x43, 0x1a, 0x03, 0x05, 0x23, 0x42 };
723 static const uint8_t res2[] =
724 { 0x00, 0x16, 0x52, 0x08, 0x08, 0x09, 0x10, 0x10, 0x00, 0x00, 0x00,
725 0x21, 0x43, GSM0808_IE_TMSI, 0x04, 0x12, 0x34, 0x56, 0x78, 0x1a,
726 0x03, 0x05, 0x23, 0x42 };
727 static const uint8_t res3[] =
728 { 0x00, 0x18, 0x52, 0x08, 0x08, 0x09, 0x10, 0x10, 0x00, 0x00, 0x00,
729 0x21, 0x43, GSM0808_IE_TMSI, 0x04, 0x12, 0x34, 0x56, 0x78, 0x1a,
730 0x03, 0x05, 0x23, 0x42, GSM0808_IE_CHANNEL_NEEDED,
731 RSL_CHANNEED_TCH_ForH };
732
733 struct msgb *msg;
Stefan Sperling11a4d9d2018-02-15 18:28:04 +0100734 struct gsm0808_cell_id_list2 cil;
Philipp Maier3d48ec02017-03-29 17:37:55 +0200735 uint32_t tmsi = 0x12345678;
736 uint8_t chan_needed = RSL_CHANNEED_TCH_ForH;
737
738 char imsi[] = "001010000001234";
739
740 cil.id_discr = CELL_IDENT_LAC;
Stefan Sperling11a4d9d2018-02-15 18:28:04 +0100741 cil.id_list[0].lac = 0x2342;
Philipp Maier3d48ec02017-03-29 17:37:55 +0200742 cil.id_list_len = 1;
743
744 printf("Testing creating Paging Request\n");
Stefan Sperling11a4d9d2018-02-15 18:28:04 +0100745 msg = gsm0808_create_paging2(imsi, NULL, &cil, NULL);
Philipp Maier3d48ec02017-03-29 17:37:55 +0200746 VERIFY(msg, res, ARRAY_SIZE(res));
747 msgb_free(msg);
748
Stefan Sperling11a4d9d2018-02-15 18:28:04 +0100749 msg = gsm0808_create_paging2(imsi, &tmsi, &cil, NULL);
Philipp Maier3d48ec02017-03-29 17:37:55 +0200750 VERIFY(msg, res2, ARRAY_SIZE(res2));
751 msgb_free(msg);
752
Stefan Sperling11a4d9d2018-02-15 18:28:04 +0100753 msg = gsm0808_create_paging2(imsi, &tmsi, &cil, &chan_needed);
Philipp Maier3d48ec02017-03-29 17:37:55 +0200754 VERIFY(msg, res3, ARRAY_SIZE(res3));
755 msgb_free(msg);
756}
757
Harald Weltee61d4592022-11-03 11:05:58 +0100758static void test_create_dtap(void)
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +0100759{
760 static const uint8_t res[] = { 0x01, 0x03, 0x02, 0x23, 0x42 };
761 struct msgb *msg, *l3;
762
763 printf("Testing creating DTAP\n");
764 l3 = msgb_alloc_headroom(512, 128, "test");
765 l3->l3h = l3->data;
766 msgb_v_put(l3, 0x23);
767 msgb_v_put(l3, 0x42);
768
769 msg = gsm0808_create_dtap(l3, 0x3);
770 VERIFY(msg, res, ARRAY_SIZE(res));
771 msgb_free(msg);
772 msgb_free(l3);
773}
774
Harald Weltee61d4592022-11-03 11:05:58 +0100775static void test_prepend_dtap(void)
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +0100776{
777 static const uint8_t res[] = { 0x01, 0x03, 0x02, 0x23, 0x42 };
778 struct msgb *in_msg;
779
780 printf("Testing prepend DTAP\n");
781
782 in_msg = msgb_alloc_headroom(512, 128, "test");
783 msgb_v_put(in_msg, 0x23);
784 msgb_v_put(in_msg, 0x42);
785
786 gsm0808_prepend_dtap_header(in_msg, 0x3);
787 in_msg->l3h = in_msg->data;
788 VERIFY(in_msg, res, ARRAY_SIZE(res));
789 msgb_free(in_msg);
790}
791
Harald Weltee61d4592022-11-03 11:05:58 +0100792static void test_enc_dec_lcls(void)
Max969fb2e2018-12-10 11:01:10 +0100793{
794 static const uint8_t res[] = {
795 GSM0808_IE_GLOBAL_CALL_REF,
796 0x0d, /* GCR length */
797 0x03, /* .net_len */
798 0xf1, 0xf2, 0xf3, /* .net */
799 0x02, /* .node length */
800 0xde, 0xad, /* .node */
801 0x05, /* length of Call. Ref. */
802 0x41, 0x42, 0x43, 0x44, 0x45 /* .cr - Call. Ref. */
803 };
804 uint8_t len;
805 struct msgb *msg;
Max969fb2e2018-12-10 11:01:10 +0100806 int rc;
807 struct tlv_parsed tp;
Max3b901252019-01-15 14:15:11 +0100808 struct osmo_lcls *lcls_out, lcls_in = {
809 .gcr = {
810 .net_len = 3,
811 .net = { 0xf1, 0xf2, 0xf3 },
812 .node = 0xDEAD,
813 .cr = { 0x41, 0x42, 0x43, 0x44, 0x45 },
814 },
815 .gcr_available = true,
Max47022152018-12-19 18:51:00 +0100816 .config = GSM0808_LCLS_CFG_NA,
817 .control = GSM0808_LCLS_CSC_NA,
818 .corr_needed = true,
819 };
820
821 msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM, "LCLS IE");
Max969fb2e2018-12-10 11:01:10 +0100822 if (!msg)
823 return;
824
Max3b901252019-01-15 14:15:11 +0100825 lcls_out = talloc_zero(msg, struct osmo_lcls);
826 if (!lcls_out)
827 return;
828
Max47022152018-12-19 18:51:00 +0100829 len = gsm0808_enc_lcls(msg, &lcls_in);
Max969fb2e2018-12-10 11:01:10 +0100830 printf("Testing Global Call Reference IE encoder...\n\t%d bytes added: %s\n",
831 len, len == ARRAY_SIZE(res) ? "OK" : "FAIL");
832
833 if (!msgb_eq_data_print(msg, res, ARRAY_SIZE(res)))
834 abort();
835
836 rc = osmo_bssap_tlv_parse(&tp, msgb_data(msg), msgb_length(msg));
837 if (rc < 0) {
838 printf("parsing failed: %s [%s]\n", strerror(-rc), msgb_hexdump(msg));
839 abort();
840 }
841
Max3b901252019-01-15 14:15:11 +0100842 rc = gsm0808_dec_lcls(lcls_out, &tp);
Max969fb2e2018-12-10 11:01:10 +0100843 if (rc < 0) {
844 printf("decoding failed: %s [%s]\n", strerror(-rc), msgb_hexdump(msg));
845 abort();
846 }
847
Max3b901252019-01-15 14:15:11 +0100848 if (lcls_out->config != lcls_in.config) {
Max4fd64e52019-01-14 19:27:44 +0100849 printf("LCLS Config parsed wrong: %s != %s\n",
Max3b901252019-01-15 14:15:11 +0100850 gsm0808_lcls_config_name(lcls_out->config), gsm0808_lcls_config_name(lcls_in.config));
Max4fd64e52019-01-14 19:27:44 +0100851 abort();
852 }
853
Max3b901252019-01-15 14:15:11 +0100854 if (lcls_out->control != lcls_in.control) {
Max4fd64e52019-01-14 19:27:44 +0100855 printf("LCLS Control parsed wrong: %s != %s\n",
Max3b901252019-01-15 14:15:11 +0100856 gsm0808_lcls_control_name(lcls_out->control), gsm0808_lcls_control_name(lcls_in.control));
Max4fd64e52019-01-14 19:27:44 +0100857 abort();
858 }
859
Max3b901252019-01-15 14:15:11 +0100860 if (!osmo_gcr_eq(&lcls_out->gcr, &lcls_in.gcr)) {
Max5ec0cf52019-01-15 16:37:09 +0100861 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 +0100862 abort();
863 }
Max969fb2e2018-12-10 11:01:10 +0100864
Max5ec0cf52019-01-15 16:37:09 +0100865 printf("\tdecoded %d bytes: %s:\n%s\n", rc, rc == len ? "OK" : "FAIL", osmo_lcls_dump(lcls_out));
866 printf("\t%s\n", osmo_gcr_dump(lcls_out));
Max969fb2e2018-12-10 11:01:10 +0100867 msgb_free(msg);
868}
869
Harald Weltee61d4592022-11-03 11:05:58 +0100870static void test_enc_dec_aoip_trasp_addr_v4(void)
Philipp Maier22401432017-03-24 17:59:26 +0100871{
872 struct sockaddr_storage enc_addr;
873 struct sockaddr_storage dec_addr;
874 struct sockaddr_in enc_addr_in;
875 struct msgb *msg;
876 uint8_t rc_enc;
877 int rc_dec;
878
879 memset(&enc_addr_in, 0, sizeof(enc_addr_in));
880 enc_addr_in.sin_family = AF_INET;
881 enc_addr_in.sin_port = htons(1234);
882 inet_aton("255.0.255.255", &enc_addr_in.sin_addr);
883
884 memset(&enc_addr, 0, sizeof(enc_addr));
885 memcpy(&enc_addr, &enc_addr_in, sizeof(enc_addr_in));
886
887 msg = msgb_alloc(1024, "output buffer");
888 rc_enc = gsm0808_enc_aoip_trasp_addr(msg, &enc_addr);
889 OSMO_ASSERT(rc_enc == 8);
890 rc_dec =
891 gsm0808_dec_aoip_trasp_addr(&dec_addr, msg->data + 2, msg->len - 2);
892 OSMO_ASSERT(rc_dec == 6);
893 OSMO_ASSERT(memcmp(&enc_addr, &dec_addr, sizeof(enc_addr)) == 0);
894
895 msgb_free(msg);
896}
897
Harald Weltee61d4592022-11-03 11:05:58 +0100898static void test_enc_dec_aoip_trasp_addr_v6(void)
Philipp Maier22401432017-03-24 17:59:26 +0100899{
900 struct sockaddr_storage enc_addr;
901 struct sockaddr_storage dec_addr;
902 struct sockaddr_in6 enc_addr_in;
903 struct msgb *msg;
904 uint8_t rc_enc;
905 int rc_dec;
906
907 memset(&enc_addr_in, 0, sizeof(enc_addr_in));
908 enc_addr_in.sin6_family = AF_INET6;
909 enc_addr_in.sin6_port = htons(4567);
910 inet_pton(AF_INET6, "2001:0db8:85a3:08d3:1319:8a2e:0370:7344",
911 &enc_addr_in.sin6_addr);
912
913 memset(&enc_addr, 0, sizeof(enc_addr));
914 memcpy(&enc_addr, &enc_addr_in, sizeof(enc_addr_in));
915
916 msg = msgb_alloc(1024, "output buffer");
917 rc_enc = gsm0808_enc_aoip_trasp_addr(msg, &enc_addr);
918 OSMO_ASSERT(rc_enc == 20);
919 rc_dec =
920 gsm0808_dec_aoip_trasp_addr(&dec_addr, msg->data + 2, msg->len - 2);
921 OSMO_ASSERT(rc_dec == 18);
922 OSMO_ASSERT(memcmp(&enc_addr, &dec_addr, sizeof(enc_addr)) == 0);
923
924 msgb_free(msg);
925}
926
Harald Weltee61d4592022-11-03 11:05:58 +0100927static void test_enc_aoip_trasp_addr_msg_too_small(void)
Oliver Smithc66b35b2022-08-05 11:27:55 +0200928{
929 struct msgb *msg;
930 struct sockaddr_storage enc_addr;
931 struct sockaddr_in enc_addr_in;
932 uint8_t rc_enc;
933
934 memset(&enc_addr_in, 0, sizeof(enc_addr_in));
935 enc_addr_in.sin_family = AF_INET;
936 enc_addr_in.sin_port = htons(1234);
937 inet_aton("255.0.255.255", &enc_addr_in.sin_addr);
938
939 memset(&enc_addr, 0, sizeof(enc_addr));
940 memcpy(&enc_addr, &enc_addr_in, sizeof(enc_addr_in));
941
942 msg = msgb_alloc(7, "output buffer");
943 rc_enc = gsm0808_enc_aoip_trasp_addr(msg, &enc_addr);
944 OSMO_ASSERT(rc_enc == 0);
945
946 msgb_free(msg);
947}
948
Harald Weltee61d4592022-11-03 11:05:58 +0100949static void test_gsm0808_enc_dec_speech_codec(void)
Philipp Maier6f725d62017-03-24 18:03:17 +0100950{
Neels Hofmeyr9a4286b2018-04-20 12:27:52 +0200951 struct gsm0808_speech_codec enc_sc = {
952 .pi = true,
953 .tf = true,
954 .type = GSM0808_SCT_FR2,
955 };
956 struct gsm0808_speech_codec dec_sc = {};
Philipp Maier6f725d62017-03-24 18:03:17 +0100957 struct msgb *msg;
958 uint8_t rc_enc;
959 int rc_dec;
960
Philipp Maier6f725d62017-03-24 18:03:17 +0100961 msg = msgb_alloc(1024, "output buffer");
Vadim Yanitskiy6db830f2022-12-14 00:45:25 +0700962 rc_enc = gsm0808_enc_speech_codec2(msg, &enc_sc);
Philipp Maier6f725d62017-03-24 18:03:17 +0100963 OSMO_ASSERT(rc_enc == 3);
964
965 rc_dec = gsm0808_dec_speech_codec(&dec_sc, msg->data + 2, msg->len - 2);
966 OSMO_ASSERT(rc_dec == 1);
967
968 OSMO_ASSERT(memcmp(&enc_sc, &dec_sc, sizeof(enc_sc)) == 0);
969
970 msgb_free(msg);
971}
972
973
Harald Weltee61d4592022-11-03 11:05:58 +0100974static void test_gsm0808_enc_dec_speech_codec_with_cfg(void)
Philipp Maierbb839662017-06-01 17:11:19 +0200975{
Neels Hofmeyrc62c9342018-04-15 23:31:47 +0200976 struct gsm0808_speech_codec enc_sc = {
977 .pi = true,
978 .tf = true,
979 .type = GSM0808_SCT_FR3,
980 .cfg = 0xabcd,
981 };
982 struct gsm0808_speech_codec dec_sc = {};
Philipp Maierbb839662017-06-01 17:11:19 +0200983 struct msgb *msg;
984 uint8_t rc_enc;
985 int rc_dec;
986
Philipp Maierbb839662017-06-01 17:11:19 +0200987 msg = msgb_alloc(1024, "output buffer");
Vadim Yanitskiy6db830f2022-12-14 00:45:25 +0700988 rc_enc = gsm0808_enc_speech_codec2(msg, &enc_sc);
Philipp Maierbb839662017-06-01 17:11:19 +0200989 OSMO_ASSERT(rc_enc == 5);
990
991 rc_dec = gsm0808_dec_speech_codec(&dec_sc, msg->data + 2, msg->len - 2);
992 OSMO_ASSERT(rc_dec == 3);
993
994 OSMO_ASSERT(memcmp(&enc_sc, &dec_sc, sizeof(enc_sc)) == 0);
995
996 msgb_free(msg);
997}
998
Harald Weltee61d4592022-11-03 11:05:58 +0100999static void test_gsm0808_enc_dec_speech_codec_ext_with_cfg(void)
Philipp Maier6f725d62017-03-24 18:03:17 +01001000{
Neels Hofmeyr9a4286b2018-04-20 12:27:52 +02001001 struct gsm0808_speech_codec enc_sc = {
1002 .pi = true,
1003 .tf = true,
1004 .type = GSM0808_SCT_CSD,
1005 .cfg = 0xc0,
1006 };
1007 struct gsm0808_speech_codec dec_sc = {};
Philipp Maier6f725d62017-03-24 18:03:17 +01001008 struct msgb *msg;
1009 uint8_t rc_enc;
1010 int rc_dec;
1011
Philipp Maier6f725d62017-03-24 18:03:17 +01001012 msg = msgb_alloc(1024, "output buffer");
Vadim Yanitskiy6db830f2022-12-14 00:45:25 +07001013 rc_enc = gsm0808_enc_speech_codec2(msg, &enc_sc);
Philipp Maierbb839662017-06-01 17:11:19 +02001014 OSMO_ASSERT(rc_enc == 5);
Philipp Maier6f725d62017-03-24 18:03:17 +01001015
1016 rc_dec = gsm0808_dec_speech_codec(&dec_sc, msg->data + 2, msg->len - 2);
Philipp Maierbb839662017-06-01 17:11:19 +02001017 OSMO_ASSERT(rc_dec == 3);
Philipp Maier6f725d62017-03-24 18:03:17 +01001018
1019 OSMO_ASSERT(memcmp(&enc_sc, &dec_sc, sizeof(enc_sc)) == 0);
1020
1021 msgb_free(msg);
1022}
1023
Harald Weltee61d4592022-11-03 11:05:58 +01001024static void test_gsm0808_enc_dec_speech_codec_list(void)
Philipp Maier6f725d62017-03-24 18:03:17 +01001025{
Neels Hofmeyr9a4286b2018-04-20 12:27:52 +02001026 struct gsm0808_speech_codec_list enc_scl = {
1027 .codec = {
1028 {
1029 .pi = true,
1030 .tf = true,
1031 .type = GSM0808_SCT_FR3,
1032 .cfg = 0xcdef,
1033 },
1034
1035 {
1036 .fi = true,
1037 .pt = true,
1038 .type = GSM0808_SCT_FR2,
1039 },
1040
1041 {
1042 .fi = true,
1043 .tf = true,
1044 .type = GSM0808_SCT_CSD,
1045 .cfg = 0xc0,
1046 },
1047 },
1048 .len = 3,
1049 };
1050 struct gsm0808_speech_codec_list dec_scl = {};
Philipp Maier6f725d62017-03-24 18:03:17 +01001051 struct msgb *msg;
1052 uint8_t rc_enc;
1053 int rc_dec;
1054
Philipp Maier6f725d62017-03-24 18:03:17 +01001055 msg = msgb_alloc(1024, "output buffer");
Vadim Yanitskiy6db830f2022-12-14 00:45:25 +07001056 rc_enc = gsm0808_enc_speech_codec_list2(msg, &enc_scl);
Philipp Maier6f725d62017-03-24 18:03:17 +01001057 OSMO_ASSERT(rc_enc == 9);
1058
1059 rc_dec = gsm0808_dec_speech_codec_list(&dec_scl, msg->data + 2, msg->len - 2);
1060 OSMO_ASSERT(rc_dec == 7);
1061
1062 OSMO_ASSERT(memcmp(&enc_scl, &dec_scl, sizeof(enc_scl)) == 0);
1063
1064 msgb_free(msg);
1065}
1066
Harald Weltee61d4592022-11-03 11:05:58 +01001067static void test_gsm0808_enc_dec_empty_speech_codec_list(void)
Philipp Maierf6c369f2018-10-16 15:24:47 +02001068{
1069 struct gsm0808_speech_codec_list enc_scl = {
1070 .len = 0,
1071 };
1072 struct gsm0808_speech_codec_list dec_scl = {};
1073 struct msgb *msg;
1074 uint8_t rc_enc;
1075 int rc_dec;
1076
1077 msg = msgb_alloc(1024, "output buffer");
Vadim Yanitskiy6db830f2022-12-14 00:45:25 +07001078 rc_enc = gsm0808_enc_speech_codec_list2(msg, &enc_scl);
Philipp Maierf6c369f2018-10-16 15:24:47 +02001079 OSMO_ASSERT(rc_enc == 2);
1080
1081 rc_dec = gsm0808_dec_speech_codec_list(&dec_scl, msg->data + 2, msg->len - 2);
1082 OSMO_ASSERT(rc_dec == 0);
1083
1084 OSMO_ASSERT(memcmp(&enc_scl, &dec_scl, sizeof(enc_scl)) == 0);
1085
1086 msgb_free(msg);
1087}
1088
Oliver Smithf047a4a2023-01-31 13:10:03 +01001089static void test_gsm0808_enc_dec_channel_type_data(void)
1090{
1091 struct gsm0808_channel_type enc_ct = {
1092 .ch_indctr = GSM0808_CHAN_DATA,
1093 .ch_rate_type = GSM0808_DATA_HALF_PREF,
1094
1095 .data_transparent = true,
Oliver Smith14471002023-03-03 10:00:29 +01001096 .data_rate = GSM0808_DATA_RATE_TRANSP_4k8,
Oliver Smithf047a4a2023-01-31 13:10:03 +01001097 };
1098 struct gsm0808_channel_type dec_ct = {};
1099 struct msgb *msg;
1100 uint8_t ct_enc_expected[] = { GSM0808_IE_CHANNEL_TYPE,
Oliver Smith57d4fae2023-02-27 10:28:40 +01001101 0x03, 0x02, 0x0b, 0x11,
Oliver Smithf047a4a2023-01-31 13:10:03 +01001102 };
1103 uint8_t rc_enc;
1104 int rc_dec;
1105
1106 msg = msgb_alloc(1024, "output buffer");
1107 rc_enc = gsm0808_enc_channel_type(msg, &enc_ct);
1108 OSMO_ASSERT(rc_enc == 5);
1109 if (memcmp(ct_enc_expected, msg->data, msg->len)) {
1110 printf(" got: %s\n", osmo_hexdump(msg->data, msg->len));
1111 printf("expect: %s\n", osmo_hexdump(ct_enc_expected, sizeof(ct_enc_expected)));
1112 OSMO_ASSERT(false);
1113 }
1114
1115 rc_dec = gsm0808_dec_channel_type(&dec_ct, msg->data + 2, msg->len - 2);
1116 OSMO_ASSERT(rc_dec == 3);
1117 OSMO_ASSERT(dec_ct.ch_indctr == enc_ct.ch_indctr);
1118 OSMO_ASSERT(dec_ct.ch_rate_type == enc_ct.ch_rate_type);
1119 OSMO_ASSERT(dec_ct.data_transparent == enc_ct.data_transparent);
1120 OSMO_ASSERT(dec_ct.data_rate == enc_ct.data_rate);
1121 OSMO_ASSERT(dec_ct.data_rate_allowed_is_set == enc_ct.data_rate_allowed_is_set);
1122 OSMO_ASSERT(dec_ct.data_asym_pref_is_set == enc_ct.data_asym_pref_is_set);
1123
1124 msgb_free(msg);
1125}
1126
1127static void test_gsm0808_enc_dec_channel_type_data_asym_pref(void)
1128{
1129 struct gsm0808_channel_type enc_ct = {
1130 .ch_indctr = GSM0808_CHAN_DATA,
1131 .ch_rate_type = GSM0808_DATA_HALF_PREF,
1132
1133 .data_transparent = false,
Oliver Smith14471002023-03-03 10:00:29 +01001134 .data_rate = GSM0808_DATA_RATE_NON_TRANSP_6k0,
Oliver Smithf047a4a2023-01-31 13:10:03 +01001135 .data_rate_allowed_is_set = true,
Oliver Smith14471002023-03-03 10:00:29 +01001136 .data_rate_allowed = GSM0808_DATA_RATE_NON_TRANSP_ALLOWED_6k0
1137 | GSM0808_DATA_RATE_NON_TRANSP_ALLOWED_12k0
1138 | GSM0808_DATA_RATE_NON_TRANSP_ALLOWED_14k5,
Oliver Smithf047a4a2023-01-31 13:10:03 +01001139 .data_asym_pref_is_set = true,
1140 .data_asym_pref = GSM0808_CT_ASYM_PREF_UL,
1141 };
1142 struct gsm0808_channel_type dec_ct = {};
1143 struct msgb *msg;
1144 uint8_t ct_enc_expected[] = { GSM0808_IE_CHANNEL_TYPE,
Oliver Smith57d4fae2023-02-27 10:28:40 +01001145 0x05, 0x02, 0x0b, 0xd1, 0x8b, 0x20,
Oliver Smithf047a4a2023-01-31 13:10:03 +01001146 };
1147 uint8_t rc_enc;
1148 int rc_dec;
1149
1150 msg = msgb_alloc(1024, "output buffer");
1151 rc_enc = gsm0808_enc_channel_type(msg, &enc_ct);
1152 OSMO_ASSERT(rc_enc == 7);
1153 if (memcmp(ct_enc_expected, msg->data, msg->len)) {
1154 printf(" got: %s\n", osmo_hexdump(msg->data, msg->len));
1155 printf("expect: %s\n", osmo_hexdump(ct_enc_expected, sizeof(ct_enc_expected)));
1156 OSMO_ASSERT(false);
1157 }
1158
1159 rc_dec = gsm0808_dec_channel_type(&dec_ct, msg->data + 2, msg->len - 2);
1160 OSMO_ASSERT(rc_dec == 5);
1161 OSMO_ASSERT(dec_ct.ch_indctr == enc_ct.ch_indctr);
1162 OSMO_ASSERT(dec_ct.ch_rate_type == enc_ct.ch_rate_type);
1163 OSMO_ASSERT(dec_ct.data_transparent == enc_ct.data_transparent);
1164 OSMO_ASSERT(dec_ct.data_rate == enc_ct.data_rate);
1165 OSMO_ASSERT(dec_ct.data_rate_allowed_is_set == enc_ct.data_rate_allowed_is_set);
1166 OSMO_ASSERT(dec_ct.data_asym_pref_is_set == enc_ct.data_asym_pref_is_set);
1167
1168 msgb_free(msg);
1169}
1170
Oliver Smith02b90952023-01-31 16:42:55 +01001171static void test_gsm0808_enc_dec_channel_type_speech(void)
Philipp Maiere0c65302017-03-28 17:05:40 +02001172{
Neels Hofmeyr9a4286b2018-04-20 12:27:52 +02001173 struct gsm0808_channel_type enc_ct = {
1174 .ch_indctr = GSM0808_CHAN_SPEECH,
1175 .ch_rate_type = GSM0808_SPEECH_HALF_PREF,
1176 .perm_spch = { GSM0808_PERM_FR3, GSM0808_PERM_HR3 },
1177 .perm_spch_len = 2,
1178 };
1179 struct gsm0808_channel_type dec_ct = {};
Philipp Maiere0c65302017-03-28 17:05:40 +02001180 struct msgb *msg;
1181 uint8_t ct_enc_expected[] = { GSM0808_IE_CHANNEL_TYPE,
1182 0x04, 0x01, 0x0b, 0xa1, 0x25
1183 };
1184 uint8_t rc_enc;
1185 int rc_dec;
1186
Philipp Maiere0c65302017-03-28 17:05:40 +02001187 msg = msgb_alloc(1024, "output buffer");
1188 rc_enc = gsm0808_enc_channel_type(msg, &enc_ct);
1189 OSMO_ASSERT(rc_enc == 6);
1190 OSMO_ASSERT(memcmp(ct_enc_expected, msg->data, msg->len) == 0);
1191
1192 rc_dec = gsm0808_dec_channel_type(&dec_ct, msg->data + 2, msg->len - 2);
1193 OSMO_ASSERT(rc_dec == 4);
Pau Espin Pedrol2605ffc2019-07-29 16:44:22 +02001194 OSMO_ASSERT(enc_ct.ch_indctr == dec_ct.ch_indctr);
1195 OSMO_ASSERT(enc_ct.ch_rate_type == dec_ct.ch_rate_type);
1196 OSMO_ASSERT(enc_ct.perm_spch_len == dec_ct.perm_spch_len);
1197 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 +02001198
1199 msgb_free(msg);
1200}
1201
Oliver Smith8d9ed732023-02-20 13:01:29 +01001202static void test_gsm0808_enc_dec_channel_type_sign(void)
1203{
1204 struct gsm0808_channel_type enc_ct = {
1205 .ch_indctr = GSM0808_CHAN_SIGN,
1206 .ch_rate_type = GSM0808_SIGN_FULL_PREF_NO_CHANGE,
1207 };
1208 struct gsm0808_channel_type dec_ct = {};
1209 struct msgb *msg;
1210 uint8_t ct_enc_expected[] = { GSM0808_IE_CHANNEL_TYPE,
1211 0x03, 0x03, 0x1a, 0x00
1212 };
1213 uint8_t rc_enc;
1214 int rc_dec;
1215
1216 msg = msgb_alloc(1024, "output buffer");
1217 rc_enc = gsm0808_enc_channel_type(msg, &enc_ct);
1218 OSMO_ASSERT(rc_enc == 5);
1219 OSMO_ASSERT(memcmp(ct_enc_expected, msg->data, msg->len) == 0);
1220
1221 rc_dec = gsm0808_dec_channel_type(&dec_ct, msg->data + 2, msg->len - 2);
1222 OSMO_ASSERT(rc_dec == 2);
1223 OSMO_ASSERT(enc_ct.ch_indctr == dec_ct.ch_indctr);
1224 OSMO_ASSERT(enc_ct.ch_rate_type == dec_ct.ch_rate_type);
1225
1226 msgb_free(msg);
1227}
1228
Oliver Smith81e5a6f2023-01-31 12:34:26 +01001229static void test_gsm0808_dec_channel_type_err(void)
1230{
1231 struct gsm0808_channel_type ct;
1232 int rc;
1233
Oliver Smithf047a4a2023-01-31 13:10:03 +01001234 /* Unknown channel indicator */
1235 const uint8_t hex1[] = { 0x05, 0x0b, 0xa1, 0x25 };
1236 rc = gsm0808_dec_channel_type(&ct, hex1, sizeof(hex1));
1237 OSMO_ASSERT(rc == -ENOTSUP);
1238
1239 /* Data: ext in Octet 5 with transparent service */
Oliver Smith57d4fae2023-02-27 10:28:40 +01001240 const uint8_t hex2[] = { 0x02, 0x0b, 0x80, 0x00 };
Oliver Smithf047a4a2023-01-31 13:10:03 +01001241 rc = gsm0808_dec_channel_type(&ct, hex2, sizeof(hex2));
1242 OSMO_ASSERT(rc == -EINVAL);
1243
1244 /* Data: ext in Octet 5, but too short */
Oliver Smith57d4fae2023-02-27 10:28:40 +01001245 const uint8_t hex3[] = { 0x02, 0x0b, 0xc0 };
Oliver Smithf047a4a2023-01-31 13:10:03 +01001246 rc = gsm0808_dec_channel_type(&ct, hex3, sizeof(hex3));
1247 OSMO_ASSERT(rc == -EOVERFLOW);
1248
1249 /* Data: ext in Octet 5a, but too short */
Oliver Smith57d4fae2023-02-27 10:28:40 +01001250 const uint8_t hex4[] = { 0x02, 0x0b, 0xc0, 0x80 };
Oliver Smithf047a4a2023-01-31 13:10:03 +01001251 rc = gsm0808_dec_channel_type(&ct, hex4, sizeof(hex4));
1252 OSMO_ASSERT(rc == -EOVERFLOW);
1253
Oliver Smith81e5a6f2023-01-31 12:34:26 +01001254 /* Speech: extension bit is set in last byte */
Oliver Smithf047a4a2023-01-31 13:10:03 +01001255 const uint8_t hex5[] = { 0x01, 0x0b, 0xa1, 0xa5 };
1256 rc = gsm0808_dec_channel_type(&ct, hex5, sizeof(hex5));
Oliver Smith81e5a6f2023-01-31 12:34:26 +01001257 OSMO_ASSERT(rc == -EOVERFLOW);
1258}
1259
Harald Weltee61d4592022-11-03 11:05:58 +01001260static void test_gsm0808_enc_dec_encrypt_info(void)
Philipp Maier14e76b92017-03-28 18:36:52 +02001261{
Neels Hofmeyr9a4286b2018-04-20 12:27:52 +02001262 struct gsm0808_encrypt_info enc_ei = {
1263 .perm_algo = { GSM0808_ALG_ID_A5_0, GSM0808_ALG_ID_A5_1 },
1264 .perm_algo_len = 2,
1265 .key = { 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x23, 0x42, },
1266 .key_len = 8,
1267 };
1268 struct gsm0808_encrypt_info dec_ei = {};
Philipp Maier14e76b92017-03-28 18:36:52 +02001269 struct msgb *msg;
1270 uint8_t ei_enc_expected[] =
1271 { GSM0808_IE_ENCRYPTION_INFORMATION, 0x09, 0x03, 0xaa, 0xbb,
1272 0xcc, 0xdd, 0xee, 0xff, 0x23, 0x42
1273 };
1274 uint8_t rc_enc;
1275 int rc_dec;
1276
Philipp Maier14e76b92017-03-28 18:36:52 +02001277 msg = msgb_alloc(1024, "output buffer");
1278 rc_enc = gsm0808_enc_encrypt_info(msg, &enc_ei);
1279 OSMO_ASSERT(rc_enc == 11);
1280 OSMO_ASSERT(memcmp(ei_enc_expected, msg->data, msg->len) == 0);
1281
1282 rc_dec = gsm0808_dec_encrypt_info(&dec_ei, msg->data + 2, msg->len - 2);
1283 OSMO_ASSERT(rc_dec == 9);
1284
1285 OSMO_ASSERT(memcmp(&enc_ei, &dec_ei, sizeof(enc_ei)) == 0);
1286
1287 msgb_free(msg);
1288}
1289
Harald Weltee61d4592022-11-03 11:05:58 +01001290static void test_gsm0808_dec_cell_id_list_srvcc(void)
Harald Weltea87526d2022-02-15 20:06:16 +01001291{
1292 /* taken from a pcap file of a real-world 3rd party MSC (SYS#5838) */
1293 const uint8_t enc_cil[] = { 0x0b, 0x2, 0xf2, 0x10, 0x4e, 0x20, 0x15, 0xbe};
1294 struct gsm0808_cell_id_list2 dec_cil;
1295 int rc;
1296
1297 rc = gsm0808_dec_cell_id_list2(&dec_cil, enc_cil, sizeof(enc_cil));
Pau Espin Pedrolb5551ee2022-02-16 13:09:32 +01001298 OSMO_ASSERT(rc == sizeof(enc_cil));
Vadim Yanitskiya7570af2023-12-11 21:57:20 +07001299 OSMO_ASSERT(dec_cil.id_discr == CELL_IDENT_SAI);
1300 OSMO_ASSERT(dec_cil.id_list_len == 1);
Harald Weltea87526d2022-02-15 20:06:16 +01001301}
1302
Harald Weltee61d4592022-11-03 11:05:58 +01001303static void test_gsm0808_enc_dec_cell_id_list_lac(void)
Philipp Maier783047e2017-03-29 11:35:50 +02001304{
Stefan Sperling11a4d9d2018-02-15 18:28:04 +01001305 struct gsm0808_cell_id_list2 enc_cil;
1306 struct gsm0808_cell_id_list2 dec_cil;
Philipp Maier783047e2017-03-29 11:35:50 +02001307 struct msgb *msg;
1308 uint8_t rc_enc;
1309 int rc_dec;
1310
1311 memset(&enc_cil, 0, sizeof(enc_cil));
1312 enc_cil.id_discr = CELL_IDENT_LAC;
Stefan Sperling11a4d9d2018-02-15 18:28:04 +01001313 enc_cil.id_list[0].lac = 0x0124;
Neels Hofmeyrdb2fa4e2018-04-13 04:11:20 +02001314 enc_cil.id_list[1].lac = 0xABCD;
1315 enc_cil.id_list[2].lac = 0x5678;
Philipp Maier783047e2017-03-29 11:35:50 +02001316 enc_cil.id_list_len = 3;
1317
1318 msg = msgb_alloc(1024, "output buffer");
Stefan Sperling11a4d9d2018-02-15 18:28:04 +01001319 rc_enc = gsm0808_enc_cell_id_list2(msg, &enc_cil);
Neels Hofmeyrdb2fa4e2018-04-13 04:11:20 +02001320 EXPECT_ENCODED("1a 07 05 01 24 ab cd 56 78");
Philipp Maier783047e2017-03-29 11:35:50 +02001321
Stefan Sperling11a4d9d2018-02-15 18:28:04 +01001322 rc_dec = gsm0808_dec_cell_id_list2(&dec_cil, msg->data + 2, msg->len - 2);
Philipp Maier783047e2017-03-29 11:35:50 +02001323 OSMO_ASSERT(rc_dec == 7);
1324
1325 OSMO_ASSERT(memcmp(&enc_cil, &dec_cil, sizeof(enc_cil)) == 0);
1326
1327 msgb_free(msg);
1328}
1329
Harald Weltee61d4592022-11-03 11:05:58 +01001330static void test_gsm0808_enc_dec_cell_id_list_single_lac(void)
Philipp Maier783047e2017-03-29 11:35:50 +02001331{
Stefan Sperling11a4d9d2018-02-15 18:28:04 +01001332 struct gsm0808_cell_id_list2 enc_cil;
1333 struct gsm0808_cell_id_list2 dec_cil;
Philipp Maier783047e2017-03-29 11:35:50 +02001334 struct msgb *msg;
1335 uint8_t cil_enc_expected[] = { GSM0808_IE_CELL_IDENTIFIER_LIST, 0x03,
1336 0x05, 0x23, 0x42
1337 };
1338 uint8_t rc_enc;
1339 int rc_dec;
1340
1341 memset(&enc_cil, 0, sizeof(enc_cil));
1342 enc_cil.id_discr = CELL_IDENT_LAC;
Stefan Sperling11a4d9d2018-02-15 18:28:04 +01001343 enc_cil.id_list[0].lac = 0x2342;
Philipp Maier783047e2017-03-29 11:35:50 +02001344 enc_cil.id_list_len = 1;
1345
1346 msg = msgb_alloc(1024, "output buffer");
Stefan Sperling11a4d9d2018-02-15 18:28:04 +01001347 rc_enc = gsm0808_enc_cell_id_list2(msg, &enc_cil);
Philipp Maier783047e2017-03-29 11:35:50 +02001348 OSMO_ASSERT(rc_enc == 5);
1349 OSMO_ASSERT(memcmp(cil_enc_expected, msg->data, msg->len) == 0);
1350
Stefan Sperling11a4d9d2018-02-15 18:28:04 +01001351 rc_dec = gsm0808_dec_cell_id_list2(&dec_cil, msg->data + 2, msg->len - 2);
Philipp Maier783047e2017-03-29 11:35:50 +02001352 OSMO_ASSERT(rc_dec == 3);
1353
1354 OSMO_ASSERT(memcmp(&enc_cil, &dec_cil, sizeof(enc_cil)) == 0);
1355
1356 msgb_free(msg);
1357}
1358
Harald Weltee61d4592022-11-03 11:05:58 +01001359static void test_gsm0808_enc_dec_cell_id_list_multi_lac(void)
Stefan Sperlinge1a86742018-03-15 18:05:02 +01001360{
1361 struct gsm0808_cell_id_list2 enc_cil;
1362 struct gsm0808_cell_id_list2 dec_cil;
1363 struct msgb *msg;
1364 uint8_t cil_enc_expected[] = { GSM0808_IE_CELL_IDENTIFIER_LIST, 0x0b, 0x05,
1365 0x23, 0x42,
1366 0x24, 0x43,
1367 0x25, 0x44,
1368 0x26, 0x45,
1369 0x27, 0x46
1370 };
1371 uint8_t rc_enc;
1372 int rc_dec;
1373
1374 memset(&enc_cil, 0, sizeof(enc_cil));
1375 enc_cil.id_discr = CELL_IDENT_LAC;
1376 enc_cil.id_list[0].lac = 0x2342;
1377 enc_cil.id_list[1].lac = 0x2443;
1378 enc_cil.id_list[2].lac = 0x2544;
1379 enc_cil.id_list[3].lac = 0x2645;
1380 enc_cil.id_list[4].lac = 0x2746;
1381 enc_cil.id_list_len = 5;
1382
1383 msg = msgb_alloc(1024, "output buffer");
1384 rc_enc = gsm0808_enc_cell_id_list2(msg, &enc_cil);
1385 OSMO_ASSERT(rc_enc == sizeof(cil_enc_expected));
1386 OSMO_ASSERT(memcmp(cil_enc_expected, msg->data, msg->len) == 0);
1387
1388 rc_dec = gsm0808_dec_cell_id_list2(&dec_cil, msg->data + 2, msg->len - 2);
1389 OSMO_ASSERT(rc_dec == msg->len - 2);
1390 OSMO_ASSERT(memcmp(&enc_cil, &dec_cil, sizeof(enc_cil)) == 0);
1391
1392 msgb_free(msg);
1393}
1394
Harald Weltee61d4592022-11-03 11:05:58 +01001395static void test_gsm0808_enc_dec_cell_id_list_bss(void)
Philipp Maier783047e2017-03-29 11:35:50 +02001396{
Stefan Sperling11a4d9d2018-02-15 18:28:04 +01001397 struct gsm0808_cell_id_list2 enc_cil;
1398 struct gsm0808_cell_id_list2 dec_cil;
Philipp Maier783047e2017-03-29 11:35:50 +02001399 struct msgb *msg;
1400 uint8_t rc_enc;
1401 int rc_dec;
1402
1403 memset(&enc_cil, 0, sizeof(enc_cil));
Stefan Sperling11a4d9d2018-02-15 18:28:04 +01001404 enc_cil.id_discr = CELL_IDENT_BSS;
Philipp Maier783047e2017-03-29 11:35:50 +02001405
1406 msg = msgb_alloc(1024, "output buffer");
Stefan Sperling11a4d9d2018-02-15 18:28:04 +01001407 rc_enc = gsm0808_enc_cell_id_list2(msg, &enc_cil);
Philipp Maier783047e2017-03-29 11:35:50 +02001408 OSMO_ASSERT(rc_enc == 3);
1409
Stefan Sperling11a4d9d2018-02-15 18:28:04 +01001410 rc_dec = gsm0808_dec_cell_id_list2(&dec_cil, msg->data + 2, msg->len - 2);
Philipp Maier783047e2017-03-29 11:35:50 +02001411 OSMO_ASSERT(rc_dec == 1);
1412
1413 OSMO_ASSERT(memcmp(&enc_cil, &dec_cil, sizeof(enc_cil)) == 0);
1414
1415 msgb_free(msg);
1416}
1417
Harald Weltee61d4592022-11-03 11:05:58 +01001418static void test_gsm0808_enc_dec_cell_id_list_multi_lai_and_lac(void)
Stefan Sperling23381452018-03-15 19:38:15 +01001419{
1420 struct gsm0808_cell_id_list2 enc_cil;
1421 struct gsm0808_cell_id_list2 dec_cil;
1422 struct osmo_location_area_id id;
1423 struct msgb *msg;
1424 uint8_t cil_enc_expected[] = { GSM0808_IE_CELL_IDENTIFIER_LIST, 0x10, 0x04,
1425 0x92, 0x61, 0x54, 0x23, 0x42,
1426 0x92, 0x72, 0x54, 0x24, 0x43,
1427 0x92, 0x83, 0x54, 0x25, 0x44
1428 };
1429 uint8_t rc_enc;
1430 int rc_dec, i;
1431
1432 memset(&enc_cil, 0, sizeof(enc_cil));
1433 enc_cil.id_discr = CELL_IDENT_LAI_AND_LAC;
1434
1435 id.plmn.mcc = 0x123;
1436 osmo_mnc_from_str("456", &id.plmn.mnc, &id.plmn.mnc_3_digits);
1437 id.lac = 0x2342;
1438 memcpy(&enc_cil.id_list[0].lai_and_lac, &id, sizeof(id));
1439
1440 id.plmn.mcc = 0x124;
1441 osmo_mnc_from_str("457", &id.plmn.mnc, &id.plmn.mnc_3_digits);
1442 id.lac = 0x2443;
1443 memcpy(&enc_cil.id_list[1].lai_and_lac, &id, sizeof(id));
1444
1445 id.plmn.mcc = 0x125;
1446 osmo_mnc_from_str("458", &id.plmn.mnc, &id.plmn.mnc_3_digits);
1447 id.lac = 0x2544;
1448 memcpy(&enc_cil.id_list[2].lai_and_lac, &id, sizeof(id));
1449
1450 enc_cil.id_list_len = 3;
1451
1452 msg = msgb_alloc(1024, "output buffer");
1453 rc_enc = gsm0808_enc_cell_id_list2(msg, &enc_cil);
1454 OSMO_ASSERT(rc_enc == sizeof(cil_enc_expected));
1455 OSMO_ASSERT(memcmp(cil_enc_expected, msg->data, msg->len) == 0);
1456
1457 rc_dec = gsm0808_dec_cell_id_list2(&dec_cil, msg->data + 2, msg->len - 2);
1458 OSMO_ASSERT(rc_dec == msg->len - 2);
1459
1460 OSMO_ASSERT(dec_cil.id_list_len == 3);
1461 /* Check MAXLEN elements to ensure everything has been initialized. */
1462 for (i = 0; i < GSM0808_CELL_ID_LIST2_MAXLEN; i++) {
1463 struct osmo_location_area_id *enc_id;
1464 struct osmo_location_area_id *dec_id;
1465 enc_id = &enc_cil.id_list[i].lai_and_lac;
1466 dec_id = &dec_cil.id_list[i].lai_and_lac;
1467 OSMO_ASSERT(osmo_plmn_cmp(&enc_id->plmn, &dec_id->plmn) == 0);
1468 OSMO_ASSERT(enc_id->lac == dec_id->lac);
1469 }
1470
1471 msgb_free(msg);
1472}
1473
Harald Weltee61d4592022-11-03 11:05:58 +01001474static void test_gsm0808_enc_dec_cell_id_list_multi_ci(void)
Stefan Sperling9c62fc62018-03-16 10:23:34 +01001475{
1476 struct gsm0808_cell_id_list2 enc_cil;
1477 struct gsm0808_cell_id_list2 dec_cil;
1478 struct msgb *msg;
1479 uint8_t cil_enc_expected[] = { GSM0808_IE_CELL_IDENTIFIER_LIST, 0x09, 0x02,
1480 0x00, 0x01,
1481 0x00, 0x02,
1482 0x00, 0x77,
1483 0x01, 0xff,
1484 };
1485 uint8_t rc_enc;
1486 int rc_dec;
1487
1488 memset(&enc_cil, 0, sizeof(enc_cil));
1489 enc_cil.id_discr = CELL_IDENT_CI;
1490 enc_cil.id_list[0].ci = 1;
1491 enc_cil.id_list[1].ci = 2;
1492 enc_cil.id_list[2].ci = 119;
1493 enc_cil.id_list[3].ci = 511;
1494 enc_cil.id_list_len = 4;
1495
1496 msg = msgb_alloc(1024, "output buffer");
1497 rc_enc = gsm0808_enc_cell_id_list2(msg, &enc_cil);
1498 OSMO_ASSERT(rc_enc == sizeof(cil_enc_expected));
1499 OSMO_ASSERT(memcmp(cil_enc_expected, msg->data, msg->len) == 0);
1500
1501 rc_dec = gsm0808_dec_cell_id_list2(&dec_cil, msg->data + 2, msg->len - 2);
1502 OSMO_ASSERT(rc_dec == msg->len - 2);
1503 OSMO_ASSERT(memcmp(&enc_cil, &dec_cil, sizeof(enc_cil)) == 0);
1504
1505 msgb_free(msg);
1506}
1507
Harald Weltee61d4592022-11-03 11:05:58 +01001508static void test_gsm0808_enc_dec_cell_id_list_multi_lac_and_ci(void)
Stefan Sperlinged4327c2018-03-16 11:02:59 +01001509{
1510 struct gsm0808_cell_id_list2 enc_cil;
1511 struct gsm0808_cell_id_list2 dec_cil;
1512 struct msgb *msg;
1513 uint8_t cil_enc_expected[] = { GSM0808_IE_CELL_IDENTIFIER_LIST, 0x15, 0x01,
1514 0x23, 0x42, 0x00, 0x01,
1515 0x24, 0x43, 0x00, 0x02,
1516 0x25, 0x44, 0x00, 0x77,
1517 0x26, 0x45, 0x01, 0xff,
1518 0x27, 0x46, 0x02, 0xfe,
1519 };
1520 uint8_t rc_enc;
1521 int rc_dec;
1522
1523 memset(&enc_cil, 0, sizeof(enc_cil));
1524 enc_cil.id_discr = CELL_IDENT_LAC_AND_CI;
1525 enc_cil.id_list[0].lac_and_ci.lac = 0x2342;
1526 enc_cil.id_list[0].lac_and_ci.ci = 1;
1527 enc_cil.id_list[1].lac_and_ci.lac = 0x2443;
1528 enc_cil.id_list[1].lac_and_ci.ci = 2;
1529 enc_cil.id_list[2].lac_and_ci.lac = 0x2544;
1530 enc_cil.id_list[2].lac_and_ci.ci = 119;
1531 enc_cil.id_list[3].lac_and_ci.lac = 0x2645;
1532 enc_cil.id_list[3].lac_and_ci.ci = 511;
1533 enc_cil.id_list[4].lac_and_ci.lac = 0x2746;
1534 enc_cil.id_list[4].lac_and_ci.ci = 766;
1535 enc_cil.id_list_len = 5;
1536
1537 msg = msgb_alloc(1024, "output buffer");
1538 rc_enc = gsm0808_enc_cell_id_list2(msg, &enc_cil);
1539 OSMO_ASSERT(rc_enc == sizeof(cil_enc_expected));
1540 OSMO_ASSERT(memcmp(cil_enc_expected, msg->data, msg->len) == 0);
1541
1542 rc_dec = gsm0808_dec_cell_id_list2(&dec_cil, msg->data + 2, msg->len - 2);
1543 OSMO_ASSERT(rc_dec == msg->len - 2);
1544 OSMO_ASSERT(memcmp(&enc_cil, &dec_cil, sizeof(enc_cil)) == 0);
1545
1546 msgb_free(msg);
1547}
1548
Harald Weltee61d4592022-11-03 11:05:58 +01001549static void test_gsm0808_enc_dec_cell_id_list_multi_global(void)
Stefan Sperling483f3862018-03-16 12:21:26 +01001550{
1551 struct gsm0808_cell_id_list2 enc_cil;
1552 struct gsm0808_cell_id_list2 dec_cil;
1553 struct msgb *msg;
1554 uint8_t cil_enc_expected[] = { GSM0808_IE_CELL_IDENTIFIER_LIST, 0x16, 0x00,
Neels Hofmeyr473485c2018-03-23 02:04:18 +01001555 0x21, 0x63, 0x54, 0x23, 0x42, 0x00, 0x1,
Neels Hofmeyrc44fc232018-03-23 02:15:12 +01001556 0x21, 0xf4, 0x75, 0x24, 0x43, 0x00, 0x2,
Neels Hofmeyr8b8cd932018-03-23 01:47:37 +01001557 0x21, 0x75, 0x00, 0x25, 0x44, 0x00, 0x77
Stefan Sperling483f3862018-03-16 12:21:26 +01001558 };
Stefan Sperling483f3862018-03-16 12:21:26 +01001559 uint8_t rc_enc;
1560 int rc_dec, i;
1561
Neels Hofmeyrc1991df2018-03-23 02:00:00 +01001562 enc_cil = (struct gsm0808_cell_id_list2){
1563 .id_discr = CELL_IDENT_WHOLE_GLOBAL,
1564 .id_list_len = 3,
1565 .id_list = {
1566 {
1567 .global = {
Neels Hofmeyr473485c2018-03-23 02:04:18 +01001568 .lai = { .plmn = { .mcc = 123, .mnc = 456 },
Neels Hofmeyrc1991df2018-03-23 02:00:00 +01001569 .lac = 0x2342 },
1570 .cell_identity = 1,
1571 }
1572 },
1573 {
1574 .global = {
Neels Hofmeyrc44fc232018-03-23 02:15:12 +01001575 .lai = { .plmn = { .mcc = 124, .mnc = 57 },
Neels Hofmeyrc1991df2018-03-23 02:00:00 +01001576 .lac = 0x2443 },
1577 .cell_identity = 2,
1578 }
1579 },
1580 {
1581 .global = {
Neels Hofmeyrc44fc232018-03-23 02:15:12 +01001582 .lai = { .plmn = { .mcc = 125, .mnc = 7,
1583 .mnc_3_digits = true },
Neels Hofmeyrc1991df2018-03-23 02:00:00 +01001584 .lac = 0x2544 },
1585 .cell_identity = 119,
1586 }
1587 },
1588 }
1589 };
Stefan Sperling483f3862018-03-16 12:21:26 +01001590
1591 msg = msgb_alloc(1024, "output buffer");
1592 rc_enc = gsm0808_enc_cell_id_list2(msg, &enc_cil);
1593 OSMO_ASSERT(rc_enc == sizeof(cil_enc_expected));
Neels Hofmeyrc1991df2018-03-23 02:00:00 +01001594 if (memcmp(cil_enc_expected, msg->data, msg->len)) {
1595 printf(" got: %s\n", osmo_hexdump(msg->data, msg->len));
1596 printf("expect: %s\n", osmo_hexdump(cil_enc_expected, sizeof(cil_enc_expected)));
1597 OSMO_ASSERT(false);
1598 }
Stefan Sperling483f3862018-03-16 12:21:26 +01001599
1600 rc_dec = gsm0808_dec_cell_id_list2(&dec_cil, msg->data + 2, msg->len - 2);
1601 OSMO_ASSERT(rc_dec == msg->len - 2);
1602
1603 /* Check MAXLEN elements to ensure everything has been initialized. */
1604 for (i = 0; i < GSM0808_CELL_ID_LIST2_MAXLEN; i++) {
1605 struct osmo_cell_global_id *enc_id;
1606 struct osmo_cell_global_id *dec_id;
1607 enc_id = &enc_cil.id_list[i].global;
1608 dec_id = &dec_cil.id_list[i].global;
1609 OSMO_ASSERT(osmo_plmn_cmp(&enc_id->lai.plmn, &dec_id->lai.plmn) == 0);
1610 OSMO_ASSERT(enc_id->lai.lac == dec_id->lai.lac);
1611 OSMO_ASSERT(enc_id->cell_identity == dec_id->cell_identity);
1612 }
1613
1614 msgb_free(msg);
1615}
1616
Neels Hofmeyr74663d92018-03-23 01:46:42 +01001617static void print_cil(const struct gsm0808_cell_id_list2 *cil)
1618{
Neels Hofmeyra4399c82018-04-17 02:26:10 +02001619 printf(" cell_id_list == %s\n", gsm0808_cell_id_list_name(cil));
Neels Hofmeyr74663d92018-03-23 01:46:42 +01001620}
1621
Harald Weltee61d4592022-11-03 11:05:58 +01001622void test_cell_id_list_add(void) {
Neels Hofmeyra4399c82018-04-17 02:26:10 +02001623 size_t zu;
1624
Neels Hofmeyr74663d92018-03-23 01:46:42 +01001625 const struct gsm0808_cell_id_list2 cgi1 = {
1626 .id_discr = CELL_IDENT_WHOLE_GLOBAL,
1627 .id_list_len = 1,
1628 .id_list = {
1629 {
1630 .global = {
1631 .lai = {
1632 .plmn = { .mcc = 1, .mnc = 2, .mnc_3_digits = false },
1633 .lac = 3,
1634 },
1635 .cell_identity = 4,
1636 }
1637 },
1638 },
1639 };
1640
1641 const struct gsm0808_cell_id_list2 cgi2 = {
1642 .id_discr = CELL_IDENT_WHOLE_GLOBAL,
1643 .id_list_len = 2,
1644 .id_list = {
1645 {
1646 .global = {
1647 .lai = {
1648 .plmn = { .mcc = 1, .mnc = 2, .mnc_3_digits = true },
1649 .lac = 3,
1650 },
1651 .cell_identity = 4,
1652 }
1653 },
1654 {
1655 .global = {
1656 .lai = {
1657 .plmn = { .mcc = 5, .mnc = 6, .mnc_3_digits = true },
1658 .lac = 7,
1659 },
1660 .cell_identity = 8,
1661 }
1662 },
1663 },
1664 };
1665
1666 const struct gsm0808_cell_id_list2 cgi2a = {
1667 .id_discr = CELL_IDENT_WHOLE_GLOBAL,
1668 .id_list_len = 2,
1669 .id_list = {
1670 {
1671 .global = cgi2.id_list[0].global
1672 },
1673 {
1674 .global = {
1675 .lai = {
1676 .plmn = { .mcc = 9, .mnc = 10, .mnc_3_digits = true },
1677 .lac = 11,
1678 },
1679 .cell_identity = 12,
1680 }
1681 },
1682 },
1683 };
1684
1685 const struct gsm0808_cell_id_list2 cgi3 = {
1686 .id_discr = CELL_IDENT_WHOLE_GLOBAL,
1687 .id_list_len = 2,
1688 .id_list = {
1689 {
1690 .global = {
1691 .lai = {
1692 .plmn = { .mcc = 13, .mnc = 14, .mnc_3_digits = true },
1693 .lac = 15,
1694 },
1695 .cell_identity = 16,
1696 }
1697 },
1698 {
1699 .global = {
1700 .lai = {
1701 .plmn = { .mcc = 16, .mnc = 17, .mnc_3_digits = true },
1702 .lac = 18,
1703 },
1704 .cell_identity = 19,
1705 }
1706 },
1707 },
1708 };
1709
1710
1711 const struct gsm0808_cell_id_list2 lac1 = {
1712 .id_discr = CELL_IDENT_LAC,
1713 .id_list_len = 1,
1714 .id_list = {
1715 {
1716 .lac = 123
1717 },
1718 },
1719 };
1720
1721 const struct gsm0808_cell_id_list2 lac2 = {
1722 .id_discr = CELL_IDENT_LAC,
1723 .id_list_len = 2,
1724 .id_list = {
1725 {
1726 .lac = 456
1727 },
1728 {
1729 .lac = 789
1730 },
1731 },
1732 };
1733
1734 struct gsm0808_cell_id_list2 cil = {};
1735
1736 printf("------- %s\n", __func__);
1737
1738 print_cil(&cil);
1739
1740#define ADD_QUIET(other_cil, expect_rc) do { \
1741 int rc = gsm0808_cell_id_list_add(&cil, &other_cil); \
Neels Hofmeyra4399c82018-04-17 02:26:10 +02001742 printf("gsm0808_cell_id_list_add(&cil, &" #other_cil ") --> rc = %d\n", rc); \
Neels Hofmeyr74663d92018-03-23 01:46:42 +01001743 OSMO_ASSERT(rc == expect_rc); \
1744 } while(0)
1745
1746#define ADD(other_cil, expect_rc) ADD_QUIET(other_cil, expect_rc); print_cil(&cil)
1747
1748 ADD(lac1, 1);
1749 ADD(lac1, 0);
1750 ADD(lac2, 2);
1751 ADD(lac2, 0);
1752 ADD(cil, 0);
1753 ADD(cgi1, -EINVAL);
1754
Neels Hofmeyra4399c82018-04-17 02:26:10 +02001755 printf("* can't add to BSS list\n");
Neels Hofmeyr74663d92018-03-23 01:46:42 +01001756 cil.id_list_len = 0;
1757 cil.id_discr = CELL_IDENT_BSS;
1758 print_cil(&cil);
1759 ADD(lac1, -EINVAL);
1760
Neels Hofmeyra4399c82018-04-17 02:26:10 +02001761 printf("* other types (including NO_CELL) take on new type iff empty\n");
Neels Hofmeyr74663d92018-03-23 01:46:42 +01001762 cil.id_list_len = 0;
1763 cil.id_discr = CELL_IDENT_NO_CELL;
1764 print_cil(&cil);
1765 ADD(cgi1, 1);
1766 ADD(cgi1, 0);
1767 ADD(cgi2, 2);
1768 ADD(cgi2, 0);
1769
Neels Hofmeyra4399c82018-04-17 02:26:10 +02001770 printf("* test gsm0808_cell_id_list_name_buf()'s return val\n");
1771 zu = strlen(gsm0808_cell_id_list_name(&cil));
1772 printf(" strlen(gsm0808_cell_id_list_name(cil)) == %zu\n", zu);
1773 zu ++;
1774 while (1) {
1775 char buf[128] = "?";
1776 int rc;
1777 OSMO_ASSERT(zu < sizeof(buf));
1778 buf[zu] = '#';
1779 rc = gsm0808_cell_id_list_name_buf(buf, zu, &cil);
1780 printf(" gsm0808_cell_id_list_name_buf(buf, %zu, cil)) == %d \"%s\"\n",
1781 zu, rc, buf);
1782 OSMO_ASSERT(buf[zu] == '#');
1783 if (!zu)
1784 break;
1785 zu /= 2;
1786 }
1787
1788 printf("* list-full behavior\n");
Neels Hofmeyr74663d92018-03-23 01:46:42 +01001789 cil.id_list_len = GSM0808_CELL_ID_LIST2_MAXLEN - 1;
Neels Hofmeyra4399c82018-04-17 02:26:10 +02001790 printf("cil.id_list_len = %u\n", cil.id_list_len);
Neels Hofmeyr74663d92018-03-23 01:46:42 +01001791 ADD_QUIET(cgi2a, 1);
1792 printf("cil.id_list_len = %u\n", cil.id_list_len);
1793
1794 cil.id_list_len = GSM0808_CELL_ID_LIST2_MAXLEN - 1;
Neels Hofmeyra4399c82018-04-17 02:26:10 +02001795 printf("cil.id_list_len = %u\n", cil.id_list_len);
Neels Hofmeyr74663d92018-03-23 01:46:42 +01001796 ADD_QUIET(cgi3, -ENOSPC);
Neels Hofmeyra4399c82018-04-17 02:26:10 +02001797 printf("cil.id_list_len = %u\n", cil.id_list_len);
Neels Hofmeyr74663d92018-03-23 01:46:42 +01001798 ADD_QUIET(cgi2a, -ENOSPC);
1799 printf("cil.id_list_len = %u\n", cil.id_list_len);
1800
1801 printf("------- %s done\n", __func__);
1802}
1803
Harald Weltee61d4592022-11-03 11:05:58 +01001804static void test_gsm0808_enc_dec_cell_id_lac(void)
Neels Hofmeyr250e7f72018-04-13 03:30:14 +02001805{
1806 struct gsm0808_cell_id enc_ci = {
1807 .id_discr = CELL_IDENT_LAC,
1808 .id.lac = 0x0124,
1809 };
1810 struct gsm0808_cell_id dec_ci;
1811 struct msgb *msg;
1812 uint8_t rc_enc;
1813 int rc_dec;
1814
1815 memset(&dec_ci, 0xa5, sizeof(dec_ci));
1816
1817 msg = msgb_alloc(1024, "output buffer");
1818 rc_enc = gsm0808_enc_cell_id(msg, &enc_ci);
1819 EXPECT_ENCODED("05 03 05 01 24");
1820
1821 rc_dec = gsm0808_dec_cell_id(&dec_ci, msg->data + 2, msg->len - 2);
1822 OSMO_ASSERT(rc_dec == 3);
1823
1824 OSMO_ASSERT(enc_ci.id_discr == dec_ci.id_discr
1825 && enc_ci.id.lac == dec_ci.id.lac);
1826
1827 msgb_free(msg);
1828}
1829
Harald Weltee61d4592022-11-03 11:05:58 +01001830static void test_gsm0808_enc_dec_cell_id_bss(void)
Neels Hofmeyr250e7f72018-04-13 03:30:14 +02001831{
1832 struct gsm0808_cell_id enc_ci = {
1833 .id_discr = CELL_IDENT_BSS,
1834 };
1835 struct gsm0808_cell_id dec_ci;
1836 struct msgb *msg;
1837 uint8_t rc_enc;
1838 int rc_dec;
1839
1840 msg = msgb_alloc(1024, "output buffer");
1841 rc_enc = gsm0808_enc_cell_id(msg, &enc_ci);
1842 EXPECT_ENCODED("05 01 06");
1843
1844 rc_dec = gsm0808_dec_cell_id(&dec_ci, msg->data + 2, msg->len - 2);
1845 OSMO_ASSERT(rc_dec == 1);
1846
1847 OSMO_ASSERT(enc_ci.id_discr == dec_ci.id_discr);
1848
1849 msgb_free(msg);
1850}
1851
Harald Weltee61d4592022-11-03 11:05:58 +01001852static void test_gsm0808_enc_dec_cell_id_no_cell(void)
Neels Hofmeyr250e7f72018-04-13 03:30:14 +02001853{
1854 struct gsm0808_cell_id enc_ci = {
1855 .id_discr = CELL_IDENT_NO_CELL,
1856 };
1857 struct gsm0808_cell_id dec_ci;
1858 struct msgb *msg;
1859 uint8_t rc_enc;
1860 int rc_dec;
1861
1862 msg = msgb_alloc(1024, "output buffer");
1863 rc_enc = gsm0808_enc_cell_id(msg, &enc_ci);
1864 EXPECT_ENCODED("05 01 03");
1865
1866 rc_dec = gsm0808_dec_cell_id(&dec_ci, msg->data + 2, msg->len - 2);
1867 OSMO_ASSERT(rc_dec == 1);
1868
1869 OSMO_ASSERT(enc_ci.id_discr == dec_ci.id_discr);
1870
1871 msgb_free(msg);
1872}
1873
Harald Weltee61d4592022-11-03 11:05:58 +01001874static void test_gsm0808_enc_dec_cell_id_lai_and_lac(void)
Neels Hofmeyr250e7f72018-04-13 03:30:14 +02001875{
1876 struct gsm0808_cell_id enc_ci = {
1877 .id_discr = CELL_IDENT_LAI_AND_LAC,
1878 .id.lai_and_lac = {
1879 .plmn = {
1880 .mcc = 123,
1881 .mnc = 456,
1882 },
1883 .lac = 0x2342,
1884 },
1885 };
1886 struct gsm0808_cell_id dec_ci;
1887 struct msgb *msg;
1888 uint8_t rc_enc;
1889 int rc_dec;
1890
1891 msg = msgb_alloc(1024, "output buffer");
1892 rc_enc = gsm0808_enc_cell_id(msg, &enc_ci);
1893 EXPECT_ENCODED("05 06 04 21 63 54 23 42");
1894
1895 memset(&dec_ci, 0xa5, sizeof(dec_ci));
1896 rc_dec = gsm0808_dec_cell_id(&dec_ci, msg->data + 2, msg->len - 2);
1897 OSMO_ASSERT(rc_dec == msg->len - 2);
1898
1899 OSMO_ASSERT(enc_ci.id_discr == dec_ci.id_discr
1900 && osmo_plmn_cmp(&enc_ci.id.lai_and_lac.plmn, &dec_ci.id.lai_and_lac.plmn) == 0
1901 && enc_ci.id.lai_and_lac.lac == dec_ci.id.lai_and_lac.lac);
1902 msgb_free(msg);
1903}
1904
Harald Weltee61d4592022-11-03 11:05:58 +01001905static void test_gsm0808_enc_dec_cell_id_ci(void)
Neels Hofmeyr250e7f72018-04-13 03:30:14 +02001906{
1907 struct gsm0808_cell_id enc_ci = {
1908 .id_discr = CELL_IDENT_CI,
1909 .id.ci = 0x423,
1910 };
1911 struct gsm0808_cell_id dec_ci;
1912 struct msgb *msg;
1913 uint8_t rc_enc;
1914 int rc_dec;
1915
1916 msg = msgb_alloc(1024, "output buffer");
1917 rc_enc = gsm0808_enc_cell_id(msg, &enc_ci);
1918 EXPECT_ENCODED("05 03 02 04 23");
1919
1920 rc_dec = gsm0808_dec_cell_id(&dec_ci, msg->data + 2, msg->len - 2);
1921 OSMO_ASSERT(rc_dec == msg->len - 2);
1922 OSMO_ASSERT(enc_ci.id_discr == dec_ci.id_discr
1923 && enc_ci.id.ci == dec_ci.id.ci);
1924
1925 msgb_free(msg);
1926}
1927
Harald Weltee61d4592022-11-03 11:05:58 +01001928static void test_gsm0808_enc_dec_cell_id_lac_and_ci(void)
Neels Hofmeyr250e7f72018-04-13 03:30:14 +02001929{
1930 struct gsm0808_cell_id enc_ci = {
1931 .id_discr = CELL_IDENT_LAC_AND_CI,
1932 .id.lac_and_ci = {
1933 .lac = 0x423,
1934 .ci = 0x235,
1935 },
1936 };
1937 struct gsm0808_cell_id dec_ci;
1938 struct msgb *msg;
1939 uint8_t rc_enc;
1940 int rc_dec;
1941
1942 msg = msgb_alloc(1024, "output buffer");
1943 rc_enc = gsm0808_enc_cell_id(msg, &enc_ci);
1944 EXPECT_ENCODED("05 05 01 04 23 02 35");
1945
1946 rc_dec = gsm0808_dec_cell_id(&dec_ci, msg->data + 2, msg->len - 2);
1947 OSMO_ASSERT(rc_dec == msg->len - 2);
1948 OSMO_ASSERT(enc_ci.id_discr == dec_ci.id_discr
1949 && enc_ci.id.lac_and_ci.lac == dec_ci.id.lac_and_ci.lac
1950 && enc_ci.id.lac_and_ci.ci == dec_ci.id.lac_and_ci.ci);
1951
1952 msgb_free(msg);
1953}
1954
Harald Weltee61d4592022-11-03 11:05:58 +01001955static void test_gsm0808_enc_dec_cell_id_global(void)
Neels Hofmeyr250e7f72018-04-13 03:30:14 +02001956{
1957 struct gsm0808_cell_id enc_ci = {
1958 .id_discr = CELL_IDENT_WHOLE_GLOBAL,
1959 .id.global = {
1960 .lai = {
1961 .plmn = { .mcc = 123, .mnc = 456 },
1962 .lac = 0x2342
1963 },
1964 .cell_identity = 0x423,
1965 }
1966 };
1967 struct gsm0808_cell_id dec_ci;
1968 struct msgb *msg;
1969 uint8_t rc_enc;
1970 int rc_dec;
1971
1972 msg = msgb_alloc(1024, "output buffer");
1973 rc_enc = gsm0808_enc_cell_id(msg, &enc_ci);
1974 EXPECT_ENCODED("05 08 00 21 63 54 23 42 04 23");
1975
1976 rc_dec = gsm0808_dec_cell_id(&dec_ci, msg->data + 2, msg->len - 2);
1977 OSMO_ASSERT(rc_dec == msg->len - 2);
1978
1979 OSMO_ASSERT(enc_ci.id_discr == dec_ci.id_discr
1980 && osmo_plmn_cmp(&enc_ci.id.global.lai.plmn,
1981 &dec_ci.id.global.lai.plmn) == 0
1982 && enc_ci.id.global.lai.lac == dec_ci.id.global.lai.lac
1983 && enc_ci.id.global.cell_identity == dec_ci.id.global.cell_identity);
1984 msgb_free(msg);
1985}
1986
Harald Weltee61d4592022-11-03 11:05:58 +01001987static void test_gsm0808_enc_dec_cell_id_global_ps(void)
Pau Espin Pedrol52489852021-02-15 16:26:37 +01001988{
1989 struct gsm0808_cell_id enc_cgi = {
1990 .id_discr = CELL_IDENT_WHOLE_GLOBAL,
1991 .id.global = {
1992 .lai = {
1993 .plmn = { .mcc = 123, .mnc = 456 },
1994 .lac = 0x2342
1995 },
1996 .cell_identity = 0x423,
1997 }
1998 };
1999 struct gsm0808_cell_id enc_cgi_ps = {
2000 .id_discr = CELL_IDENT_WHOLE_GLOBAL_PS,
2001 .id.global_ps = {
2002 .rai = {
2003 .lac = {
2004 .plmn = { .mcc = 123, .mnc = 456 },
2005 .lac = 0x2342
2006 },
2007 .rac = 0xcc,
2008 },
2009 .cell_identity = 0x423,
2010 }
2011 };
2012 struct msgb *msg_cgi, *msg_cgi_ps;
2013 uint8_t rc_enc;
2014
2015 msg_cgi = msgb_alloc(1024, "output buffer (CGI)");
2016 rc_enc = gsm0808_enc_cell_id(msg_cgi, &enc_cgi);
2017 OSMO_ASSERT(rc_enc > 0);
2018
2019 msg_cgi_ps = msgb_alloc(1024, "output buffer (CGI-PS)");
2020 rc_enc = gsm0808_enc_cell_id(msg_cgi_ps, &enc_cgi_ps);
2021 OSMO_ASSERT(rc_enc > 0);
2022
2023 OSMO_ASSERT(msgb_eq(msg_cgi, msg_cgi_ps));
2024
2025 msgb_free(msg_cgi);
2026 msgb_free(msg_cgi_ps);
2027}
2028
Neels Hofmeyrf2c0fcc2022-09-07 00:37:08 +02002029static void print_s15_s0(uint16_t s15_s0, bool full_rate)
2030{
2031 int i;
2032 printf(" S15-S0 = 0x%04x = 0b" OSMO_BIN_SPEC OSMO_BIN_SPEC "\n", s15_s0,
2033 OSMO_BIN_PRINT(s15_s0 >> 8), OSMO_BIN_PRINT(s15_s0));
2034 for (i = 0; i < 16; i++) {
2035 uint8_t modes;
2036 int m;
2037 int space;
2038
2039 if (!(s15_s0 & (1 << i)))
2040 continue;
2041
2042 space = 6;
2043 if (i < 10)
2044 space++;
2045
2046 printf(" S%d", i);
2047
2048 modes = gsm0808_amr_modes_from_cfg[full_rate ? 1 : 0][i];
2049 if (!modes) {
2050 printf(" (empty)\n");
2051 continue;
2052 }
2053
2054 for (m = 0; m < 8; m++) {
2055 if (!(modes & (1 << m))) {
2056 /* avoid whitespace at line ends -- accumulate whitespace width until there is
2057 * non-whitespace to actually be printed.*/
2058 space += 8;
2059 continue;
2060 }
2061 printf("%*s", space, gsm0808_amr_mode_name(m));
2062 space = 8;
2063 }
2064 printf("\n");
2065 }
2066}
2067
2068static void print_mr_cfg(const struct gsm48_multi_rate_conf *cfg)
2069{
2070 printf(" cfg.smod=%u spare=%u icmi=%u nscb=%u ver=%u\n",
2071 cfg->smod, cfg->spare, cfg->icmi, cfg->nscb, cfg->ver);
2072 printf(" ");
2073#define PRINT_MODE_BIT(NAME) do { \
2074 if (cfg->NAME) \
2075 printf(" " #NAME "=1"); \
2076 else \
2077 printf(" -------"); \
2078 } while (0)
2079 PRINT_MODE_BIT(m4_75);
2080 PRINT_MODE_BIT(m5_15);
2081 PRINT_MODE_BIT(m5_90);
2082 PRINT_MODE_BIT(m6_70);
2083 PRINT_MODE_BIT(m7_40);
2084 PRINT_MODE_BIT(m7_95);
2085 PRINT_MODE_BIT(m10_2);
2086 PRINT_MODE_BIT(m12_2);
2087 printf("\n");
2088}
2089
Philipp Maier5f2eb152018-09-19 13:40:21 +02002090static void test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(struct gsm48_multi_rate_conf *cfg)
2091{
2092 uint16_t s15_s0;
2093
2094 printf("Input:\n");
Neels Hofmeyrf2c0fcc2022-09-07 00:37:08 +02002095 print_mr_cfg(cfg);
Philipp Maier5f2eb152018-09-19 13:40:21 +02002096
2097 s15_s0 = gsm0808_sc_cfg_from_gsm48_mr_cfg(cfg, true);
2098 printf("Result (fr):\n");
Neels Hofmeyrf2c0fcc2022-09-07 00:37:08 +02002099 print_s15_s0(s15_s0, true);
Philipp Maier5f2eb152018-09-19 13:40:21 +02002100
2101 s15_s0 = gsm0808_sc_cfg_from_gsm48_mr_cfg(cfg, false);
2102 printf("Result (hr):\n");
Neels Hofmeyrf2c0fcc2022-09-07 00:37:08 +02002103 print_s15_s0(s15_s0, false);
Philipp Maier5f2eb152018-09-19 13:40:21 +02002104
2105 printf("\n");
2106}
2107
2108static void test_gsm0808_sc_cfg_from_gsm48_mr_cfg(void)
2109{
2110 struct gsm48_multi_rate_conf cfg;
2111
2112 printf("Testing gsm0808_sc_cfg_from_gsm48_mr_cfg():\n");
2113
2114 memset(&cfg, 0, sizeof(cfg));
2115
2116 cfg.m4_75 = 0;
2117 cfg.m5_15 = 0;
2118 cfg.m5_90 = 0;
2119 cfg.m6_70 = 0;
2120 cfg.m7_40 = 0;
2121 cfg.m7_95 = 0;
2122 cfg.m10_2 = 0;
2123 cfg.m12_2 = 0;
2124 test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(&cfg);
2125
2126 cfg.m4_75 = 1;
2127 cfg.m5_15 = 0;
2128 cfg.m5_90 = 0;
2129 cfg.m6_70 = 0;
2130 cfg.m7_40 = 0;
2131 cfg.m7_95 = 0;
2132 cfg.m10_2 = 0;
2133 cfg.m12_2 = 0;
2134 test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(&cfg);
2135
2136 cfg.m4_75 = 0;
2137 cfg.m5_15 = 1;
2138 cfg.m5_90 = 0;
2139 cfg.m6_70 = 0;
2140 cfg.m7_40 = 0;
2141 cfg.m7_95 = 0;
2142 cfg.m10_2 = 0;
2143 cfg.m12_2 = 0;
2144 test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(&cfg);
2145
2146 cfg.m4_75 = 0;
2147 cfg.m5_15 = 0;
2148 cfg.m5_90 = 1;
2149 cfg.m6_70 = 0;
2150 cfg.m7_40 = 0;
2151 cfg.m7_95 = 0;
2152 cfg.m10_2 = 0;
2153 cfg.m12_2 = 0;
2154 test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(&cfg);
2155
2156 cfg.m4_75 = 0;
2157 cfg.m5_15 = 0;
2158 cfg.m5_90 = 0;
2159 cfg.m6_70 = 1;
2160 cfg.m7_40 = 0;
2161 cfg.m7_95 = 0;
2162 cfg.m10_2 = 0;
2163 cfg.m12_2 = 0;
2164 test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(&cfg);
2165
2166 cfg.m4_75 = 0;
2167 cfg.m5_15 = 0;
2168 cfg.m5_90 = 0;
2169 cfg.m6_70 = 0;
2170 cfg.m7_40 = 1;
2171 cfg.m7_95 = 0;
2172 cfg.m10_2 = 0;
2173 cfg.m12_2 = 0;
2174 test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(&cfg);
2175
2176 cfg.m4_75 = 0;
2177 cfg.m5_15 = 0;
2178 cfg.m5_90 = 0;
2179 cfg.m6_70 = 0;
2180 cfg.m7_40 = 0;
2181 cfg.m7_95 = 1;
2182 cfg.m10_2 = 0;
2183 cfg.m12_2 = 0;
2184 test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(&cfg);
2185
2186 cfg.m4_75 = 0;
2187 cfg.m5_15 = 0;
2188 cfg.m5_90 = 0;
2189 cfg.m6_70 = 0;
2190 cfg.m7_40 = 0;
2191 cfg.m7_95 = 0;
2192 cfg.m10_2 = 1;
2193 cfg.m12_2 = 0;
2194 test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(&cfg);
2195
2196 cfg.m4_75 = 0;
2197 cfg.m5_15 = 0;
2198 cfg.m5_90 = 0;
2199 cfg.m6_70 = 0;
2200 cfg.m7_40 = 0;
2201 cfg.m7_95 = 0;
2202 cfg.m10_2 = 0;
2203 cfg.m12_2 = 1;
2204 test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(&cfg);
2205
2206 cfg.m4_75 = 1;
2207 cfg.m5_15 = 1;
2208 cfg.m5_90 = 1;
2209 cfg.m6_70 = 1;
2210 cfg.m7_40 = 0;
2211 cfg.m7_95 = 0;
2212 cfg.m10_2 = 0;
2213 cfg.m12_2 = 0;
2214 test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(&cfg);
2215
2216 cfg.m4_75 = 0;
2217 cfg.m5_15 = 0;
2218 cfg.m5_90 = 0;
2219 cfg.m6_70 = 0;
2220 cfg.m7_40 = 1;
2221 cfg.m7_95 = 1;
2222 cfg.m10_2 = 1;
2223 cfg.m12_2 = 1;
2224 test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(&cfg);
2225
2226 cfg.m4_75 = 0;
2227 cfg.m5_15 = 0;
2228 cfg.m5_90 = 1;
2229 cfg.m6_70 = 1;
2230 cfg.m7_40 = 0;
2231 cfg.m7_95 = 0;
2232 cfg.m10_2 = 1;
2233 cfg.m12_2 = 1;
2234 test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(&cfg);
2235
2236 cfg.m4_75 = 1;
2237 cfg.m5_15 = 1;
2238 cfg.m5_90 = 0;
2239 cfg.m6_70 = 0;
2240 cfg.m7_40 = 1;
2241 cfg.m7_95 = 1;
2242 cfg.m10_2 = 0;
2243 cfg.m12_2 = 0;
2244 test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(&cfg);
2245
2246 cfg.m4_75 = 0;
2247 cfg.m5_15 = 1;
2248 cfg.m5_90 = 0;
2249 cfg.m6_70 = 1;
2250 cfg.m7_40 = 0;
2251 cfg.m7_95 = 1;
2252 cfg.m10_2 = 0;
2253 cfg.m12_2 = 1;
2254 test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(&cfg);
2255
2256 cfg.m4_75 = 1;
2257 cfg.m5_15 = 0;
2258 cfg.m5_90 = 1;
2259 cfg.m6_70 = 0;
2260 cfg.m7_40 = 1;
2261 cfg.m7_95 = 0;
2262 cfg.m10_2 = 1;
2263 cfg.m12_2 = 0;
2264 test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(&cfg);
2265
2266 cfg.m4_75 = 1;
2267 cfg.m5_15 = 1;
2268 cfg.m5_90 = 1;
2269 cfg.m6_70 = 1;
2270 cfg.m7_40 = 1;
2271 cfg.m7_95 = 1;
2272 cfg.m10_2 = 1;
2273 cfg.m12_2 = 1;
2274 test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(&cfg);
Philipp Maier94d79fd2019-03-01 10:40:48 +01002275
2276 cfg.m4_75 = 1;
2277 cfg.m5_15 = 0;
2278 cfg.m5_90 = 1;
2279 cfg.m6_70 = 0;
2280 cfg.m7_40 = 1;
2281 cfg.m7_95 = 0;
2282 cfg.m10_2 = 0;
2283 cfg.m12_2 = 1;
2284 test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(&cfg);
2285
2286 cfg.m4_75 = 1;
2287 cfg.m5_15 = 0;
2288 cfg.m5_90 = 1;
2289 cfg.m6_70 = 0;
2290 cfg.m7_40 = 1;
2291 cfg.m7_95 = 0;
2292 cfg.m10_2 = 0;
2293 cfg.m12_2 = 0;
2294 test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(&cfg);
Pau Espin Pedrol1bd495a2021-02-15 16:15:59 +01002295
Philipp Maier5f2eb152018-09-19 13:40:21 +02002296}
2297
Philipp Maier8515d032018-09-25 15:57:49 +02002298static void test_gsm48_mr_cfg_from_gsm0808_sc_cfg_single(uint16_t s15_s0)
2299{
2300 struct gsm48_multi_rate_conf cfg;
Philipp Maier3713af82019-02-27 16:48:25 +01002301 int rc;
Philipp Maier8515d032018-09-25 15:57:49 +02002302
2303 printf("Input:\n");
Neels Hofmeyrf2c0fcc2022-09-07 00:37:08 +02002304 print_s15_s0(s15_s0, true);
Philipp Maier8515d032018-09-25 15:57:49 +02002305
Philipp Maier3713af82019-02-27 16:48:25 +01002306 rc = gsm48_mr_cfg_from_gsm0808_sc_cfg(&cfg, s15_s0);
Philipp Maier8515d032018-09-25 15:57:49 +02002307
2308 printf("Output:\n");
Neels Hofmeyrf2c0fcc2022-09-07 00:37:08 +02002309 print_mr_cfg(&cfg);
Philipp Maier8515d032018-09-25 15:57:49 +02002310
Philipp Maier3713af82019-02-27 16:48:25 +01002311 if (rc != 0)
2312 printf(" Result invalid!\n");
2313
Philipp Maier8515d032018-09-25 15:57:49 +02002314 printf("\n");
2315}
2316
Harald Weltee61d4592022-11-03 11:05:58 +01002317void test_gsm48_mr_cfg_from_gsm0808_sc_cfg(void)
Philipp Maier8515d032018-09-25 15:57:49 +02002318{
2319 printf("Testing gsm48_mr_cfg_from_gsm0808_sc_cfg():\n");
2320
Philipp Maier3713af82019-02-27 16:48:25 +01002321 /* Test with settings as defined in 3GPP TS 28.062, Table 7.11.3.1.3-2,
2322 * (up to four codecs may become selected) */
Philipp Maier8515d032018-09-25 15:57:49 +02002323 test_gsm48_mr_cfg_from_gsm0808_sc_cfg_single
2324 (GSM0808_SC_CFG_DEFAULT_AMR_4_75);
2325 test_gsm48_mr_cfg_from_gsm0808_sc_cfg_single
2326 (GSM0808_SC_CFG_DEFAULT_AMR_5_15);
2327 test_gsm48_mr_cfg_from_gsm0808_sc_cfg_single
2328 (GSM0808_SC_CFG_DEFAULT_AMR_5_90);
2329 test_gsm48_mr_cfg_from_gsm0808_sc_cfg_single
2330 (GSM0808_SC_CFG_DEFAULT_AMR_6_70);
2331 test_gsm48_mr_cfg_from_gsm0808_sc_cfg_single
2332 (GSM0808_SC_CFG_DEFAULT_AMR_7_40);
2333 test_gsm48_mr_cfg_from_gsm0808_sc_cfg_single
2334 (GSM0808_SC_CFG_DEFAULT_AMR_7_95);
2335 test_gsm48_mr_cfg_from_gsm0808_sc_cfg_single
2336 (GSM0808_SC_CFG_DEFAULT_AMR_10_2);
2337 test_gsm48_mr_cfg_from_gsm0808_sc_cfg_single
2338 (GSM0808_SC_CFG_DEFAULT_AMR_12_2);
2339
Philipp Maier3713af82019-02-27 16:48:25 +01002340 /* Test with settings as defined in 3GPP TS 28.062, Table 7.11.3.1.3-2,
2341 * but pick only one distinctive setting at a time */
2342 test_gsm48_mr_cfg_from_gsm0808_sc_cfg_single(GSM0808_SC_CFG_AMR_4_75);
Philipp Maier8515d032018-09-25 15:57:49 +02002343 test_gsm48_mr_cfg_from_gsm0808_sc_cfg_single
Philipp Maier3713af82019-02-27 16:48:25 +01002344 (GSM0808_SC_CFG_AMR_4_75_5_90_7_40_12_20);
2345 test_gsm48_mr_cfg_from_gsm0808_sc_cfg_single(GSM0808_SC_CFG_AMR_5_90);
2346 test_gsm48_mr_cfg_from_gsm0808_sc_cfg_single(GSM0808_SC_CFG_AMR_6_70);
2347 test_gsm48_mr_cfg_from_gsm0808_sc_cfg_single(GSM0808_SC_CFG_AMR_7_40);
2348 test_gsm48_mr_cfg_from_gsm0808_sc_cfg_single(GSM0808_SC_CFG_AMR_7_95);
2349 test_gsm48_mr_cfg_from_gsm0808_sc_cfg_single(GSM0808_SC_CFG_AMR_10_2);
2350 test_gsm48_mr_cfg_from_gsm0808_sc_cfg_single(GSM0808_SC_CFG_AMR_12_2);
2351
2352 /* Arbitrary, but valid combinations */
2353 test_gsm48_mr_cfg_from_gsm0808_sc_cfg_single(GSM0808_SC_CFG_AMR_7_40 |
2354 GSM0808_SC_CFG_AMR_6_70 |
2355 GSM0808_SC_CFG_AMR_10_2);
2356 test_gsm48_mr_cfg_from_gsm0808_sc_cfg_single(GSM0808_SC_CFG_AMR_7_95 |
2357 GSM0808_SC_CFG_AMR_4_75);
2358 test_gsm48_mr_cfg_from_gsm0808_sc_cfg_single(GSM0808_SC_CFG_AMR_5_90 |
2359 GSM0808_SC_CFG_AMR_12_2);
Philipp Maier8515d032018-09-25 15:57:49 +02002360 test_gsm48_mr_cfg_from_gsm0808_sc_cfg_single
Philipp Maier3713af82019-02-27 16:48:25 +01002361 (GSM0808_SC_CFG_AMR_4_75_5_90_7_40_12_20 | GSM0808_SC_CFG_AMR_5_90 |
2362 GSM0808_SC_CFG_AMR_12_2);
2363
2364 /* Invalid combinations */
Philipp Maier8515d032018-09-25 15:57:49 +02002365 test_gsm48_mr_cfg_from_gsm0808_sc_cfg_single
Philipp Maier3713af82019-02-27 16:48:25 +01002366 (GSM0808_SC_CFG_AMR_4_75_5_90_7_40_12_20 | GSM0808_SC_CFG_AMR_6_70);
2367 test_gsm48_mr_cfg_from_gsm0808_sc_cfg_single(GSM0808_SC_CFG_AMR_7_40 |
2368 GSM0808_SC_CFG_AMR_6_70 |
2369 GSM0808_SC_CFG_AMR_10_2 |
2370 GSM0808_SC_CFG_AMR_7_95 |
2371 GSM0808_SC_CFG_AMR_4_75);
2372 test_gsm48_mr_cfg_from_gsm0808_sc_cfg_single(0x0000);
2373 test_gsm48_mr_cfg_from_gsm0808_sc_cfg_single(0xffff);
Philipp Maier8515d032018-09-25 15:57:49 +02002374}
2375
Neels Hofmeyrd01ef752018-09-21 15:57:26 +02002376struct test_cell_id_matching_data {
2377 struct gsm0808_cell_id id;
2378 struct gsm0808_cell_id match_id;
2379 bool expect_match;
2380 bool expect_exact_match;
2381};
2382
2383#define lac_23 { .id_discr = CELL_IDENT_LAC, .id.lac = 23, }
2384#define lac_42 { .id_discr = CELL_IDENT_LAC, .id.lac = 42, }
2385#define ci_5 { .id_discr = CELL_IDENT_CI, .id.ci = 5, }
2386#define ci_6 { .id_discr = CELL_IDENT_CI, .id.ci = 6, }
2387#define lac_ci_23_5 { \
2388 .id_discr = CELL_IDENT_LAC_AND_CI, \
2389 .id.lac_and_ci = { .lac = 23, .ci = 5, }, \
2390 }
2391#define lac_ci_42_6 { \
2392 .id_discr = CELL_IDENT_LAC_AND_CI, \
2393 .id.lac_and_ci = { .lac = 42, .ci = 6, }, \
2394 }
2395#define lai_23_042_23 { \
2396 .id_discr = CELL_IDENT_LAI_AND_LAC, \
2397 .id.lai_and_lac = { .plmn = { .mcc = 23, .mnc = 42, .mnc_3_digits = true }, .lac = 23, }, \
2398 }
2399#define lai_23_042_42 { \
2400 .id_discr = CELL_IDENT_LAI_AND_LAC, \
2401 .id.lai_and_lac = { .plmn = { .mcc = 23, .mnc = 42, .mnc_3_digits = true }, .lac = 42, }, \
2402 }
2403#define lai_23_99_23 { \
2404 .id_discr = CELL_IDENT_LAI_AND_LAC, \
2405 .id.lai_and_lac = { .plmn = { .mcc = 23, .mnc = 99, .mnc_3_digits = false }, .lac = 23, }, \
2406 }
2407#define lai_23_42_23 { \
2408 .id_discr = CELL_IDENT_LAI_AND_LAC, \
2409 .id.lai_and_lac = { .plmn = { .mcc = 23, .mnc = 42, .mnc_3_digits = false }, .lac = 23, }, \
2410 }
2411#define cgi_23_042_23_5 { \
2412 .id_discr = CELL_IDENT_WHOLE_GLOBAL, \
2413 .id.global = { \
2414 .lai = { .plmn = { .mcc = 23, .mnc = 42, .mnc_3_digits = true }, .lac = 23, }, \
2415 .cell_identity = 5, \
2416 }, \
2417 }
2418#define cgi_23_042_42_6 { \
2419 .id_discr = CELL_IDENT_WHOLE_GLOBAL, \
2420 .id.global = { \
2421 .lai = { .plmn = { .mcc = 23, .mnc = 42, .mnc_3_digits = true }, .lac = 42, }, \
2422 .cell_identity = 6, \
2423 }, \
2424 }
2425#define cgi_23_99_23_5 { \
2426 .id_discr = CELL_IDENT_WHOLE_GLOBAL, \
2427 .id.global = { \
2428 .lai = { .plmn = { .mcc = 23, .mnc = 99, .mnc_3_digits = false }, .lac = 23, }, \
2429 .cell_identity = 5, \
2430 }, \
2431 }
2432
2433
2434static const struct test_cell_id_matching_data test_cell_id_matching_tests[] = {
2435 { .id = lac_23, .match_id = lac_23, .expect_match = true, .expect_exact_match = true },
2436 { .id = lac_23, .match_id = lac_42, .expect_match = false, .expect_exact_match = false },
2437 { .id = lac_23, .match_id = ci_5, .expect_match = true, .expect_exact_match = false },
2438 { .id = lac_23, .match_id = ci_6, .expect_match = true, .expect_exact_match = false },
2439 { .id = lac_23, .match_id = lac_ci_23_5, .expect_match = true, .expect_exact_match = false },
2440 { .id = lac_23, .match_id = lac_ci_42_6, .expect_match = false, .expect_exact_match = false },
2441 { .id = lac_23, .match_id = lai_23_042_23, .expect_match = true, .expect_exact_match = false },
2442 { .id = lac_23, .match_id = lai_23_042_42, .expect_match = false, .expect_exact_match = false },
2443 { .id = lac_23, .match_id = lai_23_99_23, .expect_match = true, .expect_exact_match = false },
2444 { .id = lac_23, .match_id = lai_23_42_23, .expect_match = true, .expect_exact_match = false },
2445 { .id = lac_23, .match_id = cgi_23_042_23_5, .expect_match = true, .expect_exact_match = false },
2446 { .id = lac_23, .match_id = cgi_23_042_42_6, .expect_match = false, .expect_exact_match = false },
2447 { .id = lac_23, .match_id = cgi_23_99_23_5, .expect_match = true, .expect_exact_match = false },
2448 { .id = ci_5, .match_id = lac_23, .expect_match = true, .expect_exact_match = false },
2449 { .id = ci_5, .match_id = lac_42, .expect_match = true, .expect_exact_match = false },
2450 { .id = ci_5, .match_id = ci_5, .expect_match = true, .expect_exact_match = true },
2451 { .id = ci_5, .match_id = ci_6, .expect_match = false, .expect_exact_match = false },
2452 { .id = ci_5, .match_id = lac_ci_23_5, .expect_match = true, .expect_exact_match = false },
2453 { .id = ci_5, .match_id = lac_ci_42_6, .expect_match = false, .expect_exact_match = false },
2454 { .id = ci_5, .match_id = lai_23_042_23, .expect_match = true, .expect_exact_match = false },
2455 { .id = ci_5, .match_id = lai_23_042_42, .expect_match = true, .expect_exact_match = false },
2456 { .id = ci_5, .match_id = lai_23_99_23, .expect_match = true, .expect_exact_match = false },
2457 { .id = ci_5, .match_id = lai_23_42_23, .expect_match = true, .expect_exact_match = false },
2458 { .id = ci_5, .match_id = cgi_23_042_23_5, .expect_match = true, .expect_exact_match = false },
2459 { .id = ci_5, .match_id = cgi_23_042_42_6, .expect_match = false, .expect_exact_match = false },
2460 { .id = ci_5, .match_id = cgi_23_99_23_5, .expect_match = true, .expect_exact_match = false },
2461 { .id = lac_ci_23_5, .match_id = lac_23, .expect_match = true, .expect_exact_match = false },
2462 { .id = lac_ci_23_5, .match_id = lac_42, .expect_match = false, .expect_exact_match = false },
2463 { .id = lac_ci_23_5, .match_id = ci_5, .expect_match = true, .expect_exact_match = false },
2464 { .id = lac_ci_23_5, .match_id = ci_6, .expect_match = false, .expect_exact_match = false },
2465 { .id = lac_ci_23_5, .match_id = lac_ci_23_5, .expect_match = true, .expect_exact_match = true },
2466 { .id = lac_ci_23_5, .match_id = lac_ci_42_6, .expect_match = false, .expect_exact_match = false },
2467 { .id = lac_ci_23_5, .match_id = lai_23_042_23, .expect_match = true, .expect_exact_match = false },
2468 { .id = lac_ci_23_5, .match_id = lai_23_042_42, .expect_match = false, .expect_exact_match = false },
2469 { .id = lac_ci_23_5, .match_id = lai_23_99_23, .expect_match = true, .expect_exact_match = false },
2470 { .id = lac_ci_23_5, .match_id = lai_23_42_23, .expect_match = true, .expect_exact_match = false },
2471 { .id = lac_ci_23_5, .match_id = cgi_23_042_23_5, .expect_match = true, .expect_exact_match = false },
2472 { .id = lac_ci_23_5, .match_id = cgi_23_042_42_6, .expect_match = false, .expect_exact_match = false },
2473 { .id = lac_ci_23_5, .match_id = cgi_23_99_23_5, .expect_match = true, .expect_exact_match = false },
2474 { .id = lai_23_042_23, .match_id = lac_23, .expect_match = true, .expect_exact_match = false },
2475 { .id = lai_23_042_23, .match_id = lac_42, .expect_match = false, .expect_exact_match = false },
2476 { .id = lai_23_042_23, .match_id = ci_5, .expect_match = true, .expect_exact_match = false },
2477 { .id = lai_23_042_23, .match_id = ci_6, .expect_match = true, .expect_exact_match = false },
2478 { .id = lai_23_042_23, .match_id = lac_ci_23_5, .expect_match = true, .expect_exact_match = false },
2479 { .id = lai_23_042_23, .match_id = lac_ci_42_6, .expect_match = false, .expect_exact_match = false },
2480 { .id = lai_23_042_23, .match_id = lai_23_042_23, .expect_match = true, .expect_exact_match = true },
2481 { .id = lai_23_042_23, .match_id = lai_23_042_42, .expect_match = false, .expect_exact_match = false },
2482 { .id = lai_23_042_23, .match_id = lai_23_99_23, .expect_match = false, .expect_exact_match = false },
2483 { .id = lai_23_042_23, .match_id = lai_23_42_23, .expect_match = false, .expect_exact_match = false },
2484 { .id = lai_23_042_23, .match_id = cgi_23_042_23_5, .expect_match = true, .expect_exact_match = false },
2485 { .id = lai_23_042_23, .match_id = cgi_23_042_42_6, .expect_match = false, .expect_exact_match = false },
2486 { .id = lai_23_042_23, .match_id = cgi_23_99_23_5, .expect_match = false, .expect_exact_match = false },
2487 { .id = cgi_23_042_23_5, .match_id = lac_23, .expect_match = true, .expect_exact_match = false },
2488 { .id = cgi_23_042_23_5, .match_id = lac_42, .expect_match = false, .expect_exact_match = false },
2489 { .id = cgi_23_042_23_5, .match_id = ci_5, .expect_match = true, .expect_exact_match = false },
2490 { .id = cgi_23_042_23_5, .match_id = ci_6, .expect_match = false, .expect_exact_match = false },
2491 { .id = cgi_23_042_23_5, .match_id = lac_ci_23_5, .expect_match = true, .expect_exact_match = false },
2492 { .id = cgi_23_042_23_5, .match_id = lac_ci_42_6, .expect_match = false, .expect_exact_match = false },
2493 { .id = cgi_23_042_23_5, .match_id = lai_23_042_23, .expect_match = true, .expect_exact_match = false },
2494 { .id = cgi_23_042_23_5, .match_id = lai_23_042_42, .expect_match = false, .expect_exact_match = false },
2495 { .id = cgi_23_042_23_5, .match_id = lai_23_99_23, .expect_match = false, .expect_exact_match = false },
2496 { .id = cgi_23_042_23_5, .match_id = lai_23_42_23, .expect_match = false, .expect_exact_match = false },
2497 { .id = cgi_23_042_23_5, .match_id = cgi_23_042_23_5, .expect_match = true, .expect_exact_match = true },
2498 { .id = cgi_23_042_23_5, .match_id = cgi_23_042_42_6, .expect_match = false, .expect_exact_match = false },
2499 { .id = cgi_23_042_23_5, .match_id = cgi_23_99_23_5, .expect_match = false, .expect_exact_match = false },
2500};
2501
Harald Weltee61d4592022-11-03 11:05:58 +01002502static void test_cell_id_matching(void)
Neels Hofmeyrd01ef752018-09-21 15:57:26 +02002503{
2504 int i;
2505 bool ok = true;
2506 printf("\n%s\n", __func__);
2507
2508 for (i = 0; i < ARRAY_SIZE(test_cell_id_matching_tests); i++) {
2509 const struct test_cell_id_matching_data *d = &test_cell_id_matching_tests[i];
2510 int exact_match;
2511
2512 for (exact_match = 0; exact_match < 2; exact_match++) {
2513 bool result;
2514 bool expect_result = exact_match ? d->expect_exact_match : d->expect_match;
2515
2516 result = gsm0808_cell_ids_match(&d->id, &d->match_id, (bool)exact_match);
2517
2518 printf("[%d] %s %s %s%s\n",
2519 i,
2520 gsm0808_cell_id_name(&d->id),
2521 gsm0808_cell_id_name2(&d->match_id),
2522 result ? "MATCH" : "don't match",
2523 exact_match ? " exactly" : "");
2524 if (result != expect_result) {
2525 printf(" ERROR: expected %s\n", d->expect_match ? "MATCH" : "no match");
2526 ok = false;
2527 }
2528 }
2529 }
2530
2531 OSMO_ASSERT(ok);
2532}
2533
2534static bool test_cell_id_list_matching_discrs(bool test_match,
2535 enum CELL_IDENT id_discr,
2536 enum CELL_IDENT list_discr)
2537{
2538 int i, j;
2539 const struct gsm0808_cell_id *id = NULL;
2540 struct gsm0808_cell_id_list2 list = {};
2541 int match_idx = -1;
2542 int result;
2543
2544 for (i = 0; i < ARRAY_SIZE(test_cell_id_matching_tests); i++) {
2545 const struct test_cell_id_matching_data *d = &test_cell_id_matching_tests[i];
2546 if (id_discr != d->id.id_discr)
2547 continue;
2548 id = &d->id;
2549 break;
2550 }
2551
2552 if (!id) {
2553 printf("Did not find any entry for %s\n", gsm0808_cell_id_discr_name(id_discr));
2554 return true;
2555 }
2556
2557 /* Collect those entries with exactly this id on the left, of type list_discr on the right.
2558 * Collect the mismatches first, for more interesting match indexes in the results. */
2559 for (j = 0; j < 2; j++) {
2560 bool collect_matches = (bool)j;
2561
2562 /* If we want to have a mismatching list, don't add any entries that match. */
2563 if (!test_match && collect_matches)
2564 continue;
2565
2566 for (i = 0; i < ARRAY_SIZE(test_cell_id_matching_tests); i++) {
2567 const struct test_cell_id_matching_data *d = &test_cell_id_matching_tests[i];
2568 struct gsm0808_cell_id_list2 add;
2569
2570 /* Ignore those with a different d->id */
2571 if (!gsm0808_cell_ids_match(&d->id, id, true))
2572 continue;
2573
2574 /* Ignore those with a different d->match_id discr */
2575 if (d->match_id.id_discr != list_discr)
2576 continue;
2577
2578 if (collect_matches != d->expect_match)
2579 continue;
2580
2581 if (match_idx < 0 && d->expect_match) {
2582 match_idx = list.id_list_len;
2583 }
2584
2585 gsm0808_cell_id_to_list(&add, &d->match_id);
2586 gsm0808_cell_id_list_add(&list, &add);
2587 }
2588 }
2589
2590 if (!list.id_list_len) {
2591 printf("%s vs. %s: No match_id entries to test %s\n",
2592 gsm0808_cell_id_name(id),
2593 gsm0808_cell_id_discr_name(list_discr),
2594 test_match ? "MATCH" : "mismatch");
2595 return true;
2596 }
2597
2598 result = gsm0808_cell_id_matches_list(id, &list, 0, false);
2599
2600 printf("%s and %s: ",
2601 gsm0808_cell_id_name(id),
2602 gsm0808_cell_id_list_name(&list));
2603 if (result >= 0)
2604 printf("MATCH at [%d]\n", result);
2605 else
2606 printf("mismatch\n");
2607
2608 if (test_match
2609 && (result < 0 || result != match_idx)) {
2610 printf(" ERROR: expected MATCH at %d\n", match_idx);
2611 return false;
2612 }
2613
2614 if (!test_match && result >= 0) {
2615 printf(" ERROR: expected mismatch\n");
2616 return false;
2617 }
2618
2619 return true;
2620}
2621
Neels Hofmeyr3a504532019-02-10 22:28:27 +01002622const enum CELL_IDENT cell_ident_discrs[] = {
2623 CELL_IDENT_LAC, CELL_IDENT_CI, CELL_IDENT_LAC_AND_CI, CELL_IDENT_LAI_AND_LAC,
2624 CELL_IDENT_WHOLE_GLOBAL,
2625};
2626
2627
Neels Hofmeyrd01ef752018-09-21 15:57:26 +02002628static void test_cell_id_list_matching(bool test_match)
2629{
2630 int i, j;
2631 bool ok = true;
2632
Neels Hofmeyrd01ef752018-09-21 15:57:26 +02002633 printf("\n%s(%s)\n", __func__, test_match ? "test match" : "test mismatch");
2634
2635 /* Autogenerate Cell ID lists from above dataset, which should match / not match. */
Neels Hofmeyr3a504532019-02-10 22:28:27 +01002636 for (i = 0; i < ARRAY_SIZE(cell_ident_discrs); i++) {
2637 for (j = 0; j < ARRAY_SIZE(cell_ident_discrs); j++)
Neels Hofmeyrd01ef752018-09-21 15:57:26 +02002638 if (!test_cell_id_list_matching_discrs(test_match,
Neels Hofmeyr3a504532019-02-10 22:28:27 +01002639 cell_ident_discrs[i], cell_ident_discrs[j]))
Neels Hofmeyrd01ef752018-09-21 15:57:26 +02002640 ok = false;
2641 }
2642
2643 OSMO_ASSERT(ok);
2644}
2645
Neels Hofmeyr3a504532019-02-10 22:28:27 +01002646
2647static const struct gsm0808_cell_id test_gsm0808_cell_id_to_from_cgi_data[] = {
2648 lac_23,
2649 lac_42,
2650 ci_5,
2651 ci_6,
2652 lac_ci_23_5,
2653 lac_ci_42_6,
2654 lai_23_042_23,
2655 lai_23_042_42,
2656 lai_23_99_23,
2657 lai_23_42_23,
2658 cgi_23_042_23_5,
2659 cgi_23_042_42_6,
2660 cgi_23_99_23_5,
2661 { .id_discr = CELL_IDENT_NO_CELL },
2662 { .id_discr = 423 },
2663};
2664
Harald Weltee61d4592022-11-03 11:05:58 +01002665static void test_gsm0808_cell_id_to_from_cgi(void)
Neels Hofmeyr3a504532019-02-10 22:28:27 +01002666{
2667 int i;
2668 int j;
2669
2670 printf("\n%s()\n", __func__);
2671
2672 for (i = 0; i < ARRAY_SIZE(test_gsm0808_cell_id_to_from_cgi_data); i++) {
2673 const struct gsm0808_cell_id *from_cid = &test_gsm0808_cell_id_to_from_cgi_data[i];
2674 struct osmo_cell_global_id cgi = {
2675 .lai = {
2676 .plmn = {
2677 .mcc = 777,
2678 .mnc = 7,
2679 .mnc_3_digits = true,
2680 },
2681 .lac = 7777,
2682 },
2683 .cell_identity = 7777,
2684 };
2685 struct gsm0808_cell_id cid = {};
2686 int rc;
2687
2688 rc = gsm0808_cell_id_to_cgi(&cgi, from_cid);
2689 printf("cid %s -> cgi %s", gsm0808_cell_id_name(from_cid), osmo_cgi_name(&cgi));
2690
2691 if (rc & OSMO_CGI_PART_PLMN)
2692 printf(" PLMN");
2693 if (rc & OSMO_CGI_PART_LAC)
2694 printf(" LAC");
2695 if (rc & OSMO_CGI_PART_CI)
2696 printf(" CI");
2697
2698 gsm0808_cell_id_from_cgi(&cid, from_cid->id_discr, &cgi);
2699 printf(" -> cid %s\n", gsm0808_cell_id_name(&cid));
2700 if (!gsm0808_cell_ids_match(from_cid, &cid, true))
2701 printf(" MISMATCH!\n");
2702
2703 for (j = 0; j < ARRAY_SIZE(cell_ident_discrs); j++) {
2704 enum CELL_IDENT discr = cell_ident_discrs[j];
2705
2706 gsm0808_cell_id_from_cgi(&cid, discr, &cgi);
2707 printf(" --> gsm0808_cell_id{%s} = %s\n", gsm0808_cell_id_discr_name(discr), gsm0808_cell_id_name(&cid));
2708 }
2709 }
2710}
2711
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +01002712int main(int argc, char **argv)
2713{
Max969fb2e2018-12-10 11:01:10 +01002714 void *ctx = talloc_named_const(NULL, 0, "gsm0808 test");
2715 msgb_talloc_ctx_init(ctx, 0);
2716 osmo_init_logging2(ctx, NULL);
2717
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +01002718 printf("Testing generation of GSM0808 messages\n");
Philipp Maier4f4905f2018-11-30 13:36:12 +01002719 test_gsm0808_enc_cause();
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +01002720 test_create_layer3();
Philipp Maierfa896ab2017-03-27 16:55:32 +02002721 test_create_layer3_aoip();
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +01002722 test_create_reset();
Philipp Maier15596e22017-04-05 17:55:27 +02002723 test_create_reset_ack();
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +01002724 test_create_clear_command();
Harald Weltecf665fc2019-02-18 13:45:36 +01002725 test_create_clear_command2();
2726 test_create_clear_command2_csfb();
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +01002727 test_create_clear_complete();
Philipp Maierb478dd32017-03-29 15:50:05 +02002728 test_create_cipher();
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +01002729 test_create_cipher_complete();
2730 test_create_cipher_reject();
Maxed651d22018-11-07 15:25:05 +01002731 test_create_cipher_reject_ext();
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +01002732 test_create_cm_u();
2733 test_create_sapi_reject();
Philipp Maierc6144a22017-03-29 17:53:43 +02002734 test_create_ass();
Max52074322018-11-30 10:44:07 +01002735 test_create_ass2();
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +01002736 test_create_ass_compl();
Philipp Maierfa896ab2017-03-27 16:55:32 +02002737 test_create_ass_compl_aoip();
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +01002738 test_create_ass_fail();
Philipp Maierfa896ab2017-03-27 16:55:32 +02002739 test_create_ass_fail_aoip();
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +01002740 test_create_clear_rqst();
Philipp Maier3d48ec02017-03-29 17:37:55 +02002741 test_create_paging();
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +01002742 test_create_dtap();
2743 test_prepend_dtap();
Max969fb2e2018-12-10 11:01:10 +01002744
Max47022152018-12-19 18:51:00 +01002745 test_enc_dec_lcls();
Max969fb2e2018-12-10 11:01:10 +01002746
Philipp Maier22401432017-03-24 17:59:26 +01002747 test_enc_dec_aoip_trasp_addr_v4();
2748 test_enc_dec_aoip_trasp_addr_v6();
Oliver Smithc66b35b2022-08-05 11:27:55 +02002749 test_enc_aoip_trasp_addr_msg_too_small();
Philipp Maier6f725d62017-03-24 18:03:17 +01002750 test_gsm0808_enc_dec_speech_codec();
Philipp Maier6f725d62017-03-24 18:03:17 +01002751 test_gsm0808_enc_dec_speech_codec_ext_with_cfg();
Philipp Maierbb839662017-06-01 17:11:19 +02002752 test_gsm0808_enc_dec_speech_codec_with_cfg();
Philipp Maier6f725d62017-03-24 18:03:17 +01002753 test_gsm0808_enc_dec_speech_codec_list();
Philipp Maierf6c369f2018-10-16 15:24:47 +02002754 test_gsm0808_enc_dec_empty_speech_codec_list();
Oliver Smithf047a4a2023-01-31 13:10:03 +01002755 test_gsm0808_enc_dec_channel_type_data();
2756 test_gsm0808_enc_dec_channel_type_data_asym_pref();
Oliver Smith02b90952023-01-31 16:42:55 +01002757 test_gsm0808_enc_dec_channel_type_speech();
Oliver Smith8d9ed732023-02-20 13:01:29 +01002758 test_gsm0808_enc_dec_channel_type_sign();
Oliver Smith81e5a6f2023-01-31 12:34:26 +01002759 test_gsm0808_dec_channel_type_err();
Philipp Maier14e76b92017-03-28 18:36:52 +02002760 test_gsm0808_enc_dec_encrypt_info();
Neels Hofmeyr250e7f72018-04-13 03:30:14 +02002761
Philipp Maier783047e2017-03-29 11:35:50 +02002762 test_gsm0808_enc_dec_cell_id_list_lac();
2763 test_gsm0808_enc_dec_cell_id_list_single_lac();
Stefan Sperlinge1a86742018-03-15 18:05:02 +01002764 test_gsm0808_enc_dec_cell_id_list_multi_lac();
Philipp Maier783047e2017-03-29 11:35:50 +02002765 test_gsm0808_enc_dec_cell_id_list_bss();
Stefan Sperling23381452018-03-15 19:38:15 +01002766 test_gsm0808_enc_dec_cell_id_list_multi_lai_and_lac();
Stefan Sperling9c62fc62018-03-16 10:23:34 +01002767 test_gsm0808_enc_dec_cell_id_list_multi_ci();
Stefan Sperlinged4327c2018-03-16 11:02:59 +01002768 test_gsm0808_enc_dec_cell_id_list_multi_lac_and_ci();
Stefan Sperling483f3862018-03-16 12:21:26 +01002769 test_gsm0808_enc_dec_cell_id_list_multi_global();
Harald Weltea87526d2022-02-15 20:06:16 +01002770 test_gsm0808_dec_cell_id_list_srvcc();
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +01002771
Neels Hofmeyr74663d92018-03-23 01:46:42 +01002772 test_cell_id_list_add();
2773
Neels Hofmeyr250e7f72018-04-13 03:30:14 +02002774 test_gsm0808_enc_dec_cell_id_lac();
2775 test_gsm0808_enc_dec_cell_id_bss();
2776 test_gsm0808_enc_dec_cell_id_no_cell();
2777 test_gsm0808_enc_dec_cell_id_lai_and_lac();
2778 test_gsm0808_enc_dec_cell_id_ci();
2779 test_gsm0808_enc_dec_cell_id_lac_and_ci();
2780 test_gsm0808_enc_dec_cell_id_global();
Pau Espin Pedrol52489852021-02-15 16:26:37 +01002781 test_gsm0808_enc_dec_cell_id_global_ps();
Philipp Maier5f2eb152018-09-19 13:40:21 +02002782 test_gsm0808_sc_cfg_from_gsm48_mr_cfg();
Philipp Maier8515d032018-09-25 15:57:49 +02002783 test_gsm48_mr_cfg_from_gsm0808_sc_cfg();
Philipp Maier5f2eb152018-09-19 13:40:21 +02002784
Neels Hofmeyrd01ef752018-09-21 15:57:26 +02002785 test_cell_id_matching();
2786 test_cell_id_list_matching(true);
2787 test_cell_id_list_matching(false);
2788
Neels Hofmeyr3a504532019-02-10 22:28:27 +01002789 test_gsm0808_cell_id_to_from_cgi();
2790
Alexander Chemeris22630e62020-05-13 00:44:04 +03002791 test_dec_confusion();
Pau Espin Pedrola3987fc2022-03-18 13:17:28 +01002792 test_dec_perform_location_report_sys5891();
Alexander Chemeris22630e62020-05-13 00:44:04 +03002793
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +01002794 printf("Done\n");
2795 return EXIT_SUCCESS;
2796}