From 457eb9af72e6e7aa85c26b65ba4d053f9ecbffac Mon Sep 17 00:00:00 2001 From: Paul Jakma Date: Thu, 27 Jul 2006 19:59:58 +0000 Subject: [zebra] Add test rig code, for testing the zebra RIB 2006-07-27 Paul Jakma * {ioctl,kernel}_null.c: Dummy/Null kernel method implementations, useful for testing zebra code that calls such methods. * {redistribute,misc}_null.c: Dummy/Null methods, as above. But for zclient, and for various misc functions. * test_main.c: Test harness for zebra, currently just to test the RIB. * Makefile.am: Build testzebra using above. * zebra_rib.c: Add a global for the workqueue hold time, useful for testing. --- zebra/ChangeLog | 12 ++ zebra/Makefile.am | 8 ++ zebra/ioctl_null.c | 34 +++++ zebra/kernel_null.c | 25 ++++ zebra/misc_null.c | 4 + zebra/redistribute_null.c | 26 ++++ zebra/test_main.c | 337 ++++++++++++++++++++++++++++++++++++++++++++++ zebra/zebra_rib.c | 7 + 8 files changed, 453 insertions(+) create mode 100644 zebra/ioctl_null.c create mode 100644 zebra/kernel_null.c create mode 100644 zebra/misc_null.c create mode 100644 zebra/redistribute_null.c create mode 100644 zebra/test_main.c diff --git a/zebra/ChangeLog b/zebra/ChangeLog index 36e717d9..2e9328da 100644 --- a/zebra/ChangeLog +++ b/zebra/ChangeLog @@ -1,3 +1,15 @@ +2006-07-27 Paul Jakma + + * {ioctl,kernel}_null.c: Dummy/Null kernel method implementations, + useful for testing zebra code that calls such methods. + * {redistribute,misc}_null.c: Dummy/Null methods, as above. But + for zclient, and for various misc functions. + * test_main.c: Test harness for zebra, currently just to test the + RIB. + * Makefile.am: Build testzebra using above. + * zebra_rib.c: Add a global for the workqueue hold time, useful + for testing. + 2006-07-27 Rumen Svobodnikov * connected.c: (connected_up_ipv4) interface connected routes always diff --git a/zebra/Makefile.am b/zebra/Makefile.am index 751f606f..7527562a 100644 --- a/zebra/Makefile.am +++ b/zebra/Makefile.am @@ -21,17 +21,25 @@ otherobj = $(ioctl_method) $(ipforward) $(if_method) $(if_proc) \ sbin_PROGRAMS = zebra +noinst_PROGRAMS = testzebra + zebra_SOURCES = \ zserv.c main.c interface.c connected.c zebra_rib.c \ redistribute.c debug.c rtadv.c zebra_snmp.c zebra_vty.c \ irdp_main.c irdp_interface.c irdp_packet.c router-id.c +testzebra_SOURCES = test_main.c zebra_rib.c interface.c connected.c debug.c \ + zebra_vty.c \ + kernel_null.c redistribute_null.c ioctl_null.c misc_null.c + noinst_HEADERS = \ connected.h ioctl.h rib.h rt.h zserv.h redistribute.h debug.h rtadv.h \ interface.h ipforward.h irdp.h router-id.h kernel_socket.h zebra_LDADD = $(otherobj) $(LIBCAP) $(LIB_IPV6) ../lib/libzebra.la +testzebra_LDADD = $(LIBCAP) $(LIB_IPV6) ../lib/libzebra.la + zebra_DEPENDENCIES = $(otherobj) EXTRA_DIST = if_ioctl.c if_ioctl_solaris.c if_netlink.c if_proc.c \ diff --git a/zebra/ioctl_null.c b/zebra/ioctl_null.c new file mode 100644 index 00000000..d1f3db08 --- /dev/null +++ b/zebra/ioctl_null.c @@ -0,0 +1,34 @@ +#include + +#include "zebra/rib.h" +#include "zebra/rt.h" +#include "zebra/ioctl.h" + +void ifreq_set_name (struct ifreq *a, struct interface *b) { return; } + +int if_set_prefix (struct interface *a, struct connected *b) { return 0; } +#pragma weak if_unset_prefix = if_set_prefix +#pragma weak if_prefix_add_ipv6 = if_set_prefix +#pragma weak if_prefix_delete_ipv6 = if_set_prefix + +int if_ioctl (u_long a, caddr_t b) { return 0; } + +int if_set_flags (struct interface *a, uint64_t b) { return 0; } +#pragma weak if_unset_flags = if_set_flags + +void if_get_flags (struct interface *a) { return; } +#pragma weak if_get_metric = if_get_flags +#pragma weak if_get_mtu = if_get_flags + +#ifdef SOLARIS_IPV6 +#pragma weak if_ioctl_ipv6 = if_ioctl +struct connected *if_lookup_linklocal(struct interface *a) { return 0; } + +#define AF_IOCTL(af, request, buffer) \ + ((af) == AF_INET? if_ioctl(request, buffer) : \ + if_ioctl_ipv6(request, buffer)) +#else /* SOLARIS_IPV6 */ + +#define AF_IOCTL(af, request, buffer) if_ioctl(request, buffer) + +#endif /* SOLARIS_IPV6 */ diff --git a/zebra/kernel_null.c b/zebra/kernel_null.c new file mode 100644 index 00000000..a84f4371 --- /dev/null +++ b/zebra/kernel_null.c @@ -0,0 +1,25 @@ +/* NULL kernel methods for testing. */ + +#include + +#include "zebra/zserv.h" +#include "zebra/rt.h" +#include "zebra/redistribute.h" + +int kernel_add_ipv4 (struct prefix *a, struct rib *b) { return 0; } +#pragma weak kernel_delete_ipv4 = kernel_add_ipv4 +int kernel_add_ipv6 (struct prefix *a, struct rib *b) { return 0; } +#pragma weak kernel_delete_ipv6 = kernel_add_ipv6 +int kernel_delete_ipv6_old (struct prefix_ipv6 *dest, struct in6_addr *gate, + unsigned int index, int flags, int table) +{ return 0; } + +int kernel_add_route (struct prefix_ipv4 *a, struct in_addr *b, int c, int d) +{ return 0; } + +int kernel_address_add_ipv4 (struct interface *a, struct connected *b) +{ return 0; } +#pragma weak kernel_address_delete_ipv4 = kernel_address_add_ipv4 + +void kernel_init (void) { return; } +#pragma weak route_read = kernel_init diff --git a/zebra/misc_null.c b/zebra/misc_null.c new file mode 100644 index 00000000..8063c90d --- /dev/null +++ b/zebra/misc_null.c @@ -0,0 +1,4 @@ + +void ifstat_update_proc (void) { return; } +#pragma weak rtadv_config_write = ifstat_update_proc +#pragma weak irdp_config_write = ifstat_update_proc diff --git a/zebra/redistribute_null.c b/zebra/redistribute_null.c new file mode 100644 index 00000000..e57a73b9 --- /dev/null +++ b/zebra/redistribute_null.c @@ -0,0 +1,26 @@ +#include +#include "zebra/rib.h" +#include "zebra/zserv.h" + +#include "zebra/redistribute.h" + +void zebra_redistribute_add (int a, struct zserv *b, int c) +{ return; } +#pragma weak zebra_redistribute_delete = zebra_redistribute_add +#pragma weak zebra_redistribute_default_add = zebra_redistribute_add +#pragma weak zebra_redistribute_default_delete = zebra_redistribute_add + +void redistribute_add (struct prefix *a, struct rib *b) +{ return; } +#pragma weak redistribute_delete = redistribute_add + +void zebra_interface_up_update (struct interface *a) +{ return; } +#pragma weak zebra_interface_down_update = zebra_interface_up_update +#pragma weak zebra_interface_add_update = zebra_interface_up_update +#pragma weak zebra_interface_delete_update = zebra_interface_up_update + +void zebra_interface_address_add_update (struct interface *a, + struct connected *b) +{ return; } +#pragma weak zebra_interface_address_delete_update = zebra_interface_address_add_update diff --git a/zebra/test_main.c b/zebra/test_main.c new file mode 100644 index 00000000..59cec462 --- /dev/null +++ b/zebra/test_main.c @@ -0,0 +1,337 @@ +/* main routine. + * Copyright (C) 1997, 98 Kunihiro Ishiguro + * + * GNU Zebra 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. + * + * GNU Zebra 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 GNU Zebra; see the file COPYING. If not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ + +#include + +#include +#include "getopt.h" +#include "command.h" +#include "thread.h" +#include "filter.h" +#include "memory.h" +#include "prefix.h" +#include "log.h" +#include "privs.h" +#include "sigevent.h" + +#include "zebra/rib.h" +#include "zebra/zserv.h" +#include "zebra/debug.h" +#include "zebra/router-id.h" +#include "zebra/interface.h" + +/* Zebra instance */ +struct zebra_t zebrad = +{ + .rtm_table_default = 0, +}; + +/* process id. */ +pid_t old_pid; +pid_t pid; + +/* zebra_rib's workqueue hold time. Private export for use by test code only */ +extern int rib_process_hold_time; + +/* Pacify zclient.o in libzebra, which expects this variable. */ +struct thread_master *master; + +/* Command line options. */ +struct option longopts[] = +{ + { "batch", no_argument, NULL, 'b'}, + { "daemon", no_argument, NULL, 'd'}, + { "log_mode", no_argument, NULL, 'l'}, + { "config_file", required_argument, NULL, 'f'}, + { "help", no_argument, NULL, 'h'}, + { "vty_addr", required_argument, NULL, 'A'}, + { "vty_port", required_argument, NULL, 'P'}, + { "version", no_argument, NULL, 'v'}, + { "rib_hold", required_argument, NULL, 'r'}, + { 0 } +}; + +zebra_capabilities_t _caps_p [] = +{ + ZCAP_NET_ADMIN, + ZCAP_SYS_ADMIN, + ZCAP_NET_RAW, +}; + +/* Default configuration file path. */ +char config_default[] = SYSCONFDIR DEFAULT_CONFIG_FILE; + +/* Process ID saved for use by init system */ +const char *pid_file = PATH_ZEBRA_PID; + +/* Help information display. */ +static void +usage (char *progname, int status) +{ + if (status != 0) + fprintf (stderr, "Try `%s --help' for more information.\n", progname); + else + { + printf ("Usage : %s [OPTION...]\n\n"\ + "Daemon which manages kernel routing table management and "\ + "redistribution between different routing protocols.\n\n"\ + "-b, --batch Runs in batch mode\n"\ + "-d, --daemon Runs in daemon mode\n"\ + "-f, --config_file Set configuration file name\n"\ + "-l, --log_mode Set verbose log mode flag\n"\ + "-A, --vty_addr Set vty's bind address\n"\ + "-P, --vty_port Set vty's port number\n"\ + "-r, --rib_hold Set rib-queue hold time\n"\ + "-v, --version Print program version\n"\ + "-h, --help Display this help and exit\n"\ + "\n"\ + "Report bugs to %s\n", progname, ZEBRA_BUG_ADDRESS); + } + + exit (status); +} + +static unsigned int test_ifindex = 0; + +/* testrib commands */ +DEFUN (test_interface_state, + test_interface_state_cmd, + "state (up|down)", + "configure interface\n" + "up\n" + "down\n") +{ + struct interface *ifp; + if (argc < 1) + return CMD_WARNING; + + ifp = vty->index; + if (ifp->ifindex == IFINDEX_INTERNAL) + { + ifp->ifindex = ++test_ifindex; + ifp->mtu = 1500; + ifp->flags = IFF_BROADCAST|IFF_MULTICAST; + } + + switch (argv[0][0]) + { + case 'u': + SET_FLAG (ifp->flags, IFF_UP); + if_add_update (ifp); + printf ("up\n"); + break; + case 'd': + UNSET_FLAG (ifp->flags, IFF_UP); + if_delete_update (ifp); + printf ("down\n"); + break; + default: + return CMD_WARNING; + } + return CMD_SUCCESS; +} + +static void +test_cmd_init (void) +{ + install_element (INTERFACE_NODE, &test_interface_state_cmd); +} + +/* SIGHUP handler. */ +static void +sighup (void) +{ + zlog_info ("SIGHUP received"); + + /* Reload of config file. */ + ; +} + +/* SIGINT handler. */ +static void +sigint (void) +{ + zlog_notice ("Terminating on signal"); + + exit (0); +} + +/* SIGUSR1 handler. */ +static void +sigusr1 (void) +{ + zlog_rotate (NULL); +} + +struct quagga_signal_t zebra_signals[] = +{ + { + .signal = SIGHUP, + .handler = &sighup, + }, + { + .signal = SIGUSR1, + .handler = &sigusr1, + }, + { + .signal = SIGINT, + .handler = &sigint, + }, + { + .signal = SIGTERM, + .handler = &sigint, + }, +}; + +/* Main startup routine. */ +int +main (int argc, char **argv) +{ + char *p; + char *vty_addr = NULL; + int vty_port = 0; + int batch_mode = 0; + int daemon_mode = 0; + char *config_file = NULL; + char *progname; + struct thread thread; + + /* Set umask before anything for security */ + umask (0027); + + /* preserve my name */ + progname = ((p = strrchr (argv[0], '/')) ? ++p : argv[0]); + + zlog_default = openzlog (progname, ZLOG_ZEBRA, + LOG_CONS|LOG_NDELAY|LOG_PID, LOG_DAEMON); + + while (1) + { + int opt; + + opt = getopt_long (argc, argv, "bdlf:hA:P:r:v", longopts, 0); + + if (opt == EOF) + break; + + switch (opt) + { + case 0: + break; + case 'b': + batch_mode = 1; + case 'd': + daemon_mode = 1; + break; + case 'l': + /* log_mode = 1; */ + break; + case 'f': + config_file = optarg; + break; + case 'A': + vty_addr = optarg; + break; + case 'P': + /* Deal with atoi() returning 0 on failure, and zebra not + listening on zebra port... */ + if (strcmp(optarg, "0") == 0) + { + vty_port = 0; + break; + } + vty_port = atoi (optarg); + break; + case 'r': + rib_process_hold_time = atoi(optarg); + break; + case 'v': + print_version (progname); + exit (0); + break; + case 'h': + usage (progname, 0); + break; + default: + usage (progname, 1); + break; + } + } + + /* port and conf file mandatory */ + if (!vty_port || !config_file) + usage (progname, 1); + + /* Make master thread emulator. */ + zebrad.master = thread_master_create (); + + /* Vty related initialize. */ + signal_init (zebrad.master, Q_SIGC(zebra_signals), zebra_signals); + cmd_init (1); + vty_init (zebrad.master); + memory_init (); + if_init(); + zebra_debug_init (); + zebra_if_init (); + test_cmd_init (); + + /* Zebra related initialize. */ + rib_init (); + access_list_init (); + + /* Make kernel routing socket. */ + kernel_init (); + route_read (); + zebra_vty_init(); + + /* Sort VTY commands. */ + sort_node (); + + /* Configuration file read*/ + vty_read_config (config_file, config_default); + + /* Clean up rib. */ + rib_weed_tables (); + + /* Exit when zebra is working in batch mode. */ + if (batch_mode) + exit (0); + + /* Needed for BSD routing socket. */ + old_pid = getpid (); + + /* Daemonize. */ + if (daemon_mode) + daemon (0, 0); + + /* Needed for BSD routing socket. */ + pid = getpid (); + + /* Make vty server socket. */ + vty_serv_sock (vty_addr, vty_port, "/tmp/test_zebra"); + + /* Print banner. */ + zlog_notice ("Zebra %s starting: vty@%d", QUAGGA_VERSION, vty_port); + + while (thread_fetch (zebrad.master, &thread)) + thread_call (&thread); + + /* Not reached... */ + return 0; +} diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index 665e5673..7373c6d8 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -42,6 +42,12 @@ /* Default rtm_table for all clients */ extern struct zebra_t zebrad; +/* Hold time for RIB process, should be very minimal. + * it is useful to able to set it otherwise for testing, hence exported + * as global here for test-rig code. + */ +int rib_process_hold_time = 10; + /* Each route type's string and default distance value. */ struct { @@ -1120,6 +1126,7 @@ rib_queue_init (struct zebra_t *zebra) zebra->ribq->spec.del_item_data = &rib_queue_qnode_del; /* XXX: TODO: These should be runtime configurable via vty */ zebra->ribq->spec.max_retries = 3; + zebra->ribq->spec.hold = rib_process_hold_time; return; } -- cgit v1.2.1