mirror_frr/tests/bgpd/test_aspath.c
Donald Sharp c2d020ad71 bgpd: Add ability to set tcp socket buffer size
Add -s X or --socket_size X to the bgp cli to allow
the end user to specify the outgoing bgp tcp kernel
socket buffer size.

It is recommended that this option is only used on
large scale operations.

Signed-off-by: Donald Sharp <sharpd@cumulusnetworks.com>
2019-10-16 07:42:05 -04:00

1396 lines
39 KiB
C

/*
* Copyright (C) 2005 Sun Microsystems, Inc.
*
* This file is part of Quagga.
*
* Quagga is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2, or (at your option) any
* later version.
*
* Quagga is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; see the file COPYING; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <zebra.h>
#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 = NULL;
struct thread_master *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;
} 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},
},
{
/* 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,
},
},
{
/* 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},
},
{
/* 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},
},
{
/* 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},
},
{
/* 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},
},
{
/* 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},
},
{
/* 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},
},
{
/* 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},
},
{
/* 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},
},
{
/* 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},
},
{
/* 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},
},
{
/* 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},
},
{
/* 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},
},
{
/* 14 */
"long",
"seq(8466,3,52737,4096,34285,<repeated 49 more times>)",
{
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},
},
{
/* 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},
},
{
/* 16 */
"empty",
"<empty>",
{},
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},
},
{
/* 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},
},
{
/* 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},
},
{
/* 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},
},
{
/* 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},
},
{
/* 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},
},
{
/* 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},
},
{
/* 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},
},
{
/* 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},
},
{
/* 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},
},
{
/* 27 */
"invalid segment type",
"type=8(4096 3456)",
{0x8, 0x2, 0x10, 0x00, 0x0d, 0x80},
14,
{NULL, NULL, 0, 0, 0, 0, 0, 0},
},
{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,
PEER_CAP_AS4_RCV,
{
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,
PEER_CAP_AS4_RCV | PEER_CAP_AS4_ADV,
{
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,
PEER_CAP_AS4_RCV | PEER_CAP_AS4_ADV,
{
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,
PEER_CAP_AS4_RCV | PEER_CAP_AS4_ADV,
{
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,
PEER_CAP_AS4_RCV | PEER_CAP_AS4_ADV,
{
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,
-1,
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],
},
{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)
{
struct stream *s = NULL;
struct aspath *as;
if (len) {
s = stream_new(len);
stream_put(s, data, len);
}
as = aspath_parse(s, len, use32bit);
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);
/* Excercise AS4 parsing a bit, with a dogfood test */
if (!s)
s = stream_new(4096);
bytes4 = aspath_put(s, as, 1);
as4 = make_aspath(STREAM_DATA(s), bytes4, 1);
asstr = aspath_str2aspath(sp->shouldbe);
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, doesnt: %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);
printf("aspath: %s\nvalidating...:\n", aspath_print(asp));
if (!validate(asp, &t->sp))
printf(OK "\n");
else
printf(FAILED "\n");
printf("\n");
if (asp)
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);
asp2 = make_aspath(t->test2->asdata, t->test2->len, 0);
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);
asp2 = aspath_empty();
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");
if (asp1)
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);
asp2 = make_aspath(t->test2->asdata, t->test2->len, 0);
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);
asp2 = make_aspath(t->test2->asdata, t->test2->len, 0);
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);
asp2 = make_aspath(t2->asdata, t2->len, 0);
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);
peer.curr = stream_new(BGP_MAX_PACKET_SIZE);
peer.obuf = stream_fifo_new();
peer.bgp = &bgp;
peer.host = (char *)"none";
peer.fd = -1;
peer.cap = t->cap;
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:
if (attr.aspath)
aspath_unintern(&attr.aspath);
if (asp)
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(thread_master_create(NULL), BGP_SOCKET_SNDBUF_SIZE);
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());
}