blob: b67219cdf809ee1bfc274a9233b854e2850e1102 [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
31struct neighbor_ident_list *nil;
32
33static const struct neighbor_ident_key *k(int from_bts, uint16_t arfcn, enum bsic_kind kind, uint16_t bsic)
34{
35 static struct neighbor_ident_key key;
36 key = (struct neighbor_ident_key){
37 .from_bts = from_bts,
38 .arfcn = arfcn,
39 .bsic_kind = kind,
40 .bsic = bsic,
41 };
42 return &key;
43}
44
45static const struct gsm0808_cell_id_list2 cgi1 = {
46 .id_discr = CELL_IDENT_WHOLE_GLOBAL,
47 .id_list_len = 1,
48 .id_list = {
49 {
50 .global = {
51 .lai = {
52 .plmn = { .mcc = 1, .mnc = 2, .mnc_3_digits = false },
53 .lac = 3,
54 },
55 .cell_identity = 4,
56 }
57 },
58 },
59};
60
61static const struct gsm0808_cell_id_list2 cgi2 = {
62 .id_discr = CELL_IDENT_WHOLE_GLOBAL,
63 .id_list_len = 2,
64 .id_list = {
65 {
66 .global = {
67 .lai = {
68 .plmn = { .mcc = 1, .mnc = 2, .mnc_3_digits = false },
69 .lac = 3,
70 },
71 .cell_identity = 4,
72 }
73 },
74 {
75 .global = {
76 .lai = {
77 .plmn = { .mcc = 5, .mnc = 6, .mnc_3_digits = true },
78 .lac = 7,
79 },
80 .cell_identity = 8,
81 }
82 },
83 },
84};
85
86static const struct gsm0808_cell_id_list2 lac1 = {
87 .id_discr = CELL_IDENT_LAC,
88 .id_list_len = 1,
89 .id_list = {
90 {
91 .lac = 123
92 },
93 },
94};
95
96static const struct gsm0808_cell_id_list2 lac2 = {
97 .id_discr = CELL_IDENT_LAC,
98 .id_list_len = 2,
99 .id_list = {
100 {
101 .lac = 456
102 },
103 {
104 .lac = 789
105 },
106 },
107};
108
109void print_cil(const struct gsm0808_cell_id_list2 *cil)
110{
111 unsigned int i;
112 if (!cil) {
113 printf(" cell_id_list == NULL\n");
114 return;
115 }
116 switch (cil->id_discr) {
117 case CELL_IDENT_WHOLE_GLOBAL:
118 printf(" cell_id_list cgi[%u] = {\n", cil->id_list_len);
119 for (i = 0; i < cil->id_list_len; i++)
120 printf(" %2d: %s\n", i, osmo_cgi_name(&cil->id_list[i].global));
121 printf(" }\n");
122 break;
123 case CELL_IDENT_LAC:
124 printf(" cell_id_list lac[%u] = {\n", cil->id_list_len);
125 for (i = 0; i < cil->id_list_len; i++)
126 printf(" %2d: %u\n", i, cil->id_list[i].lac);
127 printf(" }\n");
128 break;
129 default:
130 printf(" Unimplemented id_disc\n");
131 }
132}
133
134static int print_nil_i;
135
136bool nil_cb(const struct neighbor_ident_key *key, const struct gsm0808_cell_id_list2 *val,
137 void *cb_data)
138{
139 printf(" %2d: %s\n", print_nil_i++, neighbor_ident_key_name(key));
140 print_cil(val);
141 return true;
142}
143
144void print_nil()
145{
146 print_nil_i = 0;
147 neighbor_ident_iter(nil, nil_cb, NULL);
148 if (!print_nil_i)
149 printf(" (empty)\n");
150}
151
152#define check_add(key, val, expect_rc) \
153 do { \
154 int rc; \
155 rc = neighbor_ident_add(nil, key, val); \
156 printf("neighbor_ident_add(" #key ", " #val ") --> expect rc=" #expect_rc ", got %d\n", rc); \
157 if (rc != expect_rc) \
158 printf("ERROR\n"); \
159 print_nil(); \
160 } while(0)
161
162#define check_del(key, expect_rc) \
163 do { \
164 bool rc; \
165 rc = neighbor_ident_del(nil, key); \
166 printf("neighbor_ident_del(" #key ") --> %s\n", rc ? "entry deleted" : "nothing deleted"); \
167 if (rc != expect_rc) \
168 printf("ERROR: expected: %s\n", expect_rc ? "entry deleted" : "nothing deleted"); \
169 print_nil(); \
170 } while(0)
171
172#define check_get(key, expect_rc) \
173 do { \
174 const struct gsm0808_cell_id_list2 *rc; \
175 rc = neighbor_ident_get(nil, key); \
176 printf("neighbor_ident_get(" #key ") --> %s\n", \
177 rc ? "entry returned" : "NULL"); \
178 if (((bool)expect_rc) != ((bool) rc)) \
179 printf("ERROR: expected %s\n", expect_rc ? "an entry" : "NULL"); \
180 if (rc) \
181 print_cil(rc); \
182 } while(0)
183
184int main(void)
185{
186 void *ctx = talloc_named_const(NULL, 0, "neighbor_ident_test");
187
188 printf("\n--- testing NULL neighbor_ident_list\n");
189 nil = NULL;
190 check_add(k(0, 1, BSIC_6BIT, 2), &cgi1, -ENOMEM);
191 check_get(k(0, 1, BSIC_6BIT, 2), false);
192 check_del(k(0, 1, BSIC_6BIT, 2), false);
193
194 printf("\n--- adding entries, test that no two identical entries are added\n");
195 nil = neighbor_ident_init(ctx);
196 check_add(k(0, 1, BSIC_6BIT, 2), &cgi1, 1);
197 check_get(k(0, 1, BSIC_6BIT, 2), true);
198 check_add(k(0, 1, BSIC_6BIT, 2), &cgi1, 1);
199 check_add(k(0, 1, BSIC_6BIT, 2), &cgi2, 2);
200 check_add(k(0, 1, BSIC_6BIT, 2), &cgi2, 2);
201 check_del(k(0, 1, BSIC_6BIT, 2), true);
202
203 printf("\n--- Cannot mix cell identifier types for one entry\n");
204 check_add(k(0, 1, BSIC_6BIT, 2), &cgi1, 1);
205 check_add(k(0, 1, BSIC_6BIT, 2), &lac1, -EINVAL);
206 check_del(k(0, 1, BSIC_6BIT, 2), true);
207 neighbor_ident_free(nil);
208
209 printf("\n--- BTS matching: specific BTS is stronger\n");
210 nil = neighbor_ident_init(ctx);
211 check_add(k(NEIGHBOR_IDENT_KEY_ANY_BTS, 1, BSIC_6BIT, 2), &lac1, 1);
212 check_add(k(3, 1, BSIC_6BIT, 2), &lac2, 2);
213 check_get(k(2, 1, BSIC_6BIT, 2), true);
214 check_get(k(3, 1, BSIC_6BIT, 2), true);
215 check_get(k(4, 1, BSIC_6BIT, 2), true);
216 check_get(k(NEIGHBOR_IDENT_KEY_ANY_BTS, 1, BSIC_6BIT, 2), true);
217 neighbor_ident_free(nil);
218
219 printf("\n--- BSIC matching: 6bit and 9bit are different realms, and wildcard match is weaker\n");
220 nil = neighbor_ident_init(ctx);
221 check_add(k(0, 1, BSIC_NONE, 0), &cgi1, 1);
222 check_add(k(0, 1, BSIC_6BIT, 2), &lac1, 1);
223 check_add(k(0, 1, BSIC_9BIT, 2), &lac2, 2);
224 check_get(k(0, 1, BSIC_6BIT, 2), true);
225 check_get(k(0, 1, BSIC_9BIT, 2), true);
226 printf("--- wildcard matches both 6bit and 9bit BSIC regardless:\n");
227 check_get(k(0, 1, BSIC_6BIT, 23), true);
228 check_get(k(0, 1, BSIC_9BIT, 23), true);
229 neighbor_ident_free(nil);
230
231 printf("\n--- Value ranges\n");
232 nil = neighbor_ident_init(ctx);
233 check_add(k(0, 6, BSIC_6BIT, 1 << 6), &lac1, -ERANGE);
234 check_add(k(0, 9, BSIC_9BIT, 1 << 9), &lac1, -ERANGE);
235 check_add(k(0, 6, BSIC_6BIT, -1), &lac1, -ERANGE);
236 check_add(k(0, 9, BSIC_9BIT, -1), &lac1, -ERANGE);
237 check_add(k(NEIGHBOR_IDENT_KEY_ANY_BTS - 1, 1, BSIC_NONE, 1), &cgi2, -ERANGE);
238 check_add(k(256, 1, BSIC_NONE, 1), &cgi2, -ERANGE);
239 check_add(k(0, 0, BSIC_NONE, 0), &cgi1, 1);
240 check_add(k(255, 65535, BSIC_NONE, 65535), &lac1, 1);
241 check_add(k(0, 0, BSIC_6BIT, 0), &cgi2, 2);
242 check_add(k(255, 65535, BSIC_6BIT, 0x3f), &lac2, 2);
243 check_add(k(0, 0, BSIC_9BIT, 0), &cgi1, 1);
244 check_add(k(255, 65535, BSIC_9BIT, 0x1ff), &cgi2, 2);
245
246 neighbor_ident_free(nil);
247
248 printf("\n--- size limits\n");
249 {
250 int i;
251 struct gsm0808_cell_id_list2 a = { .id_discr = CELL_IDENT_LAC };
252 struct gsm0808_cell_id_list2 b = {
253 .id_discr = CELL_IDENT_LAC,
254 .id_list = {
255 { .lac = 423 }
256 },
257 .id_list_len = 1,
258 };
259 for (i = 0; i < ARRAY_SIZE(a.id_list); i++) {
260 a.id_list[a.id_list_len ++].lac = i;
261 }
262
263 nil = neighbor_ident_init(ctx);
264
265 i = neighbor_ident_add(nil, k(0, 1, BSIC_6BIT, 2), &a);
266 printf("Added first cell identifier list (added %u) --> rc = %d\n", a.id_list_len, i);
267 i = neighbor_ident_add(nil, k(0, 1, BSIC_6BIT, 2), &b);
268 printf("Added second cell identifier list (tried to add %u) --> rc = %d\n", b.id_list_len, i);
269 if (i != -ENOSPC)
270 printf("ERROR: expected rc=%d\n", -ENOSPC);
271 neighbor_ident_free(nil);
272 }
273
274 OSMO_ASSERT(talloc_total_blocks(ctx) == 1);
275 talloc_free(ctx);
276
277 return 0;
278}