1*4a2c408dSclaudio /* $OpenBSD: rde_aspa_test.c,v 1.5 2023/08/16 08:29:41 claudio Exp $ */
281623c4aSclaudio
381623c4aSclaudio /*
481623c4aSclaudio * Copyright (c) 2022 Claudio Jeker <claudio@openbsd.org>
581623c4aSclaudio *
681623c4aSclaudio * Permission to use, copy, modify, and distribute this software for any
781623c4aSclaudio * purpose with or without fee is hereby granted, provided that the above
881623c4aSclaudio * copyright notice and this permission notice appear in all copies.
981623c4aSclaudio *
1081623c4aSclaudio * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1181623c4aSclaudio * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1281623c4aSclaudio * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1381623c4aSclaudio * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1481623c4aSclaudio * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1581623c4aSclaudio * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1681623c4aSclaudio * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1781623c4aSclaudio */
1881623c4aSclaudio
1981623c4aSclaudio #include <assert.h>
2081623c4aSclaudio #include <err.h>
2181623c4aSclaudio #include <stdio.h>
2281623c4aSclaudio
2381623c4aSclaudio #include "rde_aspa.c"
2481623c4aSclaudio
2581623c4aSclaudio static struct aspath *build_aspath(const uint32_t *, uint32_t, int);
2681623c4aSclaudio static const char *print_aspath(const uint32_t *, uint32_t);
2781623c4aSclaudio
2881623c4aSclaudio static void reverse_state(struct aspa_state *, struct aspa_state *);
2981623c4aSclaudio static void print_state(struct aspa_state *, struct aspa_state *);
3081623c4aSclaudio
3181623c4aSclaudio struct aspa_test_set {
3281623c4aSclaudio uint32_t customeras;
3381623c4aSclaudio const uint32_t *providers;
3481623c4aSclaudio uint32_t pascnt;
3581623c4aSclaudio };
3681623c4aSclaudio
3781623c4aSclaudio struct cp_test {
3881623c4aSclaudio uint32_t customeras;
3981623c4aSclaudio uint32_t provideras;
40a01a053bSclaudio uint8_t expected_result;
4181623c4aSclaudio };
4281623c4aSclaudio
4381623c4aSclaudio struct aspath_test {
4481623c4aSclaudio const uint32_t *aspath;
4581623c4aSclaudio uint32_t aspathcnt;
4681623c4aSclaudio struct aspa_state state;
4781623c4aSclaudio };
4881623c4aSclaudio
4981623c4aSclaudio struct aspa_test {
5081623c4aSclaudio const uint32_t *aspath;
5181623c4aSclaudio uint32_t aspathcnt;
5281623c4aSclaudio enum role role;
5381623c4aSclaudio uint8_t expected_result;
5481623c4aSclaudio };
5581623c4aSclaudio
5681623c4aSclaudio struct aspa_test_set testset[] = {
5781623c4aSclaudio /* test vectors from github.com/benmaddison/aspa-fuzz */
58*4a2c408dSclaudio { 1, (const uint32_t []){ 4, 5, 6 }, 3 },
59*4a2c408dSclaudio { 2, (const uint32_t []){ 10, 11 }, 2 },
60*4a2c408dSclaudio { 3, (const uint32_t []){ 1, 13, 14 }, 3 },
61*4a2c408dSclaudio { 4, (const uint32_t []){ 16, 24 }, 2 },
62*4a2c408dSclaudio { 5, (const uint32_t []){ 1, 17, 25 }, 3 },
63*4a2c408dSclaudio { 8, (const uint32_t []){ 0 }, 1 },
64*4a2c408dSclaudio { 9, (const uint32_t []){ 2 }, 1 },
65*4a2c408dSclaudio { 10, (const uint32_t []){ 0 }, 1 },
66*4a2c408dSclaudio { 11, (const uint32_t []){ 2 }, 1 },
67*4a2c408dSclaudio { 12, (const uint32_t []){ 3 }, 1 },
68*4a2c408dSclaudio { 13, (const uint32_t []){ 0 }, 1 },
69*4a2c408dSclaudio { 14, (const uint32_t []){ 3, 25 }, 2 },
70*4a2c408dSclaudio { 15, (const uint32_t []){ 4 }, 1 },
71*4a2c408dSclaudio { 16, (const uint32_t []){ 4 }, 1 },
72*4a2c408dSclaudio { 17, (const uint32_t []){ 5 }, 1 },
73*4a2c408dSclaudio { 18, (const uint32_t []){ 6 }, 1 },
74*4a2c408dSclaudio { 20, (const uint32_t []){ 19 }, 1 },
75*4a2c408dSclaudio { 21, (const uint32_t []){ 0 }, 1 },
76*4a2c408dSclaudio { 23, (const uint32_t []){ 22 }, 1 },
77*4a2c408dSclaudio { 24, (const uint32_t []){ 0 }, 1 },
78*4a2c408dSclaudio { 25, (const uint32_t []){ 0 }, 1 },
79*4a2c408dSclaudio { 26, (const uint32_t []){ 5 }, 1 },
80*4a2c408dSclaudio { 27, (const uint32_t []){ 14 }, 1 },
8181623c4aSclaudio /* tests to simulate slides-110-sidrops-sriram-aspa-alg-accuracy-01 */
82*4a2c408dSclaudio { 101, (const uint32_t []){ 102 }, 1 },
83*4a2c408dSclaudio { 102, (const uint32_t []){ 103, 104, 105 }, 3 },
84*4a2c408dSclaudio { 103, (const uint32_t []){ 111, 112, 203 }, 3 },
8581623c4aSclaudio /* 104 no ASPA */
86*4a2c408dSclaudio { 105, (const uint32_t []){ 0 }, 1 },
8781623c4aSclaudio
8881623c4aSclaudio /* 111 no ASPA */
89*4a2c408dSclaudio { 112, (const uint32_t []){ 0 }, 1 },
90*4a2c408dSclaudio { 113, (const uint32_t []){ 104, 105, 204, 205 }, 4 },
9181623c4aSclaudio
92*4a2c408dSclaudio { 121, (const uint32_t []){ 131, 132, 133 }, 3 },
93*4a2c408dSclaudio { 123, (const uint32_t []){ 0 }, 1 },
94*4a2c408dSclaudio { 131, (const uint32_t []){ 121, 122, 123 }, 3 },
95*4a2c408dSclaudio { 133, (const uint32_t []){ 0 }, 1 },
9681623c4aSclaudio
9781623c4aSclaudio
98*4a2c408dSclaudio { 201, (const uint32_t []){ 202 }, 1 },
99*4a2c408dSclaudio { 202, (const uint32_t []){ 203, 204, 205 }, 3 },
100*4a2c408dSclaudio { 203, (const uint32_t []){ 103, 111, 112 }, 3 },
10181623c4aSclaudio /* 204 no ASPA */
102*4a2c408dSclaudio { 205, (const uint32_t []){ 0 }, 1 },
10381623c4aSclaudio
10481623c4aSclaudio /* extra test for big table test */
10581623c4aSclaudio { 65000, (const uint32_t []){
10681623c4aSclaudio 3, 5, 10, 15, 20, 21, 22, 23, 24, 25,
10781623c4aSclaudio 30, 35, 40, 45, 50, 51, 52, 53, 54, 55,
108*4a2c408dSclaudio 60, 65, 70, 75, 80, 81, 82, 83, 87, 90 }, 30 },
109*4a2c408dSclaudio { 196618, (const uint32_t []){ 1, 2, 3, 4 }, 4 },
11081623c4aSclaudio };
11181623c4aSclaudio
11281623c4aSclaudio struct cp_test cp_testset[] = {
113*4a2c408dSclaudio { 6, 1, UNKNOWN },
114*4a2c408dSclaudio { 42, 1, UNKNOWN },
11581623c4aSclaudio
116*4a2c408dSclaudio { 1, 2, NOT_PROVIDER },
117*4a2c408dSclaudio { 1, 3, NOT_PROVIDER },
118*4a2c408dSclaudio { 1, 7, NOT_PROVIDER },
119*4a2c408dSclaudio { 5, 2, NOT_PROVIDER },
120*4a2c408dSclaudio { 5, 16, NOT_PROVIDER },
121*4a2c408dSclaudio { 5, 18, NOT_PROVIDER },
122*4a2c408dSclaudio { 5, 24, NOT_PROVIDER },
123*4a2c408dSclaudio { 5, 26, NOT_PROVIDER },
124*4a2c408dSclaudio { 8, 2, NOT_PROVIDER },
125*4a2c408dSclaudio { 9, 5, NOT_PROVIDER },
126*4a2c408dSclaudio { 27, 13, NOT_PROVIDER },
127*4a2c408dSclaudio { 27, 15, NOT_PROVIDER },
12881623c4aSclaudio
129*4a2c408dSclaudio { 1, 4, PROVIDER },
130*4a2c408dSclaudio { 1, 5, PROVIDER },
131*4a2c408dSclaudio { 1, 6, PROVIDER },
132*4a2c408dSclaudio { 2, 10, PROVIDER },
133*4a2c408dSclaudio { 2, 11, PROVIDER },
134*4a2c408dSclaudio { 9, 2, PROVIDER },
135*4a2c408dSclaudio { 27, 14, PROVIDER },
13681623c4aSclaudio
137*4a2c408dSclaudio { 196618, 1, PROVIDER },
138*4a2c408dSclaudio { 196618, 2, PROVIDER },
139*4a2c408dSclaudio { 196618, 3, PROVIDER },
140*4a2c408dSclaudio { 196618, 4, PROVIDER },
141*4a2c408dSclaudio { 196618, 5, NOT_PROVIDER },
14281623c4aSclaudio
14381623c4aSclaudio /* big provider set test */
144*4a2c408dSclaudio { 65000, 1, NOT_PROVIDER },
145*4a2c408dSclaudio { 65000, 2, NOT_PROVIDER },
146*4a2c408dSclaudio { 65000, 3, PROVIDER },
147*4a2c408dSclaudio { 65000, 4, NOT_PROVIDER },
148*4a2c408dSclaudio { 65000, 5, PROVIDER },
149*4a2c408dSclaudio { 65000, 15, PROVIDER },
150*4a2c408dSclaudio { 65000, 19, NOT_PROVIDER },
151*4a2c408dSclaudio { 65000, 20, PROVIDER },
152*4a2c408dSclaudio { 65000, 21, PROVIDER },
153*4a2c408dSclaudio { 65000, 22, PROVIDER },
154*4a2c408dSclaudio { 65000, 23, PROVIDER },
155*4a2c408dSclaudio { 65000, 24, PROVIDER },
156*4a2c408dSclaudio { 65000, 25, PROVIDER },
157*4a2c408dSclaudio { 65000, 26, NOT_PROVIDER },
158*4a2c408dSclaudio { 65000, 85, NOT_PROVIDER },
159*4a2c408dSclaudio { 65000, 86, NOT_PROVIDER },
160*4a2c408dSclaudio { 65000, 87, PROVIDER },
161*4a2c408dSclaudio { 65000, 88, NOT_PROVIDER },
162*4a2c408dSclaudio { 65000, 89, NOT_PROVIDER },
163*4a2c408dSclaudio { 65000, 90, PROVIDER },
164*4a2c408dSclaudio { 65000, 91, NOT_PROVIDER },
165*4a2c408dSclaudio { 65000, 92, NOT_PROVIDER },
166*4a2c408dSclaudio { 65000, 6666, NOT_PROVIDER },
16781623c4aSclaudio };
16881623c4aSclaudio
16981623c4aSclaudio struct aspath_test aspath_testset[] = {
17081623c4aSclaudio { (const uint32_t []) { 1 }, 1, { 1, 1, 0, 0, 1, 0, 0 } },
17181623c4aSclaudio { (const uint32_t []) { 7 }, 1, { 1, 1, 0, 0, 1, 0, 0 } },
17281623c4aSclaudio { (const uint32_t []) { 8 }, 1, { 1, 1, 0, 0, 1, 0, 0 } },
17381623c4aSclaudio
17481623c4aSclaudio { (const uint32_t []) { 1, 1 }, 2, { 1, 1, 0, 0, 1, 0, 0 } },
17581623c4aSclaudio { (const uint32_t []) { 7, 7 }, 2, { 1, 1, 0, 0, 1, 0, 0 } },
17681623c4aSclaudio { (const uint32_t []) { 8, 8 }, 2, { 1, 1, 0, 0, 1, 0, 0 } },
17781623c4aSclaudio
17881623c4aSclaudio { (const uint32_t []) { 1, 1, 1 }, 3, { 1, 1, 0, 0, 1, 0, 0 } },
17981623c4aSclaudio { (const uint32_t []) { 7, 7, 7 }, 3, { 1, 1, 0, 0, 1, 0, 0 } },
18081623c4aSclaudio { (const uint32_t []) { 8, 8, 8 }, 3, { 1, 1, 0, 0, 1, 0, 0 } },
18181623c4aSclaudio
18281623c4aSclaudio { (const uint32_t []) { 1, 5 }, 2, { 2, 1, 0, 0, 2, 0, 0 } },
18381623c4aSclaudio { (const uint32_t []) { 1, 1, 5, 5 }, 4, { 2, 1, 0, 0, 2, 0, 0 } },
18481623c4aSclaudio { (const uint32_t []) { 1, 5, 17 }, 3, { 3, 1, 0, 0, 3, 0, 0 } },
18581623c4aSclaudio
18681623c4aSclaudio { (const uint32_t []) { 1, 4 }, 2, { 2, 2, 0, 1, 2, 0, 0 } },
18781623c4aSclaudio { (const uint32_t []) { 1, 6 }, 2, { 2, 2, 1, 0, 2, 0, 0 } },
18881623c4aSclaudio { (const uint32_t []) { 1, 17 }, 2, { 2, 2, 0, 1, 1, 0, 2 } },
18981623c4aSclaudio
19081623c4aSclaudio { (const uint32_t []) { 42, 43, 44 }, 3, { 3, 3, 2, 0, 1, 2, 0 } },
19181623c4aSclaudio
19281623c4aSclaudio { (const uint32_t []) { 42, 1, 5, 17, 44 }, 5,
19381623c4aSclaudio { 5, 5, 4, 1, 1, 2, 5 } },
19481623c4aSclaudio
19581623c4aSclaudio /* 1 ?> 6 -? 11 -- 12 -- 13 ?- 19 <? 20 */
19681623c4aSclaudio { (const uint32_t []) { 1, 6, 11, 12, 13, 19, 20 }, 7,
19781623c4aSclaudio { 7, 6, 5, 4, 2, 3, 4 } },
19881623c4aSclaudio };
19981623c4aSclaudio
20081623c4aSclaudio /*
20181623c4aSclaudio * For simplicity the relation between is described as 123 LR 124 where:
20281623c4aSclaudio * R: ? if ASPA(123) is empty
20381623c4aSclaudio * > if 124 is a provider of 123
20481623c4aSclaudio * - otherwise (124 is not part of the provider list)
20581623c4aSclaudio * L: ? if ASPA(124) is empty
20681623c4aSclaudio * > if 123 is a provider of of 124
20781623c4aSclaudio * - otherwise (123 is not part of the provider list)
20881623c4aSclaudio *
20981623c4aSclaudio * e.g. 1 -> 2 (2 is provider of 1 but 1 is not for 2)
21081623c4aSclaudio * 1 ?> 2 (2 is provider of 1 but 2 has no ASPA set defined)
21181623c4aSclaudio */
21281623c4aSclaudio struct aspa_test aspa_testset[] = {
21381623c4aSclaudio /* empty ASPATH are invalid by default */
214a01a053bSclaudio { (const uint32_t []) { }, 0, ROLE_CUSTOMER, ASPA_INVALID },
215a01a053bSclaudio { (const uint32_t []) { }, 0, ROLE_PROVIDER, ASPA_INVALID },
216a01a053bSclaudio { (const uint32_t []) { }, 0, ROLE_RS, ASPA_INVALID },
217a01a053bSclaudio { (const uint32_t []) { }, 0, ROLE_RS_CLIENT, ASPA_INVALID },
218a01a053bSclaudio { (const uint32_t []) { }, 0, ROLE_PEER, ASPA_INVALID },
21981623c4aSclaudio
220a01a053bSclaudio { (const uint32_t []) { 2 }, 1, ROLE_RS_CLIENT, ASPA_VALID },
221a01a053bSclaudio { (const uint32_t []) { 2 }, 1, ROLE_PEER, ASPA_VALID },
22281623c4aSclaudio
223a01a053bSclaudio { (const uint32_t []) { 3 }, 1, ROLE_PROVIDER, ASPA_VALID },
224a01a053bSclaudio { (const uint32_t []) { 4 }, 1, ROLE_CUSTOMER, ASPA_VALID },
225a01a053bSclaudio { (const uint32_t []) { 5 }, 1, ROLE_CUSTOMER, ASPA_VALID },
226a01a053bSclaudio { (const uint32_t []) { 6 }, 1, ROLE_CUSTOMER, ASPA_VALID },
22781623c4aSclaudio
228a01a053bSclaudio { (const uint32_t []) { 7 }, 1, ROLE_PROVIDER, ASPA_VALID },
229a01a053bSclaudio { (const uint32_t []) { 7 }, 1, ROLE_PEER, ASPA_VALID },
230a01a053bSclaudio { (const uint32_t []) { 7 }, 1, ROLE_RS_CLIENT, ASPA_VALID },
23181623c4aSclaudio
232a01a053bSclaudio { (const uint32_t []) { 2, 8 }, 2, ROLE_PEER, ASPA_INVALID },
233a01a053bSclaudio { (const uint32_t []) { 2, 8 }, 2, ROLE_RS_CLIENT, ASPA_INVALID },
234a01a053bSclaudio
235a01a053bSclaudio { (const uint32_t []) { 2, 9 }, 2, ROLE_PEER, ASPA_VALID },
236a01a053bSclaudio { (const uint32_t []) { 2, 9 }, 2, ROLE_RS_CLIENT, ASPA_VALID },
237a01a053bSclaudio
238a01a053bSclaudio { (const uint32_t []) { 2, 10 }, 2, ROLE_PEER, ASPA_INVALID },
239a01a053bSclaudio { (const uint32_t []) { 2, 10 }, 2, ROLE_RS_CLIENT, ASPA_INVALID },
240a01a053bSclaudio
241a01a053bSclaudio { (const uint32_t []) { 2, 11 }, 2, ROLE_PEER, ASPA_VALID },
242a01a053bSclaudio { (const uint32_t []) { 2, 11 }, 2, ROLE_RS_CLIENT, ASPA_VALID },
243a01a053bSclaudio
244a01a053bSclaudio { (const uint32_t []) { 3, 8 }, 2, ROLE_PROVIDER, ASPA_INVALID },
245a01a053bSclaudio { (const uint32_t []) { 3, 12 }, 2, ROLE_PROVIDER, ASPA_VALID },
246a01a053bSclaudio { (const uint32_t []) { 3, 13 }, 2, ROLE_PROVIDER, ASPA_INVALID },
247a01a053bSclaudio { (const uint32_t []) { 3, 14 }, 2, ROLE_PROVIDER, ASPA_VALID },
248a01a053bSclaudio
249a01a053bSclaudio { (const uint32_t []) { 4, 8 }, 2, ROLE_CUSTOMER, ASPA_VALID },
250a01a053bSclaudio { (const uint32_t []) { 4, 15 }, 2, ROLE_CUSTOMER, ASPA_VALID },
251a01a053bSclaudio { (const uint32_t []) { 4, 16 }, 2, ROLE_CUSTOMER, ASPA_VALID },
252a01a053bSclaudio { (const uint32_t []) { 4, 24 }, 2, ROLE_CUSTOMER, ASPA_VALID },
253a01a053bSclaudio
254a01a053bSclaudio { (const uint32_t []) { 5, 8 }, 2, ROLE_CUSTOMER, ASPA_VALID },
255a01a053bSclaudio { (const uint32_t []) { 5, 17 }, 2, ROLE_CUSTOMER, ASPA_VALID },
256a01a053bSclaudio { (const uint32_t []) { 5, 25 }, 2, ROLE_CUSTOMER, ASPA_VALID },
257a01a053bSclaudio { (const uint32_t []) { 5, 26 }, 2, ROLE_CUSTOMER, ASPA_VALID },
258a01a053bSclaudio
259a01a053bSclaudio { (const uint32_t []) { 6, 18 }, 2, ROLE_CUSTOMER, ASPA_VALID },
260a01a053bSclaudio { (const uint32_t []) { 6, 19 }, 2, ROLE_CUSTOMER, ASPA_VALID },
261a01a053bSclaudio
262a01a053bSclaudio { (const uint32_t []) { 7, 19 }, 2, ROLE_PROVIDER, ASPA_UNKNOWN },
263a01a053bSclaudio { (const uint32_t []) { 7, 19 }, 2, ROLE_PEER, ASPA_UNKNOWN },
264a01a053bSclaudio { (const uint32_t []) { 7, 19 }, 2, ROLE_RS_CLIENT, ASPA_UNKNOWN },
265a01a053bSclaudio { (const uint32_t []) { 7, 21 }, 2, ROLE_PROVIDER, ASPA_INVALID },
266a01a053bSclaudio { (const uint32_t []) { 7, 21 }, 2, ROLE_PEER, ASPA_INVALID },
267a01a053bSclaudio { (const uint32_t []) { 7, 21 }, 2, ROLE_RS_CLIENT, ASPA_INVALID },
268a01a053bSclaudio
269a01a053bSclaudio { (const uint32_t []) { 6, 19, 20 }, 3, ROLE_CUSTOMER, ASPA_VALID },
270a01a053bSclaudio { (const uint32_t []) { 20, 19, 6 }, 3, ROLE_CUSTOMER, ASPA_VALID },
271a01a053bSclaudio
272a01a053bSclaudio { (const uint32_t []) { 3, 14, 25 }, 3, ROLE_PROVIDER, ASPA_INVALID },
273a01a053bSclaudio { (const uint32_t []) { 3, 14, 19 }, 3, ROLE_PROVIDER, ASPA_UNKNOWN },
274a01a053bSclaudio { (const uint32_t []) { 3, 14, 19 }, 3, ROLE_PEER, ASPA_UNKNOWN },
275a01a053bSclaudio { (const uint32_t []) { 3, 14, 19 }, 3, ROLE_RS_CLIENT, ASPA_UNKNOWN },
276a01a053bSclaudio { (const uint32_t []) { 3, 14, 21 }, 3, ROLE_PROVIDER, ASPA_INVALID },
277a01a053bSclaudio { (const uint32_t []) { 3, 14, 21 }, 3, ROLE_PEER, ASPA_INVALID },
278a01a053bSclaudio { (const uint32_t []) { 3, 14, 21 }, 3, ROLE_RS_CLIENT, ASPA_INVALID },
279a01a053bSclaudio { (const uint32_t []) { 3, 14, 27 }, 3, ROLE_PROVIDER, ASPA_VALID },
280a01a053bSclaudio { (const uint32_t []) { 3, 14, 27 }, 3, ROLE_PEER, ASPA_VALID },
281a01a053bSclaudio { (const uint32_t []) { 3, 14, 27 }, 3, ROLE_RS_CLIENT, ASPA_VALID },
282a01a053bSclaudio
283a01a053bSclaudio { (const uint32_t []) { 7, 19, 22, 21 }, 4, ROLE_PROVIDER,
284a01a053bSclaudio ASPA_INVALID },
285a01a053bSclaudio { (const uint32_t []) { 7, 19, 22, 21 }, 4, ROLE_PEER, ASPA_INVALID },
286a01a053bSclaudio { (const uint32_t []) { 7, 19, 22, 21 }, 4, ROLE_RS_CLIENT,
28781623c4aSclaudio ASPA_INVALID },
28881623c4aSclaudio
289a01a053bSclaudio { (const uint32_t []) { 6, 19, 22, 23 }, 4, ROLE_CUSTOMER,
29081623c4aSclaudio ASPA_UNKNOWN },
29181623c4aSclaudio
29281623c4aSclaudio { (const uint32_t []) { 1, 5, 17, 13, 3, 14, 27 }, 7, ROLE_CUSTOMER,
293a01a053bSclaudio ASPA_VALID },
29481623c4aSclaudio { (const uint32_t []) { 27, 14, 3, 13, 17, 5, 1 }, 7, ROLE_CUSTOMER,
295a01a053bSclaudio ASPA_VALID },
29681623c4aSclaudio
29781623c4aSclaudio { (const uint32_t []) { 27, 14, 3, 6, 7, 19, 17, 5, 1 }, 9,
298a01a053bSclaudio ROLE_CUSTOMER, ASPA_INVALID },
29981623c4aSclaudio { (const uint32_t []) { 27, 14, 3, 7, 19, 6, 1, 5, 17 }, 9,
300a01a053bSclaudio ROLE_CUSTOMER, ASPA_UNKNOWN },
30181623c4aSclaudio
30281623c4aSclaudio /* check L < K (ramps overlap) */
30381623c4aSclaudio { (const uint32_t []) { 201, 202, 203, 103, 102, 101 }, 6,
304a01a053bSclaudio ROLE_CUSTOMER, ASPA_VALID },
30581623c4aSclaudio { (const uint32_t []) { 101, 102, 103, 203, 202, 201 }, 6,
306a01a053bSclaudio ROLE_CUSTOMER, ASPA_VALID },
30781623c4aSclaudio
30881623c4aSclaudio /* check L == K (ramps touch) 203 ?> 111 <? 103 */
30981623c4aSclaudio { (const uint32_t []) { 201, 202, 203, 111, 103, 102, 101 }, 7,
310a01a053bSclaudio ROLE_CUSTOMER, ASPA_VALID },
31181623c4aSclaudio { (const uint32_t []) { 101, 102, 103, 111, 203, 202, 201 }, 7,
312a01a053bSclaudio ROLE_CUSTOMER, ASPA_VALID },
31381623c4aSclaudio /* check L == K (ramps touch) 203 -> 111 <- 103 */
31481623c4aSclaudio { (const uint32_t []) { 201, 202, 203, 112, 103, 102, 101 }, 7,
315a01a053bSclaudio ROLE_CUSTOMER, ASPA_VALID },
31681623c4aSclaudio { (const uint32_t []) { 101, 102, 103, 112, 203, 202, 201 }, 7,
317a01a053bSclaudio ROLE_CUSTOMER, ASPA_VALID },
31881623c4aSclaudio
31981623c4aSclaudio /* check L - K == 1 (204 ?? 104) */
32081623c4aSclaudio { (const uint32_t []) { 201, 202, 204, 104, 102, 101 }, 6,
321a01a053bSclaudio ROLE_CUSTOMER, ASPA_VALID },
32281623c4aSclaudio /* check L - K == 1 (204 -? 105) */
32381623c4aSclaudio { (const uint32_t []) { 201, 202, 204, 105, 102, 101 }, 6,
324a01a053bSclaudio ROLE_CUSTOMER, ASPA_VALID },
32581623c4aSclaudio /* check L - K == 1 (205 ?- 104) */
32681623c4aSclaudio { (const uint32_t []) { 201, 202, 205, 104, 102, 101 }, 6,
327a01a053bSclaudio ROLE_CUSTOMER, ASPA_VALID },
32881623c4aSclaudio /* check L - K == 1 (205 -- 105) */
32981623c4aSclaudio { (const uint32_t []) { 201, 202, 205, 105, 102, 101 }, 6,
330a01a053bSclaudio ROLE_CUSTOMER, ASPA_VALID },
33181623c4aSclaudio
33281623c4aSclaudio /* check L - K == 2 invalid cases (205 ?- 111 -? 105) */
33381623c4aSclaudio { (const uint32_t []) { 201, 202, 205, 111, 105, 102, 101 }, 7,
334a01a053bSclaudio ROLE_CUSTOMER, ASPA_INVALID },
33581623c4aSclaudio /* check L - K == 2 invalid cases (205 -- 112 -- 105) */
33681623c4aSclaudio { (const uint32_t []) { 201, 202, 205, 112, 105, 102, 101 }, 7,
337a01a053bSclaudio ROLE_CUSTOMER, ASPA_INVALID },
33881623c4aSclaudio /* check L - K == 2 invalid cases (205 <- 113 -> 105) */
33981623c4aSclaudio { (const uint32_t []) { 201, 202, 205, 113, 105, 102, 101 }, 7,
340a01a053bSclaudio ROLE_CUSTOMER, ASPA_INVALID },
34181623c4aSclaudio
34281623c4aSclaudio /* check L - K == 2 unknown cases (205 ?- 111 ?? 104) */
34381623c4aSclaudio { (const uint32_t []) { 201, 202, 205, 111, 104, 102, 101 }, 7,
344a01a053bSclaudio ROLE_CUSTOMER, ASPA_UNKNOWN },
34581623c4aSclaudio /* check L - K == 2 unknown cases (204 ?? 111 -? 105) */
34681623c4aSclaudio { (const uint32_t []) { 201, 202, 204, 111, 105, 102, 101 }, 7,
347a01a053bSclaudio ROLE_CUSTOMER, ASPA_UNKNOWN },
34881623c4aSclaudio /* check L - K == 2 unknown cases (204 ?? 111 ?? 104) */
34981623c4aSclaudio { (const uint32_t []) { 201, 202, 204, 111, 104, 102, 101 }, 7,
350a01a053bSclaudio ROLE_CUSTOMER, ASPA_UNKNOWN },
35181623c4aSclaudio /* check L - K == 2 unknown cases (205 -- 112 ?- 104) */
35281623c4aSclaudio { (const uint32_t []) { 201, 202, 205, 112, 104, 102, 101 }, 7,
353a01a053bSclaudio ROLE_CUSTOMER, ASPA_UNKNOWN },
35481623c4aSclaudio /* check L - K == 2 unknown cases (204 -? 112 -- 105) */
35581623c4aSclaudio { (const uint32_t []) { 201, 202, 204, 112, 105, 102, 101 }, 7,
356a01a053bSclaudio ROLE_CUSTOMER, ASPA_UNKNOWN },
35781623c4aSclaudio /* check L - K == 2 unknown cases (204 -? 112 ?- 104) */
35881623c4aSclaudio { (const uint32_t []) { 201, 202, 204, 112, 104, 102, 101 }, 7,
359a01a053bSclaudio ROLE_CUSTOMER, ASPA_UNKNOWN },
36081623c4aSclaudio /* check L - K == 2 unknown cases (205 <- 113 ?> 104) */
36181623c4aSclaudio { (const uint32_t []) { 201, 202, 205, 113, 104, 102, 101 }, 7,
362a01a053bSclaudio ROLE_CUSTOMER, ASPA_UNKNOWN },
36381623c4aSclaudio /* check L - K == 2 unknown cases (204 <? 113 -> 105) */
36481623c4aSclaudio { (const uint32_t []) { 201, 202, 204, 113, 105, 102, 101 }, 7,
365a01a053bSclaudio ROLE_CUSTOMER, ASPA_UNKNOWN },
36681623c4aSclaudio /* check L - K == 2 unknown cases (204 <? 113 ?> 104) */
36781623c4aSclaudio { (const uint32_t []) { 201, 202, 204, 113, 104, 102, 101 }, 7,
368a01a053bSclaudio ROLE_CUSTOMER, ASPA_UNKNOWN },
36981623c4aSclaudio };
37081623c4aSclaudio
37181623c4aSclaudio static struct rde_aspa *
load_test_set(struct aspa_test_set * testv,uint32_t numentries)37281623c4aSclaudio load_test_set(struct aspa_test_set *testv, uint32_t numentries)
37381623c4aSclaudio {
37481623c4aSclaudio struct rde_aspa *aspa;
37581623c4aSclaudio size_t data_size = 0;
37681623c4aSclaudio uint32_t i;
37781623c4aSclaudio
378*4a2c408dSclaudio for (i = 0; i < numentries; i++)
37981623c4aSclaudio data_size += testv[i].pascnt * sizeof(uint32_t);
38081623c4aSclaudio
38181623c4aSclaudio aspa = aspa_table_prep(numentries, data_size);
38281623c4aSclaudio
383*4a2c408dSclaudio for (i = numentries; i > 0; i--)
38481623c4aSclaudio aspa_add_set(aspa, testv[i - 1].customeras,
385*4a2c408dSclaudio testv[i - 1].providers, testv[i - 1].pascnt);
38681623c4aSclaudio
38781623c4aSclaudio return aspa;
38881623c4aSclaudio }
38981623c4aSclaudio
390a01a053bSclaudio static uint8_t
vstate_for_role(struct rde_aspa_state * vstate,enum role role)391a01a053bSclaudio vstate_for_role(struct rde_aspa_state *vstate, enum role role)
392a01a053bSclaudio {
393a01a053bSclaudio if (role != ROLE_CUSTOMER) {
394*4a2c408dSclaudio return (vstate->onlyup);
395a01a053bSclaudio } else {
396*4a2c408dSclaudio return (vstate->downup);
397a01a053bSclaudio }
398a01a053bSclaudio }
39981623c4aSclaudio
40081623c4aSclaudio int
main(int argc,char ** argv)40181623c4aSclaudio main(int argc, char **argv)
40281623c4aSclaudio {
40381623c4aSclaudio struct rde_aspa *aspa;
40481623c4aSclaudio size_t num_cp = sizeof(cp_testset) / sizeof(cp_testset[0]);
40581623c4aSclaudio size_t num_aspath = sizeof(aspath_testset) / sizeof(aspath_testset[0]);
40681623c4aSclaudio size_t num_aspa = sizeof(aspa_testset) / sizeof(aspa_testset[0]);
40781623c4aSclaudio size_t i;
40881623c4aSclaudio int cp_failed = 0, aspath_failed = 0, aspa_failed = 0;
40981623c4aSclaudio
41081623c4aSclaudio /* first test, loading empty aspa table works. */
41181623c4aSclaudio aspa = load_test_set(NULL, 0);
41281623c4aSclaudio assert(aspa == NULL);
41381623c4aSclaudio aspa_table_free(aspa);
41481623c4aSclaudio
41581623c4aSclaudio aspa = load_test_set(testset, sizeof(testset) / sizeof(testset[0]));
41681623c4aSclaudio assert(aspa != NULL);
41781623c4aSclaudio
41881623c4aSclaudio printf("testing aspa_cp_lookup: ");
41981623c4aSclaudio for (i = 0; i < num_cp; i++) {
420a01a053bSclaudio uint8_t r;
42181623c4aSclaudio r = aspa_cp_lookup(aspa, cp_testset[i].customeras,
422a01a053bSclaudio cp_testset[i].provideras);
42381623c4aSclaudio
42481623c4aSclaudio if (cp_testset[i].expected_result != r) {
42581623c4aSclaudio printf("failed: cp_testset[%zu]: "
42681623c4aSclaudio "cas %u pas %u -> %d got %d\n", i,
42781623c4aSclaudio cp_testset[i].customeras,
42881623c4aSclaudio cp_testset[i].provideras,
42981623c4aSclaudio cp_testset[i].expected_result,
43081623c4aSclaudio r);
43181623c4aSclaudio cp_failed = 1;
43281623c4aSclaudio }
43381623c4aSclaudio }
43481623c4aSclaudio if (!cp_failed)
43581623c4aSclaudio printf("OK\n");
43681623c4aSclaudio
43781623c4aSclaudio printf("testing aspa_check_aspath: ");
43881623c4aSclaudio for (i = 0; i < num_aspath; i++) {
439*4a2c408dSclaudio struct aspa_state st, revst;
44081623c4aSclaudio struct aspath *a;
44181623c4aSclaudio
442*4a2c408dSclaudio memset(&st, 0, sizeof(st));
44381623c4aSclaudio a = build_aspath(aspath_testset[i].aspath,
44481623c4aSclaudio aspath_testset[i].aspathcnt, 0);
445*4a2c408dSclaudio if (aspa_check_aspath(aspa, a, &st) == -1) {
44681623c4aSclaudio printf("failed: aspath_testset[%zu]: "
44781623c4aSclaudio "aspath %s got -1\n", i,
44881623c4aSclaudio print_aspath(aspath_testset[i].aspath,
44981623c4aSclaudio aspath_testset[i].aspathcnt));
45081623c4aSclaudio aspath_failed = 1;
45181623c4aSclaudio }
45281623c4aSclaudio
453*4a2c408dSclaudio if (memcmp(&aspath_testset[i].state, &st, sizeof(st))) {
45481623c4aSclaudio printf("failed: aspath_testset[%zu]: aspath %s "
45581623c4aSclaudio "bad state", i,
45681623c4aSclaudio print_aspath(aspath_testset[i].aspath,
45781623c4aSclaudio aspath_testset[i].aspathcnt));
458*4a2c408dSclaudio print_state(&aspath_testset[i].state, &st);
45981623c4aSclaudio printf("\n");
46081623c4aSclaudio aspath_failed = 1;
46181623c4aSclaudio }
46281623c4aSclaudio free(a);
46381623c4aSclaudio
464*4a2c408dSclaudio memset(&st, 0, sizeof(st));
46581623c4aSclaudio a = build_aspath(aspath_testset[i].aspath,
46681623c4aSclaudio aspath_testset[i].aspathcnt, 1);
467*4a2c408dSclaudio if (aspa_check_aspath(aspa, a, &st) == -1) {
46881623c4aSclaudio printf("failed: reverse aspath_testset[%zu]: "
46981623c4aSclaudio "aspath %s got -1\n", i,
47081623c4aSclaudio print_aspath(aspath_testset[i].aspath,
47181623c4aSclaudio aspath_testset[i].aspathcnt));
47281623c4aSclaudio aspath_failed = 1;
47381623c4aSclaudio }
47481623c4aSclaudio
47581623c4aSclaudio reverse_state(&aspath_testset[i].state, &revst);
476*4a2c408dSclaudio if (memcmp(&revst, &st, sizeof(st))) {
47781623c4aSclaudio printf("failed: reverse aspath_testset[%zu]: aspath %s "
47881623c4aSclaudio "bad state", i,
47981623c4aSclaudio print_aspath(aspath_testset[i].aspath,
48081623c4aSclaudio aspath_testset[i].aspathcnt));
481*4a2c408dSclaudio print_state(&revst, &st);
48281623c4aSclaudio printf("\n");
48381623c4aSclaudio aspath_failed = 1;
48481623c4aSclaudio }
48581623c4aSclaudio free(a);
48681623c4aSclaudio }
48781623c4aSclaudio if (!aspath_failed)
48881623c4aSclaudio printf("OK\n");
48981623c4aSclaudio
49081623c4aSclaudio printf("testing aspa_validation: ");
49181623c4aSclaudio for (i = 0; i < num_aspa; i++) {
49281623c4aSclaudio struct aspath *a;
493a01a053bSclaudio struct rde_aspa_state vstate;
49481623c4aSclaudio uint8_t rv;
49581623c4aSclaudio
49681623c4aSclaudio a = build_aspath(aspa_testset[i].aspath,
49781623c4aSclaudio aspa_testset[i].aspathcnt, 0);
498a01a053bSclaudio aspa_validation(aspa, a, &vstate);
499a01a053bSclaudio
500a01a053bSclaudio rv = vstate_for_role(&vstate, aspa_testset[i].role);
50181623c4aSclaudio
50281623c4aSclaudio if (aspa_testset[i].expected_result != rv) {
50381623c4aSclaudio printf("failed: aspa_testset[%zu]: aspath %s role %d "
50481623c4aSclaudio "want %d got %d", i,
50581623c4aSclaudio print_aspath(aspa_testset[i].aspath,
50681623c4aSclaudio aspa_testset[i].aspathcnt),
50781623c4aSclaudio aspa_testset[i].role,
50881623c4aSclaudio aspa_testset[i].expected_result,
50981623c4aSclaudio rv);
51081623c4aSclaudio aspa_failed = 1;
51181623c4aSclaudio }
51281623c4aSclaudio
51381623c4aSclaudio free(a);
51481623c4aSclaudio }
51581623c4aSclaudio if (!aspa_failed)
51681623c4aSclaudio printf("OK\n");
51781623c4aSclaudio
51881623c4aSclaudio aspa_table_free(aspa);
51981623c4aSclaudio
52081623c4aSclaudio return cp_failed | aspath_failed | aspa_failed;
52181623c4aSclaudio }
52281623c4aSclaudio
52381623c4aSclaudio __dead void
fatalx(const char * emsg,...)52481623c4aSclaudio fatalx(const char *emsg, ...)
52581623c4aSclaudio {
52681623c4aSclaudio va_list ap;
52781623c4aSclaudio va_start(ap, emsg);
52881623c4aSclaudio verrx(2, emsg, ap);
52981623c4aSclaudio }
53081623c4aSclaudio
53181623c4aSclaudio __dead void
fatal(const char * emsg,...)53281623c4aSclaudio fatal(const char *emsg, ...)
53381623c4aSclaudio {
53481623c4aSclaudio va_list ap;
53581623c4aSclaudio va_start(ap, emsg);
53681623c4aSclaudio verr(2, emsg, ap);
53781623c4aSclaudio }
53881623c4aSclaudio
53981623c4aSclaudio uint32_t
aspath_extract(const void * seg,int pos)54081623c4aSclaudio aspath_extract(const void *seg, int pos)
54181623c4aSclaudio {
54281623c4aSclaudio const u_char *ptr = seg;
54381623c4aSclaudio uint32_t as;
54481623c4aSclaudio
54581623c4aSclaudio /* minimal pos check, return 0 since that is an invalid ASN */
54681623c4aSclaudio if (pos < 0 || pos >= ptr[1])
54781623c4aSclaudio return (0);
54881623c4aSclaudio ptr += 2 + sizeof(uint32_t) * pos;
54981623c4aSclaudio memcpy(&as, ptr, sizeof(uint32_t));
55081623c4aSclaudio return (ntohl(as));
55181623c4aSclaudio }
55281623c4aSclaudio
55381623c4aSclaudio static struct aspath *
build_aspath(const uint32_t * asns,uint32_t asncnt,int rev)55481623c4aSclaudio build_aspath(const uint32_t *asns, uint32_t asncnt, int rev)
55581623c4aSclaudio {
55681623c4aSclaudio struct aspath *aspath;
55781623c4aSclaudio uint32_t i, idx, as;
55881623c4aSclaudio uint16_t len;
55981623c4aSclaudio
56081623c4aSclaudio /* don't mess around with multi segment ASPATHs */
56181623c4aSclaudio if (asncnt >= 255)
56281623c4aSclaudio errx(1, "asncnt too big");
56381623c4aSclaudio
56481623c4aSclaudio if (asncnt == 0)
56581623c4aSclaudio len = 0;
56681623c4aSclaudio else
56781623c4aSclaudio len = 2 + sizeof(uint32_t) * asncnt;
56881623c4aSclaudio aspath = malloc(ASPATH_HEADER_SIZE + len);
56981623c4aSclaudio if (aspath == NULL)
57081623c4aSclaudio err(1, NULL);
57181623c4aSclaudio
57281623c4aSclaudio aspath->len = len;
57381623c4aSclaudio aspath->ascnt = asncnt; /* lie but nothing cares */
57481623c4aSclaudio aspath->source_as = 0;
5759043a933Sclaudio
5769043a933Sclaudio if (len == 0)
5779043a933Sclaudio return aspath;
5789043a933Sclaudio
5799043a933Sclaudio if (rev)
5809043a933Sclaudio aspath->source_as = asns[asncnt - 1];
5819043a933Sclaudio else
58281623c4aSclaudio aspath->source_as = asns[0];
5839043a933Sclaudio
58481623c4aSclaudio aspath->data[0] = AS_SEQUENCE;
58581623c4aSclaudio aspath->data[1] = asncnt;
58681623c4aSclaudio for (i = 0; i < asncnt; i++) {
58781623c4aSclaudio if (rev)
58881623c4aSclaudio idx = asncnt - 1 - i;
58981623c4aSclaudio else
59081623c4aSclaudio idx = i;
59181623c4aSclaudio as = htonl(asns[idx]);
59281623c4aSclaudio memcpy(aspath->data + 2 + sizeof(as) * i, &as,
59381623c4aSclaudio sizeof(uint32_t));
59481623c4aSclaudio }
59581623c4aSclaudio
59681623c4aSclaudio return aspath;
59781623c4aSclaudio }
59881623c4aSclaudio
59981623c4aSclaudio static const char *
print_aspath(const uint32_t * asns,uint32_t asncnt)60081623c4aSclaudio print_aspath(const uint32_t *asns, uint32_t asncnt)
60181623c4aSclaudio {
60281623c4aSclaudio static char buf[1024];
60381623c4aSclaudio char b[16];
60481623c4aSclaudio uint32_t i;
60581623c4aSclaudio
60681623c4aSclaudio strlcpy(buf, "", sizeof(buf));
60781623c4aSclaudio for (i = 0; i < asncnt; i++) {
60881623c4aSclaudio snprintf(b, sizeof(b), "%d", asns[i]);
60981623c4aSclaudio if (i > 0)
61081623c4aSclaudio strlcat(buf, " ", sizeof(buf));
61181623c4aSclaudio strlcat(buf, b, sizeof(buf));
61281623c4aSclaudio }
61381623c4aSclaudio return buf;
61481623c4aSclaudio }
61581623c4aSclaudio
61681623c4aSclaudio static void
reverse_state(struct aspa_state * in,struct aspa_state * rev)61781623c4aSclaudio reverse_state(struct aspa_state *in, struct aspa_state *rev)
61881623c4aSclaudio {
61981623c4aSclaudio memset(rev, 0, sizeof(*rev));
62081623c4aSclaudio rev->nhops = in->nhops;
62181623c4aSclaudio rev->nup_p = in->nhops + 1 - in->ndown_p;
62281623c4aSclaudio if (in->ndown_u != 0)
62381623c4aSclaudio rev->nup_u = in->nhops + 1 - in->ndown_u;
62481623c4aSclaudio if (in->ndown_np != 0)
62581623c4aSclaudio rev->nup_np = in->nhops + 1 - in->ndown_np;
62681623c4aSclaudio rev->ndown_p = in->nhops + 1 - in->nup_p;
62781623c4aSclaudio if (in->nup_u != 0)
62881623c4aSclaudio rev->ndown_u = in->nhops + 1 - in->nup_u;
62981623c4aSclaudio if (in->nup_np != 0)
63081623c4aSclaudio rev->ndown_np = in->nhops + 1 - in->nup_np;
63181623c4aSclaudio }
63281623c4aSclaudio
63381623c4aSclaudio static void
print_state(struct aspa_state * a,struct aspa_state * b)63481623c4aSclaudio print_state(struct aspa_state *a, struct aspa_state *b)
63581623c4aSclaudio {
63681623c4aSclaudio if (a->nhops != b->nhops)
63781623c4aSclaudio printf(" nhops %d != %d", a->nhops, b->nhops);
63881623c4aSclaudio if (a->nup_p != b->nup_p)
63981623c4aSclaudio printf(" nup_p %d != %d", a->nup_p, b->nup_p);
64081623c4aSclaudio if (a->nup_u != b->nup_u)
64181623c4aSclaudio printf(" nup_u %d != %d", a->nup_u, b->nup_u);
64281623c4aSclaudio if (a->nup_np != b->nup_np)
64381623c4aSclaudio printf(" nup_np %d != %d", a->nup_np, b->nup_np);
64481623c4aSclaudio if (a->ndown_p != b->ndown_p)
64581623c4aSclaudio printf(" ndown_p %d != %d", a->ndown_p, b->ndown_p);
64681623c4aSclaudio if (a->ndown_u != b->ndown_u)
64781623c4aSclaudio printf(" ndown_u %d != %d", a->ndown_u, b->ndown_u);
64881623c4aSclaudio if (a->ndown_np != b->ndown_np)
64981623c4aSclaudio printf(" ndown_np %d != %d", a->ndown_np, b->ndown_np);
65081623c4aSclaudio }
6510f5e1a03Sclaudio
6520f5e1a03Sclaudio time_t
getmonotime(void)6530f5e1a03Sclaudio getmonotime(void)
6540f5e1a03Sclaudio {
6550f5e1a03Sclaudio return time(NULL);
6560f5e1a03Sclaudio }
657