// SPDX-License-Identifier: GPL-2.0-or-later /* * Copyright (C) 2005 Sun Microsystems, Inc. */ #include #include "vty.h" #include "stream.h" #include "privs.h" #include "queue.h" #include "filter.h" #include "frr_pthread.h" #include "bgpd/bgpd.c" #include "bgpd/bgp_aspath.h" #include "bgpd/bgp_attr.h" #include "bgpd/bgp_packet.h" #define VT100_RESET "\x1b[0m" #define VT100_RED "\x1b[31m" #define VT100_GREEN "\x1b[32m" #define VT100_YELLOW "\x1b[33m" #define OK VT100_GREEN "OK" VT100_RESET #define FAILED VT100_RED "failed" VT100_RESET /* need these to link in libbgp */ struct zebra_privs_t bgpd_privs = {}; struct event_loop *master = NULL; static int failed = 0; /* specification for a test - what the results should be */ struct test_spec { const char *shouldbe; /* the string the path should parse to */ const char *shouldbe_delete_confed; /* ditto, but once confeds are deleted */ const unsigned int hops; /* aspath_count_hops result */ const unsigned int confeds; /* aspath_count_confeds */ const int private_as; /* whether the private_as check should pass or fail */ #define NOT_ALL_PRIVATE 0 #define ALL_PRIVATE 1 const as_t does_loop; /* an ASN which should trigger loop-check */ const as_t doesnt_loop; /* one which should not */ const as_t first; /* the first ASN, if there is one */ #define NULL_ASN 0 }; /* test segments to parse and validate, and use for other tests */ static struct test_segment { const char *name; const char *desc; const uint8_t asdata[1024]; int len; struct test_spec sp; enum asnotation_mode asnotation; } test_segments[] = { { /* 0 */ "seq1", "seq(8466,3,52737,4096)", {0x2, 0x4, 0x21, 0x12, 0x00, 0x03, 0xce, 0x01, 0x10, 0x00}, 10, {"8466 3 52737 4096", "8466 3 52737 4096", 4, 0, NOT_ALL_PRIVATE, 4096, 4, 8466}, 0, }, { /* 1 */ "seq2", "seq(8722) seq(4)", {0x2, 0x1, 0x22, 0x12, 0x2, 0x1, 0x00, 0x04}, 8, { "8722 4", "8722 4", 2, 0, NOT_ALL_PRIVATE, 4, 5, 8722, }, 0, }, { /* 2 */ "seq3", "seq(8466,3,52737,4096,8722,4)", {0x2, 0x6, 0x21, 0x12, 0x00, 0x03, 0xce, 0x01, 0x10, 0x00, 0x22, 0x12, 0x00, 0x04}, 14, {"8466 3 52737 4096 8722 4", "8466 3 52737 4096 8722 4", 6, 0, NOT_ALL_PRIVATE, 3, 5, 8466}, 0, }, { /* 3 */ "seqset", "seq(8482,51457) set(5204)", {0x2, 0x2, 0x21, 0x22, 0xc9, 0x01, 0x1, 0x1, 0x14, 0x54}, 10, {"8482 51457 {5204}", "8482 51457 {5204}", 3, 0, NOT_ALL_PRIVATE, 5204, 51456, 8482}, 0, }, { /* 4 */ "seqset2", "seq(8467, 59649) set(4196,48658) set(17322,30745)", {0x2, 0x2, 0x21, 0x13, 0xe9, 0x01, 0x1, 0x2, 0x10, 0x64, 0xbe, 0x12, 0x1, 0x2, 0x43, 0xaa, 0x78, 0x19}, 18, {"8467 59649 {4196,48658} {17322,30745}", "8467 59649 {4196,48658} {17322,30745}", 4, 0, NOT_ALL_PRIVATE, 48658, 1, 8467}, 0, }, { /* 5 */ "multi", "seq(6435,59408,21665) set(2457,61697,4369), seq(1842,41590,51793)", {0x2, 0x3, 0x19, 0x23, 0xe8, 0x10, 0x54, 0xa1, 0x1, 0x3, 0x09, 0x99, 0xf1, 0x01, 0x11, 0x11, 0x2, 0x3, 0x07, 0x32, 0xa2, 0x76, 0xca, 0x51}, 24, {"6435 59408 21665 {2457,4369,61697} 1842 41590 51793", "6435 59408 21665 {2457,4369,61697} 1842 41590 51793", 7, 0, NOT_ALL_PRIVATE, 51793, 1, 6435}, 0, }, { /* 6 */ "confed", "confseq(123,456,789)", {0x3, 0x3, 0x00, 0x7b, 0x01, 0xc8, 0x03, 0x15}, 8, {"(123 456 789)", "", 0, 3, NOT_ALL_PRIVATE, 789, 1, NULL_ASN}, 0, }, { /* 7 */ "confed2", "confseq(123,456,789) confseq(111,222)", {0x3, 0x3, 0x00, 0x7b, 0x01, 0xc8, 0x03, 0x15, 0x3, 0x2, 0x00, 0x6f, 0x00, 0xde}, 14, {"(123 456 789) (111 222)", "", 0, 5, NOT_ALL_PRIVATE, 111, 1, NULL_ASN}, 0, }, { /* 8 */ "confset", "confset(456,123,789)", {0x4, 0x3, 0x01, 0xc8, 0x00, 0x7b, 0x03, 0x15}, 8, {"[123,456,789]", "", 0, 1, NOT_ALL_PRIVATE, 123, 1, NULL_ASN}, 0, }, { /* 9 */ "confmulti", "confseq(123,456,789) confset(222,111) seq(8722) set(4196,48658)", {0x3, 0x3, 0x00, 0x7b, 0x01, 0xc8, 0x03, 0x15, 0x4, 0x2, 0x00, 0xde, 0x00, 0x6f, 0x2, 0x1, 0x22, 0x12, 0x1, 0x2, 0x10, 0x64, 0xbe, 0x12}, 24, {"(123 456 789) [111,222] 8722 {4196,48658}", "8722 {4196,48658}", 2, 4, NOT_ALL_PRIVATE, 123, 1, NULL_ASN}, 0, }, { /* 10 */ "seq4", "seq(8466,2,52737,4096,8722,4)", {0x2, 0x6, 0x21, 0x12, 0x00, 0x02, 0xce, 0x01, 0x10, 0x00, 0x22, 0x12, 0x00, 0x04}, 14, {"8466 2 52737 4096 8722 4", "8466 2 52737 4096 8722 4", 6, 0, NOT_ALL_PRIVATE, 4096, 1, 8466}, 0, }, { /* 11 */ "tripleseq1", "seq(8466,2,52737) seq(4096,8722,4) seq(8722)", {0x2, 0x3, 0x21, 0x12, 0x00, 0x02, 0xce, 0x01, 0x2, 0x3, 0x10, 0x00, 0x22, 0x12, 0x00, 0x04, 0x2, 0x1, 0x22, 0x12}, 20, {"8466 2 52737 4096 8722 4 8722", "8466 2 52737 4096 8722 4 8722", 7, 0, NOT_ALL_PRIVATE, 4096, 1, 8466}, 0, }, { /* 12 */ "someprivate", "seq(8466,64512,52737,65535)", {0x2, 0x4, 0x21, 0x12, 0xfc, 0x00, 0xce, 0x01, 0xff, 0xff}, 10, {"8466 64512 52737 65535", "8466 64512 52737 65535", 4, 0, NOT_ALL_PRIVATE, 65535, 4, 8466}, 0, }, { /* 13 */ "allprivate", "seq(65534,64512,64513,65535)", {0x2, 0x4, 0xff, 0xfe, 0xfc, 0x00, 0xfc, 0x01, 0xff, 0xff}, 10, {"65534 64512 64513 65535", "65534 64512 64513 65535", 4, 0, ALL_PRIVATE, 65534, 4, 65534}, 0, }, { /* 14 */ "long", "seq(8466,3,52737,4096,34285,)", { 0x2, 0xfa, 0x21, 0x12, 0x00, 0x03, 0xce, 0x01, 0x10, 0x00, 0x85, 0xed, 0x21, 0x12, 0x00, 0x03, 0xce, 0x01, 0x10, 0x00, 0x85, 0xed, 0x21, 0x12, 0x00, 0x03, 0xce, 0x01, 0x10, 0x00, 0x85, 0xed, 0x21, 0x12, 0x00, 0x03, 0xce, 0x01, 0x10, 0x00, 0x85, 0xed, 0x21, 0x12, 0x00, 0x03, 0xce, 0x01, 0x10, 0x00, 0x85, 0xed, 0x21, 0x12, 0x00, 0x03, 0xce, 0x01, 0x10, 0x00, 0x85, 0xed, 0x21, 0x12, 0x00, 0x03, 0xce, 0x01, 0x10, 0x00, 0x85, 0xed, 0x21, 0x12, 0x00, 0x03, 0xce, 0x01, 0x10, 0x00, 0x85, 0xed, 0x21, 0x12, 0x00, 0x03, 0xce, 0x01, 0x10, 0x00, 0x85, 0xed, 0x21, 0x12, 0x00, 0x03, 0xce, 0x01, 0x10, 0x00, 0x85, 0xed, 0x21, 0x12, 0x00, 0x03, 0xce, 0x01, 0x10, 0x00, 0x85, 0xed, 0x21, 0x12, 0x00, 0x03, 0xce, 0x01, 0x10, 0x00, 0x85, 0xed, 0x21, 0x12, 0x00, 0x03, 0xce, 0x01, 0x10, 0x00, 0x85, 0xed, 0x21, 0x12, 0x00, 0x03, 0xce, 0x01, 0x10, 0x00, 0x85, 0xed, 0x21, 0x12, 0x00, 0x03, 0xce, 0x01, 0x10, 0x00, 0x85, 0xed, 0x21, 0x12, 0x00, 0x03, 0xce, 0x01, 0x10, 0x00, 0x85, 0xed, 0x21, 0x12, 0x00, 0x03, 0xce, 0x01, 0x10, 0x00, 0x85, 0xed, 0x21, 0x12, 0x00, 0x03, 0xce, 0x01, 0x10, 0x00, 0x85, 0xed, 0x21, 0x12, 0x00, 0x03, 0xce, 0x01, 0x10, 0x00, 0x85, 0xed, 0x21, 0x12, 0x00, 0x03, 0xce, 0x01, 0x10, 0x00, 0x85, 0xed, 0x21, 0x12, 0x00, 0x03, 0xce, 0x01, 0x10, 0x00, 0x85, 0xed, 0x21, 0x12, 0x00, 0x03, 0xce, 0x01, 0x10, 0x00, 0x85, 0xed, 0x21, 0x12, 0x00, 0x03, 0xce, 0x01, 0x10, 0x00, 0x85, 0xed, 0x21, 0x12, 0x00, 0x03, 0xce, 0x01, 0x10, 0x00, 0x85, 0xed, 0x21, 0x12, 0x00, 0x03, 0xce, 0x01, 0x10, 0x00, 0x85, 0xed, 0x21, 0x12, 0x00, 0x03, 0xce, 0x01, 0x10, 0x00, 0x85, 0xed, 0x21, 0x12, 0x00, 0x03, 0xce, 0x01, 0x10, 0x00, 0x85, 0xed, 0x21, 0x12, 0x00, 0x03, 0xce, 0x01, 0x10, 0x00, 0x85, 0xed, 0x21, 0x12, 0x00, 0x03, 0xce, 0x01, 0x10, 0x00, 0x85, 0xed, 0x21, 0x12, 0x00, 0x03, 0xce, 0x01, 0x10, 0x00, 0x85, 0xed, 0x21, 0x12, 0x00, 0x03, 0xce, 0x01, 0x10, 0x00, 0x85, 0xed, 0x21, 0x12, 0x00, 0x03, 0xce, 0x01, 0x10, 0x00, 0x85, 0xed, 0x21, 0x12, 0x00, 0x03, 0xce, 0x01, 0x10, 0x00, 0x85, 0xed, 0x21, 0x12, 0x00, 0x03, 0xce, 0x01, 0x10, 0x00, 0x85, 0xed, 0x21, 0x12, 0x00, 0x03, 0xce, 0x01, 0x10, 0x00, 0x85, 0xed, 0x21, 0x12, 0x00, 0x03, 0xce, 0x01, 0x10, 0x00, 0x85, 0xed, 0x21, 0x12, 0x00, 0x03, 0xce, 0x01, 0x10, 0x00, 0x85, 0xed, 0x21, 0x12, 0x00, 0x03, 0xce, 0x01, 0x10, 0x00, 0x85, 0xed, 0x21, 0x12, 0x00, 0x03, 0xce, 0x01, 0x10, 0x00, 0x85, 0xed, 0x21, 0x12, 0x00, 0x03, 0xce, 0x01, 0x10, 0x00, 0x85, 0xed, 0x21, 0x12, 0x00, 0x03, 0xce, 0x01, 0x10, 0x00, 0x85, 0xed, 0x21, 0x12, 0x00, 0x03, 0xce, 0x01, 0x10, 0x00, 0x85, 0xed, 0x21, 0x12, 0x00, 0x03, 0xce, 0x01, 0x10, 0x00, 0x85, 0xed, 0x21, 0x12, 0x00, 0x03, 0xce, 0x01, 0x10, 0x00, 0x85, 0xed, 0x21, 0x12, 0x00, 0x03, 0xce, 0x01, 0x10, 0x00, 0x85, 0xed, 0x21, 0x12, 0x00, 0x03, 0xce, 0x01, 0x10, 0x00, 0x85, 0xed, 0x21, 0x12, 0x00, 0x03, 0xce, 0x01, 0x10, 0x00, 0x85, 0xed, 0x21, 0x12, 0x00, 0x03, 0xce, 0x01, 0x10, 0x00, 0x85, 0xed, 0x21, 0x12, 0x00, 0x03, 0xce, 0x01, 0x10, 0x00, 0x85, 0xed, 0x21, 0x12, 0x00, 0x03, 0xce, 0x01, 0x10, 0x00, 0x85, 0xed, }, 502, {"8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285", "8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285", 250, 0, NOT_ALL_PRIVATE, 4096, 4, 8466}, 0, }, { /* 15 */ "seq1extra", "seq(8466,3,52737,4096,3456)", {0x2, 0x5, 0x21, 0x12, 0x00, 0x03, 0xce, 0x01, 0x10, 0x00, 0x0d, 0x80}, 12, {"8466 3 52737 4096 3456", "8466 3 52737 4096 3456", 5, 0, NOT_ALL_PRIVATE, 4096, 4, 8466}, 0, }, { /* 16 */ "empty", "", {}, 0, {"", "", 0, 0, 0, 0, 0, 0}, 0, }, { /* 17 */ "redundantset", "seq(8466,3,52737,4096,3456) set(7099,8153,8153,8153)", {0x2, 0x5, 0x21, 0x12, 0x00, 0x03, 0xce, 0x01, 0x10, 0x00, 0x0d, 0x80, 0x1, 0x4, 0x1b, 0xbb, 0x1f, 0xd9, 0x1f, 0xd9, 0x1f, 0xd9}, 22, {/* We shouldn't ever /generate/ such paths. However, we should * cope with them fine. */ "8466 3 52737 4096 3456 {7099,8153}", "8466 3 52737 4096 3456 {7099,8153}", 6, 0, NOT_ALL_PRIVATE, 4096, 4, 8466}, 0, }, { /* 18 */ "reconcile_lead_asp", "seq(6435,59408,21665) set(23456,23456,23456), seq(23456,23456,23456)", {0x2, 0x3, 0x19, 0x23, 0xe8, 0x10, 0x54, 0xa1, 0x1, 0x3, 0x5b, 0xa0, 0x5b, 0xa0, 0x5b, 0xa0, 0x2, 0x3, 0x5b, 0xa0, 0x5b, 0xa0, 0x5b, 0xa0}, 24, {"6435 59408 21665 {23456} 23456 23456 23456", "6435 59408 21665 {23456} 23456 23456 23456", 7, 0, NOT_ALL_PRIVATE, 23456, 1, 6435}, 0, }, { /* 19 */ "reconcile_new_asp", "set(2457,61697,4369), seq(1842,41591,51793)", {0x1, 0x3, 0x09, 0x99, 0xf1, 0x01, 0x11, 0x11, 0x2, 0x3, 0x07, 0x32, 0xa2, 0x77, 0xca, 0x51}, 16, {"{2457,4369,61697} 1842 41591 51793", "{2457,4369,61697} 1842 41591 51793", 4, 0, NOT_ALL_PRIVATE, 51793, 1, 2457}, 0, }, { /* 20 */ "reconcile_confed", "confseq(123,456,789) confset(456,124,788) seq(6435,59408,21665) set(23456,23456,23456), seq(23456,23456,23456)", {0x3, 0x3, 0x00, 0x7b, 0x01, 0xc8, 0x03, 0x15, 0x4, 0x3, 0x01, 0xc8, 0x00, 0x7c, 0x03, 0x14, 0x2, 0x3, 0x19, 0x23, 0xe8, 0x10, 0x54, 0xa1, 0x1, 0x3, 0x5b, 0xa0, 0x5b, 0xa0, 0x5b, 0xa0, 0x2, 0x3, 0x5b, 0xa0, 0x5b, 0xa0, 0x5b, 0xa0}, 40, {"(123 456 789) [124,456,788] 6435 59408 21665 {23456} 23456 23456 23456", "6435 59408 21665 {23456} 23456 23456 23456", 7, 4, NOT_ALL_PRIVATE, 23456, 1, 6435}, 0, }, { /* 21 */ "reconcile_start_trans", "seq(23456,23456,23456) seq(6435,59408,21665)", { 0x2, 0x3, 0x5b, 0xa0, 0x5b, 0xa0, 0x5b, 0xa0, 0x2, 0x3, 0x19, 0x23, 0xe8, 0x10, 0x54, 0xa1, }, 16, {"23456 23456 23456 6435 59408 21665", "23456 23456 23456 6435 59408 21665", 6, 0, NOT_ALL_PRIVATE, 21665, 1, 23456}, 0, }, { /* 22 */ "reconcile_start_trans4", "seq(1842,41591,51793) seq(6435,59408,21665)", { 0x2, 0x3, 0x07, 0x32, 0xa2, 0x77, 0xca, 0x51, 0x2, 0x3, 0x19, 0x23, 0xe8, 0x10, 0x54, 0xa1, }, 16, {"1842 41591 51793 6435 59408 21665", "1842 41591 51793 6435 59408 21665", 6, 0, NOT_ALL_PRIVATE, 41591, 1, 1842}, 0, }, { /* 23 */ "reconcile_start_trans_error", "seq(23456,23456,23456) seq(6435,59408)", { 0x2, 0x3, 0x5b, 0xa0, 0x5b, 0xa0, 0x5b, 0xa0, 0x2, 0x2, 0x19, 0x23, 0xe8, 0x10, }, 14, {"23456 23456 23456 6435 59408", "23456 23456 23456 6435 59408", 5, 0, NOT_ALL_PRIVATE, 59408, 1, 23456}, 0, }, { /* 24 */ "redundantset2", "seq(8466,3,52737,4096,3456) set(7099,8153,8153,8153,7099)", { 0x2, 0x5, 0x21, 0x12, 0x00, 0x03, 0xce, 0x01, 0x10, 0x00, 0x0d, 0x80, 0x1, 0x5, 0x1b, 0xbb, 0x1f, 0xd9, 0x1f, 0xd9, 0x1f, 0xd9, 0x1b, 0xbb, }, 24, {/* We should weed out duplicate set members. */ "8466 3 52737 4096 3456 {7099,8153}", "8466 3 52737 4096 3456 {7099,8153}", 6, 0, NOT_ALL_PRIVATE, 4096, 4, 8466}, 0, }, { /* 25 */ "zero-size overflow", "#ASNs = 0, data = seq(8466 3 52737 4096 3456)", {0x2, 0x0, 0x21, 0x12, 0x00, 0x03, 0xce, 0x01, 0x10, 0x00, 0x0d, 0x80}, 12, {NULL, NULL, 0, 0, 0, 0, 0, 0}, 0, }, { /* 26 */ "zero-size overflow + valid segment", "seq(#AS=0:8466 3 52737),seq(4096 3456)", {0x2, 0x0, 0x21, 0x12, 0x00, 0x03, 0xce, 0x01, 0x2, 0x2, 0x10, 0x00, 0x0d, 0x80}, 14, {NULL, NULL, 0, 0, 0, 0, 0, 0}, 0, }, { /* 27 */ "invalid segment type", "type=8(4096 3456)", {0x8, 0x2, 0x10, 0x00, 0x0d, 0x80}, 14, {NULL, NULL, 0, 0, 0, 0, 0, 0}, 0, }, { /* 28 */ "BGP_AS_ZERO", "seq(8466,3,52737,0,4096)", {0x2, 0x5, 0x21, 0x12, 0x00, 0x03, 0xce, 0x01, 0x00, 0x00, 0x10, 0x00}, 12, {"8466 3 52737 0 4096", "8466 3 52737 0 4096", 5, 0, NOT_ALL_PRIVATE, 4096, 4, 8466}, 0, }, { /* 29 */ "seq3_asdot+", "seq(0.8466,0.3,0.52737,0.4096,0.8722,0.4)", {0x2, 0x6, 0x21, 0x12, 0x00, 0x03, 0xce, 0x01, 0x10, 0x00, 0x22, 0x12, 0x00, 0x04}, 14, {"0.8466 0.3 0.52737 0.4096 0.8722 0.4", "0.8466 0.3 0.52737 0.4096 0.8722 0.4", 6, 0, NOT_ALL_PRIVATE, 3, 5, 8466}, ASNOTATION_DOTPLUS, }, { /* 30 */ "confmulti_asdot+", "confseq(0.123,0.456,0.789) confset(0.222,0.111) seq(0.8722) set(0.4196,0.48658)", {0x3, 0x3, 0x00, 0x7b, 0x01, 0xc8, 0x03, 0x15, 0x4, 0x2, 0x00, 0xde, 0x00, 0x6f, 0x2, 0x1, 0x22, 0x12, 0x1, 0x2, 0x10, 0x64, 0xbe, 0x12}, 24, {"(0.123 0.456 0.789) [0.111,0.222] 0.8722 {0.4196,0.48658}", "0.8722 {0.4196,0.48658}", 2, 4, NOT_ALL_PRIVATE, 123, 1, NULL_ASN}, ASNOTATION_DOTPLUS, }, { /* 31 */ "someprivate asdot+", "seq(0.8466,0.64512,0.52737,0.65535)", {0x2, 0x4, 0x21, 0x12, 0xfc, 0x00, 0xce, 0x01, 0xff, 0xff}, 10, {"0.8466 0.64512 0.52737 0.65535", "0.8466 0.64512 0.52737 0.65535", 4, 0, NOT_ALL_PRIVATE, 65535, 4, 8466}, ASNOTATION_DOTPLUS, }, { /* 32 */ "BGP_AS_ZERO asdot+", "seq(0.8466,0.3,0.52737,0.0,0.4096)", {0x2, 0x5, 0x21, 0x12, 0x00, 0x03, 0xce, 0x01, 0x00, 0x00, 0x10, 0x00}, 12, {"0.8466 0.3 0.52737 0.0 0.4096", "0.8466 0.3 0.52737 0.0 0.4096", 5, 0, NOT_ALL_PRIVATE, 4096, 4, 8466}, ASNOTATION_DOTPLUS, }, {NULL, NULL, {0}, 0, {NULL, 0, 0}}}; #define COMMON_ATTRS \ BGP_ATTR_FLAG_TRANS, BGP_ATTR_ORIGIN, 1, BGP_ORIGIN_EGP, \ BGP_ATTR_FLAG_TRANS, BGP_ATTR_NEXT_HOP, 4, 192, 0, 2, 0 #define COMMON_ATTR_SIZE 11 /* */ static struct aspath_tests { const char *desc; const struct test_segment *segment; const char *shouldbe; /* String it should evaluate to */ const enum as4 { AS4_DATA, AS2_DATA } as4; /* whether data should be as4 or not (ie as2) */ const int result; /* expected result for bgp_attr_parse */ const int cap; /* capabilities to set for peer */ const char attrheader[1024]; size_t len; const struct test_segment *old_segment; } aspath_tests[] = { /* 0 */ { "basic test", &test_segments[0], "8466 3 52737 4096", AS2_DATA, 0, 0, { COMMON_ATTRS, BGP_ATTR_FLAG_TRANS, BGP_ATTR_AS_PATH, 10, }, COMMON_ATTR_SIZE + 3, }, /* 1 */ { "length too short", &test_segments[0], "8466 3 52737 4096", AS2_DATA, -1, 0, { COMMON_ATTRS, BGP_ATTR_FLAG_TRANS, BGP_ATTR_AS_PATH, 8, }, COMMON_ATTR_SIZE + 3, }, /* 2 */ { "length too long", &test_segments[0], "8466 3 52737 4096", AS2_DATA, -1, 0, { COMMON_ATTRS, BGP_ATTR_FLAG_TRANS, BGP_ATTR_AS_PATH, 12, }, COMMON_ATTR_SIZE + 3, }, /* 3 */ { "incorrect flag", &test_segments[0], "8466 3 52737 4096", AS2_DATA, -1, 0, { COMMON_ATTRS, BGP_ATTR_FLAG_TRANS | BGP_ATTR_FLAG_OPTIONAL, BGP_ATTR_AS_PATH, 10, }, COMMON_ATTR_SIZE + 3, }, /* 4 */ { "as4_path, with as2 format data", &test_segments[0], "8466 3 52737 4096", AS2_DATA, -1, 0, { COMMON_ATTRS, BGP_ATTR_FLAG_TRANS | BGP_ATTR_FLAG_OPTIONAL, BGP_ATTR_AS4_PATH, 10, }, COMMON_ATTR_SIZE + 3, }, /* 5 */ { "as4, with incorrect attr length", &test_segments[0], "8466 3 52737 4096", AS4_DATA, -1, 0, { COMMON_ATTRS, BGP_ATTR_FLAG_TRANS | BGP_ATTR_FLAG_OPTIONAL, BGP_ATTR_AS4_PATH, 10, }, COMMON_ATTR_SIZE + 3, }, /* 6 */ { "basic 4-byte as-path", &test_segments[0], "8466 3 52737 4096", AS4_DATA, 0, PEER_CAP_AS4_RCV | PEER_CAP_AS4_ADV, { COMMON_ATTRS, BGP_ATTR_FLAG_TRANS, BGP_ATTR_AS_PATH, 18, }, COMMON_ATTR_SIZE + 3, }, /* 7 */ { "4b AS_PATH: too short", &test_segments[0], "8466 3 52737 4096", AS4_DATA, -1, 0, { COMMON_ATTRS, BGP_ATTR_FLAG_TRANS, BGP_ATTR_AS_PATH, 16, }, COMMON_ATTR_SIZE + 3, }, /* 8 */ { "4b AS_PATH: too long", &test_segments[0], "8466 3 52737 4096", AS4_DATA, -1, 0, { COMMON_ATTRS, BGP_ATTR_FLAG_TRANS, BGP_ATTR_AS_PATH, 20, }, COMMON_ATTR_SIZE + 3, }, /* 9 */ { "4b AS_PATH: too long2", &test_segments[0], "8466 3 52737 4096", AS4_DATA, -1, 0, { COMMON_ATTRS, BGP_ATTR_FLAG_TRANS, BGP_ATTR_AS_PATH, 22, }, COMMON_ATTR_SIZE + 3, }, /* 10 */ { "4b AS_PATH: bad flags", &test_segments[0], "8466 3 52737 4096", AS4_DATA, -1, 0, { COMMON_ATTRS, BGP_ATTR_FLAG_TRANS | BGP_ATTR_FLAG_OPTIONAL, BGP_ATTR_AS_PATH, 18, }, COMMON_ATTR_SIZE + 3, }, /* 11 */ { "4b AS4_PATH w/o AS_PATH", &test_segments[6], NULL, AS4_DATA, -2, PEER_CAP_AS4_ADV, { COMMON_ATTRS, BGP_ATTR_FLAG_TRANS | BGP_ATTR_FLAG_OPTIONAL, BGP_ATTR_AS4_PATH, 14, }, COMMON_ATTR_SIZE + 3, }, /* 12 */ { "4b AS4_PATH: confed", &test_segments[6], "8466 3 52737 4096 (123 456 789)", AS4_DATA, 0, PEER_CAP_AS4_ADV, { COMMON_ATTRS, BGP_ATTR_FLAG_TRANS | BGP_ATTR_FLAG_OPTIONAL, BGP_ATTR_AS4_PATH, 14, }, COMMON_ATTR_SIZE + 3, &test_segments[0], }, /* 13 */ { "4b AS4_PATH: BGP_AS_ZERO", &test_segments[28], "8466 3 52737 0 4096", AS4_DATA, -2, PEER_CAP_AS4_RCV | PEER_CAP_AS4_ADV, { COMMON_ATTRS, BGP_ATTR_FLAG_TRANS | BGP_ATTR_FLAG_OPTIONAL, BGP_ATTR_AS4_PATH, 22, }, COMMON_ATTR_SIZE + 3, }, {NULL, NULL, NULL, 0, 0, 0, {0}, 0}, }; /* prepending tests */ static struct tests { const struct test_segment *test1; const struct test_segment *test2; struct test_spec sp; } prepend_tests[] = { /* 0 */ { &test_segments[0], &test_segments[1], {"8466 3 52737 4096 8722 4", "8466 3 52737 4096 8722 4", 6, 0, NOT_ALL_PRIVATE, 4096, 1, 8466}, }, /* 1 */ {&test_segments[1], &test_segments[3], {"8722 4 8482 51457 {5204}", "8722 4 8482 51457 {5204}", 5, 0, NOT_ALL_PRIVATE, 5204, 1, 8722}}, /* 2 */ { &test_segments[3], &test_segments[4], {"8482 51457 {5204} 8467 59649 {4196,48658} {17322,30745}", "8482 51457 {5204} 8467 59649 {4196,48658} {17322,30745}", 7, 0, NOT_ALL_PRIVATE, 5204, 1, 8482}, }, /* 3 */ {&test_segments[4], &test_segments[5], {"8467 59649 {4196,48658} {17322,30745} 6435 59408 21665 {2457,4369,61697} 1842 41590 51793", "8467 59649 {4196,48658} {17322,30745} 6435 59408 21665 {2457,4369,61697} 1842 41590 51793", 11, 0, NOT_ALL_PRIVATE, 61697, 1, 8467}}, /* 4 */ { &test_segments[5], &test_segments[6], {"6435 59408 21665 {2457,4369,61697} 1842 41590 51793", "6435 59408 21665 {2457,4369,61697} 1842 41590 51793", 7, 0, NOT_ALL_PRIVATE, 1842, 1, 6435}, }, /* 5 */ {&test_segments[6], &test_segments[7], {"(123 456 789) (123 456 789) (111 222)", "", 0, 8, NOT_ALL_PRIVATE, 111, 1, 0}}, {&test_segments[7], &test_segments[8], {"(123 456 789) (111 222) [123,456,789]", "", 0, 6, NOT_ALL_PRIVATE, 111, 1, 0}}, { &test_segments[8], &test_segments[9], {"[123,456,789] (123 456 789) [111,222] 8722 {4196,48658}", "8722 {4196,48658}", 2, 5, NOT_ALL_PRIVATE, 456, 1, NULL_ASN}, }, { &test_segments[9], &test_segments[8], {"(123 456 789) [111,222] 8722 {4196,48658} [123,456,789]", "8722 {4196,48658}", 2, 5, NOT_ALL_PRIVATE, 48658, 1, NULL_ASN}, }, { &test_segments[14], &test_segments[11], {"8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 2 52737 4096 8722 4 8722", "8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 2 52737 4096 8722 4 8722", 257, 0, NOT_ALL_PRIVATE, 4096, 1000, 8466}, }, {NULL, NULL, { NULL, 0, 0, 0, 0, 0, 0, }}, }; struct tests reconcile_tests[] = { { &test_segments[18], &test_segments[19], {"6435 59408 21665 {2457,4369,61697} 1842 41591 51793", "6435 59408 21665 {2457,4369,61697} 1842 41591 51793", 7, 0, NOT_ALL_PRIVATE, 51793, 1, 6435}, }, { &test_segments[19], &test_segments[18], /* AS_PATH (19) has more hops than NEW_AS_PATH, * so just AS_PATH should be used (though, this practice * is bad imho). */ {"{2457,4369,61697} 1842 41591 51793 6435 59408 21665 {23456} 23456 23456 23456", "{2457,4369,61697} 1842 41591 51793 6435 59408 21665 {23456} 23456 23456 23456", 11, 0, NOT_ALL_PRIVATE, 51793, 1, 6435}, }, { &test_segments[20], &test_segments[19], {"(123 456 789) [124,456,788] 6435 59408 21665 {2457,4369,61697} 1842 41591 51793", "6435 59408 21665 {2457,4369,61697} 1842 41591 51793", 7, 4, NOT_ALL_PRIVATE, 51793, 1, 6435}, }, { &test_segments[21], &test_segments[22], {"1842 41591 51793 6435 59408 21665", "1842 41591 51793 6435 59408 21665", 6, 0, NOT_ALL_PRIVATE, 51793, 1, 1842}, }, { &test_segments[23], &test_segments[22], {"23456 23456 23456 6435 59408 1842 41591 51793 6435 59408 21665", "23456 23456 23456 6435 59408 1842 41591 51793 6435 59408 21665", 11, 0, NOT_ALL_PRIVATE, 51793, 1, 1842}, }, {NULL, NULL, { NULL, 0, 0, 0, 0, 0, 0, }}, }; struct tests aggregate_tests[] = { { &test_segments[0], &test_segments[2], {"8466 3 52737 4096 {4,8722}", "8466 3 52737 4096 {4,8722}", 5, 0, NOT_ALL_PRIVATE, 4, 1, 8466}, }, { &test_segments[2], &test_segments[0], {"8466 3 52737 4096 {4,8722}", "8466 3 52737 4096 {4,8722}", 5, 0, NOT_ALL_PRIVATE, 8722, 1, 8466}, }, { &test_segments[2], &test_segments[10], {"8466 {2,3,4,4096,8722,52737}", "8466 {2,3,4,4096,8722,52737}", 2, 0, NOT_ALL_PRIVATE, 8722, 5, 8466}, }, { &test_segments[10], &test_segments[2], {"8466 {2,3,4,4096,8722,52737}", "8466 {2,3,4,4096,8722,52737}", 2, 0, NOT_ALL_PRIVATE, 2, 20000, 8466}, }, { &test_segments[5], &test_segments[18], {"6435 59408 21665 {1842,2457,4369,23456,41590,51793,61697}", "6435 59408 21665 {1842,2457,4369,23456,41590,51793,61697}", 4, 0, NOT_ALL_PRIVATE, 41590, 1, 6435}, }, {NULL, NULL, {NULL, 0, 0}}, }; struct compare_tests { int test_index1; int test_index2; #define CMP_RES_YES 1 #define CMP_RES_NO 0 char shouldbe_cmp; char shouldbe_confed; } left_compare[] = { {0, 1, CMP_RES_NO, CMP_RES_NO}, {0, 2, CMP_RES_YES, CMP_RES_NO}, {0, 11, CMP_RES_YES, CMP_RES_NO}, {0, 15, CMP_RES_YES, CMP_RES_NO}, {0, 16, CMP_RES_NO, CMP_RES_NO}, {1, 11, CMP_RES_NO, CMP_RES_NO}, {6, 7, CMP_RES_NO, CMP_RES_YES}, {6, 8, CMP_RES_NO, CMP_RES_NO}, {7, 8, CMP_RES_NO, CMP_RES_NO}, {1, 9, CMP_RES_YES, CMP_RES_NO}, {0, 9, CMP_RES_NO, CMP_RES_NO}, {3, 9, CMP_RES_NO, CMP_RES_NO}, {0, 6, CMP_RES_NO, CMP_RES_NO}, {1, 6, CMP_RES_NO, CMP_RES_NO}, {0, 8, CMP_RES_NO, CMP_RES_NO}, {1, 8, CMP_RES_NO, CMP_RES_NO}, {11, 6, CMP_RES_NO, CMP_RES_NO}, {11, 7, CMP_RES_NO, CMP_RES_NO}, {11, 8, CMP_RES_NO, CMP_RES_NO}, {9, 6, CMP_RES_NO, CMP_RES_YES}, {9, 7, CMP_RES_NO, CMP_RES_YES}, {9, 8, CMP_RES_NO, CMP_RES_NO}, }; /* make an aspath from a data stream */ static struct aspath *make_aspath(const uint8_t *data, size_t len, int use32bit, enum asnotation_mode asnotation) { struct stream *s = NULL; struct aspath *as; if (len) { s = stream_new(len); stream_put(s, data, len); } as = aspath_parse(s, len, use32bit, asnotation); if (s) stream_free(s); return as; } static void printbytes(const uint8_t *bytes, int len) { int i = 0; while (i < len) { if (i % 2) printf("%02hhx%s", bytes[i], " "); else printf("0x%02hhx", bytes[i]); i++; } printf("\n"); } /* validate the given aspath */ static int validate(struct aspath *as, const struct test_spec *sp) { size_t bytes, bytes4; int fails = 0; const uint8_t *out; static struct stream *s; struct aspath *asinout, *asconfeddel, *asstr, *as4; if (as == NULL && sp->shouldbe == NULL) { printf("Correctly failed to parse\n"); return fails; } out = aspath_snmp_pathseg(as, &bytes); asinout = make_aspath(out, bytes, 0, as->asnotation); /* Excercise AS4 parsing a bit, with a dogfood test */ if (!s) s = stream_new(BGP_MAX_PACKET_SIZE); bytes4 = aspath_put(s, as, 1); as4 = make_aspath(STREAM_DATA(s), bytes4, 1, as->asnotation); asn_relax_as_zero(true); asstr = aspath_str2aspath(sp->shouldbe, as->asnotation); asn_relax_as_zero(false); asconfeddel = aspath_delete_confed_seq(aspath_dup(asinout)); printf("got: %s\n", aspath_print(as)); /* the parsed path should match the specified 'shouldbe' string. * We should pass the "eat our own dog food" test, be able to output * this path and then input it again. Ie the path resulting from: * * aspath_parse(aspath_put(as)) * * should: * * - also match the specified 'shouldbe' value * - hash to same value as original path * - have same hops and confed counts as original, and as the * the specified counts * * aspath_str2aspath() and shouldbe should match * * We do the same for: * * aspath_parse(aspath_put(as,USE32BIT)) * * Confederation related tests: * - aspath_delete_confed_seq(aspath) should match shouldbe_confed * - aspath_delete_confed_seq should be idempotent. */ if (strcmp(aspath_print(as), sp->shouldbe) /* hash validation */ || (aspath_key_make(as) != aspath_key_make(asinout)) /* by string */ || strcmp(aspath_print(asinout), sp->shouldbe) /* By 4-byte parsing */ || strcmp(aspath_print(as4), sp->shouldbe) /* by various path counts */ || (aspath_count_hops(as) != sp->hops) || (aspath_count_confeds(as) != sp->confeds) || (aspath_count_hops(asinout) != sp->hops) || (aspath_count_confeds(asinout) != sp->confeds)) { failed++; fails++; printf("shouldbe:\n%s\n", sp->shouldbe); printf("as4:\n%s\n", aspath_print(as4)); printf("hash keys: in: %d out->in: %d\n", aspath_key_make(as), aspath_key_make(asinout)); printf("hops: %d, counted %d %d\n", sp->hops, aspath_count_hops(as), aspath_count_hops(asinout)); printf("confeds: %d, counted %d %d\n", sp->confeds, aspath_count_confeds(as), aspath_count_confeds(asinout)); printf("out->in:\n%s\nbytes: ", aspath_print(asinout)); printbytes(out, bytes); } /* basic confed related tests */ if ((aspath_print(asconfeddel) == NULL && sp->shouldbe_delete_confed != NULL) || (aspath_print(asconfeddel) != NULL && sp->shouldbe_delete_confed == NULL) || strcmp(aspath_print(asconfeddel), sp->shouldbe_delete_confed) /* delete_confed_seq should be idempotent */ || (aspath_key_make(asconfeddel) != aspath_key_make(aspath_delete_confed_seq(asconfeddel)))) { failed++; fails++; printf("as-path minus confeds is: %s\n", aspath_print(asconfeddel)); printf("as-path minus confeds should be: %s\n", sp->shouldbe_delete_confed); } /* aspath_str2aspath test */ if ((aspath_print(asstr) == NULL && sp->shouldbe != NULL) || (aspath_print(asstr) != NULL && sp->shouldbe == NULL) || strcmp(aspath_print(asstr), sp->shouldbe)) { failed++; fails++; printf("asstr: %s\n", aspath_print(asstr)); } /* loop, private and first as checks */ if ((sp->does_loop && aspath_loop_check(as, sp->does_loop) == 0) || (sp->doesnt_loop && aspath_loop_check(as, sp->doesnt_loop) != 0) || (aspath_private_as_check(as) != sp->private_as) || (aspath_firstas_check(as, sp->first) && sp->first == 0)) { failed++; fails++; printf("firstas: %d, got %d\n", sp->first, aspath_firstas_check(as, sp->first)); printf("loop does: %d %d, doesn't: %d %d\n", sp->does_loop, aspath_loop_check(as, sp->does_loop), sp->doesnt_loop, aspath_loop_check(as, sp->doesnt_loop)); printf("private check: %d %d\n", sp->private_as, aspath_private_as_check(as)); } aspath_unintern(&asinout); aspath_unintern(&as4); aspath_free(asconfeddel); aspath_free(asstr); stream_reset(s); return fails; } static void empty_get_test(void) { struct aspath *as = aspath_empty_get(); struct test_spec sp = {"", "", 0, 0, 0, 0, 0, 0}; printf("empty_get_test, as: %s\n", aspath_print(as)); if (!validate(as, &sp)) printf("%s\n", OK); else printf("%s!\n", FAILED); printf("\n"); aspath_free(as); } /* basic parsing test */ static void parse_test(struct test_segment *t) { struct aspath *asp; printf("%s: %s\n", t->name, t->desc); asp = make_aspath(t->asdata, t->len, 0, t->asnotation); printf("aspath: %s\nvalidating...:\n", aspath_print(asp)); if (!validate(asp, &t->sp)) printf(OK "\n"); else printf(FAILED "\n"); printf("\n"); aspath_unintern(&asp); } /* prepend testing */ static void prepend_test(struct tests *t) { struct aspath *asp1, *asp2, *ascratch; printf("prepend %s: %s\n", t->test1->name, t->test1->desc); printf("to %s: %s\n", t->test2->name, t->test2->desc); asp1 = make_aspath(t->test1->asdata, t->test1->len, 0, ASNOTATION_PLAIN); asp2 = make_aspath(t->test2->asdata, t->test2->len, 0, ASNOTATION_PLAIN); ascratch = aspath_dup(asp2); aspath_unintern(&asp2); asp2 = aspath_prepend(asp1, ascratch); printf("aspath: %s\n", aspath_print(asp2)); if (!validate(asp2, &t->sp)) printf("%s\n", OK); else printf("%s!\n", FAILED); printf("\n"); aspath_unintern(&asp1); aspath_free(asp2); } /* empty-prepend testing */ static void empty_prepend_test(struct test_segment *t) { struct aspath *asp1, *asp2, *ascratch; printf("empty prepend %s: %s\n", t->name, t->desc); asp1 = make_aspath(t->asdata, t->len, 0, t->asnotation); asp2 = aspath_empty(t->asnotation); ascratch = aspath_dup(asp2); aspath_unintern(&asp2); asp2 = aspath_prepend(asp1, ascratch); printf("aspath: %s\n", aspath_print(asp2)); if (!validate(asp2, &t->sp)) printf(OK "\n"); else printf(FAILED "!\n"); printf("\n"); aspath_unintern(&asp1); aspath_free(asp2); } /* as2+as4 reconciliation testing */ static void as4_reconcile_test(struct tests *t) { struct aspath *asp1, *asp2, *ascratch; printf("reconciling %s:\n %s\n", t->test1->name, t->test1->desc); printf("with %s:\n %s\n", t->test2->name, t->test2->desc); asp1 = make_aspath(t->test1->asdata, t->test1->len, 0, ASNOTATION_PLAIN); asp2 = make_aspath(t->test2->asdata, t->test2->len, 0, ASNOTATION_PLAIN); ascratch = aspath_reconcile_as4(asp1, asp2); if (!validate(ascratch, &t->sp)) printf(OK "\n"); else printf(FAILED "!\n"); printf("\n"); aspath_unintern(&asp1); aspath_unintern(&asp2); aspath_free(ascratch); } /* aggregation testing */ static void aggregate_test(struct tests *t) { struct aspath *asp1, *asp2, *ascratch; printf("aggregate %s: %s\n", t->test1->name, t->test1->desc); printf("with %s: %s\n", t->test2->name, t->test2->desc); asp1 = make_aspath(t->test1->asdata, t->test1->len, 0, ASNOTATION_PLAIN); asp2 = make_aspath(t->test2->asdata, t->test2->len, 0, ASNOTATION_PLAIN); ascratch = aspath_aggregate(asp1, asp2); if (!validate(ascratch, &t->sp)) printf(OK "\n"); else printf(FAILED "!\n"); printf("\n"); aspath_unintern(&asp1); aspath_unintern(&asp2); aspath_free(ascratch); /* aspath_unintern (ascratch);*/ } /* cmp_left tests */ static void cmp_test(void) { unsigned int i; #define CMP_TESTS_MAX (sizeof(left_compare) / sizeof(struct compare_tests)) for (i = 0; i < CMP_TESTS_MAX; i++) { struct test_segment *t1 = &test_segments[left_compare[i].test_index1]; struct test_segment *t2 = &test_segments[left_compare[i].test_index2]; struct aspath *asp1, *asp2; printf("left cmp %s: %s\n", t1->name, t1->desc); printf("and %s: %s\n", t2->name, t2->desc); asp1 = make_aspath(t1->asdata, t1->len, 0, ASNOTATION_PLAIN); asp2 = make_aspath(t2->asdata, t2->len, 0, ASNOTATION_PLAIN); if (aspath_cmp_left(asp1, asp2) != left_compare[i].shouldbe_cmp || aspath_cmp_left(asp2, asp1) != left_compare[i].shouldbe_cmp || aspath_cmp_left_confed(asp1, asp2) != left_compare[i].shouldbe_confed || aspath_cmp_left_confed(asp2, asp1) != left_compare[i].shouldbe_confed) { failed++; printf(FAILED "\n"); printf("result should be: cmp: %d, confed: %d\n", left_compare[i].shouldbe_cmp, left_compare[i].shouldbe_confed); printf("got: cmp %d, cmp_confed: %d\n", aspath_cmp_left(asp1, asp2), aspath_cmp_left_confed(asp1, asp2)); printf("path1: %s\npath2: %s\n", aspath_print(asp1), aspath_print(asp2)); } else printf(OK "\n"); printf("\n"); aspath_unintern(&asp1); aspath_unintern(&asp2); } } static int handle_attr_test(struct aspath_tests *t) { struct bgp bgp = {0}; struct peer peer = {0}; struct attr attr = {0}; int ret; int initfail = failed; struct aspath *asp; size_t datalen; asp = make_aspath(t->segment->asdata, t->segment->len, 0, t->segment->asnotation); bgp.asnotation = t->segment->asnotation; peer.curr = stream_new(BGP_MAX_PACKET_SIZE); peer.connection = bgp_peer_connection_new(&peer); peer.connection->obuf = stream_fifo_new(); peer.bgp = &bgp; peer.host = (char *)"none"; peer.connection->fd = -1; peer.cap = t->cap; peer.max_packet_size = BGP_STANDARD_MESSAGE_MAX_PACKET_SIZE; stream_write(peer.curr, t->attrheader, t->len); datalen = aspath_put(peer.curr, asp, t->as4 == AS4_DATA); if (t->old_segment) { char dummyaspath[] = {BGP_ATTR_FLAG_TRANS, BGP_ATTR_AS_PATH, t->old_segment->len}; stream_write(peer.curr, dummyaspath, sizeof(dummyaspath)); stream_write(peer.curr, t->old_segment->asdata, t->old_segment->len); datalen += sizeof(dummyaspath) + t->old_segment->len; } ret = bgp_attr_parse(&peer, &attr, t->len + datalen, NULL, NULL); if (ret != t->result) { printf("bgp_attr_parse returned %d, expected %d\n", ret, t->result); printf("datalen %zd\n", datalen); failed++; } if (ret != 0) goto out; if (t->shouldbe && attr.aspath == NULL) { printf("aspath is NULL, but should be: %s\n", t->shouldbe); failed++; } if (t->shouldbe && attr.aspath && strcmp(attr.aspath->str, t->shouldbe)) { printf("attr str and 'shouldbe' mismatched!\n" "attr str: %s\n" "shouldbe: %s\n", attr.aspath->str, t->shouldbe); failed++; } if (!t->shouldbe && attr.aspath) { printf("aspath should be NULL, but is: %s\n", attr.aspath->str); failed++; } out: aspath_unintern(&attr.aspath); aspath_unintern(&asp); return failed - initfail; } static void attr_test(struct aspath_tests *t) { printf("%s\n", t->desc); printf("%s\n\n", handle_attr_test(t) ? FAILED : OK); } int main(void) { int i = 0; qobj_init(); bgp_master_init(event_master_create(NULL), BGP_SOCKET_SNDBUF_SIZE, list_new()); master = bm->master; bgp_option_set(BGP_OPT_NO_LISTEN); bgp_attr_init(); while (test_segments[i].name) { printf("test %u\n", i); parse_test(&test_segments[i]); empty_prepend_test(&test_segments[i++]); } i = 0; while (prepend_tests[i].test1) { printf("prepend test %u\n", i); prepend_test(&prepend_tests[i++]); } i = 0; while (aggregate_tests[i].test1) { printf("aggregate test %u\n", i); aggregate_test(&aggregate_tests[i++]); } i = 0; while (reconcile_tests[i].test1) { printf("reconcile test %u\n", i); as4_reconcile_test(&reconcile_tests[i++]); } i = 0; cmp_test(); i = 0; empty_get_test(); i = 0; frr_pthread_init(); bgp_pthreads_init(); bgp_pth_ka->running = true; while (aspath_tests[i].desc) { printf("aspath_attr test %d\n", i); attr_test(&aspath_tests[i++]); } printf("failures: %d\n", failed); printf("aspath count: %ld\n", aspath_count()); return (failed + aspath_count()); }