From: Marcel Röthke Date: Fri, 15 Jun 2018 11:28:06 +0000 (+0200) Subject: bgpd: add test for bgp_table_range_lookup X-Git-Tag: frr-6.1-dev~178^2 X-Git-Url: https://git.puffer.fish/?a=commitdiff_plain;h=a98b00ee3e4b4a3e5232075cd9ca15bb8c0c1e31;p=mirror%2Ffrr.git bgpd: add test for bgp_table_range_lookup Signed-off-by: Marcel Röthke --- diff --git a/tests/Makefile.am b/tests/Makefile.am index 32d2db768a..a7dec67348 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -21,7 +21,8 @@ TESTS_BGPD = \ bgpd/test_peer_attr \ bgpd/test_ecommunity \ bgpd/test_mp_attr \ - bgpd/test_mpath + bgpd/test_mpath \ + bgpd/test_bgp_table else TESTS_BGPD = endif @@ -143,6 +144,7 @@ bgpd_test_peer_attr_SOURCES = bgpd/test_peer_attr.c bgpd_test_ecommunity_SOURCES = bgpd/test_ecommunity.c bgpd_test_mp_attr_SOURCES = bgpd/test_mp_attr.c bgpd_test_mpath_SOURCES = bgpd/test_mpath.c +bgpd_test_bgp_table_SOURCES = bgpd/test_bgp_table.c isisd_test_fuzz_isis_tlv_SOURCES = isisd/test_fuzz_isis_tlv.c nodist_isisd_test_fuzz_isis_tlv_SOURCES = isisd/test_fuzz_isis_tlv_tests.h BUILT_SOURCES=isisd/test_fuzz_isis_tlv_tests.h @@ -186,6 +188,7 @@ bgpd_test_peer_attr_LDADD = $(BGP_TEST_LDADD) bgpd_test_ecommunity_LDADD = $(BGP_TEST_LDADD) bgpd_test_mp_attr_LDADD = $(BGP_TEST_LDADD) bgpd_test_mpath_LDADD = $(BGP_TEST_LDADD) +bgpd_test_bgp_table_LDADD = $(BGP_TEST_LDADD) isisd_test_fuzz_isis_tlv_LDADD = $(ISISD_TEST_LDADD) isisd_test_isis_vertex_queue_LDADD = $(ISISD_TEST_LDADD) ospf6d_test_lsdb_LDADD = $(OSPF6_TEST_LDADD) diff --git a/tests/bgpd/test_bgp_table b/tests/bgpd/test_bgp_table new file mode 100755 index 0000000000..05a7e8947b --- /dev/null +++ b/tests/bgpd/test_bgp_table @@ -0,0 +1,228 @@ +#! /bin/sh + +# bgpd/test_bgp_table - temporary wrapper script for .libs/test_bgp_table +# Generated by libtool (GNU libtool) 2.4.6.40-6ca5-dirty +# +# The bgpd/test_bgp_table program cannot be directly executed until all the libtool +# libraries that it depends on are installed. +# +# This wrapper script should never be moved out of the build directory. +# If it is, it will not operate correctly. + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +sed_quote_subst='s|\([`"$\\]\)|\\\1|g' + +# Be Bourne compatible +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac +fi +BIN_SH=xpg4; export BIN_SH # for Tru64 +DUALCASE=1; export DUALCASE # for MKS sh + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +relink_command="(cd /home/marcel/src/haw/frr-1/tests; { test -z \"\${LIBRARY_PATH+set}\" || unset LIBRARY_PATH || { LIBRARY_PATH=; export LIBRARY_PATH; }; }; { test -z \"\${COMPILER_PATH+set}\" || unset COMPILER_PATH || { COMPILER_PATH=; export COMPILER_PATH; }; }; { test -z \"\${GCC_EXEC_PREFIX+set}\" || unset GCC_EXEC_PREFIX || { GCC_EXEC_PREFIX=; export GCC_EXEC_PREFIX; }; }; { test -z \"\${LD_RUN_PATH+set}\" || unset LD_RUN_PATH || { LD_RUN_PATH=; export LD_RUN_PATH; }; }; { test -z \"\${LD_LIBRARY_PATH+set}\" || unset LD_LIBRARY_PATH || { LD_LIBRARY_PATH=; export LD_LIBRARY_PATH; }; }; PATH=/home/marcel/.cargo/bin:/home/marcel/dotfiles/bin:/home/marcel/bin:/usr/local/sbin:/usr/local/bin:/usr/bin:/usr/bin/site_perl:/usr/bin/vendor_perl:/usr/bin/core_perl; export PATH; gcc -std=gnu11 -g3 -O0 -fno-omit-frame-pointer -funwind-tables -Wall -Wextra -Wmissing-prototypes -Wmissing-declarations -Wpointer-arith -Wbad-function-cast -Wwrite-strings -Wno-unused-result -Wno-unused-parameter -Wno-missing-field-initializers -pthread -rdynamic -o \$progdir/\$file bgpd/test_bgp_table.o ../bgpd/libbgp.a ../bgpd/rfp-example/librfp/librfp.a ../lib/.libs/libfrr.so -lcap -ldl -lm -lcrypt -ljson-c -lrt -pthread -Wl,-rpath -Wl,/home/marcel/src/haw/frr-1/lib/.libs -Wl,-rpath -Wl,/usr/local/lib)" + +# This environment variable determines our operation mode. +if test "$libtool_install_magic" = "%%%MAGIC variable%%%"; then + # install mode needs the following variables: + generated_by_libtool_version='2.4.6.40-6ca5-dirty' + notinst_deplibs=' ../lib/libfrr.la' +else + # When we are sourced in execute mode, $file and $ECHO are already set. + if test "$libtool_execute_magic" != "%%%MAGIC variable%%%"; then + file="$0" + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +$1 +_LTECHO_EOF' +} + ECHO="printf %s\\n" + fi + +# Very basic option parsing. These options are (a) specific to +# the libtool wrapper, (b) are identical between the wrapper +# /script/ and the wrapper /executable/ that is used only on +# windows platforms, and (c) all begin with the string --lt- +# (application programs are unlikely to have options that match +# this pattern). +# +# There are only two supported options: --lt-debug and +# --lt-dump-script. There is, deliberately, no --lt-help. +# +# The first argument to this parsing function should be the +# script's ../libtool value, followed by no. +lt_option_debug= +func_parse_lt_options () +{ + lt_script_arg0=$0 + shift + for lt_opt + do + case "$lt_opt" in + --lt-debug) lt_option_debug=1 ;; + --lt-dump-script) + lt_dump_D=`$ECHO "X$lt_script_arg0" | sed -e 's/^X//' -e 's%/[^/]*$%%'` + test "X$lt_dump_D" = "X$lt_script_arg0" && lt_dump_D=. + lt_dump_F=`$ECHO "X$lt_script_arg0" | sed -e 's/^X//' -e 's%^.*/%%'` + cat "$lt_dump_D/$lt_dump_F" + exit 0 + ;; + --lt-*) + $ECHO "Unrecognized --lt- option: '$lt_opt'" 1>&2 + exit 1 + ;; + esac + done + + # Print the debug banner immediately: + if test -n "$lt_option_debug"; then + echo "test_bgp_table:bgpd/test_bgp_table:$LINENO: libtool wrapper (GNU libtool) 2.4.6.40-6ca5-dirty" 1>&2 + fi +} + +# Used when --lt-debug. Prints its arguments to stdout +# (redirection is the responsibility of the caller) +func_lt_dump_args () +{ + lt_dump_args_N=1; + for lt_arg + do + $ECHO "test_bgp_table:bgpd/test_bgp_table:$LINENO: newargv[$lt_dump_args_N]: $lt_arg" + lt_dump_args_N=`expr $lt_dump_args_N + 1` + done +} + +# Core function for launching the target application +func_exec_program_core () +{ + + if test -n "$lt_option_debug"; then + $ECHO "test_bgp_table:bgpd/test_bgp_table:$LINENO: newargv[0]: $progdir/$program" 1>&2 + func_lt_dump_args ${1+"$@"} 1>&2 + fi + exec "$progdir/$program" ${1+"$@"} + + $ECHO "$0: cannot exec $program $*" 1>&2 + exit 1 +} + +# A function to encapsulate launching the target application +# Strips options in the --lt-* namespace from $@ and +# launches target application with the remaining arguments. +func_exec_program () +{ + case " $* " in + *\ --lt-*) + for lt_wr_arg + do + case $lt_wr_arg in + --lt-*) ;; + *) set x "$@" "$lt_wr_arg"; shift;; + esac + shift + done ;; + esac + func_exec_program_core ${1+"$@"} +} + + # Parse options + func_parse_lt_options "$0" ${1+"$@"} + + # Find the directory that this script lives in. + thisdir=`$ECHO "$file" | sed 's%/[^/]*$%%'` + test "x$thisdir" = "x$file" && thisdir=. + + # Follow symbolic links until we get to the real thisdir. + file=`ls -ld "$file" | sed -n 's/.*-> //p'` + while test -n "$file"; do + destdir=`$ECHO "$file" | sed 's%/[^/]*$%%'` + + # If there was a directory component, then change thisdir. + if test "x$destdir" != "x$file"; then + case "$destdir" in + [\\/]* | [A-Za-z]:[\\/]*) thisdir="$destdir" ;; + *) thisdir="$thisdir/$destdir" ;; + esac + fi + + file=`$ECHO "$file" | sed 's%^.*/%%'` + file=`ls -ld "$thisdir/$file" | sed -n 's/.*-> //p'` + done + + # Usually 'no', except on cygwin/mingw when embedded into + # the cwrapper. + WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=no + if test "$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR" = "yes"; then + # special case for '.' + if test "$thisdir" = "."; then + thisdir=`pwd` + fi + # remove .libs from thisdir + case "$thisdir" in + *[\\/].libs ) thisdir=`$ECHO "$thisdir" | sed 's%[\\/][^\\/]*$%%'` ;; + .libs ) thisdir=. ;; + esac + fi + + # Try to get the absolute directory name. + absdir=`cd "$thisdir" && pwd` + test -n "$absdir" && thisdir="$absdir" + + program=lt-'test_bgp_table' + progdir="$thisdir/.libs" + + if test ! -f "$progdir/$program" || + { file=`ls -1dt "$progdir/$program" "$progdir/../$program" 2>/dev/null | sed 1q`; \ + test "X$file" != "X$progdir/$program"; }; then + + file="$$-$program" + + if test ! -d "$progdir"; then + mkdir "$progdir" + else + rm -f "$progdir/$file" + fi + + # relink executable if necessary + if test -n "$relink_command"; then + if relink_command_output=`eval $relink_command 2>&1`; then : + else + $ECHO "$relink_command_output" >&2 + rm -f "$progdir/$file" + exit 1 + fi + fi + + mv -f "$progdir/$file" "$progdir/$program" 2>/dev/null || + { rm -f "$progdir/$program"; + mv -f "$progdir/$file" "$progdir/$program"; } + rm -f "$progdir/$file" + fi + + if test -f "$progdir/$program"; then + if test "$libtool_execute_magic" != "%%%MAGIC variable%%%"; then + # Run the actual program with our arguments. + func_exec_program ${1+"$@"} + fi + else + # The program doesn't exist. + $ECHO "$0: error: '$progdir/$program' does not exist" 1>&2 + $ECHO "This script is just a wrapper for $program." 1>&2 + $ECHO "See the libtool documentation for more information." 1>&2 + exit 1 + fi +fi diff --git a/tests/bgpd/test_bgp_table.c b/tests/bgpd/test_bgp_table.c new file mode 100644 index 0000000000..01ce7480d7 --- /dev/null +++ b/tests/bgpd/test_bgp_table.c @@ -0,0 +1,192 @@ +/* + * BGP Routing table range lookup test + * Copyright (C) 2012 OSR. + * Copyright (C) 2018 Marcel Röthke (marcel.roethke@haw-hamburg.de), for HAW + * Hamburg + * + * This file is part of FRRouting + * + * 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 + +#include "prefix.h" +#include "table.h" +#include "bgpd/bgp_table.h" +#include "linklist.h" + +/* + * test_node_t + * + * Information that is kept for each node in the radix tree. + */ +struct test_node_t { + + /* + * Human readable representation of the string. Allocated using + * malloc()/dup(). + */ + char *prefix_str; +}; + +/* + * add_node + * + * Add the given prefix (passed in as a string) to the given table. + */ +static void add_node(struct bgp_table *table, const char *prefix_str) +{ + struct prefix_ipv4 p; + struct test_node_t *node; + struct bgp_node *rn; + + assert(prefix_str); + + if (str2prefix_ipv4(prefix_str, &p) <= 0) + assert(0); + + rn = bgp_node_get(table, (struct prefix *)&p); + if (rn->info) { + assert(0); + return; + } + + node = malloc(sizeof(struct test_node_t)); + assert(node); + node->prefix_str = strdup(prefix_str); + assert(node->prefix_str); + rn->info = node; +} + +static void print_range_result(struct list *list) +{ + + struct listnode *listnode; + struct bgp_node *bnode; + + for (ALL_LIST_ELEMENTS_RO(list, listnode, bnode)) { + char buf[PREFIX2STR_BUFFER]; + + prefix2str(&bnode->p, buf, PREFIX2STR_BUFFER); + printf("%s\n", buf); + } +} + +static void check_lookup_result(struct list *list, va_list arglist) +{ + char *prefix_str; + unsigned int prefix_count = 0; + + printf("Searching results\n"); + while ((prefix_str = va_arg(arglist, char *))) { + struct listnode *listnode; + struct bgp_node *bnode; + struct prefix p; + bool found = false; + + prefix_count++; + printf("Searching for %s\n", prefix_str); + + if (str2prefix(prefix_str, &p) <= 0) + assert(0); + + for (ALL_LIST_ELEMENTS_RO(list, listnode, bnode)) { + if (prefix_same(&bnode->p, &p)) + found = true; + } + + assert(found); + } + + printf("Checking for unexpected result items\n"); + printf("Expecting %d found %d\n", prefix_count, listcount(list)); + assert(prefix_count == listcount(list)); +} + +static void do_test(struct bgp_table *table, const char *prefix, uint8_t maxlen, + ...) +{ + va_list arglist; + struct list *list = list_new(); + struct prefix p; + + list->del = (void (*)(void *))bgp_unlock_node; + + va_start(arglist, maxlen); + printf("\nDoing lookup for %s-%d\n", prefix, maxlen); + if (str2prefix(prefix, &p) <= 0) + assert(0); + bgp_table_range_lookup(table, &p, maxlen, list); + print_range_result(list); + + check_lookup_result(list, arglist); + + list_delete_and_null(&list); + + va_end(arglist); + + printf("Checks successfull\n"); +} + +/* + * test_range_lookup + */ +static void test_range_lookup(void) +{ + struct bgp_table *table = bgp_table_init(NULL, AFI_IP, SAFI_UNICAST); + + printf("Testing bgp_table_range_lookup\n"); + + printf("Setup bgp_table"); + const char *prefixes[] = {"1.16.0.0/16", "1.16.128.0/18", + "1.16.192.0/18", "1.16.64.0/19", + "1.16.160.0/19", "1.16.32.0/20", + "1.16.32.0/21", "16.0.0.0/16"}; + + int num_prefixes = sizeof(prefixes) / sizeof(prefixes[0]); + + for (int i = 0; i < num_prefixes; i++) + add_node(table, prefixes[i]); + + do_test(table, "1.16.0.0/17", 20, "1.16.64.0/19", "1.16.32.0/20", NULL); + do_test(table, "1.16.128.0/17", 20, "1.16.128.0/18", "1.16.192.0/18", + "1.16.160.0/19", NULL); + + do_test(table, "1.16.128.0/17", 20, "1.16.128.0/18", "1.16.192.0/18", + "1.16.160.0/19", NULL); + + do_test(table, "1.16.0.0/16", 18, "1.16.0.0/16", "1.16.128.0/18", + "1.16.192.0/18", NULL); + + do_test(table, "1.16.0.0/16", 21, "1.16.0.0/16", "1.16.128.0/18", + "1.16.192.0/18", "1.16.64.0/19", "1.16.160.0/19", + "1.16.32.0/20", "1.16.32.0/21", NULL); + + do_test(table, "1.17.0.0/16", 20, NULL); + + do_test(table, "128.0.0.0/8", 16, NULL); + + do_test(table, "16.0.0.0/8", 16, "16.0.0.0/16", NULL); + + do_test(table, "0.0.0.0/3", 21, "1.16.0.0/16", "1.16.128.0/18", + "1.16.192.0/18", "1.16.64.0/19", "1.16.160.0/19", + "1.16.32.0/20", "1.16.32.0/21", "16.0.0.0/16", NULL); +} + +int main(void) +{ + test_range_lookup(); +} diff --git a/tests/bgpd/test_bgp_table.py b/tests/bgpd/test_bgp_table.py new file mode 100644 index 0000000000..4423530fe0 --- /dev/null +++ b/tests/bgpd/test_bgp_table.py @@ -0,0 +1,7 @@ +import frrtest + +class TestTable(frrtest.TestMultiOut): + program = './test_bgp_table' + +for i in range(6): + TestTable.onesimple('Checks successfull')