xref: /openbsd-src/regress/usr.sbin/bgpd/unittests/rde_aspa_test.c (revision 4a2c408de7aa871da60ea7a066233502ab912e73)
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