]> git.proxmox.com Git - mirror_frr.git/commitdiff
bgpd: add test for bgp_table_range_lookup
authorMarcel Röthke <marcel.roethke@haw-hamburg.de>
Fri, 15 Jun 2018 11:28:06 +0000 (13:28 +0200)
committerMarcel Röthke <marcel.roethke@haw-hamburg.de>
Thu, 5 Jul 2018 14:06:37 +0000 (16:06 +0200)
Signed-off-by: Marcel Röthke <marcel.roethke@haw-hamburg.de>
tests/Makefile.am
tests/bgpd/test_bgp_table [new file with mode: 0755]
tests/bgpd/test_bgp_table.c [new file with mode: 0644]
tests/bgpd/test_bgp_table.py [new file with mode: 0644]

index 32d2db768a0fa8e19aa6a8e3d3a3b5918e345672..a7dec67348218df46fecb8927998c576fe371187 100644 (file)
@@ -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 (executable)
index 0000000..05a7e89
--- /dev/null
@@ -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 (file)
index 0000000..01ce748
--- /dev/null
@@ -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 <zebra.h>
+
+#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 (file)
index 0000000..4423530
--- /dev/null
@@ -0,0 +1,7 @@
+import frrtest
+
+class TestTable(frrtest.TestMultiOut):
+    program = './test_bgp_table'
+
+for i in range(6):
+    TestTable.onesimple('Checks successfull')