blob: 9acbea0350963786583499f54af9b628b115af08 [file] [log] [blame]
Neels Hofmeyr19bed232018-03-22 04:54:57 +01001/* Test the neighbor_ident.h API */
2/*
3 * (C) 2018 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
4 * All Rights Reserved
5 *
6 * Author: Neels Hofmeyr <nhofmeyr@sysmocom.de>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU Affero General Public License as published by
10 * the Free Software Foundation; either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU Affero General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 *
21 */
22
23#include <talloc.h>
24#include <stdio.h>
25#include <errno.h>
26
27#include <osmocom/gsm/gsm0808.h>
28
29#include <osmocom/bsc/neighbor_ident.h>
30
Neels Hofmeyr31f525e2018-05-14 18:14:15 +020031static struct neighbor_ident_list *nil;
Neels Hofmeyr19bed232018-03-22 04:54:57 +010032
Neels Hofmeyr431e0852018-03-22 04:54:57 +010033static const struct neighbor_ident_key *k(int from_bts, uint16_t arfcn, uint8_t bsic)
Neels Hofmeyr19bed232018-03-22 04:54:57 +010034{
35 static struct neighbor_ident_key key;
36 key = (struct neighbor_ident_key){
37 .from_bts = from_bts,
38 .arfcn = arfcn,
Neels Hofmeyr19bed232018-03-22 04:54:57 +010039 .bsic = bsic,
40 };
41 return &key;
42}
43
44static const struct gsm0808_cell_id_list2 cgi1 = {
45 .id_discr = CELL_IDENT_WHOLE_GLOBAL,
46 .id_list_len = 1,
47 .id_list = {
48 {
49 .global = {
50 .lai = {
51 .plmn = { .mcc = 1, .mnc = 2, .mnc_3_digits = false },
52 .lac = 3,
53 },
54 .cell_identity = 4,
55 }
56 },
57 },
58};
59
60static const struct gsm0808_cell_id_list2 cgi2 = {
61 .id_discr = CELL_IDENT_WHOLE_GLOBAL,
62 .id_list_len = 2,
63 .id_list = {
64 {
65 .global = {
66 .lai = {
67 .plmn = { .mcc = 1, .mnc = 2, .mnc_3_digits = false },
68 .lac = 3,
69 },
70 .cell_identity = 4,
71 }
72 },
73 {
74 .global = {
75 .lai = {
76 .plmn = { .mcc = 5, .mnc = 6, .mnc_3_digits = true },
77 .lac = 7,
78 },
79 .cell_identity = 8,
80 }
81 },
82 },
83};
84
85static const struct gsm0808_cell_id_list2 lac1 = {
86 .id_discr = CELL_IDENT_LAC,
87 .id_list_len = 1,
88 .id_list = {
89 {
90 .lac = 123
91 },
92 },
93};
94
95static const struct gsm0808_cell_id_list2 lac2 = {
96 .id_discr = CELL_IDENT_LAC,
97 .id_list_len = 2,
98 .id_list = {
99 {
100 .lac = 456
101 },
102 {
103 .lac = 789
104 },
105 },
106};
107
Neels Hofmeyr31f525e2018-05-14 18:14:15 +0200108static void print_cil(const struct gsm0808_cell_id_list2 *cil)
Neels Hofmeyr19bed232018-03-22 04:54:57 +0100109{
110 unsigned int i;
111 if (!cil) {
112 printf(" cell_id_list == NULL\n");
113 return;
114 }
115 switch (cil->id_discr) {
116 case CELL_IDENT_WHOLE_GLOBAL:
117 printf(" cell_id_list cgi[%u] = {\n", cil->id_list_len);
118 for (i = 0; i < cil->id_list_len; i++)
119 printf(" %2d: %s\n", i, osmo_cgi_name(&cil->id_list[i].global));
120 printf(" }\n");
121 break;
122 case CELL_IDENT_LAC:
123 printf(" cell_id_list lac[%u] = {\n", cil->id_list_len);
124 for (i = 0; i < cil->id_list_len; i++)
125 printf(" %2d: %u\n", i, cil->id_list[i].lac);
126 printf(" }\n");
127 break;
128 default:
129 printf(" Unimplemented id_disc\n");
130 }
131}
132
133static int print_nil_i;
134
Neels Hofmeyr31f525e2018-05-14 18:14:15 +0200135static bool nil_cb(const struct neighbor_ident_key *key, const struct gsm0808_cell_id_list2 *val,
Neels Hofmeyr19bed232018-03-22 04:54:57 +0100136 void *cb_data)
137{
138 printf(" %2d: %s\n", print_nil_i++, neighbor_ident_key_name(key));
139 print_cil(val);
140 return true;
141}
142
Neels Hofmeyr31f525e2018-05-14 18:14:15 +0200143static void print_nil()
Neels Hofmeyr19bed232018-03-22 04:54:57 +0100144{
145 print_nil_i = 0;
146 neighbor_ident_iter(nil, nil_cb, NULL);
147 if (!print_nil_i)
148 printf(" (empty)\n");
149}
150
151#define check_add(key, val, expect_rc) \
152 do { \
153 int rc; \
154 rc = neighbor_ident_add(nil, key, val); \
155 printf("neighbor_ident_add(" #key ", " #val ") --> expect rc=" #expect_rc ", got %d\n", rc); \
156 if (rc != expect_rc) \
157 printf("ERROR\n"); \
158 print_nil(); \
159 } while(0)
160
161#define check_del(key, expect_rc) \
162 do { \
163 bool rc; \
164 rc = neighbor_ident_del(nil, key); \
165 printf("neighbor_ident_del(" #key ") --> %s\n", rc ? "entry deleted" : "nothing deleted"); \
166 if (rc != expect_rc) \
167 printf("ERROR: expected: %s\n", expect_rc ? "entry deleted" : "nothing deleted"); \
168 print_nil(); \
169 } while(0)
170
171#define check_get(key, expect_rc) \
172 do { \
173 const struct gsm0808_cell_id_list2 *rc; \
174 rc = neighbor_ident_get(nil, key); \
175 printf("neighbor_ident_get(" #key ") --> %s\n", \
176 rc ? "entry returned" : "NULL"); \
177 if (((bool)expect_rc) != ((bool) rc)) \
178 printf("ERROR: expected %s\n", expect_rc ? "an entry" : "NULL"); \
179 if (rc) \
180 print_cil(rc); \
181 } while(0)
182
183int main(void)
184{
185 void *ctx = talloc_named_const(NULL, 0, "neighbor_ident_test");
186
187 printf("\n--- testing NULL neighbor_ident_list\n");
188 nil = NULL;
Neels Hofmeyr431e0852018-03-22 04:54:57 +0100189 check_add(k(0, 1, 2), &cgi1, -ENOMEM);
190 check_get(k(0, 1, 2), false);
191 check_del(k(0, 1, 2), false);
Neels Hofmeyr19bed232018-03-22 04:54:57 +0100192
193 printf("\n--- adding entries, test that no two identical entries are added\n");
194 nil = neighbor_ident_init(ctx);
Neels Hofmeyr431e0852018-03-22 04:54:57 +0100195 check_add(k(0, 1, 2), &cgi1, 1);
196 check_get(k(0, 1, 2), true);
197 check_add(k(0, 1, 2), &cgi1, 1);
198 check_add(k(0, 1, 2), &cgi2, 2);
199 check_add(k(0, 1, 2), &cgi2, 2);
200 check_del(k(0, 1, 2), true);
Neels Hofmeyr19bed232018-03-22 04:54:57 +0100201
202 printf("\n--- Cannot mix cell identifier types for one entry\n");
Neels Hofmeyr431e0852018-03-22 04:54:57 +0100203 check_add(k(0, 1, 2), &cgi1, 1);
204 check_add(k(0, 1, 2), &lac1, -EINVAL);
205 check_del(k(0, 1, 2), true);
Neels Hofmeyr19bed232018-03-22 04:54:57 +0100206 neighbor_ident_free(nil);
207
208 printf("\n--- BTS matching: specific BTS is stronger\n");
209 nil = neighbor_ident_init(ctx);
Neels Hofmeyr431e0852018-03-22 04:54:57 +0100210 check_add(k(NEIGHBOR_IDENT_KEY_ANY_BTS, 1, 2), &lac1, 1);
211 check_add(k(3, 1, 2), &lac2, 2);
212 check_get(k(2, 1, 2), true);
213 check_get(k(3, 1, 2), true);
214 check_get(k(4, 1, 2), true);
215 check_get(k(NEIGHBOR_IDENT_KEY_ANY_BTS, 1, 2), true);
Neels Hofmeyr19bed232018-03-22 04:54:57 +0100216 neighbor_ident_free(nil);
217
218 printf("\n--- BSIC matching: 6bit and 9bit are different realms, and wildcard match is weaker\n");
219 nil = neighbor_ident_init(ctx);
Neels Hofmeyr431e0852018-03-22 04:54:57 +0100220 check_add(k(0, 1, BSIC_ANY), &cgi1, 1);
221 check_add(k(0, 1, 2), &lac1, 1);
222 check_add(k(0, 1, 2), &lac2, 2);
223 check_get(k(0, 1, 2), true);
224 check_get(k(0, 1, 2), true);
Neels Hofmeyr19bed232018-03-22 04:54:57 +0100225 neighbor_ident_free(nil);
226
227 printf("\n--- Value ranges\n");
228 nil = neighbor_ident_init(ctx);
Neels Hofmeyr431e0852018-03-22 04:54:57 +0100229 check_add(k(0, 6, 1 << 6), &lac1, -ERANGE);
230 check_add(k(0, 6, BSIC_ANY - 1), &lac1, -ERANGE);
231 check_add(k(NEIGHBOR_IDENT_KEY_ANY_BTS - 1, 1, BSIC_ANY), &cgi2, -ERANGE);
232 check_add(k(256, 1, BSIC_ANY), &cgi2, -ERANGE);
233 check_add(k(0, 0, BSIC_ANY), &cgi1, 1);
234 check_add(k(255, 65535, BSIC_ANY), &lac1, 1);
235 check_add(k(0, 0, 0), &cgi2, 2);
236 check_add(k(255, 65535, 0x3f), &lac2, 2);
Neels Hofmeyr19bed232018-03-22 04:54:57 +0100237
238 neighbor_ident_free(nil);
239
240 printf("\n--- size limits\n");
241 {
242 int i;
243 struct gsm0808_cell_id_list2 a = { .id_discr = CELL_IDENT_LAC };
244 struct gsm0808_cell_id_list2 b = {
245 .id_discr = CELL_IDENT_LAC,
246 .id_list = {
247 { .lac = 423 }
248 },
249 .id_list_len = 1,
250 };
251 for (i = 0; i < ARRAY_SIZE(a.id_list); i++) {
252 a.id_list[a.id_list_len ++].lac = i;
253 }
254
255 nil = neighbor_ident_init(ctx);
256
Neels Hofmeyr431e0852018-03-22 04:54:57 +0100257 i = neighbor_ident_add(nil, k(0, 1, 2), &a);
Neels Hofmeyr19bed232018-03-22 04:54:57 +0100258 printf("Added first cell identifier list (added %u) --> rc = %d\n", a.id_list_len, i);
Neels Hofmeyr431e0852018-03-22 04:54:57 +0100259 i = neighbor_ident_add(nil, k(0, 1, 2), &b);
Neels Hofmeyr19bed232018-03-22 04:54:57 +0100260 printf("Added second cell identifier list (tried to add %u) --> rc = %d\n", b.id_list_len, i);
261 if (i != -ENOSPC)
262 printf("ERROR: expected rc=%d\n", -ENOSPC);
263 neighbor_ident_free(nil);
264 }
265
266 OSMO_ASSERT(talloc_total_blocks(ctx) == 1);
267 talloc_free(ctx);
268
269 return 0;
270}