From 4c4bd463e5e7209c0558c96678f7292da79f7338 Mon Sep 17 00:00:00 2001 From: claudio Date: Fri, 22 Jan 2021 17:18:13 +0000 Subject: [PATCH] Extend test with an full depth search of all possible prefix_evaluations. This currently fails because the MED is not handled properly. Fix for this will follow shortly. --- .../usr.sbin/bgpd/unittests/rde_decide_test.c | 131 +++++++++++++++--- 1 file changed, 108 insertions(+), 23 deletions(-) diff --git a/regress/usr.sbin/bgpd/unittests/rde_decide_test.c b/regress/usr.sbin/bgpd/unittests/rde_decide_test.c index bff05edfdbb..f0b011b82af 100644 --- a/regress/usr.sbin/bgpd/unittests/rde_decide_test.c +++ b/regress/usr.sbin/bgpd/unittests/rde_decide_test.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rde_decide_test.c,v 1.3 2021/01/22 13:57:32 claudio Exp $ */ +/* $OpenBSD: rde_decide_test.c,v 1.4 2021/01/22 17:18:13 claudio Exp $ */ /* * Copyright (c) 2020 Claudio Jeker @@ -158,6 +158,8 @@ struct rde_aspath med_asp[] = { { .aspath = &asdata[0].a, .med = 150, .lpref = 100, .origin = ORIGIN_EGP }, { .aspath = &asdata[2].a, .med = 75, .lpref = 100, .origin = ORIGIN_EGP }, { .aspath = &asdata[2].a, .med = 125, .lpref = 100, .origin = ORIGIN_EGP }, + { .aspath = &asdata[1].a, .med = 110, .lpref = 100, .origin = ORIGIN_EGP }, + { .aspath = &asdata[1].a, .med = 90, .lpref = 100, .origin = ORIGIN_EGP }, }; /* @@ -174,7 +176,12 @@ struct prefix med_pfx2 = struct prefix med_pfx3 = { .re = &dummy_re, .aspath = &med_asp[2], .peer = &peer3, .nexthop = &nh_reach, .lastchange = T1, }; struct prefix med_pfx4 = - { .re = &dummy_re, .aspath = &med_asp[3], .peer = &peer1, .nexthop = &nh_reach, .lastchange = T1, }; + { .re = &dummy_re, .aspath = &med_asp[3], .peer = &peer1_a4, .nexthop = &nh_reach, .lastchange = T1, }; +/* the next two prefixes have a longer aspath than med_pfx1 & 2 */ +struct prefix med_pfx5 = + { .re = &dummy_re, .aspath = &med_asp[5], .peer = &peer3, .nexthop = &nh_reach, .lastchange = T1, }; +struct prefix med_pfx6 = + { .re = &dummy_re, .aspath = &med_asp[4], .peer = &peer1, .nexthop = &nh_reach, .lastchange = T1, }; /* * Define two prefixes where pfx1 > pfx2 if 'rde route-age evaluate' @@ -185,60 +192,134 @@ struct prefix age_pfx1 = struct prefix age_pfx2 = { .re = &dummy_re, .aspath = &asp[0], .peer = &peer1, .nexthop = &nh_reach, .lastchange = T2, }; -int prefix_cmp(struct prefix *, struct prefix *); +int prefix_cmp(struct prefix *, struct prefix *, int *); int decision_flags = BGPD_FLAG_DECISION_ROUTEAGE; int failed; -void -test(struct prefix *a, struct prefix *b) +static int +test(struct prefix *a, struct prefix *b, int v) { - if (prefix_cmp(a, b) < 0) { - printf(" FAILED\n"); - failed = 1; - } else if (prefix_cmp(b, a) > 0) { - printf(" reverse cmp FAILED\n"); - failed = 1; - } else + int rv = 0, dummy; + if (prefix_cmp(a, b, &dummy) < 0) { + if (v) printf(" FAILED\n"); + failed = rv = 1; + } else if (prefix_cmp(b, a, &dummy) > 0) { + if (v) printf(" reverse cmp FAILED\n"); + failed = rv = 1; + } else if (v) printf(" OK\n"); + + return rv; +} + +static size_t +which(struct prefix **orig, struct prefix *p) +{ + size_t i; + + for (i = 0; orig[i] != NULL; i++) + if (orig[i] == p) + return i; + return 9999; +} + +/* + * Evaluate a set of prefixes in all possible ways. + * The input in orig should be in the expected order. + */ +static int +test_evaluate(struct prefix **orig, struct prefix **in, size_t nin) +{ + struct prefix *next[nin - 1]; + size_t i, j, n; + int r = 0; + + if (nin == 0) { + struct prefix *xp; + + j = 0; + LIST_FOREACH(xp, &dummy_re.prefix_h, entry.list.rib) + if (which(orig, xp) != j++) + r = 1; + if (r != 0) { + printf("bad order"); + LIST_FOREACH(xp, &dummy_re.prefix_h, entry.list.rib) + printf(" %zu", which(orig, xp)); + printf(" FAILED\n"); + } + } + for (i = 0; i < nin; i++) { + /* add prefix to dummy_re */ + prefix_evaluate(&dummy_re, in[i], NULL); + + for (n = j = 0; j < nin; j++) { + if (j == i) + continue; + next[n++] = in[j]; + } + r |= test_evaluate(orig, next, n); + + /* remove prefix from dummy_re */ + prefix_evaluate(&dummy_re, NULL, in[i]); + } + + return r; } int main(int argc, char **argv) { - size_t i, ntest;; + struct prefix *med_strict[7] = { + &med_pfx1, &med_pfx2, &med_pfx3, &med_pfx4, + &med_pfx5, &med_pfx6, NULL + }; + struct prefix *med_always[7] = { + &med_pfx3, &med_pfx1, &med_pfx4, &med_pfx2, + &med_pfx5, &med_pfx6, NULL + }; + size_t i, ntest; ntest = sizeof(test_pfx) / sizeof(*test_pfx); for (i = 1; i < ntest; i++) { printf("test %zu: %s", i, test_pfx[i].what); - test(&test_pfx[0].p, &test_pfx[i].p); + test(&test_pfx[0].p, &test_pfx[i].p, 1); } printf("test NULL element"); - test(&test_pfx[0].p, NULL); + test(&test_pfx[0].p, NULL, 1); printf("test rde med compare strict 1"); - test(&med_pfx1, &med_pfx2); + test(&med_pfx1, &med_pfx2, 1); printf("test rde med compare strict 2"); - test(&med_pfx1, &med_pfx3); + test(&med_pfx1, &med_pfx3, 1); printf("test rde med compare strict 3"); - test(&med_pfx4, &med_pfx1); + test(&med_pfx4, &med_pfx1, 1); decision_flags |= BGPD_FLAG_DECISION_MED_ALWAYS; printf("test rde med compare always 1"); - test(&med_pfx1, &med_pfx2); + test(&med_pfx1, &med_pfx2, 1); printf("test rde med compare always 2"); - test(&med_pfx3, &med_pfx1); + test(&med_pfx3, &med_pfx1, 1); printf("test rde med compare always 3"); - test(&med_pfx1, &med_pfx4); + test(&med_pfx1, &med_pfx4, 1); printf("test rde route-age evaluate"); - test(&age_pfx1, &age_pfx2); + test(&age_pfx1, &age_pfx2, 1); decision_flags &= ~BGPD_FLAG_DECISION_ROUTEAGE; printf("test rde route-age ignore"); - test(&age_pfx2, &age_pfx1); + test(&age_pfx2, &age_pfx1, 1); + + decision_flags = 0; + printf("evaluate with rde med compare strict\n"); + if (test_evaluate(med_strict, med_strict, 6) == 0) + printf("all OK\n"); + decision_flags = BGPD_FLAG_DECISION_MED_ALWAYS; + printf("evaluate with rde med compare always\n"); + if (test_evaluate(med_always, med_always, 6) == 0) + printf("all OK\n"); if (failed) printf("some tests FAILED\n"); @@ -247,12 +328,16 @@ main(int argc, char **argv) exit(failed); } +/* this function is called by prefix_cmp to alter the decision process */ int rde_decisionflags(void) { return decision_flags; } +/* + * Helper functions need to link and run the tests. + */ u_int32_t rde_local_as(void) { -- 2.20.1