1 /* $OpenBSD: rde_aspa_test.c,v 1.5 2023/08/16 08:29:41 claudio Exp $ */
2
3 /*
4 * Copyright (c) 2022 Claudio Jeker <claudio@openbsd.org>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19 #include <assert.h>
20 #include <err.h>
21 #include <stdio.h>
22
23 #include "rde_aspa.c"
24
25 static struct aspath *build_aspath(const uint32_t *, uint32_t, int);
26 static const char *print_aspath(const uint32_t *, uint32_t);
27
28 static void reverse_state(struct aspa_state *, struct aspa_state *);
29 static void print_state(struct aspa_state *, struct aspa_state *);
30
31 struct aspa_test_set {
32 uint32_t customeras;
33 const uint32_t *providers;
34 uint32_t pascnt;
35 };
36
37 struct cp_test {
38 uint32_t customeras;
39 uint32_t provideras;
40 uint8_t expected_result;
41 };
42
43 struct aspath_test {
44 const uint32_t *aspath;
45 uint32_t aspathcnt;
46 struct aspa_state state;
47 };
48
49 struct aspa_test {
50 const uint32_t *aspath;
51 uint32_t aspathcnt;
52 enum role role;
53 uint8_t expected_result;
54 };
55
56 struct aspa_test_set testset[] = {
57 /* test vectors from github.com/benmaddison/aspa-fuzz */
58 { 1, (const uint32_t []){ 4, 5, 6 }, 3 },
59 { 2, (const uint32_t []){ 10, 11 }, 2 },
60 { 3, (const uint32_t []){ 1, 13, 14 }, 3 },
61 { 4, (const uint32_t []){ 16, 24 }, 2 },
62 { 5, (const uint32_t []){ 1, 17, 25 }, 3 },
63 { 8, (const uint32_t []){ 0 }, 1 },
64 { 9, (const uint32_t []){ 2 }, 1 },
65 { 10, (const uint32_t []){ 0 }, 1 },
66 { 11, (const uint32_t []){ 2 }, 1 },
67 { 12, (const uint32_t []){ 3 }, 1 },
68 { 13, (const uint32_t []){ 0 }, 1 },
69 { 14, (const uint32_t []){ 3, 25 }, 2 },
70 { 15, (const uint32_t []){ 4 }, 1 },
71 { 16, (const uint32_t []){ 4 }, 1 },
72 { 17, (const uint32_t []){ 5 }, 1 },
73 { 18, (const uint32_t []){ 6 }, 1 },
74 { 20, (const uint32_t []){ 19 }, 1 },
75 { 21, (const uint32_t []){ 0 }, 1 },
76 { 23, (const uint32_t []){ 22 }, 1 },
77 { 24, (const uint32_t []){ 0 }, 1 },
78 { 25, (const uint32_t []){ 0 }, 1 },
79 { 26, (const uint32_t []){ 5 }, 1 },
80 { 27, (const uint32_t []){ 14 }, 1 },
81 /* tests to simulate slides-110-sidrops-sriram-aspa-alg-accuracy-01 */
82 { 101, (const uint32_t []){ 102 }, 1 },
83 { 102, (const uint32_t []){ 103, 104, 105 }, 3 },
84 { 103, (const uint32_t []){ 111, 112, 203 }, 3 },
85 /* 104 no ASPA */
86 { 105, (const uint32_t []){ 0 }, 1 },
87
88 /* 111 no ASPA */
89 { 112, (const uint32_t []){ 0 }, 1 },
90 { 113, (const uint32_t []){ 104, 105, 204, 205 }, 4 },
91
92 { 121, (const uint32_t []){ 131, 132, 133 }, 3 },
93 { 123, (const uint32_t []){ 0 }, 1 },
94 { 131, (const uint32_t []){ 121, 122, 123 }, 3 },
95 { 133, (const uint32_t []){ 0 }, 1 },
96
97
98 { 201, (const uint32_t []){ 202 }, 1 },
99 { 202, (const uint32_t []){ 203, 204, 205 }, 3 },
100 { 203, (const uint32_t []){ 103, 111, 112 }, 3 },
101 /* 204 no ASPA */
102 { 205, (const uint32_t []){ 0 }, 1 },
103
104 /* extra test for big table test */
105 { 65000, (const uint32_t []){
106 3, 5, 10, 15, 20, 21, 22, 23, 24, 25,
107 30, 35, 40, 45, 50, 51, 52, 53, 54, 55,
108 60, 65, 70, 75, 80, 81, 82, 83, 87, 90 }, 30 },
109 { 196618, (const uint32_t []){ 1, 2, 3, 4 }, 4 },
110 };
111
112 struct cp_test cp_testset[] = {
113 { 6, 1, UNKNOWN },
114 { 42, 1, UNKNOWN },
115
116 { 1, 2, NOT_PROVIDER },
117 { 1, 3, NOT_PROVIDER },
118 { 1, 7, NOT_PROVIDER },
119 { 5, 2, NOT_PROVIDER },
120 { 5, 16, NOT_PROVIDER },
121 { 5, 18, NOT_PROVIDER },
122 { 5, 24, NOT_PROVIDER },
123 { 5, 26, NOT_PROVIDER },
124 { 8, 2, NOT_PROVIDER },
125 { 9, 5, NOT_PROVIDER },
126 { 27, 13, NOT_PROVIDER },
127 { 27, 15, NOT_PROVIDER },
128
129 { 1, 4, PROVIDER },
130 { 1, 5, PROVIDER },
131 { 1, 6, PROVIDER },
132 { 2, 10, PROVIDER },
133 { 2, 11, PROVIDER },
134 { 9, 2, PROVIDER },
135 { 27, 14, PROVIDER },
136
137 { 196618, 1, PROVIDER },
138 { 196618, 2, PROVIDER },
139 { 196618, 3, PROVIDER },
140 { 196618, 4, PROVIDER },
141 { 196618, 5, NOT_PROVIDER },
142
143 /* big provider set test */
144 { 65000, 1, NOT_PROVIDER },
145 { 65000, 2, NOT_PROVIDER },
146 { 65000, 3, PROVIDER },
147 { 65000, 4, NOT_PROVIDER },
148 { 65000, 5, PROVIDER },
149 { 65000, 15, PROVIDER },
150 { 65000, 19, NOT_PROVIDER },
151 { 65000, 20, PROVIDER },
152 { 65000, 21, PROVIDER },
153 { 65000, 22, PROVIDER },
154 { 65000, 23, PROVIDER },
155 { 65000, 24, PROVIDER },
156 { 65000, 25, PROVIDER },
157 { 65000, 26, NOT_PROVIDER },
158 { 65000, 85, NOT_PROVIDER },
159 { 65000, 86, NOT_PROVIDER },
160 { 65000, 87, PROVIDER },
161 { 65000, 88, NOT_PROVIDER },
162 { 65000, 89, NOT_PROVIDER },
163 { 65000, 90, PROVIDER },
164 { 65000, 91, NOT_PROVIDER },
165 { 65000, 92, NOT_PROVIDER },
166 { 65000, 6666, NOT_PROVIDER },
167 };
168
169 struct aspath_test aspath_testset[] = {
170 { (const uint32_t []) { 1 }, 1, { 1, 1, 0, 0, 1, 0, 0 } },
171 { (const uint32_t []) { 7 }, 1, { 1, 1, 0, 0, 1, 0, 0 } },
172 { (const uint32_t []) { 8 }, 1, { 1, 1, 0, 0, 1, 0, 0 } },
173
174 { (const uint32_t []) { 1, 1 }, 2, { 1, 1, 0, 0, 1, 0, 0 } },
175 { (const uint32_t []) { 7, 7 }, 2, { 1, 1, 0, 0, 1, 0, 0 } },
176 { (const uint32_t []) { 8, 8 }, 2, { 1, 1, 0, 0, 1, 0, 0 } },
177
178 { (const uint32_t []) { 1, 1, 1 }, 3, { 1, 1, 0, 0, 1, 0, 0 } },
179 { (const uint32_t []) { 7, 7, 7 }, 3, { 1, 1, 0, 0, 1, 0, 0 } },
180 { (const uint32_t []) { 8, 8, 8 }, 3, { 1, 1, 0, 0, 1, 0, 0 } },
181
182 { (const uint32_t []) { 1, 5 }, 2, { 2, 1, 0, 0, 2, 0, 0 } },
183 { (const uint32_t []) { 1, 1, 5, 5 }, 4, { 2, 1, 0, 0, 2, 0, 0 } },
184 { (const uint32_t []) { 1, 5, 17 }, 3, { 3, 1, 0, 0, 3, 0, 0 } },
185
186 { (const uint32_t []) { 1, 4 }, 2, { 2, 2, 0, 1, 2, 0, 0 } },
187 { (const uint32_t []) { 1, 6 }, 2, { 2, 2, 1, 0, 2, 0, 0 } },
188 { (const uint32_t []) { 1, 17 }, 2, { 2, 2, 0, 1, 1, 0, 2 } },
189
190 { (const uint32_t []) { 42, 43, 44 }, 3, { 3, 3, 2, 0, 1, 2, 0 } },
191
192 { (const uint32_t []) { 42, 1, 5, 17, 44 }, 5,
193 { 5, 5, 4, 1, 1, 2, 5 } },
194
195 /* 1 ?> 6 -? 11 -- 12 -- 13 ?- 19 <? 20 */
196 { (const uint32_t []) { 1, 6, 11, 12, 13, 19, 20 }, 7,
197 { 7, 6, 5, 4, 2, 3, 4 } },
198 };
199
200 /*
201 * For simplicity the relation between is described as 123 LR 124 where:
202 * R: ? if ASPA(123) is empty
203 * > if 124 is a provider of 123
204 * - otherwise (124 is not part of the provider list)
205 * L: ? if ASPA(124) is empty
206 * > if 123 is a provider of of 124
207 * - otherwise (123 is not part of the provider list)
208 *
209 * e.g. 1 -> 2 (2 is provider of 1 but 1 is not for 2)
210 * 1 ?> 2 (2 is provider of 1 but 2 has no ASPA set defined)
211 */
212 struct aspa_test aspa_testset[] = {
213 /* empty ASPATH are invalid by default */
214 { (const uint32_t []) { }, 0, ROLE_CUSTOMER, ASPA_INVALID },
215 { (const uint32_t []) { }, 0, ROLE_PROVIDER, ASPA_INVALID },
216 { (const uint32_t []) { }, 0, ROLE_RS, ASPA_INVALID },
217 { (const uint32_t []) { }, 0, ROLE_RS_CLIENT, ASPA_INVALID },
218 { (const uint32_t []) { }, 0, ROLE_PEER, ASPA_INVALID },
219
220 { (const uint32_t []) { 2 }, 1, ROLE_RS_CLIENT, ASPA_VALID },
221 { (const uint32_t []) { 2 }, 1, ROLE_PEER, ASPA_VALID },
222
223 { (const uint32_t []) { 3 }, 1, ROLE_PROVIDER, ASPA_VALID },
224 { (const uint32_t []) { 4 }, 1, ROLE_CUSTOMER, ASPA_VALID },
225 { (const uint32_t []) { 5 }, 1, ROLE_CUSTOMER, ASPA_VALID },
226 { (const uint32_t []) { 6 }, 1, ROLE_CUSTOMER, ASPA_VALID },
227
228 { (const uint32_t []) { 7 }, 1, ROLE_PROVIDER, ASPA_VALID },
229 { (const uint32_t []) { 7 }, 1, ROLE_PEER, ASPA_VALID },
230 { (const uint32_t []) { 7 }, 1, ROLE_RS_CLIENT, ASPA_VALID },
231
232 { (const uint32_t []) { 2, 8 }, 2, ROLE_PEER, ASPA_INVALID },
233 { (const uint32_t []) { 2, 8 }, 2, ROLE_RS_CLIENT, ASPA_INVALID },
234
235 { (const uint32_t []) { 2, 9 }, 2, ROLE_PEER, ASPA_VALID },
236 { (const uint32_t []) { 2, 9 }, 2, ROLE_RS_CLIENT, ASPA_VALID },
237
238 { (const uint32_t []) { 2, 10 }, 2, ROLE_PEER, ASPA_INVALID },
239 { (const uint32_t []) { 2, 10 }, 2, ROLE_RS_CLIENT, ASPA_INVALID },
240
241 { (const uint32_t []) { 2, 11 }, 2, ROLE_PEER, ASPA_VALID },
242 { (const uint32_t []) { 2, 11 }, 2, ROLE_RS_CLIENT, ASPA_VALID },
243
244 { (const uint32_t []) { 3, 8 }, 2, ROLE_PROVIDER, ASPA_INVALID },
245 { (const uint32_t []) { 3, 12 }, 2, ROLE_PROVIDER, ASPA_VALID },
246 { (const uint32_t []) { 3, 13 }, 2, ROLE_PROVIDER, ASPA_INVALID },
247 { (const uint32_t []) { 3, 14 }, 2, ROLE_PROVIDER, ASPA_VALID },
248
249 { (const uint32_t []) { 4, 8 }, 2, ROLE_CUSTOMER, ASPA_VALID },
250 { (const uint32_t []) { 4, 15 }, 2, ROLE_CUSTOMER, ASPA_VALID },
251 { (const uint32_t []) { 4, 16 }, 2, ROLE_CUSTOMER, ASPA_VALID },
252 { (const uint32_t []) { 4, 24 }, 2, ROLE_CUSTOMER, ASPA_VALID },
253
254 { (const uint32_t []) { 5, 8 }, 2, ROLE_CUSTOMER, ASPA_VALID },
255 { (const uint32_t []) { 5, 17 }, 2, ROLE_CUSTOMER, ASPA_VALID },
256 { (const uint32_t []) { 5, 25 }, 2, ROLE_CUSTOMER, ASPA_VALID },
257 { (const uint32_t []) { 5, 26 }, 2, ROLE_CUSTOMER, ASPA_VALID },
258
259 { (const uint32_t []) { 6, 18 }, 2, ROLE_CUSTOMER, ASPA_VALID },
260 { (const uint32_t []) { 6, 19 }, 2, ROLE_CUSTOMER, ASPA_VALID },
261
262 { (const uint32_t []) { 7, 19 }, 2, ROLE_PROVIDER, ASPA_UNKNOWN },
263 { (const uint32_t []) { 7, 19 }, 2, ROLE_PEER, ASPA_UNKNOWN },
264 { (const uint32_t []) { 7, 19 }, 2, ROLE_RS_CLIENT, ASPA_UNKNOWN },
265 { (const uint32_t []) { 7, 21 }, 2, ROLE_PROVIDER, ASPA_INVALID },
266 { (const uint32_t []) { 7, 21 }, 2, ROLE_PEER, ASPA_INVALID },
267 { (const uint32_t []) { 7, 21 }, 2, ROLE_RS_CLIENT, ASPA_INVALID },
268
269 { (const uint32_t []) { 6, 19, 20 }, 3, ROLE_CUSTOMER, ASPA_VALID },
270 { (const uint32_t []) { 20, 19, 6 }, 3, ROLE_CUSTOMER, ASPA_VALID },
271
272 { (const uint32_t []) { 3, 14, 25 }, 3, ROLE_PROVIDER, ASPA_INVALID },
273 { (const uint32_t []) { 3, 14, 19 }, 3, ROLE_PROVIDER, ASPA_UNKNOWN },
274 { (const uint32_t []) { 3, 14, 19 }, 3, ROLE_PEER, ASPA_UNKNOWN },
275 { (const uint32_t []) { 3, 14, 19 }, 3, ROLE_RS_CLIENT, ASPA_UNKNOWN },
276 { (const uint32_t []) { 3, 14, 21 }, 3, ROLE_PROVIDER, ASPA_INVALID },
277 { (const uint32_t []) { 3, 14, 21 }, 3, ROLE_PEER, ASPA_INVALID },
278 { (const uint32_t []) { 3, 14, 21 }, 3, ROLE_RS_CLIENT, ASPA_INVALID },
279 { (const uint32_t []) { 3, 14, 27 }, 3, ROLE_PROVIDER, ASPA_VALID },
280 { (const uint32_t []) { 3, 14, 27 }, 3, ROLE_PEER, ASPA_VALID },
281 { (const uint32_t []) { 3, 14, 27 }, 3, ROLE_RS_CLIENT, ASPA_VALID },
282
283 { (const uint32_t []) { 7, 19, 22, 21 }, 4, ROLE_PROVIDER,
284 ASPA_INVALID },
285 { (const uint32_t []) { 7, 19, 22, 21 }, 4, ROLE_PEER, ASPA_INVALID },
286 { (const uint32_t []) { 7, 19, 22, 21 }, 4, ROLE_RS_CLIENT,
287 ASPA_INVALID },
288
289 { (const uint32_t []) { 6, 19, 22, 23 }, 4, ROLE_CUSTOMER,
290 ASPA_UNKNOWN },
291
292 { (const uint32_t []) { 1, 5, 17, 13, 3, 14, 27 }, 7, ROLE_CUSTOMER,
293 ASPA_VALID },
294 { (const uint32_t []) { 27, 14, 3, 13, 17, 5, 1 }, 7, ROLE_CUSTOMER,
295 ASPA_VALID },
296
297 { (const uint32_t []) { 27, 14, 3, 6, 7, 19, 17, 5, 1 }, 9,
298 ROLE_CUSTOMER, ASPA_INVALID },
299 { (const uint32_t []) { 27, 14, 3, 7, 19, 6, 1, 5, 17 }, 9,
300 ROLE_CUSTOMER, ASPA_UNKNOWN },
301
302 /* check L < K (ramps overlap) */
303 { (const uint32_t []) { 201, 202, 203, 103, 102, 101 }, 6,
304 ROLE_CUSTOMER, ASPA_VALID },
305 { (const uint32_t []) { 101, 102, 103, 203, 202, 201 }, 6,
306 ROLE_CUSTOMER, ASPA_VALID },
307
308 /* check L == K (ramps touch) 203 ?> 111 <? 103 */
309 { (const uint32_t []) { 201, 202, 203, 111, 103, 102, 101 }, 7,
310 ROLE_CUSTOMER, ASPA_VALID },
311 { (const uint32_t []) { 101, 102, 103, 111, 203, 202, 201 }, 7,
312 ROLE_CUSTOMER, ASPA_VALID },
313 /* check L == K (ramps touch) 203 -> 111 <- 103 */
314 { (const uint32_t []) { 201, 202, 203, 112, 103, 102, 101 }, 7,
315 ROLE_CUSTOMER, ASPA_VALID },
316 { (const uint32_t []) { 101, 102, 103, 112, 203, 202, 201 }, 7,
317 ROLE_CUSTOMER, ASPA_VALID },
318
319 /* check L - K == 1 (204 ?? 104) */
320 { (const uint32_t []) { 201, 202, 204, 104, 102, 101 }, 6,
321 ROLE_CUSTOMER, ASPA_VALID },
322 /* check L - K == 1 (204 -? 105) */
323 { (const uint32_t []) { 201, 202, 204, 105, 102, 101 }, 6,
324 ROLE_CUSTOMER, ASPA_VALID },
325 /* check L - K == 1 (205 ?- 104) */
326 { (const uint32_t []) { 201, 202, 205, 104, 102, 101 }, 6,
327 ROLE_CUSTOMER, ASPA_VALID },
328 /* check L - K == 1 (205 -- 105) */
329 { (const uint32_t []) { 201, 202, 205, 105, 102, 101 }, 6,
330 ROLE_CUSTOMER, ASPA_VALID },
331
332 /* check L - K == 2 invalid cases (205 ?- 111 -? 105) */
333 { (const uint32_t []) { 201, 202, 205, 111, 105, 102, 101 }, 7,
334 ROLE_CUSTOMER, ASPA_INVALID },
335 /* check L - K == 2 invalid cases (205 -- 112 -- 105) */
336 { (const uint32_t []) { 201, 202, 205, 112, 105, 102, 101 }, 7,
337 ROLE_CUSTOMER, ASPA_INVALID },
338 /* check L - K == 2 invalid cases (205 <- 113 -> 105) */
339 { (const uint32_t []) { 201, 202, 205, 113, 105, 102, 101 }, 7,
340 ROLE_CUSTOMER, ASPA_INVALID },
341
342 /* check L - K == 2 unknown cases (205 ?- 111 ?? 104) */
343 { (const uint32_t []) { 201, 202, 205, 111, 104, 102, 101 }, 7,
344 ROLE_CUSTOMER, ASPA_UNKNOWN },
345 /* check L - K == 2 unknown cases (204 ?? 111 -? 105) */
346 { (const uint32_t []) { 201, 202, 204, 111, 105, 102, 101 }, 7,
347 ROLE_CUSTOMER, ASPA_UNKNOWN },
348 /* check L - K == 2 unknown cases (204 ?? 111 ?? 104) */
349 { (const uint32_t []) { 201, 202, 204, 111, 104, 102, 101 }, 7,
350 ROLE_CUSTOMER, ASPA_UNKNOWN },
351 /* check L - K == 2 unknown cases (205 -- 112 ?- 104) */
352 { (const uint32_t []) { 201, 202, 205, 112, 104, 102, 101 }, 7,
353 ROLE_CUSTOMER, ASPA_UNKNOWN },
354 /* check L - K == 2 unknown cases (204 -? 112 -- 105) */
355 { (const uint32_t []) { 201, 202, 204, 112, 105, 102, 101 }, 7,
356 ROLE_CUSTOMER, ASPA_UNKNOWN },
357 /* check L - K == 2 unknown cases (204 -? 112 ?- 104) */
358 { (const uint32_t []) { 201, 202, 204, 112, 104, 102, 101 }, 7,
359 ROLE_CUSTOMER, ASPA_UNKNOWN },
360 /* check L - K == 2 unknown cases (205 <- 113 ?> 104) */
361 { (const uint32_t []) { 201, 202, 205, 113, 104, 102, 101 }, 7,
362 ROLE_CUSTOMER, ASPA_UNKNOWN },
363 /* check L - K == 2 unknown cases (204 <? 113 -> 105) */
364 { (const uint32_t []) { 201, 202, 204, 113, 105, 102, 101 }, 7,
365 ROLE_CUSTOMER, ASPA_UNKNOWN },
366 /* check L - K == 2 unknown cases (204 <? 113 ?> 104) */
367 { (const uint32_t []) { 201, 202, 204, 113, 104, 102, 101 }, 7,
368 ROLE_CUSTOMER, ASPA_UNKNOWN },
369 };
370
371 static struct rde_aspa *
load_test_set(struct aspa_test_set * testv,uint32_t numentries)372 load_test_set(struct aspa_test_set *testv, uint32_t numentries)
373 {
374 struct rde_aspa *aspa;
375 size_t data_size = 0;
376 uint32_t i;
377
378 for (i = 0; i < numentries; i++)
379 data_size += testv[i].pascnt * sizeof(uint32_t);
380
381 aspa = aspa_table_prep(numentries, data_size);
382
383 for (i = numentries; i > 0; i--)
384 aspa_add_set(aspa, testv[i - 1].customeras,
385 testv[i - 1].providers, testv[i - 1].pascnt);
386
387 return aspa;
388 }
389
390 static uint8_t
vstate_for_role(struct rde_aspa_state * vstate,enum role role)391 vstate_for_role(struct rde_aspa_state *vstate, enum role role)
392 {
393 if (role != ROLE_CUSTOMER) {
394 return (vstate->onlyup);
395 } else {
396 return (vstate->downup);
397 }
398 }
399
400 int
main(int argc,char ** argv)401 main(int argc, char **argv)
402 {
403 struct rde_aspa *aspa;
404 size_t num_cp = sizeof(cp_testset) / sizeof(cp_testset[0]);
405 size_t num_aspath = sizeof(aspath_testset) / sizeof(aspath_testset[0]);
406 size_t num_aspa = sizeof(aspa_testset) / sizeof(aspa_testset[0]);
407 size_t i;
408 int cp_failed = 0, aspath_failed = 0, aspa_failed = 0;
409
410 /* first test, loading empty aspa table works. */
411 aspa = load_test_set(NULL, 0);
412 assert(aspa == NULL);
413 aspa_table_free(aspa);
414
415 aspa = load_test_set(testset, sizeof(testset) / sizeof(testset[0]));
416 assert(aspa != NULL);
417
418 printf("testing aspa_cp_lookup: ");
419 for (i = 0; i < num_cp; i++) {
420 uint8_t r;
421 r = aspa_cp_lookup(aspa, cp_testset[i].customeras,
422 cp_testset[i].provideras);
423
424 if (cp_testset[i].expected_result != r) {
425 printf("failed: cp_testset[%zu]: "
426 "cas %u pas %u -> %d got %d\n", i,
427 cp_testset[i].customeras,
428 cp_testset[i].provideras,
429 cp_testset[i].expected_result,
430 r);
431 cp_failed = 1;
432 }
433 }
434 if (!cp_failed)
435 printf("OK\n");
436
437 printf("testing aspa_check_aspath: ");
438 for (i = 0; i < num_aspath; i++) {
439 struct aspa_state st, revst;
440 struct aspath *a;
441
442 memset(&st, 0, sizeof(st));
443 a = build_aspath(aspath_testset[i].aspath,
444 aspath_testset[i].aspathcnt, 0);
445 if (aspa_check_aspath(aspa, a, &st) == -1) {
446 printf("failed: aspath_testset[%zu]: "
447 "aspath %s got -1\n", i,
448 print_aspath(aspath_testset[i].aspath,
449 aspath_testset[i].aspathcnt));
450 aspath_failed = 1;
451 }
452
453 if (memcmp(&aspath_testset[i].state, &st, sizeof(st))) {
454 printf("failed: aspath_testset[%zu]: aspath %s "
455 "bad state", i,
456 print_aspath(aspath_testset[i].aspath,
457 aspath_testset[i].aspathcnt));
458 print_state(&aspath_testset[i].state, &st);
459 printf("\n");
460 aspath_failed = 1;
461 }
462 free(a);
463
464 memset(&st, 0, sizeof(st));
465 a = build_aspath(aspath_testset[i].aspath,
466 aspath_testset[i].aspathcnt, 1);
467 if (aspa_check_aspath(aspa, a, &st) == -1) {
468 printf("failed: reverse aspath_testset[%zu]: "
469 "aspath %s got -1\n", i,
470 print_aspath(aspath_testset[i].aspath,
471 aspath_testset[i].aspathcnt));
472 aspath_failed = 1;
473 }
474
475 reverse_state(&aspath_testset[i].state, &revst);
476 if (memcmp(&revst, &st, sizeof(st))) {
477 printf("failed: reverse aspath_testset[%zu]: aspath %s "
478 "bad state", i,
479 print_aspath(aspath_testset[i].aspath,
480 aspath_testset[i].aspathcnt));
481 print_state(&revst, &st);
482 printf("\n");
483 aspath_failed = 1;
484 }
485 free(a);
486 }
487 if (!aspath_failed)
488 printf("OK\n");
489
490 printf("testing aspa_validation: ");
491 for (i = 0; i < num_aspa; i++) {
492 struct aspath *a;
493 struct rde_aspa_state vstate;
494 uint8_t rv;
495
496 a = build_aspath(aspa_testset[i].aspath,
497 aspa_testset[i].aspathcnt, 0);
498 aspa_validation(aspa, a, &vstate);
499
500 rv = vstate_for_role(&vstate, aspa_testset[i].role);
501
502 if (aspa_testset[i].expected_result != rv) {
503 printf("failed: aspa_testset[%zu]: aspath %s role %d "
504 "want %d got %d", i,
505 print_aspath(aspa_testset[i].aspath,
506 aspa_testset[i].aspathcnt),
507 aspa_testset[i].role,
508 aspa_testset[i].expected_result,
509 rv);
510 aspa_failed = 1;
511 }
512
513 free(a);
514 }
515 if (!aspa_failed)
516 printf("OK\n");
517
518 aspa_table_free(aspa);
519
520 return cp_failed | aspath_failed | aspa_failed;
521 }
522
523 __dead void
fatalx(const char * emsg,...)524 fatalx(const char *emsg, ...)
525 {
526 va_list ap;
527 va_start(ap, emsg);
528 verrx(2, emsg, ap);
529 }
530
531 __dead void
fatal(const char * emsg,...)532 fatal(const char *emsg, ...)
533 {
534 va_list ap;
535 va_start(ap, emsg);
536 verr(2, emsg, ap);
537 }
538
539 uint32_t
aspath_extract(const void * seg,int pos)540 aspath_extract(const void *seg, int pos)
541 {
542 const u_char *ptr = seg;
543 uint32_t as;
544
545 /* minimal pos check, return 0 since that is an invalid ASN */
546 if (pos < 0 || pos >= ptr[1])
547 return (0);
548 ptr += 2 + sizeof(uint32_t) * pos;
549 memcpy(&as, ptr, sizeof(uint32_t));
550 return (ntohl(as));
551 }
552
553 static struct aspath *
build_aspath(const uint32_t * asns,uint32_t asncnt,int rev)554 build_aspath(const uint32_t *asns, uint32_t asncnt, int rev)
555 {
556 struct aspath *aspath;
557 uint32_t i, idx, as;
558 uint16_t len;
559
560 /* don't mess around with multi segment ASPATHs */
561 if (asncnt >= 255)
562 errx(1, "asncnt too big");
563
564 if (asncnt == 0)
565 len = 0;
566 else
567 len = 2 + sizeof(uint32_t) * asncnt;
568 aspath = malloc(ASPATH_HEADER_SIZE + len);
569 if (aspath == NULL)
570 err(1, NULL);
571
572 aspath->len = len;
573 aspath->ascnt = asncnt; /* lie but nothing cares */
574 aspath->source_as = 0;
575
576 if (len == 0)
577 return aspath;
578
579 if (rev)
580 aspath->source_as = asns[asncnt - 1];
581 else
582 aspath->source_as = asns[0];
583
584 aspath->data[0] = AS_SEQUENCE;
585 aspath->data[1] = asncnt;
586 for (i = 0; i < asncnt; i++) {
587 if (rev)
588 idx = asncnt - 1 - i;
589 else
590 idx = i;
591 as = htonl(asns[idx]);
592 memcpy(aspath->data + 2 + sizeof(as) * i, &as,
593 sizeof(uint32_t));
594 }
595
596 return aspath;
597 }
598
599 static const char *
print_aspath(const uint32_t * asns,uint32_t asncnt)600 print_aspath(const uint32_t *asns, uint32_t asncnt)
601 {
602 static char buf[1024];
603 char b[16];
604 uint32_t i;
605
606 strlcpy(buf, "", sizeof(buf));
607 for (i = 0; i < asncnt; i++) {
608 snprintf(b, sizeof(b), "%d", asns[i]);
609 if (i > 0)
610 strlcat(buf, " ", sizeof(buf));
611 strlcat(buf, b, sizeof(buf));
612 }
613 return buf;
614 }
615
616 static void
reverse_state(struct aspa_state * in,struct aspa_state * rev)617 reverse_state(struct aspa_state *in, struct aspa_state *rev)
618 {
619 memset(rev, 0, sizeof(*rev));
620 rev->nhops = in->nhops;
621 rev->nup_p = in->nhops + 1 - in->ndown_p;
622 if (in->ndown_u != 0)
623 rev->nup_u = in->nhops + 1 - in->ndown_u;
624 if (in->ndown_np != 0)
625 rev->nup_np = in->nhops + 1 - in->ndown_np;
626 rev->ndown_p = in->nhops + 1 - in->nup_p;
627 if (in->nup_u != 0)
628 rev->ndown_u = in->nhops + 1 - in->nup_u;
629 if (in->nup_np != 0)
630 rev->ndown_np = in->nhops + 1 - in->nup_np;
631 }
632
633 static void
print_state(struct aspa_state * a,struct aspa_state * b)634 print_state(struct aspa_state *a, struct aspa_state *b)
635 {
636 if (a->nhops != b->nhops)
637 printf(" nhops %d != %d", a->nhops, b->nhops);
638 if (a->nup_p != b->nup_p)
639 printf(" nup_p %d != %d", a->nup_p, b->nup_p);
640 if (a->nup_u != b->nup_u)
641 printf(" nup_u %d != %d", a->nup_u, b->nup_u);
642 if (a->nup_np != b->nup_np)
643 printf(" nup_np %d != %d", a->nup_np, b->nup_np);
644 if (a->ndown_p != b->ndown_p)
645 printf(" ndown_p %d != %d", a->ndown_p, b->ndown_p);
646 if (a->ndown_u != b->ndown_u)
647 printf(" ndown_u %d != %d", a->ndown_u, b->ndown_u);
648 if (a->ndown_np != b->ndown_np)
649 printf(" ndown_np %d != %d", a->ndown_np, b->ndown_np);
650 }
651
652 time_t
getmonotime(void)653 getmonotime(void)
654 {
655 return time(NULL);
656 }
657