From 5b848048d7077f110123d226efbd9b4bcbb290cd Mon Sep 17 00:00:00 2001 From: Martin Winter Date: Sat, 11 Mar 2017 12:48:55 +0700 Subject: [PATCH 01/61] snapcraft: Replace temporary logo with official FRR logo Signed-off-by: Martin Winter --- snapcraft/setup/gui/icon.png | Bin 21830 -> 35316 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/snapcraft/setup/gui/icon.png b/snapcraft/setup/gui/icon.png index e8f68e6ddea002f7a3f87ae71742444603640fb4..3ab3f8fc16745fbef3f5510059aebd3c11293b0c 100644 GIT binary patch delta 34459 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

3OpcLGmytGumflB;WQMVL1zNg%Og6CW&Nhe-~ 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 D8d3Un delta 20866 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 From 9cbae545f06d8cd8914c16d7d1f599c6004cc0c3 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 15 Mar 2017 09:25:43 -0400 Subject: [PATCH 02/61] zebra: Fix protobuf build on stable/2.0 When compiling w/ --enable-protobuf on stable/2.0 we were attempting to dereference the zvrf->vrf_id which got moved to zvrf->vrf->vrf_id. Signed-off-by: Donald Sharp --- zebra/zebra_fpm_protobuf.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zebra/zebra_fpm_protobuf.c b/zebra/zebra_fpm_protobuf.c index 702c355f1a..cd88af134d 100644 --- a/zebra/zebra_fpm_protobuf.c +++ b/zebra/zebra_fpm_protobuf.c @@ -53,7 +53,7 @@ create_delete_route_message (qpb_allocator_t *allocator, rib_dest_t *dest, } fpm__delete_route__init(msg); - msg->vrf_id = rib_dest_vrf(dest)->vrf_id; + msg->vrf_id = rib_dest_vrf(dest)->vrf->vrf_id; qpb_address_family_set(&msg->address_family, rib_dest_af(dest)); @@ -159,7 +159,7 @@ create_add_route_message (qpb_allocator_t *allocator, rib_dest_t *dest, fpm__add_route__init(msg); - msg->vrf_id = rib_dest_vrf(dest)->vrf_id; + msg->vrf_id = rib_dest_vrf(dest)->vrf->vrf_id; qpb_address_family_set (&msg->address_family, rib_dest_af(dest)); From 358336ef366377b4a96c59efe2d6c14e881fa18c Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 15 Mar 2017 09:37:03 -0400 Subject: [PATCH 03/61] zebra: zebra_fpm_dt.c does not always need protobuf When compiling zebra_fpm_dt.c only pull in protobuf headers if we've turned it on. Signed-off-by: Donald Sharp --- zebra/zebra_fpm_dt.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/zebra/zebra_fpm_dt.c b/zebra/zebra_fpm_dt.c index 715e250a66..7b4e1b90dc 100644 --- a/zebra/zebra_fpm_dt.c +++ b/zebra/zebra_fpm_dt.c @@ -50,8 +50,10 @@ #include "qpb/qpb_allocator.h" #include "qpb/linear_allocator.h" +#ifdef HAVE_PROTOBUF #include "qpb/qpb.h" #include "fpm/fpm.pb-c.h" +#endif /* * Externs. From d1c2443dc7990f57c8e777bd8da8f259c7414554 Mon Sep 17 00:00:00 2001 From: Martin Winter Date: Fri, 17 Mar 2017 20:43:27 -0700 Subject: [PATCH 04/61] snapcraft: Add missing snapcraft files from dist (make dist) archive Signed-off-by: Martin Winter --- snapcraft/Makefile.am | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/snapcraft/Makefile.am b/snapcraft/Makefile.am index 15813be72f..d32e18d071 100644 --- a/snapcraft/Makefile.am +++ b/snapcraft/Makefile.am @@ -1,11 +1,5 @@ EXTRA_DIST = snapcraft.yaml \ - scripts/Makefile scripts/zebra-service scripts/bgpd-service \ - scripts/isisd-service scripts/ripd-service scripts/ripngd-service \ - scripts/ospf6d-service scripts/ospfd-service \ - scripts/isisd-service scripts/pimd-service \ - scripts/ldpd-service \ - defaults/bgpd.conf.default defaults/isisd.conf.default \ - defaults/ospf6d.conf.default defaults/ospfd.conf.default \ - defaults/pimd.conf.default defaults/zebra.conf.default \ - defaults/ripd.conf.default defaults/ripngd.conf.default \ - defaults/ldpd.conf.default defaults/vtysh.conf.default + README.* \ + scripts/Makefile scripts/*-service \ + defaults/*.conf.default \ + helpers setup From 567dd75c077b36f0001d771bb287ae55c9312363 Mon Sep 17 00:00:00 2001 From: Martin Winter Date: Fri, 17 Mar 2017 20:50:09 -0700 Subject: [PATCH 05/61] snapcraft: Change setup/ to snap/ directory based on new snap format DEPRECATED: Assets in 'setup/gui' should now be placed in 'snap/gui'. See http://snapcraft.io/docs/deprecation-notices/dn3 for more information. Signed-off-by: Martin Winter --- snapcraft/Makefile.am | 2 +- snapcraft/{setup => snap}/gui/icon.png | Bin 2 files changed, 1 insertion(+), 1 deletion(-) rename snapcraft/{setup => snap}/gui/icon.png (100%) diff --git a/snapcraft/Makefile.am b/snapcraft/Makefile.am index d32e18d071..8cc4e0b4c6 100644 --- a/snapcraft/Makefile.am +++ b/snapcraft/Makefile.am @@ -2,4 +2,4 @@ EXTRA_DIST = snapcraft.yaml \ README.* \ scripts/Makefile scripts/*-service \ defaults/*.conf.default \ - helpers setup + helpers snap diff --git a/snapcraft/setup/gui/icon.png b/snapcraft/snap/gui/icon.png similarity index 100% rename from snapcraft/setup/gui/icon.png rename to snapcraft/snap/gui/icon.png From b74f1be8ff06a21a3d0fce6e078e68f69700cb55 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Mon, 13 Feb 2017 00:35:43 +0100 Subject: [PATCH 06/61] zebra: fpm: fix protobuf compile Signed-off-by: David Lamparter --- zebra/zebra_fpm_protobuf.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zebra/zebra_fpm_protobuf.c b/zebra/zebra_fpm_protobuf.c index fba57c68f5..11869d8a2b 100644 --- a/zebra/zebra_fpm_protobuf.c +++ b/zebra/zebra_fpm_protobuf.c @@ -53,7 +53,7 @@ create_delete_route_message (qpb_allocator_t *allocator, rib_dest_t *dest, } fpm__delete_route__init(msg); - msg->vrf_id = rib_dest_vrf(dest)->vrf_id; + msg->vrf_id = zvrf_id(rib_dest_vrf(dest)); qpb_address_family_set(&msg->address_family, rib_dest_af(dest)); @@ -159,7 +159,7 @@ create_add_route_message (qpb_allocator_t *allocator, rib_dest_t *dest, fpm__add_route__init(msg); - msg->vrf_id = rib_dest_vrf(dest)->vrf_id; + msg->vrf_id = zvrf_id(rib_dest_vrf(dest)); qpb_address_family_set (&msg->address_family, rib_dest_af(dest)); From d6b1bfbab0b805cd65bb602e38981ce9bbd07407 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Fri, 24 Mar 2017 10:56:35 +0100 Subject: [PATCH 07/61] ripd: fix snmp compile Signed-off-by: David Lamparter --- ripd/rip_snmp.c | 1 + 1 file changed, 1 insertion(+) diff --git a/ripd/rip_snmp.c b/ripd/rip_snmp.c index fede5bed07..36fd9c26ec 100644 --- a/ripd/rip_snmp.c +++ b/ripd/rip_snmp.c @@ -26,6 +26,7 @@ #include #include "if.h" +#include "vrf.h" #include "log.h" #include "prefix.h" #include "command.h" From 4c0a782d477d527fb795640225c5f22767105f32 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Sun, 12 Feb 2017 22:40:11 +0100 Subject: [PATCH 08/61] lib: remove unused add_snmp_pollfds() Signed-off-by: David Lamparter --- lib/thread.c | 22 ---------------------- 1 file changed, 22 deletions(-) diff --git a/lib/thread.c b/lib/thread.c index 6138e79718..e707fc584c 100644 --- a/lib/thread.c +++ b/lib/thread.c @@ -1037,28 +1037,6 @@ thread_process_fds_helper (struct thread_master *m, struct thread *thread, threa #if defined(HAVE_POLL) -#if defined(HAVE_SNMP) -/* add snmp fds to poll set */ -static void -add_snmp_pollfds(struct thread_master *m, fd_set *snmpfds, int fdsetsize) -{ - int i; - m->handler.pfdcountsnmp = m->handler.pfdcount; - /* cycle trough fds and add neccessary fds to poll set */ - for (i=0;ihandler.pfdcountsnmp <= m->handler.pfdsize); - - m->handler.pfds[m->handler.pfdcountsnmp].fd = i; - m->handler.pfds[m->handler.pfdcountsnmp].events = POLLIN; - m->handler.pfdcountsnmp++; - } - } -} -#endif - /* check poll events */ static void check_pollfds(struct thread_master *m, fd_set *readfd, int num) From 30771d65b23e4ef15a8298357b70fc083c699750 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Tue, 31 May 2016 19:25:46 +0200 Subject: [PATCH 09/61] lib: dynamic module loading This adds a "-M" option to each daemon, to load dynamic modules at startup. Modules are by default located in /usr/lib/frr/modules (lib64 if appropriate). Unloading or loading at runtime is not supported at this point to keep things simple. Signed-off-by: David Lamparter --- configure.ac | 20 ++++++ lib/Makefile.am | 5 +- lib/libfrr.c | 32 +++++++++- lib/libfrr.h | 13 +++- lib/module.c | 159 ++++++++++++++++++++++++++++++++++++++++++++++++ lib/module.h | 104 +++++++++++++++++++++++++++++++ 6 files changed, 329 insertions(+), 4 deletions(-) create mode 100644 lib/module.c create mode 100644 lib/module.h diff --git a/configure.ac b/configure.ac index e46e44a8b7..2a8cab34f1 100755 --- a/configure.ac +++ b/configure.ac @@ -55,6 +55,13 @@ dnl XXX add --pkgsrcrcdir to autoconf standard directory list somehow AC_SUBST(pkgsrcdir) AC_SUBST(pkgsrcrcdir) +AC_ARG_WITH([moduledir], [AS_HELP_STRING([--with-moduledir=DIR], [module directory (${libdir}/frr/modules)])], [ + moduledir="$withval" +], [ + moduledir="\${libdir}/frr/modules" +]) +AC_SUBST([moduledir], [$moduledir]) + AC_ARG_ENABLE(tcmalloc, AS_HELP_STRING([--enable-tcmalloc], [Turn on tcmalloc]), [case "${enableval}" in @@ -1347,6 +1354,14 @@ int main(void); AC_DEFINE_UNQUOTED(AS_TR_CPP(SNMP_${SNMP_METHOD}),,SNMP method to interface with snmpd) fi +dnl ------ +dnl dlopen +dnl ------ +AC_SEARCH_LIBS(dlopen, [dl dld], [], [ + AC_MSG_ERROR([unable to find the dlopen()]) +]) + + dnl --------------------------- dnl sockaddr and netinet checks dnl --------------------------- @@ -1646,14 +1661,18 @@ AC_DEFINE_UNQUOTED(VTYSH_BIN_PATH, "$vtysh_bin",path to vtysh binary) CFG_SYSCONF="$sysconfdir" CFG_SBIN="$sbindir" CFG_STATE="$frr_statedir" +CFG_MODULE="$moduledir" for I in 1 2 3 4 5 6 7 8 9 10; do eval CFG_SYSCONF="\"$CFG_SYSCONF\"" eval CFG_SBIN="\"$CFG_SBIN\"" eval CFG_STATE="\"$CFG_STATE\"" + eval CFG_MODULE="\"$CFG_MODULE\"" done AC_SUBST(CFG_SYSCONF) AC_SUBST(CFG_SBIN) AC_SUBST(CFG_STATE) +AC_SUBST(CFG_MODULE) +AC_DEFINE_UNQUOTED(MODULE_PATH, "$CFG_MODULE", path to modules) dnl --------------------------- dnl Check htonl works correctly @@ -1728,6 +1747,7 @@ linker flags : ${LDFLAGS} ${LIBS} ${LIBCAP} ${LIBREADLINE} ${LIBM} state file directory : ${frr_statedir} config file directory : `eval echo \`echo ${sysconfdir}\`` example directory : `eval echo \`echo ${exampledir}\`` +module directory : ${CFG_MODULE} user to run as : ${enable_user} group to run as : ${enable_group} group for vty sockets : ${enable_vty_group} diff --git a/lib/Makefile.am b/lib/Makefile.am index 1a8c7af42b..5731440640 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -31,7 +31,9 @@ libfrr_la_SOURCES = \ spf_backoff.c \ libfrr.c \ strlcpy.c \ - strlcat.c + strlcat.c \ + module.c \ + # end BUILT_SOURCES = route_types.h gitversion.h command_parse.h command_lex.h @@ -54,6 +56,7 @@ pkginclude_HEADERS = \ monotime.h \ spf_backoff.h \ srcdest_table.h \ + module.h \ libfrr.h \ # end diff --git a/lib/libfrr.c b/lib/libfrr.c index b7ce0679c3..5c047040ae 100644 --- a/lib/libfrr.c +++ b/lib/libfrr.c @@ -28,6 +28,7 @@ #include "memory_vty.h" #include "zclient.h" #include "log_int.h" +#include "module.h" const char frr_sysconfdir[] = SYSCONFDIR; const char frr_vtydir[] = DAEMON_VTY_DIR; @@ -64,14 +65,16 @@ static const struct option lo_always[] = { { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, 'v' }, { "daemon", no_argument, NULL, 'd' }, + { "module", no_argument, NULL, 'M' }, { "vty_socket", required_argument, NULL, OPTION_VTYSOCK }, { NULL } }; static const struct optspec os_always = { - "hvdi:", + "hvdM:", " -h, --help Display this help and exit\n" " -v, --version Print program version\n" " -d, --daemon Runs in daemon mode\n" + " -M, --module Load specified module\n" " --vty_socket Override vty socket path\n", lo_always }; @@ -184,12 +187,18 @@ void frr_help_exit(int status) exit(status); } +struct option_chain { + struct option_chain *next; + const char *arg; +}; +static struct option_chain *modules = NULL, **modnext = &modules; static int errors = 0; static int frr_opt(int opt) { static int vty_port_set = 0; static int vty_addr_set = 0; + struct option_chain *oc; char *err; switch (opt) { @@ -203,6 +212,13 @@ static int frr_opt(int opt) case 'd': di->daemon_mode = 1; break; + case 'M': + oc = XMALLOC(MTYPE_TMP, sizeof(*oc)); + oc->arg = optarg; + oc->next = NULL; + *modnext = oc; + modnext = &oc->next; + break; case 'i': if (di->flags & FRR_NO_CFG_PID_DRY) return 1; @@ -298,6 +314,9 @@ int frr_getopt(int argc, char * const argv[], int *longindex) struct thread_master *frr_init(void) { struct thread_master *master; + struct option_chain *oc; + struct frrmod_runtime *module; + char moderr[256]; srandom(time(NULL)); @@ -307,6 +326,17 @@ struct thread_master *frr_init(void) zlog_set_level (ZLOG_DEST_SYSLOG, zlog_default->default_lvl); #endif + frrmod_init(di->module); + while (modules) { + modules = (oc = modules)->next; + module = frrmod_load(oc->arg, moderr, sizeof(moderr)); + if (!module) { + fprintf(stderr, "%s\n", moderr); + exit(1); + } + XFREE(MTYPE_TMP, oc); + } + zprivs_init(di->privs); master = thread_master_create(); diff --git a/lib/libfrr.h b/lib/libfrr.h index d37f406f5b..71225fad38 100644 --- a/lib/libfrr.h +++ b/lib/libfrr.h @@ -26,6 +26,7 @@ #include "thread.h" #include "log.h" #include "getopt.h" +#include "module.h" #define FRR_NO_PRIVSEP (1 << 0) #define FRR_NO_TCPVTY (1 << 1) @@ -40,6 +41,7 @@ struct frr_daemon_info { const char *name; const char *logname; unsigned short instance; + struct frrmod_runtime *module; char *vty_addr; int vty_port; @@ -67,15 +69,22 @@ struct frr_daemon_info { * i.e. "ZEBRA" or "BGP" * * note that this macro is also a latch-on point for other changes (e.g. - * upcoming plugin support) that need to place some per-daemon things. Each + * upcoming module support) that need to place some per-daemon things. Each * daemon should have one of these. */ #define FRR_DAEMON_INFO(execname, constname, ...) \ static struct frr_daemon_info execname ##_di = { \ .name = # execname, \ .logname = # constname, \ + .module = THIS_MODULE, \ __VA_ARGS__ \ - }; + }; \ + FRR_COREMOD_SETUP( \ + .name = # execname, \ + .description = # execname " daemon", \ + .version = FRR_VERSION, \ + ) \ + /* end */ extern void frr_preinit(struct frr_daemon_info *daemon, int argc, char **argv); diff --git a/lib/module.c b/lib/module.c new file mode 100644 index 0000000000..4ebe3c0da2 --- /dev/null +++ b/lib/module.c @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2015-16 David Lamparter, for NetDEF, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include "config.h" + +#include +#include +#include +#include +#include +#include + +#include "module.h" +#include "memory.h" +#include "version.h" + +DEFINE_MTYPE_STATIC(LIB, MODULE_LOADNAME, "Module loading name") +DEFINE_MTYPE_STATIC(LIB, MODULE_LOADARGS, "Module loading arguments") + +static struct frrmod_info frrmod_default_info = { + .name = "libfrr", + .version = FRR_VERSION, + .description = "libfrr core module", +}; +union _frrmod_runtime_u frrmod_default = { + .r.info = &frrmod_default_info, + .r.finished_loading = 1, +}; + +// if defined(HAVE_SYS_WEAK_ALIAS_ATTRIBUTE) +// union _frrmod_runtime_u _frrmod_this_module +// __attribute__((weak, alias("frrmod_default"))); +// elif defined(HAVE_SYS_WEAK_ALIAS_PRAGMA) +#pragma weak _frrmod_this_module = frrmod_default +// else +// error need weak symbol support +// endif + +struct frrmod_runtime *frrmod_list = &frrmod_default.r; +static struct frrmod_runtime **frrmod_last = &frrmod_default.r.next; +static const char *execname = NULL; + +void frrmod_init(struct frrmod_runtime *modinfo) +{ + modinfo->finished_loading = 1; + *frrmod_last = modinfo; + frrmod_last = &modinfo->next; + + execname = modinfo->info->name; +} + +struct frrmod_runtime *frrmod_load(const char *spec, + char *err, size_t err_len) +{ + void *handle = NULL; + char name[PATH_MAX], fullpath[PATH_MAX], *args; + struct frrmod_runtime *rtinfo, **rtinfop; + const struct frrmod_info *info; + + snprintf(name, sizeof(name), "%s", spec); + args = strchr(name, ':'); + if (args) + *args++ = '\0'; + + if (!strchr(name, '/')) { + if (!handle && execname) { + snprintf(fullpath, sizeof(fullpath), "%s/%s_%s.so", + MODULE_PATH, execname, name); + handle = dlopen(fullpath, RTLD_NOW | RTLD_GLOBAL); + } + if (!handle) { + snprintf(fullpath, sizeof(fullpath), "%s/%s.so", + MODULE_PATH, name); + handle = dlopen(fullpath, RTLD_NOW | RTLD_GLOBAL); + } + } + if (!handle) { + snprintf(fullpath, sizeof(fullpath), "%s", name); + handle = dlopen(fullpath, RTLD_NOW | RTLD_GLOBAL); + } + if (!handle) { + if (err) + snprintf(err, err_len, + "loading module \"%s\" failed: %s", + name, dlerror()); + return NULL; + } + + rtinfop = dlsym(handle, "frr_module"); + if (!rtinfop) { + dlclose(handle); + if (err) + snprintf(err, err_len, + "\"%s\" is not a Quagga module: %s", + name, dlerror()); + return NULL; + } + rtinfo = *rtinfop; + rtinfo->load_name = XSTRDUP(MTYPE_MODULE_LOADNAME, name); + rtinfo->dl_handle = handle; + if (args) + rtinfo->load_args = XSTRDUP(MTYPE_MODULE_LOADARGS, args); + info = rtinfo->info; + + if (rtinfo->finished_loading) { + dlclose(handle); + if (err) + snprintf(err, err_len, + "module \"%s\" already loaded", + name); + goto out_fail; + } + + if (info->init && info->init()) { + dlclose(handle); + if (err) + snprintf(err, err_len, + "module \"%s\" initialisation failed", + name); + goto out_fail; + } + + rtinfo->finished_loading = 1; + + *frrmod_last = rtinfo; + frrmod_last = &rtinfo->next; + return rtinfo; + +out_fail: + if (rtinfo->load_args) + XFREE(MTYPE_MODULE_LOADARGS, rtinfo->load_args); + XFREE(MTYPE_MODULE_LOADNAME, rtinfo->load_name); + return NULL; +} + +#if 0 +void frrmod_unload(struct frrmod_runtime *module) +{ +} +#endif diff --git a/lib/module.h b/lib/module.h new file mode 100644 index 0000000000..cb66e60976 --- /dev/null +++ b/lib/module.h @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2015-16 David Lamparter, for NetDEF, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#ifndef _FRR_MODULE_H +#define _FRR_MODULE_H + +#include +#include + +#if !defined(__GNUC__) +# error module code needs GCC visibility extensions +#elif __GNUC__ < 4 +# error module code needs GCC visibility extensions +#else +# define DSO_PUBLIC __attribute__ ((visibility ("default"))) +# define DSO_SELF __attribute__ ((visibility ("protected"))) +# define DSO_LOCAL __attribute__ ((visibility ("hidden"))) +#endif + +struct frrmod_runtime; + +struct frrmod_info { + /* single-line few-word title */ + const char *name; + /* human-readable version number, should not contain spaces */ + const char *version; + /* one-paragraph description */ + const char *description; + + int (*init)(void); +}; + +/* primary entry point structure to be present in loadable module under + * "_frrmod_this_module" dlsym() name + * + * note space for future extensions is reserved below, so other modules + * (e.g. memory management, hooks) can add fields + * + * const members/info are in frrmod_info. + */ +struct frrmod_runtime { + struct frrmod_runtime *next; + + const struct frrmod_info *info; + void *dl_handle; + bool finished_loading; + + char *load_name; + char *load_args; +}; + +/* space-reserving foo */ +struct _frrmod_runtime_size { + struct frrmod_runtime r; + /* this will barf if frrmod_runtime exceeds 1024 bytes ... */ + uint8_t space[1024 - sizeof(struct frrmod_runtime)]; +}; +union _frrmod_runtime_u { + struct frrmod_runtime r; + struct _frrmod_runtime_size s; +}; + +extern union _frrmod_runtime_u _frrmod_this_module; +#define THIS_MODULE (&_frrmod_this_module.r) + +#define FRR_COREMOD_SETUP(...) \ + static const struct frrmod_info _frrmod_info = { __VA_ARGS__ }; \ + DSO_LOCAL union _frrmod_runtime_u _frrmod_this_module = { \ + .r.info = &_frrmod_info, \ + }; +#define FRR_MODULE_SETUP(...) \ + FRR_COREMOD_SETUP(__VA_ARGS__) \ + DSO_SELF struct frrmod_runtime *frr_module = &_frrmod_this_module.r; + +extern struct frrmod_runtime *frrmod_list; + +extern void frrmod_init(struct frrmod_runtime *modinfo); +extern struct frrmod_runtime *frrmod_load(const char *spec, + char *err, size_t err_len); +#if 0 +/* not implemented yet */ +extern void frrmod_unload(struct frrmod_runtime *module); +#endif + +#endif /* _FRR_MODULE_H */ From b249c083d53ef25c54f4347f656daebf61827581 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Sun, 12 Feb 2017 23:23:02 +0100 Subject: [PATCH 10/61] lib: add "show modules" CLI command (for simplicity, this is stuffed in with memory_vty.c) Signed-off-by: David Lamparter --- configure.ac | 42 ++++++++++++++++++++++++-- lib/memory_vty.c | 77 ++++++++++++++++++++++++++++++++++++++---------- 2 files changed, 101 insertions(+), 18 deletions(-) diff --git a/configure.ac b/configure.ac index 2a8cab34f1..b94b8bb16c 100755 --- a/configure.ac +++ b/configure.ac @@ -1354,13 +1354,49 @@ int main(void); AC_DEFINE_UNQUOTED(AS_TR_CPP(SNMP_${SNMP_METHOD}),,SNMP method to interface with snmpd) fi -dnl ------ -dnl dlopen -dnl ------ +dnl --------------- +dnl dlopen & dlinfo +dnl --------------- AC_SEARCH_LIBS(dlopen, [dl dld], [], [ AC_MSG_ERROR([unable to find the dlopen()]) ]) +AC_CHECK_HEADERS([link.h]) + +AC_MSG_CHECKING([for dlinfo(RTLD_DI_ORIGIN)]) +AC_LINK_IFELSE([AC_LANG_PROGRAM([[ +#include +#ifdef HAVE_LINK_H +#include +#endif +#include +]], [[ + char origin[1]; + dlinfo (NULL, RTLD_DI_ORIGIN, &origin); +]])], [ + AC_MSG_RESULT(yes) + AC_DEFINE(HAVE_DLINFO_ORIGIN, 1, [Have dlinfo RTLD_DI_ORIGIN]) +], [ + AC_MSG_RESULT(no) +]) + +AC_MSG_CHECKING([for dlinfo(RTLD_DI_LINKMAP)]) +AC_LINK_IFELSE([AC_LANG_PROGRAM([[ +#include +#ifdef HAVE_LINK_H +#include +#endif +#include +]], [[ + struct link_map *lm = NULL; + dlinfo (NULL, RTLD_DI_LINKMAP, &lm); +]])], [ + AC_MSG_RESULT(yes) + AC_DEFINE(HAVE_DLINFO_LINKMAP, 1, [Have dlinfo RTLD_DI_LINKMAP]) +], [ + AC_MSG_RESULT(no) +]) + dnl --------------------------- dnl sockaddr and netinet checks diff --git a/lib/memory_vty.c b/lib/memory_vty.c index 149b329130..01a41fe02e 100644 --- a/lib/memory_vty.c +++ b/lib/memory_vty.c @@ -1,23 +1,22 @@ /* - * Memory management routine + * Memory and dynamic module VTY routine + * * Copyright (C) 1998 Kunihiro Ishiguro + * Copyright (C) 2016-2017 David Lamparter for NetDEF, Inc. * - * This file is part of GNU Zebra. + * This program 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 of the License, or (at your option) + * any later version. * - * 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. + * This program 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. * - * 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. + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple + * Place, Suite 330, Boston, MA 02111-1307 USA */ #include @@ -25,9 +24,12 @@ #if (defined(GNU_LINUX) && defined(HAVE_MALLINFO)) #include #endif /* HAVE_MALLINFO */ +#include +#include #include "log.h" #include "memory.h" +#include "module.h" #include "memory_vty.h" /* Looking up memory status from vty interface. */ @@ -110,10 +112,55 @@ DEFUN (show_memory, return CMD_SUCCESS; } +DEFUN (show_modules, + show_modules_cmd, + "show modules", + "Show running system information\n" + "Loaded modules\n") +{ + struct frrmod_runtime *plug = frrmod_list; + + vty_out (vty, "%-12s %-25s %s%s%s", + "Plugin Name", "Version", "Description", + VTY_NEWLINE, VTY_NEWLINE); + while (plug) + { + const struct frrmod_info *i = plug->info; + + vty_out (vty, "%-12s %-25s %s%s", i->name, i->version, i->description, + VTY_NEWLINE); + if (plug->dl_handle) + { +#ifdef HAVE_DLINFO_ORIGIN + char origin[MAXPATHLEN] = ""; + dlinfo (plug->dl_handle, RTLD_DI_ORIGIN, &origin); +# ifdef HAVE_DLINFO_LINKMAP + const char *name; + struct link_map *lm = NULL; + dlinfo (plug->dl_handle, RTLD_DI_LINKMAP, &lm); + if (lm) + { + name = strrchr(lm->l_name, '/'); + name = name ? name + 1 : lm->l_name; + vty_out (vty, "\tfrom: %s/%s%s", origin, name, VTY_NEWLINE); + } +# else + vty_out (vty, "\tfrom: %s %s", origin, plug->load_name, VTY_NEWLINE); +# endif +#else + vty_out (vty, "\tfrom: %s%s", plug->load_name, VTY_NEWLINE); +#endif + } + plug = plug->next; + } + return CMD_SUCCESS; +} + void memory_init (void) { install_element (VIEW_NODE, &show_memory_cmd); + install_element (VIEW_NODE, &show_modules_cmd); } /* Stats querying from users */ From a5b38c5bd252ab7bf2294a2303ce845df40d82dd Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Sun, 12 Jun 2016 17:31:50 +0200 Subject: [PATCH 11/61] lib: add hook infrastructure Please refer to lib/hook.h for a description/documentation. Signed-off-by: David Lamparter --- lib/Makefile.am | 2 + lib/hook.c | 56 +++++++++++++ lib/hook.h | 187 ++++++++++++++++++++++++++++++++++++++++++ lib/libfrr.c | 6 +- lib/libfrr.h | 2 + zebra/rtread_getmsg.c | 4 + 6 files changed, 256 insertions(+), 1 deletion(-) create mode 100644 lib/hook.c create mode 100644 lib/hook.h diff --git a/lib/Makefile.am b/lib/Makefile.am index 5731440640..7709ce45eb 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -33,6 +33,7 @@ libfrr_la_SOURCES = \ strlcpy.c \ strlcat.c \ module.c \ + hook.c \ # end BUILT_SOURCES = route_types.h gitversion.h command_parse.h command_lex.h @@ -57,6 +58,7 @@ pkginclude_HEADERS = \ spf_backoff.h \ srcdest_table.h \ module.h \ + hook.h \ libfrr.h \ # end diff --git a/lib/hook.c b/lib/hook.c new file mode 100644 index 0000000000..04d803cd8d --- /dev/null +++ b/lib/hook.c @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2016 David Lamparter, for NetDEF, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include "memory.h" +#include "hook.h" + +DEFINE_MTYPE_STATIC(LIB, HOOK_ENTRY, "Hook entry") + +void _hook_register(struct hook *hook, void *funcptr, void *arg, bool has_arg, + struct frrmod_runtime *module, const char *funcname) +{ + struct hookent *he = XCALLOC(MTYPE_HOOK_ENTRY, sizeof(*he)); + he->hookfn = funcptr; + he->hookarg = arg; + he->has_arg = has_arg; + he->module = module; + he->fnname = funcname; + + he->next = hook->entries; + hook->entries = he; +} + +void _hook_unregister(struct hook *hook, void *funcptr, + void *arg, bool has_arg) +{ + struct hookent *he, **prev; + + for (prev = &hook->entries; (he = *prev) != NULL; prev = &he->next) + if (he->hookfn == funcptr && he->hookarg == arg + && he->has_arg == has_arg) + { + *prev = he->next; + XFREE(MTYPE_HOOK_ENTRY, he); + break; + } +} + diff --git a/lib/hook.h b/lib/hook.h new file mode 100644 index 0000000000..0cb7ab5c7d --- /dev/null +++ b/lib/hook.h @@ -0,0 +1,187 @@ +/* + * Copyright (c) 2016 David Lamparter, for NetDEF, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#ifndef _FRR_HOOK_H +#define _FRR_HOOK_H + +#include + +#include "module.h" +#include "memory.h" + +/* type-safe subscribable hook points + * + * where "type-safe" applies to the function pointers used for subscriptions + * + * overall usage: + * - to create a hook: + * + * mydaemon.h: + * #include "hook.h" + * DECLARE_HOOK (some_update_event, (struct eventinfo *info), (info)) + * + * mydaemon.c: + * DEFINE_HOOK (some_update_event, (struct eventinfo *info), (info)) + * ... + * hook_call (some_update_event, info) + * + * Note: the second and third macro args must be the hook function's + * parameter list, with the same names for each parameter. The second + * macro arg is with types (used for defining things), the third arg is + * just the names (used for passing along parameters). + * + * Do not use parameter names starting with "hook", these can collide with + * names used by the hook code itself. + * + * The return value is always "int" for now; hook_call will sum up the + * return values from each registered user. Default is 0. + * + * There are no pre-defined semantics for the value, in most cases it is + * ignored. For success/failure indication, 0 should be success, and + * handlers should make sure to only return 0 or 1 (not -1 or other values). + * + * + * - to use a hook / create a handler: + * + * #include "mydaemon.h" + * int event_handler (struct eventinfo *info) { ... } + * hook_register (some_update_event, event_handler); + * + * or, if you need an argument to be passed along (addonptr will be added + * as first argument when calling the handler): + * + * #include "mydaemon.h" + * int event_handler (void *addonptr, struct eventinfo *info) { ... } + * hook_register_arg (some_update_event, event_handler, addonptr); + * + * (addonptr isn't typesafe, but that should be manageable.) + */ + +/* TODO: + * - hook_unregister_all_module() + * - introspection / CLI / debug + * - testcases ;) + * + * For loadable modules, the idea is that hooks could be automatically + * unregistered when a module is unloaded. + * + * It's also possible to add a constructor (MTYPE style) to DEFINE_HOOK, + * which would make it possible for the CLI to show all hooks and all + * registered handlers. + */ + +struct hookent { + struct hookent *next; + void *hookfn; /* actually a function pointer */ + void *hookarg; + bool has_arg; + struct frrmod_runtime *module; + const char *fnname; +}; + +struct hook { + const char *name; + struct hookent *entries; +}; + +/* subscribe/add callback function to a hook + * + * always use hook_register(), which uses the static inline helper from + * DECLARE_HOOK in order to get type safety + */ +extern void _hook_register(struct hook *hook, void *funcptr, void *arg, + bool has_arg, struct frrmod_runtime *module, + const char *funcname); +#define hook_register(hookname, func) \ + _hook_register(&_hook_ ## hookname, \ + _hook_typecheck_ ## hookname (func), \ + NULL, false, THIS_MODULE, #func) +#define hook_register_arg(hookname, func, arg) \ + _hook_register(&_hook_ ## hookname, \ + _hook_typecheck_arg_ ## hookname (func), \ + arg, true, THIS_MODULE, #func) + +extern void _hook_unregister(struct hook *hook, void *funcptr, void *arg, + bool has_arg); +#define hook_unregister(hookname, func) \ + _hook_unregister(&_hook_ ## hookname, \ + _hook_typecheck_ ## hookname (func), NULL, false) +#define hook_unregister_arg(hookname, func, arg) \ + _hook_unregister(&_hook_ ## hookname, \ + _hook_typecheck_arg_ ## hookname (func), arg, true) + +/* invoke hooks + * this is private (static) to the file that has the DEFINE_HOOK statement + */ +#define hook_call(hookname, ...) \ + hook_call_ ## hookname (__VA_ARGS__) + +/* helpers to add the void * arg */ +#define HOOK_ADDDEF(...) (void *hookarg , ## __VA_ARGS__) +#define HOOK_ADDARG(...) (hookarg , ## __VA_ARGS__) + +/* use in header file - declares the hook and its arguments + * usage: DECLARE_HOOK(my_hook, (int arg1, struct foo *arg2), (arg1, arg2)) + * as above, "passlist" must use the same order and same names as "arglist" + * + * theoretically passlist is not neccessary, but let's keep things simple and + * use exact same args on DECLARE and DEFINE. + */ +#define DECLARE_HOOK(hookname, arglist, passlist) \ + extern struct hook _hook_ ## hookname; \ + __attribute__((unused)) \ + static void *_hook_typecheck_ ## hookname ( \ + int (*funcptr) arglist) { \ + return (void *)funcptr; } \ + __attribute__((unused)) \ + static void *_hook_typecheck_arg_ ## hookname ( \ + int (*funcptr) HOOK_ADDDEF arglist) { \ + return (void *)funcptr; } + +/* use in source file - contains hook-related definitions. + */ +#define DEFINE_HOOK(hookname, arglist, passlist) \ + struct hook _hook_ ## hookname = { \ + .name = #hookname, \ + .entries = NULL, \ + }; \ + static int hook_call_ ## hookname arglist { \ + int hooksum = 0; \ + struct hookent *he = _hook_ ## hookname .entries; \ + void *hookarg; \ + union { \ + void *voidptr; \ + int (*fptr) arglist; \ + int (*farg) HOOK_ADDDEF arglist; \ + } hookp; \ + for (; he; he = he->next) { \ + hookarg = he->hookarg; \ + hookp.voidptr = he->hookfn; \ + if (!he->has_arg) \ + hooksum += hookp.fptr passlist; \ + else \ + hooksum += hookp.farg HOOK_ADDARG passlist; \ + } \ + return hooksum; \ + } + +#endif /* _FRR_HOOK_H */ diff --git a/lib/libfrr.c b/lib/libfrr.c index 5c047040ae..64f8be2ca6 100644 --- a/lib/libfrr.c +++ b/lib/libfrr.c @@ -30,6 +30,8 @@ #include "log_int.h" #include "module.h" +DEFINE_HOOK(frr_late_init, (struct thread_master *tm), (tm)) + const char frr_sysconfdir[] = SYSCONFDIR; const char frr_vtydir[] = DAEMON_VTY_DIR; @@ -311,9 +313,9 @@ int frr_getopt(int argc, char * const argv[], int *longindex) return opt; } +static struct thread_master *master; struct thread_master *frr_init(void) { - struct thread_master *master; struct option_chain *oc; struct frrmod_runtime *module; char moderr[256]; @@ -354,6 +356,8 @@ struct thread_master *frr_init(void) void frr_config_fork(void) { + hook_call(frr_late_init, master); + if (di->instance) { snprintf(config_default, sizeof(config_default), "%s/%s-%d.conf", frr_sysconfdir, di->name, di->instance); diff --git a/lib/libfrr.h b/lib/libfrr.h index 71225fad38..a40fc34892 100644 --- a/lib/libfrr.h +++ b/lib/libfrr.h @@ -27,6 +27,7 @@ #include "log.h" #include "getopt.h" #include "module.h" +#include "hook.h" #define FRR_NO_PRIVSEP (1 << 0) #define FRR_NO_TCPVTY (1 << 1) @@ -95,6 +96,7 @@ extern void frr_help_exit(int status); extern struct thread_master *frr_init(void); +DECLARE_HOOK(frr_late_init, (struct thread_master *tm), (tm)) extern void frr_config_fork(void); extern void frr_vty_serv(void); diff --git a/zebra/rtread_getmsg.c b/zebra/rtread_getmsg.c index 1007d0ac18..4d491f3200 100644 --- a/zebra/rtread_getmsg.c +++ b/zebra/rtread_getmsg.c @@ -31,6 +31,10 @@ #include "zebra/rib.h" #include "zebra/zserv.h" +/* Thank you, Solaris, for polluting application symbol namespace. */ +#undef hook_register +#undef hook_unregister + #include #include From 46081234b48eb9569271f868e1fbd5f2bc78c9d6 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Mon, 13 Jun 2016 15:44:26 +0200 Subject: [PATCH 12/61] build: split off libfrrsnmp Signed-off-by: David Lamparter --- bgpd/Makefile.am | 4 ++-- configure.ac | 7 +++++-- lib/Makefile.am | 13 +++++++++++-- ospf6d/Makefile.am | 2 +- ospfd/Makefile.am | 2 +- ripd/Makefile.am | 2 +- zebra/Makefile.am | 2 +- 7 files changed, 22 insertions(+), 10 deletions(-) diff --git a/bgpd/Makefile.am b/bgpd/Makefile.am index 50afc7ed64..50cd2d28ec 100644 --- a/bgpd/Makefile.am +++ b/bgpd/Makefile.am @@ -94,11 +94,11 @@ noinst_HEADERS = \ $(BGP_VNC_RFAPI_HD) bgp_attr_evpn.h bgp_evpn.h bgp_evpn_vty.h bgp_vpn.h bgpd_SOURCES = bgp_main.c -bgpd_LDADD = libbgp.a $(BGP_VNC_RFP_LIB) ../lib/libfrr.la @LIBCAP@ @LIBM@ +bgpd_LDADD = libbgp.a $(BGP_VNC_RFP_LIB) ../lib/libfrr.la ../lib/libfrrsnmp.la @LIBCAP@ @LIBM@ bgpd_LDFLAGS = $(BGP_VNC_RFP_LD_FLAGS) bgp_btoa_SOURCES = bgp_btoa.c -bgp_btoa_LDADD = libbgp.a $(BGP_VNC_RFP_LIB) ../lib/libfrr.la @LIBCAP@ @LIBM@ +bgp_btoa_LDADD = libbgp.a $(BGP_VNC_RFP_LIB) ../lib/libfrr.la ../lib/libfrrsnmp.la @LIBCAP@ @LIBM@ bgp_btoa_LDFLAGS = $(BGP_VNC_RFP_LD_FLAGS) examplesdir = $(exampledir) diff --git a/configure.ac b/configure.ac index b94b8bb16c..27d4561910 100755 --- a/configure.ac +++ b/configure.ac @@ -1324,8 +1324,8 @@ if test "${enable_snmp}" != ""; then if test x"$NETSNMP_CONFIG" = x"no"; then AC_MSG_ERROR([--enable-snmp given but unable to find net-snmp-config]) fi - LIBS="$LIBS `${NETSNMP_CONFIG} --agent-libs`" - CFLAGS="`${NETSNMP_CONFIG} --base-cflags` $CFLAGS" + SNMP_LIBS="`${NETSNMP_CONFIG} --agent-libs`" + SNMP_CFLAGS="`${NETSNMP_CONFIG} --base-cflags`" AC_MSG_CHECKING([whether we can link to Net-SNMP]) AC_LINK_IFELSE([AC_LANG_PROGRAM([ int main(void); @@ -1353,6 +1353,9 @@ int main(void); AH_TEMPLATE([SNMP_AGENTX], [Use SNMP AgentX to interface with snmpd]) AC_DEFINE_UNQUOTED(AS_TR_CPP(SNMP_${SNMP_METHOD}),,SNMP method to interface with snmpd) fi +AM_CONDITIONAL([SNMP], [test "x${SNMP_METHOD}" != "x"]) +AC_SUBST(SNMP_LIBS) +AC_SUBST(SNMP_CFLAGS) dnl --------------- dnl dlopen & dlinfo diff --git a/lib/Makefile.am b/lib/Makefile.am index 7709ce45eb..14259f2e0d 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -10,7 +10,7 @@ command_lex.h: command_lex.c @if test ! -f $@; then $(MAKE) $(AM_MAKEFLAGS) command_lex.c; else :; fi command_parse.lo: command_lex.h -lib_LTLIBRARIES = libfrr.la +lib_LTLIBRARIES = libfrr.la libfrrsnmp.la libfrr_la_LDFLAGS = -version-info 0:0:0 libfrr_la_SOURCES = \ @@ -20,7 +20,7 @@ libfrr_la_SOURCES = \ command.c \ sockunion.c prefix.c thread.c if.c buffer.c table.c hash.c \ filter.c routemap.c distribute.c stream.c log.c plist.c \ - zclient.c sockopt.c smux.c agentx.c snmp.c md5.c if_rmap.c keychain.c privs.c \ + zclient.c sockopt.c md5.c if_rmap.c keychain.c privs.c \ sigevent.c pqueue.c jhash.c workqueue.c nexthop.c json.c \ ptm_lib.c csv.c bfd.c vrf.c systemd.c ns.c memory.c memory_vty.c \ imsg-buffer.c imsg.c skiplist.c \ @@ -40,6 +40,15 @@ BUILT_SOURCES = route_types.h gitversion.h command_parse.h command_lex.h libfrr_la_LIBADD = @LIBCAP@ +libfrrsnmp_la_CFLAGS = $(WERROR) $(SNMP_CFLAGS) +libfrrsnmp_la_LDFLAGS = -version-info 0:0:0 +libfrrsnmp_la_LIBADD = libfrr.la $(SNMP_LIBS) +libfrrsnmp_la_SOURCES = \ + agentx.c \ + smux.c \ + snmp.c \ + #end + pkginclude_HEADERS = \ buffer.h checksum.h filter.h getopt.h hash.h \ if.h linklist.h log.h \ diff --git a/ospf6d/Makefile.am b/ospf6d/Makefile.am index 06fc7a30af..8e62b1d5b4 100644 --- a/ospf6d/Makefile.am +++ b/ospf6d/Makefile.am @@ -28,7 +28,7 @@ noinst_HEADERS = \ ospf6d_SOURCES = \ ospf6_main.c $(libospf6_a_SOURCES) -ospf6d_LDADD = ../lib/libfrr.la @LIBCAP@ +ospf6d_LDADD = ../lib/libfrr.la ../lib/libfrrsnmp.la @LIBCAP@ examplesdir = $(exampledir) dist_examples_DATA = ospf6d.conf.sample diff --git a/ospfd/Makefile.am b/ospfd/Makefile.am index 71e0df0dc5..5555fb0da4 100644 --- a/ospfd/Makefile.am +++ b/ospfd/Makefile.am @@ -31,7 +31,7 @@ noinst_HEADERS = \ ospfd_SOURCES = ospf_main.c -ospfd_LDADD = libfrrospf.a ../lib/libfrr.la @LIBCAP@ @LIBM@ +ospfd_LDADD = libfrrospf.a ../lib/libfrr.la ../lib/libfrrsnmp.la @LIBCAP@ @LIBM@ EXTRA_DIST = OSPF-MIB.txt OSPF-TRAP-MIB.txt ChangeLog.opaque.txt diff --git a/ripd/Makefile.am b/ripd/Makefile.am index 7967ff1535..47c471aebb 100644 --- a/ripd/Makefile.am +++ b/ripd/Makefile.am @@ -21,7 +21,7 @@ noinst_HEADERS = \ ripd_SOURCES = \ rip_main.c $(librip_a_SOURCES) -ripd_LDADD = ../lib/libfrr.la @LIBCAP@ +ripd_LDADD = ../lib/libfrr.la ../lib/libfrrsnmp.la @LIBCAP@ examplesdir = $(exampledir) dist_examples_DATA = ripd.conf.sample diff --git a/zebra/Makefile.am b/zebra/Makefile.am index 50bc065c6e..4711c5e0b7 100644 --- a/zebra/Makefile.am +++ b/zebra/Makefile.am @@ -62,7 +62,7 @@ noinst_HEADERS = \ zebra_ns.h zebra_vrf.h ioctl_solaris.h zebra_static.h zebra_mpls.h \ kernel_netlink.h if_netlink.h zebra_mroute.h label_manager.h -zebra_LDADD = $(otherobj) ../lib/libfrr.la $(LIBCAP) $(Q_FPM_PB_CLIENT_LDOPTS) +zebra_LDADD = $(otherobj) ../lib/libfrr.la ../lib/libfrrsnmp.la $(LIBCAP) $(Q_FPM_PB_CLIENT_LDOPTS) testzebra_LDADD = ../lib/libfrr.la $(LIBCAP) From 3012671ffadbd839626b5c0b0b1fd36b3698f582 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Sun, 12 Jun 2016 17:32:23 +0200 Subject: [PATCH 13/61] *: use hooks for sending SNMP traps This means there are no ties into the SNMP code anymore other than the init call at startup. Signed-off-by: David Lamparter --- bgpd/Makefile.am | 2 +- bgpd/bgp_fsm.c | 14 +++----- bgpd/bgp_fsm.h | 4 +++ bgpd/bgp_snmp.c | 16 ++++++--- bgpd/bgp_snmp.h | 28 --------------- bgpd/bgpd.c | 5 ++- ospf6d/Makefile.am | 2 +- ospf6d/ospf6_interface.c | 15 +++----- ospf6d/ospf6_interface.h | 5 +++ ospf6d/ospf6_neighbor.c | 13 +++---- ospf6d/ospf6_neighbor.h | 6 ++++ ospf6d/ospf6_snmp.c | 32 ++++++++++++++--- ospf6d/ospf6_snmp.h | 31 ---------------- ospf6d/ospf6d.c | 2 +- ospfd/Makefile.am | 2 +- ospfd/ospf_interface.c | 13 +++---- ospfd/ospf_interface.h | 4 +++ ospfd/ospf_ism.c | 19 +++------- ospfd/ospf_ism.h | 10 +++--- ospfd/ospf_nsm.c | 34 ++++-------------- ospfd/ospf_nsm.h | 6 ++++ ospfd/ospf_snmp.c | 78 ++++++++++++++++++++++++++++++++++------ ospfd/ospf_snmp.h | 38 -------------------- ospfd/ospf_zebra.c | 22 ++++-------- ospfd/ospf_zebra.h | 4 +++ ripd/rip_interface.c | 11 +++--- ripd/rip_snmp.c | 20 +++++++---- ripd/ripd.h | 7 ++-- 28 files changed, 206 insertions(+), 237 deletions(-) delete mode 100644 bgpd/bgp_snmp.h delete mode 100644 ospf6d/ospf6_snmp.h delete mode 100644 ospfd/ospf_snmp.h diff --git a/bgpd/Makefile.am b/bgpd/Makefile.am index 50cd2d28ec..4050e01620 100644 --- a/bgpd/Makefile.am +++ b/bgpd/Makefile.am @@ -89,7 +89,7 @@ noinst_HEADERS = \ bgpd.h bgp_filter.h bgp_clist.h bgp_dump.h bgp_zebra.h \ bgp_ecommunity.h bgp_lcommunity.h \ bgp_mplsvpn.h bgp_nexthop.h bgp_damp.h bgp_table.h \ - bgp_advertise.h bgp_snmp.h bgp_vty.h bgp_mpath.h bgp_nht.h \ + bgp_advertise.h bgp_vty.h bgp_mpath.h bgp_nht.h \ bgp_updgrp.h bgp_bfd.h bgp_encap.h bgp_encap_tlv.h bgp_encap_types.h \ $(BGP_VNC_RFAPI_HD) bgp_attr_evpn.h bgp_evpn.h bgp_evpn_vty.h bgp_vpn.h diff --git a/bgpd/bgp_fsm.c b/bgpd/bgp_fsm.c index 7dc7f053d6..2bbdca595c 100644 --- a/bgpd/bgp_fsm.c +++ b/bgpd/bgp_fsm.c @@ -45,14 +45,14 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #include "bgpd/bgp_dump.h" #include "bgpd/bgp_open.h" #include "bgpd/bgp_advertise.h" -#ifdef HAVE_SNMP -#include "bgpd/bgp_snmp.h" -#endif /* HAVE_SNMP */ #include "bgpd/bgp_updgrp.h" #include "bgpd/bgp_nht.h" #include "bgpd/bgp_bfd.h" #include "bgpd/bgp_memory.h" +DEFINE_HOOK(peer_backward_transition, (struct peer *peer), (peer)) +DEFINE_HOOK(peer_established, (struct peer *peer), (peer)) + /* Definition of display strings corresponding to FSM events. This should be * kept consistent with the events defined in bgpd.h */ @@ -1061,9 +1061,7 @@ bgp_stop (struct peer *peer) zlog_debug ("%s remove from all update group", peer->host); update_group_remove_peer_afs(peer); -#ifdef HAVE_SNMP - bgpTrapBackwardTransition (peer); -#endif /* HAVE_SNMP */ + hook_call(peer_backward_transition, peer); /* Reset peer synctime */ peer->synctime = 0; @@ -1508,9 +1506,7 @@ bgp_establish (struct peer *peer) zlog_debug ("%s graceful restart timer stopped", peer->host); } -#ifdef HAVE_SNMP - bgpTrapEstablished (peer); -#endif /* HAVE_SNMP */ + hook_call(peer_established, peer); /* Reset uptime, send keepalive, send current table. */ peer->uptime = bgp_clock (); diff --git a/bgpd/bgp_fsm.h b/bgpd/bgp_fsm.h index e47d07702b..4d0b48f529 100644 --- a/bgpd/bgp_fsm.h +++ b/bgpd/bgp_fsm.h @@ -109,4 +109,8 @@ extern void bgp_start_routeadv (struct bgp *); */ extern void bgp_adjust_routeadv (struct peer *); +#include "hook.h" +DECLARE_HOOK(peer_backward_transition, (struct peer *peer), (peer)) +DECLARE_HOOK(peer_established, (struct peer *peer), (peer)) + #endif /* _QUAGGA_BGP_FSM_H */ diff --git a/bgpd/bgp_snmp.c b/bgpd/bgp_snmp.c index 5e6218e8a3..6896c86e40 100644 --- a/bgpd/bgp_snmp.c +++ b/bgpd/bgp_snmp.c @@ -38,7 +38,6 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #include "bgpd/bgp_attr.h" #include "bgpd/bgp_route.h" #include "bgpd/bgp_fsm.h" -#include "bgpd/bgp_snmp.h" /* BGP4-MIB described in RFC1657. */ #define BGP4MIB 1,3,6,1,2,1,15 @@ -838,7 +837,7 @@ static struct trap_object bgpTrapList[] = {3, {3, 1, BGPPEERSTATE}} }; -void +static int bgpTrapEstablished (struct peer *peer) { int ret; @@ -847,7 +846,7 @@ bgpTrapEstablished (struct peer *peer) ret = inet_aton (peer->host, &addr); if (ret == 0) - return; + return 0; oid_copy_addr (index, &addr, IN_ADDR_SIZE); @@ -857,9 +856,10 @@ bgpTrapEstablished (struct peer *peer) index, IN_ADDR_SIZE, bgpTrapList, sizeof bgpTrapList / sizeof (struct trap_object), BGPESTABLISHED); + return 0; } -void +static int bgpTrapBackwardTransition (struct peer *peer) { int ret; @@ -868,7 +868,7 @@ bgpTrapBackwardTransition (struct peer *peer) ret = inet_aton (peer->host, &addr); if (ret == 0) - return; + return 0; oid_copy_addr (index, &addr, IN_ADDR_SIZE); @@ -878,11 +878,17 @@ bgpTrapBackwardTransition (struct peer *peer) index, IN_ADDR_SIZE, bgpTrapList, sizeof bgpTrapList / sizeof (struct trap_object), BGPBACKWARDTRANSITION); + return 0; } +void bgp_snmp_init (void); + void bgp_snmp_init (void) { + hook_register(peer_established, bgpTrapEstablished); + hook_register(peer_backward_transition, bgpTrapBackwardTransition); + smux_init (bm->master); REGISTER_MIB("mibII/bgp", bgp_variables, variable, bgp_oid); } diff --git a/bgpd/bgp_snmp.h b/bgpd/bgp_snmp.h deleted file mode 100644 index 7a0d9dd007..0000000000 --- a/bgpd/bgp_snmp.h +++ /dev/null @@ -1,28 +0,0 @@ -/* BGP4 SNMP support - Copyright (C) 1999, 2000 Kunihiro Ishiguro - -This file is part of GNU Zebra. - -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. */ - -#ifndef _QUAGGA_BGP_SNMP_H -#define _QUAGGA_BGP_SNMP_H - -extern void bgp_snmp_init (void); -extern void bgpTrapEstablished (struct peer *); -extern void bgpTrapBackwardTransition (struct peer *); - -#endif /* _QUAGGA_BGP_SNMP_H */ diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index 30243e80b2..031cab902a 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -72,9 +72,6 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #include "bgpd/bgp_vty.h" #include "bgpd/bgp_mpath.h" #include "bgpd/bgp_nht.h" -#ifdef HAVE_SNMP -#include "bgpd/bgp_snmp.h" -#endif /* HAVE_SNMP */ #include "bgpd/bgp_updgrp.h" #include "bgpd/bgp_bfd.h" #include "bgpd/bgp_memory.h" @@ -7647,6 +7644,8 @@ bgp_if_finish (struct bgp *bgp) } } +extern void bgp_snmp_init (void); + void bgp_init (void) { diff --git a/ospf6d/Makefile.am b/ospf6d/Makefile.am index 8e62b1d5b4..30268c6882 100644 --- a/ospf6d/Makefile.am +++ b/ospf6d/Makefile.am @@ -22,7 +22,7 @@ noinst_HEADERS = \ ospf6_network.h ospf6_message.h ospf6_lsa.h ospf6_lsdb.h \ ospf6_top.h ospf6_area.h ospf6_interface.h ospf6_neighbor.h \ ospf6_flood.h ospf6_route.h ospf6_intra.h ospf6_zebra.h \ - ospf6_spf.h ospf6_proto.h ospf6_asbr.h ospf6_abr.h ospf6_snmp.h \ + ospf6_spf.h ospf6_proto.h ospf6_asbr.h ospf6_abr.h \ ospf6d.h ospf6_bfd.h ospf6d_SOURCES = \ diff --git a/ospf6d/ospf6_interface.c b/ospf6d/ospf6_interface.c index 8e0779df92..8cf7f4afaa 100644 --- a/ospf6d/ospf6_interface.c +++ b/ospf6d/ospf6_interface.c @@ -41,12 +41,14 @@ #include "ospf6_neighbor.h" #include "ospf6_intra.h" #include "ospf6_spf.h" -#include "ospf6_snmp.h" #include "ospf6d.h" #include "ospf6_bfd.h" DEFINE_MTYPE_STATIC(OSPF6D, CFG_PLIST_NAME, "configured prefix list names") DEFINE_QOBJ_TYPE(ospf6_interface) +DEFINE_HOOK(ospf6_interface_change, + (struct ospf6_interface *oi, int state, int old_state), + (oi, state, old_state)) unsigned char conf_debug_ospf6_interface = 0; @@ -518,16 +520,7 @@ ospf6_interface_state_change (u_char next_state, struct ospf6_interface *oi) OSPF6_INTRA_PREFIX_LSA_SCHEDULE_STUB (oi->area); } -#ifdef HAVE_SNMP - /* Terminal state or regression */ - if ((next_state == OSPF6_INTERFACE_POINTTOPOINT) || - (next_state == OSPF6_INTERFACE_DROTHER) || - (next_state == OSPF6_INTERFACE_BDR) || - (next_state == OSPF6_INTERFACE_DR) || - (next_state < prev_state)) - ospf6TrapIfStateChange (oi); -#endif - + hook_call(ospf6_interface_change, oi, next_state, prev_state); } diff --git a/ospf6d/ospf6_interface.h b/ospf6d/ospf6_interface.h index 179477a634..846cde4191 100644 --- a/ospf6d/ospf6_interface.h +++ b/ospf6d/ospf6_interface.h @@ -23,6 +23,7 @@ #define OSPF6_INTERFACE_H #include "qobj.h" +#include "hook.h" #include "if.h" /* Debug option */ @@ -182,4 +183,8 @@ extern void install_element_ospf6_clear_interface (void); extern int config_write_ospf6_debug_interface (struct vty *vty); extern void install_element_ospf6_debug_interface (void); +DECLARE_HOOK(ospf6_interface_change, + (struct ospf6_interface *oi, int state, int old_state), + (oi, state, old_state)) + #endif /* OSPF6_INTERFACE_H */ diff --git a/ospf6d/ospf6_neighbor.c b/ospf6d/ospf6_neighbor.c index ec79a1552b..118210dfc7 100644 --- a/ospf6d/ospf6_neighbor.c +++ b/ospf6d/ospf6_neighbor.c @@ -38,7 +38,6 @@ #include "ospf6_neighbor.h" #include "ospf6_intra.h" #include "ospf6_flood.h" -#include "ospf6_snmp.h" #include "ospf6d.h" #include "ospf6_bfd.h" #include "ospf6_abr.h" @@ -47,6 +46,10 @@ #include "ospf6_spf.h" #include "ospf6_zebra.h" +DEFINE_HOOK(ospf6_neighbor_change, + (struct ospf6_neighbor *on, int state, int next_state), + (on, state, next_state)) + unsigned char conf_debug_ospf6_neighbor = 0; const char *ospf6_neighbor_state_str[] = @@ -202,13 +205,7 @@ ospf6_neighbor_state_change (u_char next_state, struct ospf6_neighbor *on, int e next_state != OSPF6_NEIGHBOR_LOADING)) ospf6_maxage_remove (on->ospf6_if->area->ospf6); -#ifdef HAVE_SNMP - /* Terminal state or regression */ - if ((next_state == OSPF6_NEIGHBOR_FULL) || - (next_state == OSPF6_NEIGHBOR_TWOWAY) || - (next_state < prev_state)) - ospf6TrapNbrStateChange (on); -#endif + hook_call(ospf6_neighbor_change, on, next_state, prev_state); ospf6_bfd_trigger_event(on, prev_state, next_state); } diff --git a/ospf6d/ospf6_neighbor.h b/ospf6d/ospf6_neighbor.h index f9e197e99b..c275ff830e 100644 --- a/ospf6d/ospf6_neighbor.h +++ b/ospf6d/ospf6_neighbor.h @@ -22,6 +22,8 @@ #ifndef OSPF6_NEIGHBOR_H #define OSPF6_NEIGHBOR_H +#include "hook.h" + /* Debug option */ extern unsigned char conf_debug_ospf6_neighbor; #define OSPF6_DEBUG_NEIGHBOR_STATE 0x01 @@ -179,4 +181,8 @@ extern void ospf6_neighbor_init (void); extern int config_write_ospf6_debug_neighbor (struct vty *vty); extern void install_element_ospf6_debug_neighbor (void); +DECLARE_HOOK(ospf6_neighbor_change, + (struct ospf6_neighbor *on, int state, int next_state), + (on, state, next_state)) + #endif /* OSPF6_NEIGHBOR_H */ diff --git a/ospf6d/ospf6_snmp.c b/ospf6d/ospf6_snmp.c index 86cfd17c83..57fc94fd52 100644 --- a/ospf6d/ospf6_snmp.c +++ b/ospf6d/ospf6_snmp.c @@ -45,7 +45,8 @@ #include "ospf6_abr.h" #include "ospf6_asbr.h" #include "ospf6d.h" -#include "ospf6_snmp.h" + +void ospf6_snmp_init (struct thread_master *master); /* OSPFv3-MIB */ #define OSPFv3MIB 1,3,6,1,2,1,191 @@ -1139,11 +1140,18 @@ static struct trap_object ospf6IfTrapList[] = {4, {1, 7, 1, OSPFv3IFAREAID}} }; -void -ospf6TrapNbrStateChange (struct ospf6_neighbor *on) +static int +ospf6TrapNbrStateChange (struct ospf6_neighbor *on, + int next_state, int prev_state) { oid index[3]; + /* Terminal state or regression */ + if ((next_state != OSPF6_NEIGHBOR_FULL) && + (next_state != OSPF6_NEIGHBOR_TWOWAY) && + (next_state >= prev_state)) + return 0; + index[0] = on->ospf6_if->interface->ifindex; index[1] = on->ospf6_if->instance_id; index[2] = ntohl (on->router_id); @@ -1155,13 +1163,23 @@ ospf6TrapNbrStateChange (struct ospf6_neighbor *on) ospf6NbrTrapList, sizeof ospf6NbrTrapList / sizeof (struct trap_object), NBRSTATECHANGE); + return 0; } -void -ospf6TrapIfStateChange (struct ospf6_interface *oi) +static int +ospf6TrapIfStateChange (struct ospf6_interface *oi, + int next_state, int prev_state) { oid index[2]; + /* Terminal state or regression */ + if ((next_state != OSPF6_INTERFACE_POINTTOPOINT) && + (next_state != OSPF6_INTERFACE_DROTHER) && + (next_state != OSPF6_INTERFACE_BDR) && + (next_state != OSPF6_INTERFACE_DR) && + (next_state >= prev_state)) + return 0; + index[0] = oi->interface->ifindex; index[1] = oi->instance_id; @@ -1172,12 +1190,16 @@ ospf6TrapIfStateChange (struct ospf6_interface *oi) ospf6IfTrapList, sizeof ospf6IfTrapList / sizeof (struct trap_object), IFSTATECHANGE); + return 0; } /* Register OSPFv3-MIB. */ void ospf6_snmp_init (struct thread_master *master) { + hook_register(ospf6_interface_change, ospf6TrapIfStateChange); + hook_register(ospf6_neighbor_change, ospf6TrapNbrStateChange); + smux_init (master); REGISTER_MIB ("OSPFv3MIB", ospfv3_variables, variable, ospfv3_oid); } diff --git a/ospf6d/ospf6_snmp.h b/ospf6d/ospf6_snmp.h deleted file mode 100644 index fa1b0c37a8..0000000000 --- a/ospf6d/ospf6_snmp.h +++ /dev/null @@ -1,31 +0,0 @@ -/* OSPFv3 SNMP support - * Copyright (C) 2004 Yasuhiro Ohara - * - * This file is part of GNU Zebra. - * - * 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. - */ - -#ifndef OSPF6_SNMP_H -#define OSPF6_SNMP_H - -extern void ospf6TrapNbrStateChange (struct ospf6_neighbor *); -extern void ospf6TrapIfStateChange (struct ospf6_interface *); -extern void ospf6_snmp_init (struct thread_master *); - -#endif /*OSPF6_SNMP_H*/ - - diff --git a/ospf6d/ospf6d.c b/ospf6d/ospf6d.c index 2aaed5fcbf..9a5868f57e 100644 --- a/ospf6d/ospf6d.c +++ b/ospf6d/ospf6d.c @@ -46,7 +46,7 @@ #include "ospf6_bfd.h" #ifdef HAVE_SNMP -#include "ospf6_snmp.h" +extern void ospf6_snmp_init (struct thread_master *); #endif /*HAVE_SNMP*/ char ospf6_daemon_version[] = OSPF6_DAEMON_VERSION; diff --git a/ospfd/Makefile.am b/ospfd/Makefile.am index 5555fb0da4..52c7dade7c 100644 --- a/ospfd/Makefile.am +++ b/ospfd/Makefile.am @@ -26,7 +26,7 @@ ospfdheader_HEADERS = \ noinst_HEADERS = \ ospf_interface.h ospf_neighbor.h ospf_network.h ospf_packet.h \ ospf_zebra.h ospf_spf.h ospf_route.h ospf_ase.h ospf_abr.h ospf_ia.h \ - ospf_flood.h ospf_snmp.h ospf_te.h ospf_ri.h ospf_vty.h ospf_apiserver.h \ + ospf_flood.h ospf_te.h ospf_ri.h ospf_vty.h ospf_apiserver.h \ ospf_bfd.h ospf_memory.h ospfd_SOURCES = ospf_main.c diff --git a/ospfd/ospf_interface.c b/ospfd/ospf_interface.c index 4fb206589a..b4a282a52a 100644 --- a/ospfd/ospf_interface.c +++ b/ospfd/ospf_interface.c @@ -47,11 +47,10 @@ #include "ospfd/ospf_abr.h" #include "ospfd/ospf_network.h" #include "ospfd/ospf_dump.h" -#ifdef HAVE_SNMP -#include "ospfd/ospf_snmp.h" -#endif /* HAVE_SNMP */ DEFINE_QOBJ_TYPE(ospf_interface) +DEFINE_HOOK(ospf_vl_add, (struct ospf_vl_data *vd), (vd)) +DEFINE_HOOK(ospf_vl_delete, (struct ospf_vl_data *vd), (vd)) int ospf_if_get_output_cost (struct ospf_interface *oi) @@ -993,9 +992,7 @@ void ospf_vl_add (struct ospf *ospf, struct ospf_vl_data *vl_data) { listnode_add (ospf->vlinks, vl_data); -#ifdef HAVE_SNMP - ospf_snmp_vl_add (vl_data); -#endif /* HAVE_SNMP */ + hook_call(ospf_vl_add, vl_data); } void @@ -1004,9 +1001,7 @@ ospf_vl_delete (struct ospf *ospf, struct ospf_vl_data *vl_data) ospf_vl_shutdown (vl_data); ospf_vl_if_delete (vl_data); -#ifdef HAVE_SNMP - ospf_snmp_vl_delete (vl_data); -#endif /* HAVE_SNMP */ + hook_call(ospf_vl_delete, vl_data); listnode_delete (ospf->vlinks, vl_data); ospf_vl_data_free (vl_data); diff --git a/ospfd/ospf_interface.h b/ospfd/ospf_interface.h index bd51bbf422..39202f777a 100644 --- a/ospfd/ospf_interface.h +++ b/ospfd/ospf_interface.h @@ -24,6 +24,7 @@ #define _ZEBRA_OSPF_INTERFACE_H #include "qobj.h" +#include "hook.h" #include "ospfd/ospf_packet.h" #include "ospfd/ospf_spf.h" @@ -309,4 +310,7 @@ extern u_char ospf_default_iftype (struct interface *ifp); state of the interface. */ extern void ospf_if_set_multicast (struct ospf_interface *); +DECLARE_HOOK(ospf_vl_add, (struct ospf_vl_data *vd), (vd)) +DECLARE_HOOK(ospf_vl_delete, (struct ospf_vl_data *vd), (vd)) + #endif /* _ZEBRA_OSPF_INTERFACE_H */ diff --git a/ospfd/ospf_ism.c b/ospfd/ospf_ism.c index 9630616acc..717c99c21f 100644 --- a/ospfd/ospf_ism.c +++ b/ospfd/ospf_ism.c @@ -43,7 +43,10 @@ #include "ospfd/ospf_packet.h" #include "ospfd/ospf_flood.h" #include "ospfd/ospf_abr.h" -#include "ospfd/ospf_snmp.h" + +DEFINE_HOOK(ospf_ism_change, + (struct ospf_interface *oi, int state, int oldstate), + (oi, state, oldstate)) /* elect DR and BDR. Refer to RFC2319 section 9.4 */ static struct ospf_neighbor * @@ -545,19 +548,7 @@ ism_change_state (struct ospf_interface *oi, int state) oi->state = state; oi->state_change++; -#ifdef HAVE_SNMP - /* Terminal state or regression */ - if ((state == ISM_DR) || (state == ISM_Backup) || (state == ISM_DROther) || - (state == ISM_PointToPoint) || (state < old_state)) - { - /* ospfVirtIfStateChange */ - if (oi->type == OSPF_IFTYPE_VIRTUALLINK) - ospfTrapVirtIfStateChange (oi); - /* ospfIfStateChange */ - else - ospfTrapIfStateChange (oi); - } -#endif + hook_call(ospf_ism_change, oi, state, old_state); /* Set multicast memberships appropriately for new state. */ ospf_if_set_multicast(oi); diff --git a/ospfd/ospf_ism.h b/ospfd/ospf_ism.h index f0357a4824..fa8e6d70f6 100644 --- a/ospfd/ospf_ism.h +++ b/ospfd/ospf_ism.h @@ -24,6 +24,8 @@ #ifndef _ZEBRA_OSPF_ISM_H #define _ZEBRA_OSPF_ISM_H +#include "hook.h" + /* OSPF Interface State Machine Status. */ #define ISM_DependUpon 0 #define ISM_Down 1 @@ -35,10 +37,6 @@ #define ISM_DR 7 #define OSPF_ISM_STATE_MAX 8 -/* Because DR/DROther values are exhanged wrt RFC */ -#define ISM_SNMP(x) (((x) == ISM_DROther) ? ISM_DR : \ - ((x) == ISM_DR) ? ISM_DROther : (x)) - /* OSPF Interface State Machine Event. */ #define ISM_NoEvent 0 #define ISM_InterfaceUp 1 @@ -111,4 +109,8 @@ extern int ospf_ism_event (struct thread *); extern void ism_change_status (struct ospf_interface *, int); extern int ospf_hello_timer (struct thread *thread); +DECLARE_HOOK(ospf_ism_change, + (struct ospf_interface *oi, int state, int oldstate), + (oi, state, oldstate)) + #endif /* _ZEBRA_OSPF_ISM_H */ diff --git a/ospfd/ospf_nsm.c b/ospfd/ospf_nsm.c index 01617055ce..97f3f6a382 100644 --- a/ospfd/ospf_nsm.c +++ b/ospfd/ospf_nsm.c @@ -48,9 +48,12 @@ #include "ospfd/ospf_dump.h" #include "ospfd/ospf_flood.h" #include "ospfd/ospf_abr.h" -#include "ospfd/ospf_snmp.h" #include "ospfd/ospf_bfd.h" +DEFINE_HOOK(ospf_nsm_change, + (struct ospf_neighbor *on, int state, int oldstate), + (on, state, oldstate)) + static void nsm_clear_adj (struct ospf_neighbor *); /* OSPF NSM Timer functions. */ @@ -838,35 +841,12 @@ ospf_nsm_event (struct thread *thread) /* If state is changed. */ if (next_state != nbr->state) { + int old_state = nbr->state; + nsm_notice_state_change (nbr, next_state, event); -#ifdef HAVE_SNMP - int send_trap_virt = 0; - int send_trap = 0; - /* Terminal state or regression */ - if ((next_state == NSM_Full) - || (next_state == NSM_TwoWay) - || (next_state < nbr->state)) - { - /* ospfVirtNbrStateChange */ - if (nbr->oi->type == OSPF_IFTYPE_VIRTUALLINK) - send_trap_virt = 1; - /* ospfNbrStateChange trap */ - else - /* To/From FULL, only managed by DR */ - if (((next_state != NSM_Full) && (nbr->state != NSM_Full)) - || (nbr->oi->state == ISM_DR)) - send_trap = 1; - } -#endif nsm_change_state (nbr, next_state); -#ifdef HAVE_SNMP - if (send_trap_virt) { - ospfTrapVirtNbrStateChange(nbr); - } else if (send_trap) { - ospfTrapNbrStateChange(nbr); - } -#endif + hook_call(ospf_nsm_change, nbr, next_state, old_state); } /* Make sure timer is set. */ diff --git a/ospfd/ospf_nsm.h b/ospfd/ospf_nsm.h index 9b7e14a4ae..4531f6ec7d 100644 --- a/ospfd/ospf_nsm.h +++ b/ospfd/ospf_nsm.h @@ -24,6 +24,8 @@ #ifndef _ZEBRA_OSPF_NSM_H #define _ZEBRA_OSPF_NSM_H +#include "hook.h" + /* OSPF Neighbor State Machine State. */ #define NSM_DependUpon 0 #define NSM_Deleted 1 @@ -86,5 +88,9 @@ extern int ospf_db_summary_isempty (struct ospf_neighbor *); extern int ospf_db_summary_count (struct ospf_neighbor *); extern void ospf_db_summary_clear (struct ospf_neighbor *); +DECLARE_HOOK(ospf_nsm_change, + (struct ospf_neighbor *on, int state, int oldstate), + (on, state, oldstate)) + #endif /* _ZEBRA_OSPF_NSM_H */ diff --git a/ospfd/ospf_snmp.c b/ospfd/ospf_snmp.c index 4afbda8788..b5813d7d53 100644 --- a/ospfd/ospf_snmp.c +++ b/ospfd/ospf_snmp.c @@ -47,7 +47,7 @@ #include "ospfd/ospf_flood.h" #include "ospfd/ospf_ism.h" #include "ospfd/ospf_dump.h" -#include "ospfd/ospf_snmp.h" +#include "ospfd/ospf_zebra.h" /* OSPF2-MIB. */ #define OSPF2MIB 1,3,6,1,2,1,14 @@ -205,6 +205,10 @@ #define IPADDRESS ASN_IPADDRESS #define STRING ASN_OCTET_STR +/* Because DR/DROther values are exhanged wrt RFC */ +#define ISM_SNMP(x) (((x) == ISM_DROther) ? ISM_DR : \ + ((x) == ISM_DR) ? ISM_DROther : (x)) + /* Declare static local variables for convenience. */ SNMP_LOCAL_VARIABLES @@ -1429,7 +1433,7 @@ ospf_snmp_if_free (struct ospf_snmp_if *osif) XFREE (MTYPE_TMP, osif); } -void +static int ospf_snmp_if_delete (struct interface *ifp) { struct listnode *node, *nnode; @@ -1441,12 +1445,13 @@ ospf_snmp_if_delete (struct interface *ifp) { list_delete_node (ospf_snmp_iflist, node); ospf_snmp_if_free (osif); - return; + break; } } + return 0; } -void +static int ospf_snmp_if_update (struct interface *ifp) { struct listnode *node; @@ -1511,6 +1516,7 @@ ospf_snmp_if_update (struct interface *ifp) osif->ifp = ifp; listnode_add_after (ospf_snmp_iflist, pn, osif); + return 0; } static int @@ -1914,7 +1920,7 @@ ospfIfMetricEntry (struct variable *v, oid *name, size_t *length, int exact, static struct route_table *ospf_snmp_vl_table; -void +static int ospf_snmp_vl_add (struct ospf_vl_data *vl_data) { struct prefix_ls lp; @@ -1931,9 +1937,10 @@ ospf_snmp_vl_add (struct ospf_vl_data *vl_data) route_unlock_node (rn); rn->info = vl_data; + return 0; } -void +static int ospf_snmp_vl_delete (struct ospf_vl_data *vl_data) { struct prefix_ls lp; @@ -1947,10 +1954,11 @@ ospf_snmp_vl_delete (struct ospf_vl_data *vl_data) rn = route_node_lookup (ospf_snmp_vl_table, (struct prefix *) &lp); if (! rn) - return; + return 0; rn->info = NULL; route_unlock_node (rn); route_unlock_node (rn); + return 0; } static struct ospf_vl_data * @@ -2651,7 +2659,7 @@ static struct trap_object ospfVirtIfTrapList[] = {3, {9, 1, OSPFVIRTIFSTATE}} }; -void +static void ospfTrapNbrStateChange (struct ospf_neighbor *on) { oid index[sizeof (oid) * (IN_ADDR_SIZE + 1)]; @@ -2673,7 +2681,7 @@ ospfTrapNbrStateChange (struct ospf_neighbor *on) NBRSTATECHANGE); } -void +static void ospfTrapVirtNbrStateChange (struct ospf_neighbor *on) { oid index[sizeof (oid) * (IN_ADDR_SIZE + 1)]; @@ -2692,7 +2700,29 @@ ospfTrapVirtNbrStateChange (struct ospf_neighbor *on) VIRTNBRSTATECHANGE); } -void +static int +ospf_snmp_nsm_change (struct ospf_neighbor *nbr, + int next_state, int old_state) +{ + /* Terminal state or regression */ + if ((next_state == NSM_Full) + || (next_state == NSM_TwoWay) + || (next_state < old_state)) + { + /* ospfVirtNbrStateChange */ + if (nbr->oi->type == OSPF_IFTYPE_VIRTUALLINK) + ospfTrapVirtNbrStateChange(nbr); + /* ospfNbrStateChange trap */ + else + /* To/From FULL, only managed by DR */ + if (((next_state != NSM_Full) && (nbr->state != NSM_Full)) + || (nbr->oi->state == ISM_DR)) + ospfTrapNbrStateChange(nbr); + } + return 0; +} + +static void ospfTrapIfStateChange (struct ospf_interface *oi) { oid index[sizeof (oid) * (IN_ADDR_SIZE + 1)]; @@ -2713,7 +2743,7 @@ ospfTrapIfStateChange (struct ospf_interface *oi) IFSTATECHANGE); } -void +static void ospfTrapVirtIfStateChange (struct ospf_interface *oi) { oid index[sizeof (oid) * (IN_ADDR_SIZE + 1)]; @@ -2731,10 +2761,36 @@ ospfTrapVirtIfStateChange (struct ospf_interface *oi) sizeof ospfVirtIfTrapList / sizeof (struct trap_object), VIRTIFSTATECHANGE); } + +static int +ospf_snmp_ism_change (struct ospf_interface *oi, + int state, int old_state) +{ + /* Terminal state or regression */ + if ((state == ISM_DR) || (state == ISM_Backup) || (state == ISM_DROther) || + (state == ISM_PointToPoint) || (state < old_state)) + { + /* ospfVirtIfStateChange */ + if (oi->type == OSPF_IFTYPE_VIRTUALLINK) + ospfTrapVirtIfStateChange (oi); + /* ospfIfStateChange */ + else + ospfTrapIfStateChange (oi); + } + return 0; +} + /* Register OSPF2-MIB. */ void ospf_snmp_init () { + hook_register(ospf_if_update, ospf_snmp_if_update); + hook_register(ospf_if_delete, ospf_snmp_if_delete); + hook_register(ospf_vl_add, ospf_snmp_vl_add); + hook_register(ospf_vl_delete, ospf_snmp_vl_delete); + hook_register(ospf_ism_change, ospf_snmp_ism_change); + hook_register(ospf_nsm_change, ospf_snmp_nsm_change); + ospf_snmp_iflist = list_new (); ospf_snmp_vl_table = route_table_init (); smux_init (om->master); diff --git a/ospfd/ospf_snmp.h b/ospfd/ospf_snmp.h deleted file mode 100644 index 413d1d7f79..0000000000 --- a/ospfd/ospf_snmp.h +++ /dev/null @@ -1,38 +0,0 @@ -/* OSPFv2 SNMP support - * Copyright (C) 2000 IP Infusion Inc. - * - * Written by Kunihiro Ishiguro - * - * This file is part of GNU Zebra. - * - * 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. - */ - -#ifndef _ZEBRA_OSPF_SNMP_H -#define _ZEBRA_OSPF_SNMP_H - -extern void ospf_snmp_if_update (struct interface *); -extern void ospf_snmp_if_delete (struct interface *); - -extern void ospf_snmp_vl_add (struct ospf_vl_data *); -extern void ospf_snmp_vl_delete (struct ospf_vl_data *); - -extern void ospfTrapIfStateChange (struct ospf_interface *); -extern void ospfTrapVirtIfStateChange (struct ospf_interface *); -extern void ospfTrapNbrStateChange (struct ospf_neighbor *); -extern void ospfTrapVirtNbrStateChange (struct ospf_neighbor *); - -#endif /* _ZEBRA_OSPF_SNMP_H */ diff --git a/ospfd/ospf_zebra.c b/ospfd/ospf_zebra.c index cb14273eed..abb6db0347 100644 --- a/ospfd/ospf_zebra.c +++ b/ospfd/ospf_zebra.c @@ -50,11 +50,11 @@ #include "ospfd/ospf_neighbor.h" #include "ospfd/ospf_nsm.h" #include "ospfd/ospf_zebra.h" -#ifdef HAVE_SNMP -#include "ospfd/ospf_snmp.h" -#endif /* HAVE_SNMP */ #include "ospfd/ospf_te.h" +DEFINE_HOOK(ospf_if_update, (struct interface *ifp), (ifp)) +DEFINE_HOOK(ospf_if_delete, (struct interface *ifp), (ifp)) + /* Zebra structure to hold current status. */ struct zclient *zclient = NULL; @@ -112,9 +112,7 @@ ospf_interface_add (int command, struct zclient *zclient, zebra_size_t length, ospf_if_update (NULL, ifp); -#ifdef HAVE_SNMP - ospf_snmp_if_update (ifp); -#endif /* HAVE_SNMP */ + hook_call(ospf_if_update, ifp); return 0; } @@ -143,9 +141,7 @@ ospf_interface_delete (int command, struct zclient *zclient, ("Zebra: interface delete %s[%u] index %d flags %llx metric %d mtu %d", ifp->name, ifp->vrf_id, ifp->ifindex, (unsigned long long)ifp->flags, ifp->metric, ifp->mtu); -#ifdef HAVE_SNMP - ospf_snmp_if_delete (ifp); -#endif /* HAVE_SNMP */ + hook_call(ospf_if_delete, ifp); for (rn = route_top (IF_OIFS (ifp)); rn; rn = route_next (rn)) if (rn->info) @@ -277,9 +273,7 @@ ospf_interface_address_add (int command, struct zclient *zclient, ospf_if_update (NULL, c->ifp); -#ifdef HAVE_SNMP - ospf_snmp_if_update (c->ifp); -#endif /* HAVE_SNMP */ + hook_call(ospf_if_update, c->ifp); return 0; } @@ -324,9 +318,7 @@ ospf_interface_address_delete (int command, struct zclient *zclient, /* Call interface hook functions to clean up */ ospf_if_free (oi); -#ifdef HAVE_SNMP - ospf_snmp_if_update (c->ifp); -#endif /* HAVE_SNMP */ + hook_call(ospf_if_update, c->ifp); connected_free (c); diff --git a/ospfd/ospf_zebra.h b/ospfd/ospf_zebra.h index 8e93ed2691..22c71a49e1 100644 --- a/ospfd/ospf_zebra.h +++ b/ospfd/ospf_zebra.h @@ -24,6 +24,7 @@ #define _ZEBRA_OSPF_ZEBRA_H #include "vty.h" +#include "hook.h" #define EXTERNAL_METRIC_TYPE_1 0 #define EXTERNAL_METRIC_TYPE_2 1 @@ -79,5 +80,8 @@ extern int ospf_distance_unset (struct vty *, struct ospf *, const char *, const char *, const char *); extern void ospf_zebra_init(struct thread_master *, u_short); +DECLARE_HOOK(ospf_if_update, (struct interface *ifp), (ifp)) +DECLARE_HOOK(ospf_if_delete, (struct interface *ifp), (ifp)) + #endif /* _ZEBRA_OSPF_ZEBRA_H */ diff --git a/ripd/rip_interface.c b/ripd/rip_interface.c index 4c750faf4c..a4ee2ba570 100644 --- a/ripd/rip_interface.c +++ b/ripd/rip_interface.c @@ -42,6 +42,9 @@ #include "ripd/rip_debug.h" #include "ripd/rip_interface.h" +DEFINE_HOOK(rip_ifaddr_add, (struct connected *ifc), (ifc)) +DEFINE_HOOK(rip_ifaddr_del, (struct connected *ifc), (ifc)) + /* static prototypes */ static void rip_enable_apply (struct interface *); static void rip_passive_interface_apply (struct interface *); @@ -673,9 +676,7 @@ rip_interface_address_add (int command, struct zclient *zclient, /* Check if this prefix needs to be redistributed */ rip_apply_address_add(ifc); -#ifdef HAVE_SNMP - rip_ifaddr_add (ifc->ifp, ifc); -#endif /* HAVE_SNMP */ + hook_call(rip_ifaddr_add, ifc); } return 0; @@ -723,9 +724,7 @@ rip_interface_address_delete (int command, struct zclient *zclient, zlog_debug ("connected address %s/%d is deleted", inet_ntoa (p->u.prefix4), p->prefixlen); -#ifdef HAVE_SNMP - rip_ifaddr_delete (ifc->ifp, ifc); -#endif /* HAVE_SNMP */ + hook_call(rip_ifaddr_del, ifc); /* Chech wether this prefix needs to be removed */ rip_apply_address_del(ifc); diff --git a/ripd/rip_snmp.c b/ripd/rip_snmp.c index 36fd9c26ec..bdae0409d2 100644 --- a/ripd/rip_snmp.c +++ b/ripd/rip_snmp.c @@ -175,24 +175,27 @@ rip2Globals (struct variable *v, oid name[], size_t *length, return NULL; } -void -rip_ifaddr_add (struct interface *ifp, struct connected *ifc) +static int +rip_snmp_ifaddr_add (struct connected *ifc) { + struct interface *ifp = ifc->ifp; struct prefix *p; struct route_node *rn; p = ifc->address; if (p->family != AF_INET) - return; + return 0; rn = route_node_get (rip_ifaddr_table, p); rn->info = ifp; + return 0; } -void -rip_ifaddr_delete (struct interface *ifp, struct connected *ifc) +static int +rip_snmp_ifaddr_del (struct connected *ifc) { + struct interface *ifp = ifc->ifp; struct prefix *p; struct route_node *rn; struct interface *i; @@ -200,11 +203,11 @@ rip_ifaddr_delete (struct interface *ifp, struct connected *ifc) p = ifc->address; if (p->family != AF_INET) - return; + return 0; rn = route_node_lookup (rip_ifaddr_table, p); if (! rn) - return; + return 0; i = rn->info; if (rn && !strncmp(i->name,ifp->name,INTERFACE_NAMSIZ)) { @@ -212,6 +215,7 @@ rip_ifaddr_delete (struct interface *ifp, struct connected *ifc) route_unlock_node (rn); route_unlock_node (rn); } + return 0; } static struct interface * @@ -587,6 +591,8 @@ void rip_snmp_init () { rip_ifaddr_table = route_table_init (); + hook_register(rip_ifaddr_add, rip_snmp_ifaddr_add); + hook_register(rip_ifaddr_del, rip_snmp_ifaddr_del); smux_init (master); REGISTER_MIB("mibII/rip", rip_variables, variable, rip_oid); diff --git a/ripd/ripd.h b/ripd/ripd.h index 68b3d1fc6e..66113cdc95 100644 --- a/ripd/ripd.h +++ b/ripd/ripd.h @@ -23,6 +23,7 @@ #define _ZEBRA_RIP_H #include "qobj.h" +#include "hook.h" #include "rip_memory.h" /* RIP version number. */ @@ -432,8 +433,6 @@ extern void rip_offset_clean (void); extern void rip_info_free (struct rip_info *); extern u_char rip_distance_apply (struct rip_info *); extern void rip_redistribute_clean (void); -extern void rip_ifaddr_add (struct interface *, struct connected *); -extern void rip_ifaddr_delete (struct interface *, struct connected *); extern struct rip_info *rip_ecmp_add (struct rip_info *); extern struct rip_info *rip_ecmp_replace (struct rip_info *); @@ -448,4 +447,8 @@ extern struct thread_master *master; /* RIP statistics for SNMP. */ extern long rip_global_route_changes; extern long rip_global_queries; + +DECLARE_HOOK(rip_ifaddr_add, (struct connected *ifc), (ifc)) +DECLARE_HOOK(rip_ifaddr_del, (struct connected *ifc), (ifc)) + #endif /* _ZEBRA_RIP_H */ From 5986b66b82d2c8a15c9467032d912be07481f07d Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Sun, 12 Jun 2016 17:52:50 +0200 Subject: [PATCH 14/61] *: snmp: convert into modules Signed-off-by: David Lamparter --- bgpd/Makefile.am | 15 ++++++++++++--- bgpd/bgp_snmp.c | 29 +++++++++++++++++++++-------- bgpd/bgpd.c | 4 ---- configure.ac | 1 - lib/Makefile.am | 6 +++++- lib/agentx.c | 4 ++-- lib/smux.c | 4 ++-- lib/snmp.c | 2 -- ospf6d/Makefile.am | 12 ++++++++++-- ospf6d/ospf6_snmp.c | 29 +++++++++++++++++++---------- ospf6d/ospf6d.c | 8 -------- ospfd/Makefile.am | 12 ++++++++++-- ospfd/ospf_main.c | 3 --- ospfd/ospf_snmp.c | 31 +++++++++++++++++++++++-------- ospfd/ospfd.h | 1 - ripd/Makefile.am | 12 ++++++++++-- ripd/rip_snmp.c | 28 ++++++++++++++++++++++------ ripd/ripd.c | 5 ----- ripd/ripd.h | 1 - zebra/Makefile.am | 13 ++++++++++--- zebra/main.c | 4 ---- zebra/zebra_snmp.c | 26 +++++++++++++++++++++----- zebra/zserv.h | 1 - 23 files changed, 167 insertions(+), 84 deletions(-) diff --git a/bgpd/Makefile.am b/bgpd/Makefile.am index 4050e01620..af6c8faf03 100644 --- a/bgpd/Makefile.am +++ b/bgpd/Makefile.am @@ -67,6 +67,7 @@ INSTALL_SDATA=@INSTALL@ -m 600 AM_CFLAGS = $(WERROR) noinst_LIBRARIES = libbgp.a +module_LTLIBRARIES = sbin_PROGRAMS = bgpd bin_PROGRAMS = bgp_btoa @@ -75,7 +76,7 @@ libbgp_a_SOURCES = \ bgpd.c bgp_fsm.c bgp_aspath.c bgp_community.c bgp_attr.c \ bgp_debug.c bgp_route.c bgp_zebra.c bgp_open.c bgp_routemap.c \ bgp_packet.c bgp_network.c bgp_filter.c bgp_regex.c bgp_clist.c \ - bgp_dump.c bgp_snmp.c bgp_ecommunity.c bgp_lcommunity.c \ + bgp_dump.c bgp_ecommunity.c bgp_lcommunity.c \ bgp_mplsvpn.c bgp_nexthop.c \ bgp_damp.c bgp_table.c bgp_advertise.c bgp_vty.c bgp_mpath.c \ bgp_nht.c bgp_updgrp.c bgp_updgrp_packet.c bgp_updgrp_adv.c bgp_bfd.c \ @@ -94,13 +95,21 @@ noinst_HEADERS = \ $(BGP_VNC_RFAPI_HD) bgp_attr_evpn.h bgp_evpn.h bgp_evpn_vty.h bgp_vpn.h bgpd_SOURCES = bgp_main.c -bgpd_LDADD = libbgp.a $(BGP_VNC_RFP_LIB) ../lib/libfrr.la ../lib/libfrrsnmp.la @LIBCAP@ @LIBM@ +bgpd_LDADD = libbgp.a $(BGP_VNC_RFP_LIB) ../lib/libfrr.la @LIBCAP@ @LIBM@ bgpd_LDFLAGS = $(BGP_VNC_RFP_LD_FLAGS) bgp_btoa_SOURCES = bgp_btoa.c -bgp_btoa_LDADD = libbgp.a $(BGP_VNC_RFP_LIB) ../lib/libfrr.la ../lib/libfrrsnmp.la @LIBCAP@ @LIBM@ +bgp_btoa_LDADD = libbgp.a $(BGP_VNC_RFP_LIB) ../lib/libfrr.la @LIBCAP@ @LIBM@ bgp_btoa_LDFLAGS = $(BGP_VNC_RFP_LD_FLAGS) +if SNMP +module_LTLIBRARIES += bgpd_snmp.la +endif + +bgpd_snmp_la_SOURCES = bgp_snmp.c +bgpd_snmp_la_LDFLAGS = -avoid-version -module -shared -export-dynamic +bgpd_snmp_la_LIBADD = ../lib/libfrrsnmp.la + examplesdir = $(exampledir) dist_examples_DATA = bgpd.conf.sample bgpd.conf.sample2 \ bgpd.conf.vnc.sample diff --git a/bgpd/bgp_snmp.c b/bgpd/bgp_snmp.c index 6896c86e40..f45d683848 100644 --- a/bgpd/bgp_snmp.c +++ b/bgpd/bgp_snmp.c @@ -20,7 +20,6 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #include -#ifdef HAVE_SNMP #include #include @@ -31,6 +30,9 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #include "thread.h" #include "smux.h" #include "filter.h" +#include "hook.h" +#include "libfrr.h" +#include "version.h" #include "bgpd/bgpd.h" #include "bgpd/bgp_table.h" @@ -881,15 +883,26 @@ bgpTrapBackwardTransition (struct peer *peer) return 0; } -void bgp_snmp_init (void); +static int +bgp_snmp_init (struct thread_master *tm) +{ + smux_init (tm); + REGISTER_MIB("mibII/bgp", bgp_variables, variable, bgp_oid); + return 0; +} -void -bgp_snmp_init (void) +static int +bgp_snmp_module_init (void) { hook_register(peer_established, bgpTrapEstablished); hook_register(peer_backward_transition, bgpTrapBackwardTransition); - - smux_init (bm->master); - REGISTER_MIB("mibII/bgp", bgp_variables, variable, bgp_oid); + hook_register(frr_late_init, bgp_snmp_init); + return 0; } -#endif /* HAVE_SNMP */ + +FRR_MODULE_SETUP( + .name = "bgpd_snmp", + .version = FRR_VERSION, + .description = "bgpd AgentX SNMP module", + .init = bgp_snmp_module_init +) diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index 031cab902a..1733f2956c 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -7694,10 +7694,6 @@ bgp_init (void) /* Community list initialize. */ bgp_clist = community_list_init (); -#ifdef HAVE_SNMP - bgp_snmp_init (); -#endif /* HAVE_SNMP */ - /* BFD init */ bgp_bfd_init(); } diff --git a/configure.ac b/configure.ac index 27d4561910..466acb25d8 100755 --- a/configure.ac +++ b/configure.ac @@ -1337,7 +1337,6 @@ int main(void); ])],[AC_MSG_RESULT(yes)],[ AC_MSG_RESULT(no) AC_MSG_ERROR([--enable-snmp given but not usable])]) - AC_DEFINE(HAVE_SNMP,,SNMP) case "${enable_snmp}" in yes) SNMP_METHOD=agentx diff --git a/lib/Makefile.am b/lib/Makefile.am index 14259f2e0d..14b7130c8a 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -10,7 +10,7 @@ command_lex.h: command_lex.c @if test ! -f $@; then $(MAKE) $(AM_MAKEFLAGS) command_lex.c; else :; fi command_parse.lo: command_lex.h -lib_LTLIBRARIES = libfrr.la libfrrsnmp.la +lib_LTLIBRARIES = libfrr.la libfrr_la_LDFLAGS = -version-info 0:0:0 libfrr_la_SOURCES = \ @@ -40,6 +40,10 @@ BUILT_SOURCES = route_types.h gitversion.h command_parse.h command_lex.h libfrr_la_LIBADD = @LIBCAP@ +if SNMP +lib_LTLIBRARIES += libfrrsnmp.la +endif + libfrrsnmp_la_CFLAGS = $(WERROR) $(SNMP_CFLAGS) libfrrsnmp_la_LDFLAGS = -version-info 0:0:0 libfrrsnmp_la_LIBADD = libfrr.la $(SNMP_LIBS) diff --git a/lib/agentx.c b/lib/agentx.c index 4175e7ba92..11d5c9385d 100644 --- a/lib/agentx.c +++ b/lib/agentx.c @@ -21,7 +21,7 @@ #include -#if defined HAVE_SNMP && defined SNMP_AGENTX +#ifdef SNMP_AGENTX #include #include #include @@ -315,4 +315,4 @@ smux_trap (struct variable *vp, size_t vp_len, return 1; } -#endif /* HAVE_SNMP */ +#endif /* SNMP_AGENTX */ diff --git a/lib/smux.c b/lib/smux.c index 3abfadcd28..370b8f138e 100644 --- a/lib/smux.c +++ b/lib/smux.c @@ -21,7 +21,7 @@ #include -#if defined HAVE_SNMP && defined SNMP_SMUX +#ifdef SNMP_SMUX #include #include @@ -1445,4 +1445,4 @@ smux_start(void) /* Schedule first connection. */ smux_event (SMUX_SCHEDULE, 0); } -#endif /* HAVE_SNMP */ +#endif /* SNMP_SMUX */ diff --git a/lib/snmp.c b/lib/snmp.c index f6f9845e2d..1cbd41c720 100644 --- a/lib/snmp.c +++ b/lib/snmp.c @@ -21,7 +21,6 @@ #include -#ifdef HAVE_SNMP #include #include @@ -130,4 +129,3 @@ smux_header_table (struct variable *v, oid *name, size_t *length, int exact, return MATCH_SUCCEEDED; } -#endif /* HAVE_SNMP */ diff --git a/ospf6d/Makefile.am b/ospf6d/Makefile.am index 30268c6882..933a97ca8f 100644 --- a/ospf6d/Makefile.am +++ b/ospf6d/Makefile.am @@ -7,6 +7,7 @@ INSTALL_SDATA=@INSTALL@ -m 600 AM_CFLAGS = $(WERROR) noinst_LIBRARIES = libospf6.a +module_LTLIBRARIES = sbin_PROGRAMS = ospf6d libospf6_a_SOURCES = \ @@ -14,7 +15,7 @@ libospf6_a_SOURCES = \ ospf6_network.c ospf6_message.c ospf6_lsa.c ospf6_lsdb.c \ ospf6_top.c ospf6_area.c ospf6_interface.c ospf6_neighbor.c \ ospf6_flood.c ospf6_route.c ospf6_intra.c ospf6_zebra.c \ - ospf6_spf.c ospf6_proto.c ospf6_asbr.c ospf6_abr.c ospf6_snmp.c \ + ospf6_spf.c ospf6_proto.c ospf6_asbr.c ospf6_abr.c \ ospf6d.c ospf6_bfd.c noinst_HEADERS = \ @@ -28,7 +29,14 @@ noinst_HEADERS = \ ospf6d_SOURCES = \ ospf6_main.c $(libospf6_a_SOURCES) -ospf6d_LDADD = ../lib/libfrr.la ../lib/libfrrsnmp.la @LIBCAP@ +ospf6d_LDADD = ../lib/libfrr.la @LIBCAP@ + +if SNMP +module_LTLIBRARIES += ospf6d_snmp.la +endif +ospf6d_snmp_la_SOURCES = ospf6_snmp.c +ospf6d_snmp_la_LDFLAGS = -avoid-version -module -shared -export-dynamic +ospf6d_snmp_la_LIBADD = ../lib/libfrrsnmp.la examplesdir = $(exampledir) dist_examples_DATA = ospf6d.conf.sample diff --git a/ospf6d/ospf6_snmp.c b/ospf6d/ospf6_snmp.c index 57fc94fd52..96f1e3dd21 100644 --- a/ospf6d/ospf6_snmp.c +++ b/ospf6d/ospf6_snmp.c @@ -21,8 +21,6 @@ #include -#ifdef HAVE_SNMP - #include #include @@ -32,6 +30,8 @@ #include "vector.h" #include "vrf.h" #include "smux.h" +#include "libfrr.h" +#include "version.h" #include "ospf6_proto.h" #include "ospf6_lsa.h" @@ -46,8 +46,6 @@ #include "ospf6_asbr.h" #include "ospf6d.h" -void ospf6_snmp_init (struct thread_master *master); - /* OSPFv3-MIB */ #define OSPFv3MIB 1,3,6,1,2,1,191 @@ -1194,15 +1192,26 @@ ospf6TrapIfStateChange (struct ospf6_interface *oi, } /* Register OSPFv3-MIB. */ -void +static int ospf6_snmp_init (struct thread_master *master) +{ + smux_init (master); + REGISTER_MIB ("OSPFv3MIB", ospfv3_variables, variable, ospfv3_oid); + return 0; +} + +static int +ospf6_snmp_module_init (void) { hook_register(ospf6_interface_change, ospf6TrapIfStateChange); hook_register(ospf6_neighbor_change, ospf6TrapNbrStateChange); - - smux_init (master); - REGISTER_MIB ("OSPFv3MIB", ospfv3_variables, variable, ospfv3_oid); + hook_register(frr_late_init, ospf6_snmp_init); + return 0; } -#endif /* HAVE_SNMP */ - +FRR_MODULE_SETUP( + .name = "ospf6d_snmp", + .version = FRR_VERSION, + .description = "ospf6d AgentX SNMP module", + .init = ospf6_snmp_module_init, +) diff --git a/ospf6d/ospf6d.c b/ospf6d/ospf6d.c index 9a5868f57e..036cc6d4c8 100644 --- a/ospf6d/ospf6d.c +++ b/ospf6d/ospf6d.c @@ -45,10 +45,6 @@ #include "ospf6d.h" #include "ospf6_bfd.h" -#ifdef HAVE_SNMP -extern void ospf6_snmp_init (struct thread_master *); -#endif /*HAVE_SNMP*/ - char ospf6_daemon_version[] = OSPF6_DAEMON_VERSION; struct route_node * @@ -1215,10 +1211,6 @@ ospf6_init (void) ospf6_asbr_init (); ospf6_abr_init (); -#ifdef HAVE_SNMP - ospf6_snmp_init (master); -#endif /*HAVE_SNMP*/ - ospf6_bfd_init(); install_node (&debug_node, config_write_ospf6_debug); diff --git a/ospfd/Makefile.am b/ospfd/Makefile.am index 52c7dade7c..e9d0ed2192 100644 --- a/ospfd/Makefile.am +++ b/ospfd/Makefile.am @@ -6,13 +6,14 @@ DEFS = @DEFS@ $(LOCAL_OPTS) -DSYSCONFDIR=\"$(sysconfdir)/\" INSTALL_SDATA=@INSTALL@ -m 600 noinst_LIBRARIES = libfrrospf.a +module_LTLIBRARIES = sbin_PROGRAMS = ospfd libfrrospf_a_SOURCES = \ ospfd.c ospf_zebra.c ospf_interface.c ospf_ism.c ospf_neighbor.c \ ospf_nsm.c ospf_dump.c ospf_network.c ospf_packet.c ospf_lsa.c \ ospf_spf.c ospf_route.c ospf_ase.c ospf_abr.c ospf_ia.c ospf_flood.c \ - ospf_lsdb.c ospf_asbr.c ospf_routemap.c ospf_snmp.c \ + ospf_lsdb.c ospf_asbr.c ospf_routemap.c \ ospf_opaque.c ospf_te.c ospf_ri.c ospf_vty.c ospf_api.c ospf_apiserver.c \ ospf_bfd.c ospf_memory.c ospf_dump_api.c @@ -31,7 +32,14 @@ noinst_HEADERS = \ ospfd_SOURCES = ospf_main.c -ospfd_LDADD = libfrrospf.a ../lib/libfrr.la ../lib/libfrrsnmp.la @LIBCAP@ @LIBM@ +ospfd_LDADD = libfrrospf.a ../lib/libfrr.la @LIBCAP@ @LIBM@ + +if SNMP +module_LTLIBRARIES += ospfd_snmp.la +endif +ospfd_snmp_la_SOURCES = ospf_snmp.c +ospfd_snmp_la_LDFLAGS = -avoid-version -module -shared -export-dynamic +ospfd_snmp_la_LIBADD = ../lib/libfrrsnmp.la EXTRA_DIST = OSPF-MIB.txt OSPF-TRAP-MIB.txt ChangeLog.opaque.txt diff --git a/ospfd/ospf_main.c b/ospfd/ospf_main.c index f462c207e4..38718b35d5 100644 --- a/ospfd/ospf_main.c +++ b/ospfd/ospf_main.c @@ -225,9 +225,6 @@ main (int argc, char **argv) ospf_bfd_init(); ospf_route_map_init (); -#ifdef HAVE_SNMP - ospf_snmp_init (); -#endif /* HAVE_SNMP */ ospf_opaque_init (); /* Need to initialize the default ospf structure, so the interface mode diff --git a/ospfd/ospf_snmp.c b/ospfd/ospf_snmp.c index b5813d7d53..32449d5597 100644 --- a/ospfd/ospf_snmp.c +++ b/ospfd/ospf_snmp.c @@ -24,7 +24,6 @@ #include -#ifdef HAVE_SNMP #include #include @@ -35,6 +34,8 @@ #include "command.h" #include "memory.h" #include "smux.h" +#include "libfrr.h" +#include "version.h" #include "ospfd/ospfd.h" #include "ospfd/ospf_interface.h" @@ -2781,8 +2782,18 @@ ospf_snmp_ism_change (struct ospf_interface *oi, } /* Register OSPF2-MIB. */ -void -ospf_snmp_init () +static int +ospf_snmp_init (struct thread_master *tm) +{ + ospf_snmp_iflist = list_new (); + ospf_snmp_vl_table = route_table_init (); + smux_init (tm); + REGISTER_MIB("mibII/ospf", ospf_variables, variable, ospf_oid); + return 0; +} + +static int +ospf_snmp_module_init (void) { hook_register(ospf_if_update, ospf_snmp_if_update); hook_register(ospf_if_delete, ospf_snmp_if_delete); @@ -2791,9 +2802,13 @@ ospf_snmp_init () hook_register(ospf_ism_change, ospf_snmp_ism_change); hook_register(ospf_nsm_change, ospf_snmp_nsm_change); - ospf_snmp_iflist = list_new (); - ospf_snmp_vl_table = route_table_init (); - smux_init (om->master); - REGISTER_MIB("mibII/ospf", ospf_variables, variable, ospf_oid); + hook_register(frr_late_init, ospf_snmp_init); + return 0; } -#endif /* HAVE_SNMP */ + +FRR_MODULE_SETUP( + .name = "ospfd_snmp", + .version = FRR_VERSION, + .description = "ospfd AgentX SNMP module", + .init = ospf_snmp_module_init, +) diff --git a/ospfd/ospfd.h b/ospfd/ospfd.h index a3bd0ca12f..9198d5c620 100644 --- a/ospfd/ospfd.h +++ b/ospfd/ospfd.h @@ -574,7 +574,6 @@ extern void ospf_area_add_if (struct ospf_area *, struct ospf_interface *); extern void ospf_area_del_if (struct ospf_area *, struct ospf_interface *); extern void ospf_route_map_init (void); -extern void ospf_snmp_init (void); extern void ospf_master_init (struct thread_master *master); diff --git a/ripd/Makefile.am b/ripd/Makefile.am index 47c471aebb..827869121c 100644 --- a/ripd/Makefile.am +++ b/ripd/Makefile.am @@ -7,11 +7,12 @@ INSTALL_SDATA=@INSTALL@ -m 600 AM_CFLAGS = $(WERROR) noinst_LIBRARIES = librip.a +module_LTLIBRARIES = sbin_PROGRAMS = ripd librip_a_SOURCES = \ rip_memory.c \ - ripd.c rip_zebra.c rip_interface.c rip_debug.c rip_snmp.c \ + ripd.c rip_zebra.c rip_interface.c rip_debug.c \ rip_routemap.c rip_peer.c rip_offset.c noinst_HEADERS = \ @@ -21,7 +22,14 @@ noinst_HEADERS = \ ripd_SOURCES = \ rip_main.c $(librip_a_SOURCES) -ripd_LDADD = ../lib/libfrr.la ../lib/libfrrsnmp.la @LIBCAP@ +ripd_LDADD = ../lib/libfrr.la @LIBCAP@ + +if SNMP +module_LTLIBRARIES += ripd_snmp.la +endif +ripd_snmp_la_SOURCES = rip_snmp.c +ripd_snmp_la_LDFLAGS = -avoid-version -module -shared -export-dynamic +ripd_snmp_la_LIBADD = ../lib/libfrrsnmp.la examplesdir = $(exampledir) dist_examples_DATA = ripd.conf.sample diff --git a/ripd/rip_snmp.c b/ripd/rip_snmp.c index bdae0409d2..06cd3cef6c 100644 --- a/ripd/rip_snmp.c +++ b/ripd/rip_snmp.c @@ -21,7 +21,6 @@ #include -#ifdef HAVE_SNMP #include #include @@ -32,6 +31,8 @@ #include "command.h" #include "table.h" #include "smux.h" +#include "libfrr.h" +#include "version.h" #include "ripd/ripd.h" @@ -587,14 +588,29 @@ rip2PeerTable (struct variable *v, oid name[], size_t *length, } /* Register RIPv2-MIB. */ -void -rip_snmp_init () +static int +rip_snmp_init (struct thread_master *master) { rip_ifaddr_table = route_table_init (); - hook_register(rip_ifaddr_add, rip_snmp_ifaddr_add); - hook_register(rip_ifaddr_del, rip_snmp_ifaddr_del); smux_init (master); REGISTER_MIB("mibII/rip", rip_variables, variable, rip_oid); + return 0; } -#endif /* HAVE_SNMP */ + +static int +rip_snmp_module_init (void) +{ + hook_register(rip_ifaddr_add, rip_snmp_ifaddr_add); + hook_register(rip_ifaddr_del, rip_snmp_ifaddr_del); + + hook_register(frr_late_init, rip_snmp_init); + return 0; +} + +FRR_MODULE_SETUP( + .name = "ripd_snmp", + .version = FRR_VERSION, + .description = "ripd AgentX SNMP module", + .init = rip_snmp_module_init, +) diff --git a/ripd/ripd.c b/ripd/ripd.c index 82e460ced8..0eaa909fdb 100644 --- a/ripd/ripd.c +++ b/ripd/ripd.c @@ -4064,11 +4064,6 @@ rip_init (void) /* Debug related init. */ rip_debug_init (); - /* SNMP init. */ -#ifdef HAVE_SNMP - rip_snmp_init (); -#endif /* HAVE_SNMP */ - /* Access list install. */ access_list_init (); access_list_add_hook (rip_distribute_update_all_wrapper); diff --git a/ripd/ripd.h b/ripd/ripd.h index 66113cdc95..eeb008e3d5 100644 --- a/ripd/ripd.h +++ b/ripd/ripd.h @@ -392,7 +392,6 @@ extern void rip_if_init (void); extern void rip_if_down_all (void); extern void rip_route_map_init (void); extern void rip_route_map_reset (void); -extern void rip_snmp_init (void); extern void rip_zclient_init(struct thread_master *); extern void rip_zclient_reset (void); extern void rip_offset_init (void); diff --git a/zebra/Makefile.am b/zebra/Makefile.am index 4711c5e0b7..5958f63b51 100644 --- a/zebra/Makefile.am +++ b/zebra/Makefile.am @@ -34,13 +34,13 @@ endif AM_CFLAGS = $(WERROR) sbin_PROGRAMS = zebra - noinst_PROGRAMS = testzebra +module_LTLIBRARIES = zebra_SOURCES = \ zebra_memory.c \ zserv.c main.c interface.c connected.c zebra_rib.c zebra_routemap.c \ - redistribute.c debug.c rtadv.c zebra_snmp.c zebra_vty.c \ + redistribute.c debug.c rtadv.c zebra_vty.c \ irdp_main.c irdp_interface.c irdp_packet.c router-id.c zebra_fpm.c \ $(othersrc) zebra_ptm.c zebra_rnh.c zebra_ptm_redistribute.c \ zebra_ns.c zebra_vrf.c zebra_static.c zebra_mpls.c zebra_mpls_vty.c \ @@ -62,12 +62,19 @@ noinst_HEADERS = \ zebra_ns.h zebra_vrf.h ioctl_solaris.h zebra_static.h zebra_mpls.h \ kernel_netlink.h if_netlink.h zebra_mroute.h label_manager.h -zebra_LDADD = $(otherobj) ../lib/libfrr.la ../lib/libfrrsnmp.la $(LIBCAP) $(Q_FPM_PB_CLIENT_LDOPTS) +zebra_LDADD = $(otherobj) ../lib/libfrr.la $(LIBCAP) $(Q_FPM_PB_CLIENT_LDOPTS) testzebra_LDADD = ../lib/libfrr.la $(LIBCAP) zebra_DEPENDENCIES = $(otherobj) +if SNMP +module_LTLIBRARIES += zebra_snmp.la +endif +zebra_snmp_la_SOURCES = zebra_snmp.c +zebra_snmp_la_LDFLAGS = -avoid-version -module -shared -export-dynamic +zebra_snmp_la_LIBADD = ../lib/libfrrsnmp.la + EXTRA_DIST = if_ioctl.c if_ioctl_solaris.c if_netlink.c \ if_sysctl.c ipforward_proc.c \ ipforward_solaris.c ipforward_sysctl.c rt_netlink.c \ diff --git a/zebra/main.c b/zebra/main.c index 26e66f961d..ac19c3410d 100644 --- a/zebra/main.c +++ b/zebra/main.c @@ -329,10 +329,6 @@ main (int argc, char **argv) /* Initialize NS( and implicitly the VRF module), and make kernel routing socket. */ zebra_ns_init (); -#ifdef HAVE_SNMP - zebra_snmp_init (); -#endif /* HAVE_SNMP */ - #ifdef HAVE_FPM zfpm_init (zebrad.master, 1, 0, fpm_format); #else diff --git a/zebra/zebra_snmp.c b/zebra/zebra_snmp.c index 19364b5b91..8adb8873dc 100644 --- a/zebra/zebra_snmp.c +++ b/zebra/zebra_snmp.c @@ -25,7 +25,6 @@ #include -#ifdef HAVE_SNMP #include #include @@ -36,6 +35,9 @@ #include "smux.h" #include "table.h" #include "vrf.h" +#include "hook.h" +#include "libfrr.h" +#include "version.h" #include "zebra/rib.h" #include "zebra/zserv.h" @@ -571,10 +573,24 @@ ipCidrTable (struct variable *v, oid objid[], size_t *objid_len, return NULL; } -void -zebra_snmp_init () +static int +zebra_snmp_init (struct thread_master *tm) { - smux_init (zebrad.master); + smux_init (tm); REGISTER_MIB("mibII/ipforward", zebra_variables, variable, ipfw_oid); + return 0; } -#endif /* HAVE_SNMP */ + +static int +zebra_snmp_module_init (void) +{ + hook_register(frr_late_init, zebra_snmp_init); + return 0; +} + +FRR_MODULE_SETUP( + .name = "zebra_snmp", + .version = FRR_VERSION, + .description = "zebra AgentX SNMP module", + .init = zebra_snmp_module_init, +) diff --git a/zebra/zserv.h b/zebra/zserv.h index 9e34738238..cd1948373a 100644 --- a/zebra/zserv.h +++ b/zebra/zserv.h @@ -149,7 +149,6 @@ extern void route_read (struct zebra_ns *); extern void kernel_init (struct zebra_ns *); extern void kernel_terminate (struct zebra_ns *); extern void zebra_route_map_init (void); -extern void zebra_snmp_init (void); extern void zebra_vty_init (void); extern int zsend_vrf_add (struct zserv *, struct zebra_vrf *); From 4f8ea50c0d97e8f339b40d95ce428f4ffd66ba76 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Mon, 13 Feb 2017 00:29:37 +0100 Subject: [PATCH 15/61] zebra: fpm: convert into module Signed-off-by: David Lamparter --- configure.ac | 4 +-- zebra/Makefile.am | 42 +++++++++++++++------------ zebra/main.c | 16 +---------- zebra/misc_null.c | 7 ----- zebra/rib.h | 3 ++ zebra/zebra_fpm.c | 73 +++++++++++++++++++++++++++-------------------- zebra/zebra_fpm.h | 36 ----------------------- zebra/zebra_rib.c | 17 +++++------ zebra/zserv.c | 23 --------------- 9 files changed, 80 insertions(+), 141 deletions(-) delete mode 100644 zebra/zebra_fpm.h diff --git a/configure.ac b/configure.ac index 466acb25d8..5f2e3ed517 100755 --- a/configure.ac +++ b/configure.ac @@ -365,9 +365,7 @@ if test "${enable_shell_access}" = "yes"; then AC_DEFINE(HAVE_SHELL_ACCESS,,Allow user to use ssh/telnet/bash) fi -if test "${enable_fpm}" = "yes"; then - AC_DEFINE(HAVE_FPM,,Forwarding Plane Manager support) -fi +AM_CONDITIONAL([FPM], [test "x$enable_fpm" = "xyes"]) if test "x${enable_dev_build}" = "xyes"; then AC_DEFINE(DEV_BUILD,,Build for development) diff --git a/zebra/Makefile.am b/zebra/Makefile.am index 5958f63b51..af7a513d2f 100644 --- a/zebra/Makefile.am +++ b/zebra/Makefile.am @@ -19,18 +19,6 @@ mpls_method = @MPLS_METHOD@ otherobj = $(ioctl_method) $(ipforward) $(if_method) \ $(rt_method) $(rtread_method) $(kernel_method) $(mpls_method) -if HAVE_NETLINK -othersrc = zebra_fpm_netlink.c -endif - -if HAVE_PROTOBUF -protobuf_srcs = zebra_fpm_protobuf.c -endif - -if DEV_BUILD -dev_srcs = zebra_fpm_dt.c -endif - AM_CFLAGS = $(WERROR) sbin_PROGRAMS = zebra @@ -41,11 +29,12 @@ zebra_SOURCES = \ zebra_memory.c \ zserv.c main.c interface.c connected.c zebra_rib.c zebra_routemap.c \ redistribute.c debug.c rtadv.c zebra_vty.c \ - irdp_main.c irdp_interface.c irdp_packet.c router-id.c zebra_fpm.c \ - $(othersrc) zebra_ptm.c zebra_rnh.c zebra_ptm_redistribute.c \ + irdp_main.c irdp_interface.c irdp_packet.c router-id.c \ + zebra_ptm.c zebra_rnh.c zebra_ptm_redistribute.c \ zebra_ns.c zebra_vrf.c zebra_static.c zebra_mpls.c zebra_mpls_vty.c \ - $(protobuf_srcs) zebra_mroute.c \ - $(dev_srcs) label_manager.c + zebra_mroute.c \ + label_manager.c \ + # end testzebra_SOURCES = test_main.c zebra_rib.c interface.c connected.c debug.c \ zebra_vty.c zebra_ptm.c zebra_routemap.c zebra_ns.c zebra_vrf.c \ @@ -57,12 +46,12 @@ noinst_HEADERS = \ zebra_memory.h \ 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 \ - rt_netlink.h zebra_fpm.h zebra_fpm_private.h zebra_rnh.h \ + rt_netlink.h zebra_fpm_private.h zebra_rnh.h \ zebra_ptm_redistribute.h zebra_ptm.h zebra_routemap.h \ zebra_ns.h zebra_vrf.h ioctl_solaris.h zebra_static.h zebra_mpls.h \ kernel_netlink.h if_netlink.h zebra_mroute.h label_manager.h -zebra_LDADD = $(otherobj) ../lib/libfrr.la $(LIBCAP) $(Q_FPM_PB_CLIENT_LDOPTS) +zebra_LDADD = $(otherobj) ../lib/libfrr.la $(LIBCAP) testzebra_LDADD = ../lib/libfrr.la $(LIBCAP) @@ -75,6 +64,23 @@ zebra_snmp_la_SOURCES = zebra_snmp.c zebra_snmp_la_LDFLAGS = -avoid-version -module -shared -export-dynamic zebra_snmp_la_LIBADD = ../lib/libfrrsnmp.la +if FPM +module_LTLIBRARIES += zebra_fpm.la +endif +zebra_fpm_la_LDFLAGS = -avoid-version -module -shared -export-dynamic +zebra_fpm_la_LIBADD = $(Q_FPM_PB_CLIENT_LDOPTS) +zebra_fpm_la_SOURCES = zebra_fpm.c +if HAVE_NETLINK +zebra_fpm_la_SOURCES += zebra_fpm_netlink.c +endif +if HAVE_PROTOBUF +zebra_fpm_la_SOURCES += zebra_fpm_protobuf.c +endif +if DEV_BUILD +zebra_fpm_la_SOURCES += zebra_fpm_dt.c +endif + + EXTRA_DIST = if_ioctl.c if_ioctl_solaris.c if_netlink.c \ if_sysctl.c ipforward_proc.c \ ipforward_solaris.c ipforward_sysctl.c rt_netlink.c \ diff --git a/zebra/main.c b/zebra/main.c index ac19c3410d..459e6148d8 100644 --- a/zebra/main.c +++ b/zebra/main.c @@ -43,7 +43,6 @@ #include "zebra/router-id.h" #include "zebra/irdp.h" #include "zebra/rtadv.h" -#include "zebra/zebra_fpm.h" #include "zebra/zebra_ptm.h" #include "zebra/zebra_ns.h" #include "zebra/redistribute.h" @@ -84,7 +83,6 @@ struct option longopts[] = { "batch", no_argument, NULL, 'b'}, { "allow_delete", no_argument, NULL, 'a'}, { "keep_kernel", no_argument, NULL, 'k'}, - { "fpm_format", required_argument, NULL, 'F'}, { "socket", required_argument, NULL, 'z'}, { "ecmp", required_argument, NULL, 'e'}, { "label_socket", no_argument, NULL, 'l'}, @@ -221,21 +219,18 @@ main (int argc, char **argv) { // int batch_mode = 0; char *zserv_path = NULL; - char *fpm_format = NULL; /* Socket to external label manager */ char *lblmgr_path = NULL; - frr_preinit(&zebra_di, argc, argv); - frr_opt_add("bakF:z:e:l:r" + frr_opt_add("bakz:e:l:r" #ifdef HAVE_NETLINK "s:" #endif , longopts, " -b, --batch Runs in batch mode\n" " -a, --allow_delete Allow other processes to delete zebra routes\n" - " -F, --fpm_format Set fpm format to 'netlink' or 'protobuf'\n" " -z, --socket Set path of zebra socket\n" " -e, --ecmp Specify ECMP to use.\n" " -l, --label_socket Socket to external label manager\n"\ @@ -266,9 +261,6 @@ main (int argc, char **argv) case 'k': keep_kernel_mode = 1; break; - case 'F': - fpm_format = optarg; - break; case 'e': multipath_num = atoi (optarg); if (multipath_num > MULTIPATH_NUM || multipath_num <= 0) @@ -329,12 +321,6 @@ main (int argc, char **argv) /* Initialize NS( and implicitly the VRF module), and make kernel routing socket. */ zebra_ns_init (); -#ifdef HAVE_FPM - zfpm_init (zebrad.master, 1, 0, fpm_format); -#else - zfpm_init (zebrad.master, 0, 0, fpm_format); -#endif - /* Process the configuration file. Among other configuration * directives we can meet those installing static routes. Such * requests will not be executed immediately, but queued in diff --git a/zebra/misc_null.c b/zebra/misc_null.c index a83c307413..49cb92bd7d 100644 --- a/zebra/misc_null.c +++ b/zebra/misc_null.c @@ -25,7 +25,6 @@ #include "zebra/rtadv.h" #include "zebra/irdp.h" #include "zebra/interface.h" -#include "zebra/zebra_fpm.h" void rtadv_config_write (struct vty *vty, struct interface *ifp) { return; } void irdp_config_write (struct vty *vty, struct interface *ifp) { return; } @@ -35,9 +34,3 @@ void ifstat_update_proc (void) { return; } #ifdef HAVE_NET_RT_IFLIST void ifstat_update_sysctl (void) { return; } #endif - -void -zfpm_trigger_update (struct route_node *rn, const char *reason) -{ - return; -} diff --git a/zebra/rib.h b/zebra/rib.h index c0cde50baf..5381d76b98 100644 --- a/zebra/rib.h +++ b/zebra/rib.h @@ -24,6 +24,7 @@ #define _ZEBRA_RIB_H #include "zebra.h" +#include "hook.h" #include "linklist.h" #include "prefix.h" #include "table.h" @@ -490,4 +491,6 @@ rib_tables_iter_cleanup (rib_tables_iter_t *iter) iter->state = RIB_TABLES_ITER_S_DONE; } +DECLARE_HOOK(rib_update, (struct route_node *rn, const char *reason), (rn, reason)) + #endif /*_ZEBRA_RIB_H */ diff --git a/zebra/zebra_fpm.c b/zebra/zebra_fpm.c index afa557096c..405b2e9f79 100644 --- a/zebra/zebra_fpm.c +++ b/zebra/zebra_fpm.c @@ -25,10 +25,12 @@ #include #include "log.h" +#include "libfrr.h" #include "stream.h" #include "thread.h" #include "network.h" #include "command.h" +#include "version.h" #include "zebra/rib.h" #include "zebra/zserv.h" @@ -36,7 +38,6 @@ #include "zebra/zebra_vrf.h" #include "fpm/fpm.h" -#include "zebra_fpm.h" #include "zebra_fpm_private.h" /* @@ -254,6 +255,8 @@ typedef struct zfpm_glob_t_ static zfpm_glob_t zfpm_glob_space; static zfpm_glob_t *zfpm_g = &zfpm_glob_space; +static int zfpm_trigger_update (struct route_node *rn, const char *reason); + static int zfpm_read_cb (struct thread *thread); static int zfpm_write_cb (struct thread *thread); @@ -1296,7 +1299,6 @@ zfpm_start_connect_timer (const char *reason) zfpm_set_state (ZFPM_STATE_ACTIVE, reason); } -#if defined (HAVE_FPM) /* * zfpm_is_enabled * @@ -1307,7 +1309,6 @@ zfpm_is_enabled (void) { return zfpm_g->enabled; } -#endif /* * zfpm_conn_is_up @@ -1331,7 +1332,7 @@ zfpm_conn_is_up (void) * The zebra code invokes this function to indicate that we should * send an update to the FPM about the given route_node. */ -void +static int zfpm_trigger_update (struct route_node *rn, const char *reason) { rib_dest_t *dest; @@ -1342,7 +1343,7 @@ zfpm_trigger_update (struct route_node *rn, const char *reason) * all destinations once the connection comes up. */ if (!zfpm_conn_is_up ()) - return; + return 0; dest = rib_dest_from_rnode (rn); @@ -1353,12 +1354,12 @@ zfpm_trigger_update (struct route_node *rn, const char *reason) if (!zfpm_is_table_for_fpm (rib_dest_table (dest))) { zfpm_g->stats.non_fpm_table_triggers++; - return; + return 0; } if (CHECK_FLAG (dest->flags, RIB_DEST_UPDATE_FPM)) { zfpm_g->stats.redundant_triggers++; - return; + return 0; } if (reason) @@ -1375,9 +1376,10 @@ zfpm_trigger_update (struct route_node *rn, const char *reason) * Make sure that writes are enabled. */ if (zfpm_g->t_write) - return; + return 0; zfpm_write_on (); + return 0; } /* @@ -1411,7 +1413,6 @@ zfpm_stats_timer_cb (struct thread *t) return 0; } -#if defined (HAVE_FPM) /* * zfpm_stop_stats_timer */ @@ -1424,7 +1425,6 @@ zfpm_stop_stats_timer (void) zfpm_debug ("Stopping existing stats timer"); THREAD_TIMER_OFF (zfpm_g->t_stats); } -#endif /* * zfpm_start_stats_timer @@ -1447,7 +1447,6 @@ zfpm_start_stats_timer (void) zfpm_g->last_ivl_stats.counter, VTY_NEWLINE); \ } while (0) -#if defined (HAVE_FPM) /* * zfpm_show_stats */ @@ -1600,7 +1599,6 @@ DEFUN ( no_fpm_remote_ip, return CMD_SUCCESS; } -#endif /* * zfpm_init_message_format @@ -1670,7 +1668,7 @@ zfpm_init_message_format (const char *format) * Returns ZERO on success. */ -int fpm_remote_srv_write (struct vty *vty ) +static int fpm_remote_srv_write (struct vty *vty) { struct in_addr in; @@ -1684,6 +1682,15 @@ int fpm_remote_srv_write (struct vty *vty ) } +/* Zebra node */ +static struct cmd_node zebra_node = +{ + ZEBRA_NODE, + "", + 1 +}; + + /** * zfpm_init * @@ -1695,17 +1702,12 @@ int fpm_remote_srv_write (struct vty *vty ) * * Returns TRUE on success. */ -int -zfpm_init (struct thread_master *master, int enable, uint16_t port, - const char *format) +static int +zfpm_init (struct thread_master *master) { - static int initialized = 0; - - if (initialized) { - return 1; - } - - initialized = 1; + int enable = 1; + uint16_t port = 0; + const char *format = THIS_MODULE->load_args; memset (zfpm_g, 0, sizeof (*zfpm_g)); zfpm_g->master = master; @@ -1717,12 +1719,11 @@ zfpm_init (struct thread_master *master, int enable, uint16_t port, zfpm_stats_init (&zfpm_g->last_ivl_stats); zfpm_stats_init (&zfpm_g->cumulative_stats); -#if defined (HAVE_FPM) + install_node (&zebra_node, fpm_remote_srv_write); install_element (ENABLE_NODE, &show_zebra_fpm_stats_cmd); install_element (ENABLE_NODE, &clear_zebra_fpm_stats_cmd); install_element (CONFIG_NODE, &fpm_remote_ip_cmd); install_element (CONFIG_NODE, &no_fpm_remote_ip_cmd); -#endif zfpm_init_message_format(format); @@ -1734,10 +1735,6 @@ zfpm_init (struct thread_master *master, int enable, uint16_t port, zfpm_g->enabled = enable; - if (!enable) { - return 1; - } - if (!zfpm_g->fpm_server) zfpm_g->fpm_server = FPM_DEFAULT_IP; @@ -1751,6 +1748,20 @@ zfpm_init (struct thread_master *master, int enable, uint16_t port, zfpm_start_stats_timer (); zfpm_start_connect_timer ("initialized"); - - return 1; + return 0; } + +static int +zebra_fpm_module_init (void) +{ + hook_register(rib_update, zfpm_trigger_update); + hook_register(frr_late_init, zfpm_init); + return 0; +} + +FRR_MODULE_SETUP( + .name = "zebra_fpm", + .version = FRR_VERSION, + .description = "zebra FPM (Forwarding Plane Manager) module", + .init = zebra_fpm_module_init, +) diff --git a/zebra/zebra_fpm.h b/zebra/zebra_fpm.h deleted file mode 100644 index fdb069965b..0000000000 --- a/zebra/zebra_fpm.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Header file exported by the zebra FPM module to zebra. - * - * Copyright (C) 2012 by Open Source Routing. - * Copyright (C) 2012 by Internet Systems Consortium, Inc. ("ISC") - * - * This file is part of GNU Zebra. - * - * 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. - */ - -#ifndef _ZEBRA_FPM_H -#define _ZEBRA_FPM_H - -/* - * Externs. - */ -extern int zfpm_init (struct thread_master *master, int enable, uint16_t port, - const char *message_format); -extern void zfpm_trigger_update (struct route_node *rn, const char *reason); -extern int fpm_remote_srv_write (struct vty *vty); - -#endif /* _ZEBRA_FPM_H */ diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index f5b54a2c04..b3e70e46fa 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -48,11 +48,12 @@ #include "zebra/redistribute.h" #include "zebra/zebra_routemap.h" #include "zebra/debug.h" -#include "zebra/zebra_fpm.h" #include "zebra/zebra_rnh.h" #include "zebra/interface.h" #include "zebra/connected.h" +DEFINE_HOOK(rib_update, (struct route_node *rn, const char *reason), (rn, reason)) + /* Should we allow non Quagga processes to delete our routes */ extern int allow_delete; @@ -1110,7 +1111,7 @@ rib_install_kernel (struct route_node *rn, struct rib *rib, struct rib *old) * Make sure we update the FPM any time we send new information to * the kernel. */ - zfpm_trigger_update (rn, "installing in kernel"); + hook_call(rib_update, rn, "installing in kernel"); ret = kernel_route_rib (p, src_p, old, rib); /* If install succeeds, update FIB flag for nexthops. */ @@ -1154,7 +1155,7 @@ rib_uninstall_kernel (struct route_node *rn, struct rib *rib) * Make sure we update the FPM any time we send new information to * the kernel. */ - zfpm_trigger_update (rn, "uninstalling from kernel"); + hook_call(rib_update, rn, "uninstalling from kernel"); ret = kernel_route_rib (p, src_p, rib, NULL); for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing)) @@ -1172,7 +1173,7 @@ rib_uninstall (struct route_node *rn, struct rib *rib) if (CHECK_FLAG (rib->status, RIB_ENTRY_SELECTED_FIB)) { if (info->safi == SAFI_UNICAST) - zfpm_trigger_update (rn, "rib_uninstall"); + hook_call(rib_update, rn, "rib_uninstall"); if (! RIB_SYSTEM_ROUTE (rib)) rib_uninstall_kernel (rn, rib); @@ -1253,7 +1254,7 @@ static void rib_process_add_fib(struct zebra_vrf *zvrf, struct route_node *rn, struct rib *new) { - zfpm_trigger_update (rn, "new route selected"); + hook_call(rib_update, rn, "new route selected"); /* Update real nexthop. This may actually determine if nexthop is active or not. */ if (!nexthop_active_update (rn, new, 1)) @@ -1289,7 +1290,7 @@ static void rib_process_del_fib(struct zebra_vrf *zvrf, struct route_node *rn, struct rib *old) { - zfpm_trigger_update (rn, "removing existing route"); + hook_call(rib_update, rn, "removing existing route"); /* Uninstall from kernel. */ if (IS_ZEBRA_DEBUG_RIB) @@ -1326,7 +1327,7 @@ rib_process_update_fib (struct zebra_vrf *zvrf, struct route_node *rn, if (new != old || CHECK_FLAG (new->status, RIB_ENTRY_CHANGED)) { - zfpm_trigger_update (rn, "updating existing route"); + hook_call(rib_update, rn, "updating existing route"); /* Update the nexthop; we could determine here that nexthop is inactive. */ if (nexthop_active_update (rn, new, 1)) @@ -2874,7 +2875,7 @@ rib_close_table (struct route_table *table) continue; if (info->safi == SAFI_UNICAST) - zfpm_trigger_update (rn, NULL); + hook_call(rib_update, rn, NULL); if (! RIB_SYSTEM_ROUTE (rib)) rib_uninstall_kernel (rn, rib); diff --git a/zebra/zserv.c b/zebra/zserv.c index f9205a12c8..c1978e55cd 100644 --- a/zebra/zserv.c +++ b/zebra/zserv.c @@ -53,7 +53,6 @@ #include "zebra/zebra_ptm.h" #include "zebra/rtadv.h" #include "zebra/zebra_mpls.h" -#include "zebra/zebra_fpm.h" #include "zebra/zebra_mroute.h" #include "zebra/label_manager.h" @@ -2850,25 +2849,6 @@ static struct cmd_node forwarding_node = 1 }; -#ifdef HAVE_FPM -/* function to write the fpm config info */ -static int -config_write_fpm (struct vty *vty) -{ - return - fpm_remote_srv_write (vty); -} - -/* Zebra node */ -static struct cmd_node zebra_node = -{ - ZEBRA_NODE, - "", - 1 -}; -#endif - - /* Initialisation of zebra and installation of commands. */ void zebra_init (void) @@ -2879,9 +2859,6 @@ zebra_init (void) /* Install configuration write function. */ install_node (&table_node, config_write_table); install_node (&forwarding_node, config_write_forwarding); -#ifdef HAVE_FPM - install_node (&zebra_node, config_write_fpm); -#endif install_element (VIEW_NODE, &show_ip_forwarding_cmd); install_element (CONFIG_NODE, &ip_forwarding_cmd); From 6b0275ac354993e56e043986efbc41d3d451beee Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Sat, 25 Mar 2017 10:05:19 +0100 Subject: [PATCH 16/61] doc: document loadable module support Signed-off-by: David Lamparter --- doc/basic.texi | 46 +++++++++++++++++ doc/bgpd.8.in | 8 +++ doc/defines.texi.in | 1 + doc/dev-modules.md | 119 ++++++++++++++++++++++++++++++++++++++++++++ doc/isisd.8.in | 8 +++ doc/ldpd.8.in | 8 +++ doc/main.texi | 9 ++-- doc/nhrpd.8.in | 8 +++ doc/ospf6d.8.in | 8 +++ doc/ospfd.8.in | 8 +++ doc/pimd.8.in | 8 +++ doc/ripd.8.in | 8 +++ doc/ripngd.8.in | 8 +++ doc/snmp.texi | 4 ++ doc/watchfrr.8.in | 4 +- doc/zebra.8.in | 11 ++++ 16 files changed, 260 insertions(+), 6 deletions(-) create mode 100644 doc/dev-modules.md diff --git a/doc/basic.texi b/doc/basic.texi index cea33eaa81..05d72bc80f 100644 --- a/doc/basic.texi +++ b/doc/basic.texi @@ -18,6 +18,7 @@ daemons. * Config Commands:: Commands used in config files * Terminal Mode Commands:: Common commands used in a VTY * Common Invocation Options:: Starting the daemons +* Loadable Module Support:: Using extension modules * Virtual Terminal Interfaces:: Interacting with the daemons @end menu @@ -372,6 +373,51 @@ Print program version. @end table +@node Loadable Module Support +@section Loadable Module Support + +FRR supports loading extension modules at startup. Loading, reloading or +unloading modules at runtime is not supported (yet). To load a module, use +the following command line option at daemon startup: + +@table @samp +@item -M @var{module:options} +@itemx --module @var{module:options} + +Load the specified module, optionally passing options to it. If the module +name contains a slash (/), it is assumed to be a full pathname to a file to +be loaded. If it does not contain a slash, the +@code{@value{INSTALL_PREFIX_MODULES}} directory is searched for a module of +the given name; first with the daemon name prepended (e.g. @code{zebra_mod} +for @code{mod}), then without the daemon name prepended. + +This option is available on all daemons, though some daemons may not have +any modules available to be loaded. +@end table + + +@subsection The SNMP Module + +If SNMP is enabled during compile-time and installed as part of the package, +the @code{snmp} module can be loaded for the @command{zebra}, +@command{bgpd}, @command{ospfd}, @command{ospf6d} and @command{ripd} daemons. + +The module ignores any options passed to it. Refer to @ref{SNMP Support} +for information on its usage. + + +@subsection The FPM Module + +If FPM is enabled during compile-time and installed as part of the package, +the @code{fpm} module can be loaded for the @command{zebra} daemon. This +provides the Forwarding Plane Manager ("FPM") API. + +The module expects its argument to be either @code{netlink} or +@code{protobuf}, specifying the encapsulation to use. @code{netlink} is the +default, and @code{protobuf} may not be available if the module was built +without protobuf support. Refer to @ref{zebra FIB push interface} for more +information. + @node Virtual Terminal Interfaces @section Virtual Terminal Interfaces diff --git a/doc/bgpd.8.in b/doc/bgpd.8.in index 9026f2cdee..0df1b1dcea 100644 --- a/doc/bgpd.8.in +++ b/doc/bgpd.8.in @@ -27,6 +27,9 @@ bgpd \- a BGPv4, BGPv4\+, BGPv4\- routing engine for use with @PACKAGE_FULLNAME@ ] [ .B \-g .I group +] [ +.B \-M +.I module:options ] .SH DESCRIPTION .B bgpd @@ -76,6 +79,11 @@ When the program terminates, retain routes added by \fBbgpd\fR. \fB\-S\fR, \fB\-\-skip_runas\fR Skip setting the process effective user and group. .TP +\fB\-M\fR, \fB\-\-module \fR\fImodule:options\fR +Load a module at startup. May be specified more than once. +The \fBsnmp\fR module may be available for +\fBbgpd\fR, if the package was built with SNMP support. +.TP \fB\-v\fR, \fB\-\-version\fR Print the version and exit. .SH FILES diff --git a/doc/defines.texi.in b/doc/defines.texi.in index 43d7442939..0fadba964a 100644 --- a/doc/defines.texi.in +++ b/doc/defines.texi.in @@ -13,6 +13,7 @@ @set INSTALL_PREFIX_ETC @CFG_SYSCONF@ @set INSTALL_PREFIX_SBIN @CFG_SBIN@ @set INSTALL_PREFIX_STATE @CFG_STATE@ +@set INSTALL_PREFIX_MODULES @CFG_MODULE@ @set INSTALL_USER @enable_user@ @set INSTALL_GROUP @enable_group@ @set INSTALL_VTY_GROUP @enable_vty_group@ diff --git a/doc/dev-modules.md b/doc/dev-modules.md new file mode 100644 index 0000000000..87bc963188 --- /dev/null +++ b/doc/dev-modules.md @@ -0,0 +1,119 @@ +# Module and Hook support (developer docs) + +## What it does + +It uses `dlopen()` to load DSOs at startup. + + +## Limitations + +* can't load, unload, or reload during runtime. This just needs some work + and can probably be done in the future. +* doesn't fix any of the "things need to be changed in the code in the library" + issues. Most prominently, you can't add a CLI node because CLI nodes are + listed in the library... +* if your module crashes, the daemon crashes. Should be obvious. +* **does not provide a stable API or ABI**. Your module must match a version + of FRR and you may have to update it frequently to match changes. +* **does not create a license boundary**. Your module will need to link + libzebra and include header files from the daemons, meaning it will be + GPL-encumbered. + + +## Installation + +Look for `moduledir` in `configure.ac`, default is normally +`/usr/lib64/frr/modules` but depends on `--libdir` / `--prefix`. + +The daemon's name is prepended when looking for a module, e.g. "snmp" tries +to find "zebra_snmp" first when used in zebra. This is just to make it nicer +for the user, with the snmp module having the same name everywhere. + +Modules can be packaged separately from FRR. The SNMP and FPM modules are +good candidates for this because they have dependencies (net-snmp / protobuf) +that are not FRR dependencies. However, any distro packages should have an +"exact-match" dependency onto the FRR package. Using a module from a +different FRR version will probably blow up nicely. + +For snapcraft (and during development), modules can be loaded with full path +(e.g. -M `$SNAP/lib/frr/modules/zebra_snmp.so`). Note that libtool puts output +files in the .libs directory, so during development you have to use +`./zebra -M .libs/zebra_snmp.so`. + + +## Creating a module + +... best to look at the existing SNMP or FPM modules. + +Basic boilerplate: + +``` +#include "hook.h" +#include "module.h" + +static int +module_init (void) +{ + hook_register(frr_late_init, module_late_init); + return 0; +} + +FRR_MODULE_SETUP( + .name = "my module", + .version = "0.0", + .description = "my module", + .init = module_init, +) +``` + +The `frr_late_init` hook will be called after the daemon has finished its +other startup and is about to enter the main event loop; this is the best +place for most initialisation. + + +## Compiler & Linker magic + +There's a `THIS_MODULE` (like in the Linux kernel), which uses `visibility` +attributes to restrict it to the current module. If you get a linker error +with `_frrmod_this_module`, there is some linker SNAFU. This shouldn't be +possible, though one way to get it would be to not include libzebra (which +provides a fallback definition for the symbol). + +libzebra and the daemons each have their own `THIS_MODULE`, as do all loadable +modules. In any other libraries (e.g. `libfrrsnmp`), `THIS_MODULE` will use +the definition in libzebra; same applies if the main executable doesn't use +`FRR_DAEMON_INFO` (e.g. all testcases). + +The deciding factor here is "what dynamic linker unit are you using the symbol +from." If you're in a library function and want to know who called you, you +can't use `THIS_MODULE` (because that'll just tell you you're in the library). +Put a macro around your function that adds `THIS_MODULE` in the *caller's +code calling your function*. + +The idea is to use this in the future for module unloading. Hooks already +remember which module they were installed by, as groundwork for a function +that removes all of a module's installed hooks. + +There's also the `frr_module` symbol in modules, pretty much a standard entry +point for loadable modules. + + +## Hooks + +Hooks are just points in the code where you can register your callback to +be called. The parameter list is specific to the hook point. Since there is +no stable API, the hook code has some extra type safety checks making sure +you get a compiler warning when the hook parameter list doesn't match your +callback. Don't ignore these warnings. + + +## Relation to MTYPE macros + +The MTYPE macros, while primarily designed to decouple MTYPEs from the library +and beautify the code, also work very nicely with loadable modules -- both +constructors and destructors are executed when loading/unloading modules. + +This means there is absolutely no change required to MTYPEs, you can just use +them in a module and they will even clean up themselves when we implement +module unloading and an unload happens. In fact, it's impossible to create +a bug where unloading fails to de-register a MTYPE. diff --git a/doc/isisd.8.in b/doc/isisd.8.in index 9ffcbc618d..542c289935 100644 --- a/doc/isisd.8.in +++ b/doc/isisd.8.in @@ -23,6 +23,9 @@ isisd \- an IS-IS routing engine for use with @PACKAGE_FULLNAME@. ] [ .B \-g .I group +] [ +.B \-M +.I module:options ] .SH DESCRIPTION .B isisd @@ -63,6 +66,11 @@ interfaces. \fB\-u\fR, \fB\-\-user \fR\fIuser\fR Specify the user to run as. Default is \fI@enable_user@\fR. .TP +\fB\-M\fR, \fB\-\-module \fR\fImodule:options\fR +Load a module at startup. May be specified more than once. +There are currently no such modules for +\fBisisd\fR in the base package. +.TP \fB\-v\fR, \fB\-\-version\fR Print the version and exit. .SH FILES diff --git a/doc/ldpd.8.in b/doc/ldpd.8.in index 1683de46ca..2d68a31a50 100644 --- a/doc/ldpd.8.in +++ b/doc/ldpd.8.in @@ -23,6 +23,9 @@ ldpd \- an LDP engine for use with @PACKAGE_FULLNAME@. ] [ .B \-g .I group +] [ +.B \-M +.I module:options ] .SH DESCRIPTION .B ldpd @@ -63,6 +66,11 @@ interfaces. \fB\-u\fR, \fB\-\-user \fR\fIuser\fR Specify the user to run as. Default is \fI@enable_user@\fR. .TP +\fB\-M\fR, \fB\-\-module \fR\fImodule:options\fR +Load a module at startup. May be specified more than once. +There are currently no such modules for +\fBldpd\fR in the base package. +.TP \fB\-v\fR, \fB\-\-version\fR Print the version and exit. .SH FILES diff --git a/doc/main.texi b/doc/main.texi index dfe02e1b5d..706baa25f7 100644 --- a/doc/main.texi +++ b/doc/main.texi @@ -385,7 +385,8 @@ ip protocol rip route-map RM1 Zebra supports a 'FIB push' interface that allows an external component to learn the forwarding information computed by the Frr -routing suite. +routing suite. This is a loadable module that needs to be enabled +at startup as described in @ref{Loadable Module Support}. In Frr, the Routing Information Base (RIB) resides inside zebra. Routing protocols communicate their best routes to zebra, and @@ -440,9 +441,9 @@ independently. @end itemize As mentioned before, zebra encodes routes sent to the FPM in netlink -format by default. The format can be controlled via the -@code{--fpm_format} command-line option to zebra, which currently -takes the values @code{netlink} and @code{protobuf}. +format by default. The format can be controlled via the FPM module's +load-time option to zebra, which currently takes the values @code{netlink} +and @code{protobuf}. The zebra FPM interface uses replace semantics. That is, if a 'route add' message for a prefix is followed by another 'route add' message, diff --git a/doc/nhrpd.8.in b/doc/nhrpd.8.in index c5e4f7e324..09b662ae7c 100644 --- a/doc/nhrpd.8.in +++ b/doc/nhrpd.8.in @@ -23,6 +23,9 @@ nhrpd \- a Next Hop Routing Protocol routing engine for use with @PACKAGE_FULLNA ] [ .B \-g .I group +] [ +.B \-M +.I module:options ] .SH DESCRIPTION .B nhrpd @@ -63,6 +66,11 @@ interfaces. \fB\-u\fR, \fB\-\-user \fR\fIuser\fR Specify the user to run as. Default is \fI@enable_user@\fR. .TP +\fB\-M\fR, \fB\-\-module \fR\fImodule:options\fR +Load a module at startup. May be specified more than once. +There are currently no such modules for +\fBnhrpd\fR in the base package. +.TP \fB\-v\fR, \fB\-\-version\fR Print the version and exit. .SH FILES diff --git a/doc/ospf6d.8.in b/doc/ospf6d.8.in index 7f94782bea..02d9d8083d 100644 --- a/doc/ospf6d.8.in +++ b/doc/ospf6d.8.in @@ -23,6 +23,9 @@ ospf6d \- an OSPFv3 routing engine for use with @PACKAGE_FULLNAME@. ] [ .B \-g .I group +] [ +.B \-M +.I module:options ] .SH DESCRIPTION .B ospf6d @@ -64,6 +67,11 @@ interfaces. \fB\-u\fR, \fB\-\-user \fR\fIuser\fR Specify the user to run as. Default is \fI@enable_user@\fR. .TP +\fB\-M\fR, \fB\-\-module \fR\fImodule:options\fR +Load a module at startup. May be specified more than once. +The \fBsnmp\fR module may be available for +\fBospf6d\fR, if the package was built with SNMP support. +.TP \fB\-v\fR, \fB\-\-version\fR Print the version and exit. .SH FILES diff --git a/doc/ospfd.8.in b/doc/ospfd.8.in index 1b86551ca5..6bad777711 100644 --- a/doc/ospfd.8.in +++ b/doc/ospfd.8.in @@ -23,6 +23,9 @@ ospfd \- an OSPFv2 routing engine for use with @PACKAGE_FULLNAME@. ] [ .B \-g .I group +] [ +.B \-M +.I module:options ] .SH DESCRIPTION .B ospfd @@ -66,6 +69,11 @@ Specify the user to run as. Default is \fI@enable_user@\fR. \fB\-a\fR, \fB\-\-apiserver \fR Enable OSPF apiserver. Default is disabled. .TP +\fB\-M\fR, \fB\-\-module \fR\fImodule:options\fR +Load a module at startup. May be specified more than once. +The \fBsnmp\fR module may be available for +\fBospfd\fR, if the package was built with SNMP support. +.TP \fB\-v\fR, \fB\-\-version\fR Print the version and exit. .SH FILES diff --git a/doc/pimd.8.in b/doc/pimd.8.in index 60b844b1e7..3fb060e564 100644 --- a/doc/pimd.8.in +++ b/doc/pimd.8.in @@ -26,6 +26,9 @@ pimd \- a PIM routing for use with @PACKAGE_FULLNAME@. ] [ .B \-g .I group +] [ +.B \-M +.I module:options ] .SH DESCRIPTION .B pimd @@ -70,6 +73,11 @@ interfaces. \fB\-u\fR, \fB\-\-user \fR\fIuser\fR Specify the user to run as. Default is \fI@enable_user@\fR. .TP +\fB\-M\fR, \fB\-\-module \fR\fImodule:options\fR +Load a module at startup. May be specified more than once. +There are currently no such modules for +\fBpimd\fR in the base package. +.TP \fB\-v\fR, \fB\-\-version\fR Print the version and exit. .TP diff --git a/doc/ripd.8.in b/doc/ripd.8.in index 6db5ac3649..a84668e6dd 100644 --- a/doc/ripd.8.in +++ b/doc/ripd.8.in @@ -23,6 +23,9 @@ ripd \- a RIP routing engine for use with @PACKAGE_FULLNAME@. ] [ .B \-g .I group +] [ +.B \-M +.I module:options ] .SH DESCRIPTION .B ripd @@ -67,6 +70,11 @@ Specify the user to run as. Default is \fI@enable_user@\fR. \fB\-r\fR, \fB\-\-retain\fR When the program terminates, retain routes added by \fBripd\fR. .TP +\fB\-M\fR, \fB\-\-module \fR\fImodule:options\fR +Load a module at startup. May be specified more than once. +The \fBsnmp\fR module may be available for +\fBripd\fR, if the package was built with SNMP support. +.TP \fB\-v\fR, \fB\-\-version\fR Print the version and exit. .SH FILES diff --git a/doc/ripngd.8.in b/doc/ripngd.8.in index 4c5f2bb114..98039219a7 100644 --- a/doc/ripngd.8.in +++ b/doc/ripngd.8.in @@ -23,6 +23,9 @@ ripngd \- a RIPNG routing engine for use with @PACKAGE_FULLNAME@. ] [ .B \-g .I group +] [ +.B \-M +.I module:options ] .SH DESCRIPTION .B ripngd @@ -67,6 +70,11 @@ Specify the user to run as. Default is \fI@enable_user@\fR. \fB\-r\fR, \fB\-\-retain\fR When the program terminates, retain routes added by \fBripd\fR. .TP +\fB\-M\fR, \fB\-\-module \fR\fImodule:options\fR +Load a module at startup. May be specified more than once. +There are currently no such modules for +\fBripngd\fR in the base package. +.TP \fB\-v\fR, \fB\-\-version\fR Print the version and exit. .SH FILES diff --git a/doc/snmp.texi b/doc/snmp.texi index c2c889de76..d9656941d0 100644 --- a/doc/snmp.texi +++ b/doc/snmp.texi @@ -8,6 +8,10 @@ but is able to connect to a SNMP agent using the SMUX protocol (@cite{RFC1227}) or the AgentX protocol (@cite{RFC2741}) and make the routing protocol MIBs available through it. +Note that SNMP Support needs to be enabled at compile-time and loaded as +module on daemon startup. Refer to @ref{Loadable Module Support} on +the latter. + @menu * Getting and installing an SNMP agent:: * AgentX configuration:: diff --git a/doc/watchfrr.8.in b/doc/watchfrr.8.in index 813f87abd3..82098e1b0d 100644 --- a/doc/watchfrr.8.in +++ b/doc/watchfrr.8.in @@ -108,13 +108,13 @@ Set the logging (LOG_DEBUG), but higher number can be supplied if extra debugging messages are required. .TP -.BI \-m " number" "\fR, \fB\-\-min\-restart\-interval " number +.BI \-\-min\-restart\-interval " number Set the minimum .I number of seconds to wait between invocations of the daemon restart commands (the default value is "60"). .TP -.BI \-M " number" "\fR, \fB\-\-max\-restart\-interval " number +.BI \-\-max\-restart\-interval " number Set the maximum .I number of seconds to wait between invocations of the daemon restart commands (the diff --git a/doc/zebra.8.in b/doc/zebra.8.in index 4599a85635..f5b8bd4d80 100644 --- a/doc/zebra.8.in +++ b/doc/zebra.8.in @@ -23,6 +23,9 @@ zebra \- a routing manager for use with associated @PACKAGE_FULLNAME@ components ] [ .B \-g .I group +] [ +.B \-M +.I module:options ] .SH DESCRIPTION .B zebra @@ -86,6 +89,14 @@ maximum before starting zebra. Note that this affects Linux only. .TP +\fB\-M\fR, \fB\-\-module \fR\fImodule:options\fR +Load a module at startup. May be specified more than once. +The \fBsnmp\fR and \fBfpm\fR modules may be +available for \fBzebra\fR, if the package was built with SNMP and FPM support +respectively. The \fBfpm\fR module takes an additional colon-separated +argument specifying the encapsulation, either \fBnetlink\fR or \fBprotobuf\fR. +It should thus be loaded with \fB-M fpm:netlink\fR or \fB-M fpm:protobuf\fR. +.TP \fB\-v\fR, \fB\-\-version\fR Print the version and exit. .SH FILES From 02fe6f865ebed8d7a20e32689c084bbe0001543a Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Mon, 23 Jan 2017 20:52:13 +0100 Subject: [PATCH 17/61] COMMUNITY.md: update CodingStyle & branching Also add a note that this is documentation, not law. Signed-off-by: David Lamparter --- COMMUNITY.md | 93 +++++- doc/git_branches.svg | 721 ++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 799 insertions(+), 15 deletions(-) diff --git a/COMMUNITY.md b/COMMUNITY.md index 52777da968..704c47a95e 100644 --- a/COMMUNITY.md +++ b/COMMUNITY.md @@ -2,6 +2,16 @@ [TOC] +## General note on this document + +This document is "descriptive/post-factual" in that it documents pratices that +are in use; it is not "definitive/pre-factual" in prescribing practices. + +This means that when a procedure changes, it is agreed upon, then put into +practice, and then documented here. If this document doesn't match reality, +it's the document that needs to be updated, not reality. + + ## Git Structure The master Git for PROJECT resides on Github at @@ -10,20 +20,21 @@ The master Git for PROJECT resides on Github at ![git branches continually merging to the left from 3 lanes; float-right](doc/git_branches.svg "git branch mechanics") -There are 3 main branches for development and a release branch for each +There is one main branch for development and a release branch for each major release. -New contributions are done against the head of the Develop branch. The CI +New contributions are done against the head of the master branch. The CI systems will pick up the Github Pull Requests or the new patch from -Patchwork, run some basic build and functional tests and will merge them -into the branch automatically on success. - -Code on the develop branch will then be further tested and reviewed by the -community and merged to master on a regular interval. +Patchwork, run some basic build and functional tests. For each major release (1.0, 1.1 etc) a new release branch is created based on the master. +There was an attempt to use a "develop" branch automatically maintained by +the CI system. This is not currently in active use, though the system is +operational. If the "develop" branch is in active use and this paragraph +is still here, this document obviously wasn't updated. + ## Programming language, Tools and Libraries @@ -250,16 +261,72 @@ Portions: ### Code styling / format -GNU coding standards apply. Indentation follows the result of invoking GNU -indent (as of 2.2.8a) with the `-nut -nfc1` arguments. +Coding style standards in FRR vary depending on location. Pre-existing +code uses GNU coding standards. New code may use Linux kernel coding style. + +GNU coding style apply to the following parts: + +* lib/ +* zebra/ +* bgpd/ +* ospfd/ +* ospf6d/ +* isisd/ +* ripd/ +* ripngd/ +* vtysh/ + +Linux kernel coding style applies to: + +* nhrpd/ +* watchfrr/ +* pimd/ +* lib/{checksum,hook,imsg-buffer,imsg,libfrr,md5,module,monotime,queue}.[ch] + +BSD coding style applies to: + +* ldpd/ + +**Whitespace changes in untouched parts of the code are not acceptable in +patches that change actual code.** To change/fix formatting issues, please +create a separate patch that only does formatting changes and nothing else. + +It is acceptable to rewrap entire files to Linux kernel style, but this +**MUST** come as a separate patch that does nothing other than this +reformatting. + + +#### GNU style + +For GNU coding style, Indentation follows the result of invoking GNU indent: ``` indent -nut -nfc1 file_for_submission.c ``` -Please don’t reformat existing files (or only sections modified by your -changes), even if they don’t follow the standard. This makes it very hard to -highlight the changes +Originally, tabs were used instead of spaces, with tabs are every 8 columns. +However, tab interoperability issues mean space characters are now preferred for +new changes. We generally only clean up whitespace when code is unmaintainable +due to whitespace issues, to minimise merging conflicts. + + +#### Linux kernel & BSD style + +These styles are documented externally: + +* [https://www.kernel.org/doc/Documentation/CodingStyle](https://www.kernel.org/doc/Documentation/CodingStyle). +* [http://man.openbsd.org/style](http://man.openbsd.org/style) + +They are relatively similar but differ in details. + +pimd deviates from Linux kernel style in using 2 spaces for indentation, with +Tabs replacing 8 spaces, as well as adding a line break between `}` and `else`. +It is acceptable to convert indentation in pimd/ to Linux kernel style, but +please convert an entire file at a time. (Rationale: apart from 2-space +indentation, the styles are sufficiently close to not upset when mixed.) + +Unlike GNU style, these styles use tabs, not spaces. + ### Compile-Time conditional code @@ -307,4 +374,4 @@ of their debugs. CLI's are a complicated ugly beast. Additions or changes to the CLI should use a DEFUN to encapsulate one setting as much as is possible. Additionally as new DEFUN's are added to the system, documentation -should be provided for the new commands. \ No newline at end of file +should be provided for the new commands. diff --git a/doc/git_branches.svg b/doc/git_branches.svg index 3943eeacc8..0c2c96e39e 100644 --- a/doc/git_branches.svg +++ b/doc/git_branches.svg @@ -1,3 +1,720 @@ - -1.0ReleaseBranchMaster(Stable)Develop1.1ReleaseBranchVersion 1.0.a1Version 1.1.a1Version 1.1.a2Version 1.1.b1Patch Email (Patchwork)Github Pull RequestGithub Pull RequestPatch Email (Patchwork)Patch Email (Patchwork)Github Pull RequestGithub Pull RequestGithub Pull RequestPatch Email (Patchwork)Github Pull RequestGithub Pull RequestGithub Pull RequestGithub Pull RequestGithub Pull RequestGithub Pull RequestVersion 1.0.a2Version 1.0.b1Version 1.0.0Version 1.1.0Version 1.1.1Version 1.1.2 + + + + + image/svg+xml + + + + + + + + + + + + + + + 1.0ReleaseBranch + + + + + + + + + + Master(Stable) + + + + + + + + + 1.1ReleaseBranch + Version 1.0.a1 + Version 1.1.a1 + Version 1.1.a2 + + + + + Version 1.1.b1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Patch Email (Patchwork) + Github Pull Request + Github Pull Request + Patch Email (Patchwork) + Patch Email (Patchwork) + Github Pull Request + Github Pull Request + Github Pull Request + Patch Email (Patchwork) + Github Pull Request + Github Pull Request + Github Pull Request + Github Pull Request + Github Pull Request + Github Pull Request + + + + + + + + + Version 1.0.a2 + Version 1.0.b1 + Version 1.0.0 + Version 1.1.0 + Version 1.1.1 + Version 1.1.2 + + + + + + + + + + + + + + + + + + From 1ea8289e2abd1a020310d6cab8dfc05cdd195d5c Mon Sep 17 00:00:00 2001 From: Christian Franke Date: Tue, 28 Mar 2017 18:23:47 +0200 Subject: [PATCH 18/61] tests: format TestRefMismatch more readable Signed-off-by: Christian Franke --- tests/helpers/python/frrtest.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/tests/helpers/python/frrtest.py b/tests/helpers/python/frrtest.py index 20c854f66c..21944bcf98 100644 --- a/tests/helpers/python/frrtest.py +++ b/tests/helpers/python/frrtest.py @@ -27,6 +27,7 @@ import sys import re import inspect import os +import difflib import frrsix @@ -154,7 +155,18 @@ class TestMultiOut(_TestMultiOut): # class TestRefMismatch(Exception): - pass + def __init__(self, _test, outtext, reftext): + self.outtext = outtext.decode('utf8') if type(outtext) is bytes else outtext + self.reftext = reftext.decode('utf8') if type(reftext) is bytes else reftext + + def __str__(self): + rv = 'Expected output and actual output differ:\n' + rv += '\n'.join(difflib.unified_diff(self.reftext.splitlines(), + self.outtext.splitlines(), + 'outtext', 'reftext', + lineterm='')) + return rv + class TestExitNonzero(Exception): pass From 8efe88eacfcbffcefd274238105b932dff76803a Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Thu, 9 Mar 2017 19:00:19 +0100 Subject: [PATCH 19/61] *: track version & "defaults" in configs [CF]: Move default name to autoconf and update tests Signed-off-by: Christian Franke --- Makefile.am | 2 + bgpd/bgpd.c | 36 ++++++-- bgpd/bgpd.h | 8 +- configure.ac | 6 ++ defaults.h | 54 +++++++++++ lib/command.c | 91 +++++++++++-------- lib/version.h.in | 1 + ospf6d/ospf6_top.c | 7 +- ospfd/ospf_vty.c | 5 +- ospfd/ospfd.c | 3 + tests/lib/cli/.gitignore | 1 + .../{test_cli.refout => test_cli.refout.in} | 6 ++ vtysh/vtysh_config.c | 1 + 13 files changed, 170 insertions(+), 51 deletions(-) create mode 100644 defaults.h create mode 100644 tests/lib/cli/.gitignore rename tests/lib/cli/{test_cli.refout => test_cli.refout.in} (93%) diff --git a/Makefile.am b/Makefile.am index 63dedeac06..3e73bd0cdd 100644 --- a/Makefile.am +++ b/Makefile.am @@ -16,3 +16,5 @@ EXTRA_DIST = aclocal.m4 SERVICES REPORTING-BUGS \ tools/zebra.el tools/multiple-bgpd.sh ACLOCAL_AMFLAGS = -I m4 + +noinst_HEADERS = defaults.h diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index 5280731234..86133cd763 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -2889,10 +2889,18 @@ bgp_create (as_t *as, const char *name, enum bgp_instance_type inst_type) bgp->stalepath_time = BGP_DEFAULT_STALEPATH_TIME; bgp->dynamic_neighbors_limit = BGP_DYNAMIC_NEIGHBORS_LIMIT_DEFAULT; bgp->dynamic_neighbors_count = 0; +#if DFLT_BGP_IMPORT_CHECK bgp_flag_set (bgp, BGP_FLAG_IMPORT_CHECK); +#endif +#if DFLT_BGP_SHOW_HOSTNAME bgp_flag_set (bgp, BGP_FLAG_SHOW_HOSTNAME); +#endif +#if DFLT_BGP_LOG_NEIGHBOR_CHANGES bgp_flag_set (bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES); +#endif +#if DFLT_BGP_DETERMINISTIC_MED bgp_flag_set (bgp, BGP_FLAG_DETERMINISTIC_MED); +#endif bgp->addpath_tx_id = BGP_ADDPATH_TX_ID_FOR_DEFAULT_ORIGINATE; bgp->as = *as; @@ -7263,8 +7271,11 @@ bgp_config_write (struct vty *vty) inet_ntoa (bgp->router_id_static), VTY_NEWLINE); /* BGP log-neighbor-changes. */ - if (!bgp_flag_check (bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES)) - vty_out (vty, " no bgp log-neighbor-changes%s", VTY_NEWLINE); + if (!!bgp_flag_check (bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES) + != DFLT_BGP_LOG_NEIGHBOR_CHANGES) + vty_out (vty, " %sbgp log-neighbor-changes%s", + bgp_flag_check (bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES) ? "" : "no ", + VTY_NEWLINE); /* BGP configuration. */ if (bgp_flag_check (bgp, BGP_FLAG_ALWAYS_COMPARE_MED)) @@ -7280,8 +7291,11 @@ bgp_config_write (struct vty *vty) bgp->default_local_pref, VTY_NEWLINE); /* BGP default show-hostname */ - if (!bgp_flag_check(bgp, BGP_FLAG_SHOW_HOSTNAME)) - vty_out (vty, " no bgp default show-hostname%s", VTY_NEWLINE); + if (!!bgp_flag_check(bgp, BGP_FLAG_SHOW_HOSTNAME) + != DFLT_BGP_SHOW_HOSTNAME) + vty_out (vty, " %sbgp default show-hostname%s", + bgp_flag_check (bgp, BGP_FLAG_SHOW_HOSTNAME) ? "" : "no ", + VTY_NEWLINE); /* BGP default subgroup-pkt-queue-max. */ if (bgp->default_subgroup_pkt_queue_max != BGP_DEFAULT_SUBGROUP_PKT_QUEUE_MAX) @@ -7324,8 +7338,11 @@ bgp_config_write (struct vty *vty) vty_out (vty, " bgp enforce-first-as%s", VTY_NEWLINE); /* BGP deterministic-med. */ - if (!bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED)) - vty_out (vty, " no bgp deterministic-med%s", VTY_NEWLINE); + if (!!bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED) + != DFLT_BGP_DETERMINISTIC_MED) + vty_out (vty, " %sbgp deterministic-med%s", + bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED) ? "" : "no ", + VTY_NEWLINE); /* BGP update-delay. */ bgp_config_write_update_delay (vty, bgp); @@ -7397,8 +7414,11 @@ bgp_config_write (struct vty *vty) } /* BGP network import check. */ - if (!bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK)) - vty_out (vty, " no bgp network import-check%s", VTY_NEWLINE); + if (!!bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK) + != DFLT_BGP_IMPORT_CHECK) + vty_out (vty, " %sbgp network import-check%s", + bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK) ? "" : "no ", + VTY_NEWLINE); /* BGP flag dampening. */ if (CHECK_FLAG (bgp->af_flags[AFI_IP][SAFI_UNICAST], diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h index 510082fdc2..f1e5d7b0ad 100644 --- a/bgpd/bgpd.h +++ b/bgpd/bgpd.h @@ -29,6 +29,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #include "sockunion.h" #include "routemap.h" #include "linklist.h" +#include "defaults.h" #include "bgp_memory.h" #define BGP_MAX_HOSTNAME 64 /* Linux max, is larger than most other sys */ @@ -1052,12 +1053,13 @@ struct bgp_nlri #define BGP_EVENTS_MAX 15 /* BGP timers default value. */ +/* note: the DFLT_ ones depend on compile-time "defaults" selection */ #define BGP_INIT_START_TIMER 1 -#define BGP_DEFAULT_HOLDTIME 9 -#define BGP_DEFAULT_KEEPALIVE 3 +#define BGP_DEFAULT_HOLDTIME DFLT_BGP_HOLDTIME +#define BGP_DEFAULT_KEEPALIVE DFLT_BGP_KEEPALIVE #define BGP_DEFAULT_EBGP_ROUTEADV 0 #define BGP_DEFAULT_IBGP_ROUTEADV 0 -#define BGP_DEFAULT_CONNECT_RETRY 10 +#define BGP_DEFAULT_CONNECT_RETRY DFLT_BGP_TIMERS_CONNECT /* BGP default local preference. */ #define BGP_DEFAULT_LOCAL_PREF 100 diff --git a/configure.ac b/configure.ac index 6ff64d086a..9fc3cb72f3 100755 --- a/configure.ac +++ b/configure.ac @@ -346,7 +346,12 @@ AC_SUBST(MPLS_METHOD) if test "${enable_cumulus}" = "yes" ; then AC_DEFINE(HAVE_CUMULUS,,Compile Special Cumulus Code in) + DFLT_NAME="datacenter" +else + DFLT_NAME="traditional" fi +AC_SUBST(DFLT_NAME) +AC_DEFINE_UNQUOTED(DFLT_NAME,["$DFLT_NAME"], Name of the configuration default set) if test "${enable_shell_access}" = "yes"; then AC_DEFINE(HAVE_SHELL_ACCESS,,Allow user to use ssh/telnet/bash) @@ -1599,6 +1604,7 @@ AC_CONFIG_FILES([Makefile lib/Makefile qpb/Makefile zebra/Makefile ripd/Makefile snapcraft/Makefile snapcraft/snapcraft.yaml lib/version.h + tests/lib/cli/test_cli.refout doc/defines.texi doc/bgpd.8 doc/isisd.8 diff --git a/defaults.h b/defaults.h new file mode 100644 index 0000000000..e43fb2aa1a --- /dev/null +++ b/defaults.h @@ -0,0 +1,54 @@ +/* + * FRR switchable defaults. + * Copyright (C) 2017 David Lamparter for NetDEF, Inc. + * + * This file is part of FreeRangeRouting (FRR). + * + * FRR 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. + * + * FRR 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 FRR; see the file COPYING. If not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _FRR_DEFAULTS_H +#define _FRR_DEFAULTS_H + +#include "config.h" + +#ifdef HAVE_CUMULUS + +#define DFLT_BGP_IMPORT_CHECK 1 +#define DFLT_BGP_TIMERS_CONNECT 10 +#define DFLT_BGP_HOLDTIME 9 +#define DFLT_BGP_KEEPALIVE 3 +#define DFLT_BGP_LOG_NEIGHBOR_CHANGES 1 +#define DFLT_BGP_SHOW_HOSTNAME 1 +#define DFLT_BGP_DETERMINISTIC_MED 1 + +#define DFLT_OSPF_LOG_ADJACENCY_CHANGES 1 +#define DFLT_OSPF6_LOG_ADJACENCY_CHANGES 1 + +#else /* !HAVE_CUMULUS */ + +#define DFLT_BGP_IMPORT_CHECK 0 +#define DFLT_BGP_TIMERS_CONNECT 120 +#define DFLT_BGP_HOLDTIME 180 +#define DFLT_BGP_KEEPALIVE 60 +#define DFLT_BGP_LOG_NEIGHBOR_CHANGES 0 +#define DFLT_BGP_SHOW_HOSTNAME 0 +#define DFLT_BGP_DETERMINISTIC_MED 0 + +#define DFLT_OSPF_LOG_ADJACENCY_CHANGES 0 +#define DFLT_OSPF6_LOG_ADJACENCY_CHANGES 0 + +#endif /* !HAVE_CUMULUS */ + +#endif /* _FRR_DEFAULTS_H */ diff --git a/lib/command.c b/lib/command.c index c9b261cf2a..919e27ada4 100644 --- a/lib/command.c +++ b/lib/command.c @@ -34,6 +34,7 @@ Boston, MA 02111-1307, USA. */ #include "workqueue.h" #include "vrf.h" #include "qobj.h" +#include "defaults.h" DEFINE_MTYPE( LIB, HOST, "Host config") DEFINE_MTYPE( LIB, STRVEC, "String vector") @@ -3082,6 +3083,23 @@ DEFUN (show_version, return CMD_SUCCESS; } +/* "Set" version ... ignore version tags */ +DEFUN (frr_version_defaults, + frr_version_defaults_cmd, + "frr (version|defaults) .LINE", + "FreeRangeRouting global parameters\n" + "version configuration was written by\n" + "set of configuration defaults used\n" + "version string\n") +{ + if (vty->type == VTY_TERM || vty->type == VTY_SHELL) + /* only print this when the user tries to do run it */ + vty_out (vty, "%% NOTE: This command currently does nothing.%s" + "%% It is written to the configuration for future reference.%s", + VTY_NEWLINE, VTY_NEWLINE); + return CMD_SUCCESS; +} + /* Help display function for all node. */ DEFUN (config_help, config_help_cmd, @@ -3125,6 +3143,37 @@ DEFUN (config_list, return CMD_SUCCESS; } +static void +vty_write_config (struct vty *vty) +{ + size_t i; + struct cmd_node *node; + + if (vty->type == VTY_TERM) + { + vty_out (vty, "%sCurrent configuration:%s", VTY_NEWLINE, + VTY_NEWLINE); + vty_out (vty, "!%s", VTY_NEWLINE); + } + + vty_out (vty, "frr version %s%s", FRR_VER_SHORT, VTY_NEWLINE); + vty_out (vty, "frr defaults %s%s", DFLT_NAME, VTY_NEWLINE); + vty_out (vty, "!%s", VTY_NEWLINE); + + for (i = 0; i < vector_active (cmdvec); i++) + if ((node = vector_slot (cmdvec, i)) && node->func + && (node->vtysh || vty->type != VTY_SHELL)) + { + if ((*node->func) (vty)) + vty_out (vty, "!%s", VTY_NEWLINE); + } + + if (vty->type == VTY_TERM) + { + vty_out (vty, "end%s",VTY_NEWLINE); + } +} + /* Write current configuration into file. */ DEFUN (config_write_file, config_write_file_cmd, @@ -3132,9 +3181,7 @@ DEFUN (config_write_file, "Write running configuration to memory, network, or terminal\n" "Write to configuration file\n") { - unsigned int i; int fd, dirfd; - struct cmd_node *node; char *config_file, *slash; char *config_file_tmp = NULL; char *config_file_sav = NULL; @@ -3205,13 +3252,7 @@ DEFUN (config_write_file, vty_out (file_vty, "!\n! Zebra configuration saved from vty\n! "); vty_time_print (file_vty, 1); vty_out (file_vty, "!\n"); - - for (i = 0; i < vector_active (cmdvec); i++) - if ((node = vector_slot (cmdvec, i)) && node->func) - { - if ((*node->func) (file_vty)) - vty_out (file_vty, "!\n"); - } + vty_write_config (file_vty); vty_close (file_vty); if (stat(config_file, &conf_stat) >= 0) @@ -3277,35 +3318,8 @@ DEFUN (config_write_terminal, "Write running configuration to memory, network, or terminal\n" "Write to terminal\n") { - unsigned int i; - struct cmd_node *node; - - if (host.noconfig) - return CMD_SUCCESS; - - if (vty->type == VTY_SHELL_SERV) - { - for (i = 0; i < vector_active (cmdvec); i++) - if ((node = vector_slot (cmdvec, i)) && node->func && node->vtysh) - { - if ((*node->func) (vty)) - vty_out (vty, "!%s", VTY_NEWLINE); - } - } - else - { - vty_out (vty, "%sCurrent configuration:%s", VTY_NEWLINE, - VTY_NEWLINE); - vty_out (vty, "!%s", VTY_NEWLINE); - - for (i = 0; i < vector_active (cmdvec); i++) - if ((node = vector_slot (cmdvec, i)) && node->func) - { - if ((*node->func) (vty)) - vty_out (vty, "!%s", VTY_NEWLINE); - } - vty_out (vty, "end%s",VTY_NEWLINE); - } + if (!host.noconfig) + vty_write_config (vty); return CMD_SUCCESS; } @@ -4301,6 +4315,7 @@ cmd_init (int terminal) install_element (CONFIG_NODE, &hostname_cmd); install_element (CONFIG_NODE, &no_hostname_cmd); + install_element (CONFIG_NODE, &frr_version_defaults_cmd); if (terminal > 0) { diff --git a/lib/version.h.in b/lib/version.h.in index adc8278189..6c78bd0544 100644 --- a/lib/version.h.in +++ b/lib/version.h.in @@ -41,6 +41,7 @@ #define FRR_FULL_NAME "FreeRangeRouting" #define FRR_VERSION "@PACKAGE_VERSION@" GIT_SUFFIX +#define FRR_VER_SHORT "@PACKAGE_VERSION@" #define FRR_BUG_ADDRESS "@PACKAGE_BUGREPORT@" #define FRR_COPYRIGHT "Copyright 1996-2005 Kunihiro Ishiguro, et al." #define FRR_CONFIG_ARGS "@CONFIG_ARGS@" diff --git a/ospf6d/ospf6_top.c b/ospf6d/ospf6_top.c index 3d632b644e..f2d14ef09c 100644 --- a/ospf6d/ospf6_top.c +++ b/ospf6d/ospf6_top.c @@ -29,6 +29,7 @@ #include "table.h" #include "thread.h" #include "command.h" +#include "defaults.h" #include "ospf6_proto.h" #include "ospf6_message.h" @@ -158,7 +159,9 @@ ospf6_create (void) o->distance_table = route_table_init (); /* Enable "log-adjacency-changes" */ +#if DFLT_OSPF6_LOG_ADJACENCY_CHANGES SET_FLAG(o->config_flags, OSPF6_LOG_ADJACENCY_CHANGES); +#endif return o; } @@ -1132,8 +1135,10 @@ config_write_ospf6 (struct vty *vty) { if (CHECK_FLAG(ospf6->config_flags, OSPF6_LOG_ADJACENCY_DETAIL)) vty_out(vty, " log-adjacency-changes detail%s", VTY_NEWLINE); + else if (!DFLT_OSPF6_LOG_ADJACENCY_CHANGES) + vty_out(vty, " log-adjacency-changes%s", VTY_NEWLINE); } - else + else if (DFLT_OSPF6_LOG_ADJACENCY_CHANGES) { vty_out(vty, " no log-adjacency-changes%s", VTY_NEWLINE); } diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c index 2c3aaa6808..5faf2850d9 100644 --- a/ospfd/ospf_vty.c +++ b/ospfd/ospf_vty.c @@ -33,6 +33,7 @@ #include "plist.h" #include "log.h" #include "zclient.h" +#include "defaults.h" #include "ospfd/ospfd.h" #include "ospfd/ospf_asbr.h" @@ -9873,8 +9874,10 @@ ospf_config_write (struct vty *vty) { if (CHECK_FLAG(ospf->config, OSPF_LOG_ADJACENCY_DETAIL)) vty_out(vty, " log-adjacency-changes detail%s", VTY_NEWLINE); + else if (!DFLT_OSPF_LOG_ADJACENCY_CHANGES) + vty_out(vty, " log-adjacency-changes%s", VTY_NEWLINE); } - else + else if (DFLT_OSPF_LOG_ADJACENCY_CHANGES) { vty_out(vty, " no log-adjacency-changes%s", VTY_NEWLINE); } diff --git a/ospfd/ospfd.c b/ospfd/ospfd.c index b83093db3c..53b81c6248 100644 --- a/ospfd/ospfd.c +++ b/ospfd/ospfd.c @@ -35,6 +35,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #include "plist.h" #include "sockopt.h" #include "bfd.h" +#include "defaults.h" #include "ospfd/ospfd.h" #include "ospfd/ospf_network.h" @@ -291,7 +292,9 @@ ospf_new (u_short instance) new->write_oi_count = OSPF_WRITE_INTERFACE_COUNT_DEFAULT; /* Enable "log-adjacency-changes" */ +#if DFLT_OSPF_LOG_ADJACENCY_CHANGES SET_FLAG(new->config, OSPF_LOG_ADJACENCY_CHANGES); +#endif return new; } diff --git a/tests/lib/cli/.gitignore b/tests/lib/cli/.gitignore new file mode 100644 index 0000000000..682e95faa1 --- /dev/null +++ b/tests/lib/cli/.gitignore @@ -0,0 +1 @@ +/test_cli.refout diff --git a/tests/lib/cli/test_cli.refout b/tests/lib/cli/test_cli.refout.in similarity index 93% rename from tests/lib/cli/test_cli.refout rename to tests/lib/cli/test_cli.refout.in index 7da5494827..26f7f09a0d 100644 --- a/tests/lib/cli/test_cli.refout +++ b/tests/lib/cli/test_cli.refout.in @@ -270,6 +270,9 @@ test# show run Current configuration: ! +frr version @PACKAGE_VERSION@ +frr defaults @DFLT_NAME@ +! hostname test ! ! @@ -282,6 +285,9 @@ foohost(config)# do show run Current configuration: ! +frr version @PACKAGE_VERSION@ +frr defaults @DFLT_NAME@ +! hostname foohost ! ! diff --git a/vtysh/vtysh_config.c b/vtysh/vtysh_config.c index e60e9c091f..94c4042dd4 100644 --- a/vtysh/vtysh_config.c +++ b/vtysh/vtysh_config.c @@ -274,6 +274,7 @@ vtysh_config_parse_line (const char *line) { if (strncmp (line, "log", strlen ("log")) == 0 || strncmp (line, "hostname", strlen ("hostname")) == 0 + || strncmp (line, "frr", strlen ("frr")) == 0 ) config_add_line_uniq (config_top, line); else From 447a8fe92ebf4615ba1f6c1259af9aa64f0d21a6 Mon Sep 17 00:00:00 2001 From: Lou Berger Date: Thu, 30 Mar 2017 14:22:35 -0400 Subject: [PATCH 20/61] Rename: FreeRangeRouting FRRouting Signed-off-by: Lou Berger --- ChangeLog | 2 +- REPORTING-BUGS | 6 +++--- configure.ac | 6 +++--- defaults.h | 2 +- doc/Building_FRR_on_CentOS6.md | 2 +- doc/Building_FRR_on_CentOS7.md | 2 +- doc/Building_FRR_on_Debian8.md | 2 +- doc/Building_FRR_on_Fedora24.md | 2 +- lib/command.c | 2 +- lib/version.h.in | 2 +- ospfd/ospf_dump_api.c | 2 +- ospfd/ospf_dump_api.h | 2 +- redhat/README.rpm_build.md | 2 +- redhat/frr.spec.in | 12 ++++++------ snapcraft/README.snap_build.md | 10 +++++----- snapcraft/README.usage.md | 10 +++++----- snapcraft/snapcraft.yaml.in | 6 +++--- solaris/README.txt | 12 ++++++------ solaris/depend.daemons.in | 2 +- solaris/depend.dev.in | 2 +- solaris/depend.libs.in | 2 +- solaris/depend.smf.in | 2 +- solaris/frr.init.in | 12 ++++++------ solaris/frr.xml.in | 18 +++++++++--------- tests/helpers/python/frrtest.py | 2 +- 25 files changed, 62 insertions(+), 62 deletions(-) diff --git a/ChangeLog b/ChangeLog index a201bb6819..6793fc25d7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,4 @@ -ChangeLog information for FreeRangeRouting is for now recorded in source-code +ChangeLog information for FRRouting is for now recorded in source-code management system. Please see: http://www.freerangerouting.org/ diff --git a/REPORTING-BUGS b/REPORTING-BUGS index ea36ff5eed..a37f5c2829 100644 --- a/REPORTING-BUGS +++ b/REPORTING-BUGS @@ -1,5 +1,5 @@ -This file describes the procedure for reporting FreeRangeRouting bugs. You are not -obliged to follow this format, but it would be great help for FreeRangeRouting developers +This file describes the procedure for reporting FRRouting bugs. You are not +obliged to follow this format, but it would be great help for FRRouting developers if you report a bug as described below. Bugs submitted with woefully incomplete information may be summarily @@ -13,7 +13,7 @@ Report bugs on Github Issue Tracker at https://github.com/freerangerouting/frr/issues Please supply the following information: -1. Your FreeRangeRouting version or if it is from git then the commit reference. +1. Your FRRouting version or if it is from git then the commit reference. Please try to report bugs against git master or the latest release. 2. FRR daemons you run e.g. bgpd or ripd and full name of your OS. Any specific options you compiled Quagga with. diff --git a/configure.ac b/configure.ac index 9fc3cb72f3..cbddaa63fa 100755 --- a/configure.ac +++ b/configure.ac @@ -1,5 +1,5 @@ ## -## Configure template file for FreeRangeRouting. +## Configure template file for FRRouting. ## autoconf will generate configure script. ## ## Copyright (c) 1996, 97, 98, 99, 2000 Kunihiro Ishiguro @@ -9,7 +9,7 @@ AC_PREREQ(2.60) AC_INIT(frr, 2.0-rc2, [https://github.com/freerangerouting/frr/issues]) PACKAGE_URL="https://freerangerouting.org/" -PACKAGE_FULLNAME="FreeRangeRouting" +PACKAGE_FULLNAME="FRRouting" AC_SUBST(PACKAGE_FULLNAME) CONFIG_ARGS="$ac_configure_args" @@ -1639,7 +1639,7 @@ AC_CONFIG_FILES([vtysh/extract.pl],[chmod +x vtysh/extract.pl]) AC_OUTPUT echo " -FreeRangeRouting configuration +FRRouting configuration ------------------------------ FRR version : ${PACKAGE_VERSION} host operating system : ${host_os} diff --git a/defaults.h b/defaults.h index e43fb2aa1a..57e35f3ce6 100644 --- a/defaults.h +++ b/defaults.h @@ -2,7 +2,7 @@ * FRR switchable defaults. * Copyright (C) 2017 David Lamparter for NetDEF, Inc. * - * This file is part of FreeRangeRouting (FRR). + * This file is part of FRRouting (FRR). * * FRR 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 diff --git a/doc/Building_FRR_on_CentOS6.md b/doc/Building_FRR_on_CentOS6.md index ccb07fb2ac..1ff4748230 100644 --- a/doc/Building_FRR_on_CentOS6.md +++ b/doc/Building_FRR_on_CentOS6.md @@ -69,7 +69,7 @@ any packages** sudo groupadd -g 92 frr sudo groupadd -r -g 85 frrvt sudo useradd -u 92 -g 92 -M -r -G frrvt -s /sbin/nologin \ - -c "FRR FreeRangeRouting suite" -d /var/run/frr frr + -c "FRR FRRouting suite" -d /var/run/frr frr ### Download Source, configure and compile it (You may prefer different options on configure statement. These are just diff --git a/doc/Building_FRR_on_CentOS7.md b/doc/Building_FRR_on_CentOS7.md index cd10a91ed7..1a9bcb8817 100644 --- a/doc/Building_FRR_on_CentOS7.md +++ b/doc/Building_FRR_on_CentOS7.md @@ -28,7 +28,7 @@ any packages** sudo groupadd -g 92 frr sudo groupadd -r -g 85 frrvt sudo useradd -u 92 -g 92 -M -r -G frrvt -s /sbin/nologin \ - -c "FRR FreeRangeRouting suite" -d /var/run/frr frr + -c "FRR FRRouting suite" -d /var/run/frr frr ### Download Source, configure and compile it (You may prefer different options on configure statement. These are just diff --git a/doc/Building_FRR_on_Debian8.md b/doc/Building_FRR_on_Debian8.md index 902f8c623a..4335e76210 100644 --- a/doc/Building_FRR_on_Debian8.md +++ b/doc/Building_FRR_on_Debian8.md @@ -32,7 +32,7 @@ any packages** sudo addgroup --system --gid 92 frr sudo addgroup --system --gid 85 frrvty sudo adduser --system --ingroup frr --groups frrvty --home /var/run/frr/ \ - --gecos "FRR FreeRangeRouting suite" --shell /bin/false frr + --gecos "FRR FRRouting suite" --shell /bin/false frr sudo usermode ### Download Source, configure and compile it diff --git a/doc/Building_FRR_on_Fedora24.md b/doc/Building_FRR_on_Fedora24.md index 9617afc733..0afc5c676a 100644 --- a/doc/Building_FRR_on_Fedora24.md +++ b/doc/Building_FRR_on_Fedora24.md @@ -21,7 +21,7 @@ using any packages** sudo groupadd -g 92 frr sudo groupadd -r -g 85 frrvt sudo useradd -u 92 -g 92 -M -r -G frrvt -s /sbin/nologin \ - -c "FRR FreeRangeRouting suite" -d /var/run/frr frr + -c "FRR FRRouting suite" -d /var/run/frr frr ### Download Source, configure and compile it (You may prefer different options on configure statement. These are just diff --git a/lib/command.c b/lib/command.c index 919e27ada4..142636afce 100644 --- a/lib/command.c +++ b/lib/command.c @@ -3087,7 +3087,7 @@ DEFUN (show_version, DEFUN (frr_version_defaults, frr_version_defaults_cmd, "frr (version|defaults) .LINE", - "FreeRangeRouting global parameters\n" + "FRRouting global parameters\n" "version configuration was written by\n" "set of configuration defaults used\n" "version string\n") diff --git a/lib/version.h.in b/lib/version.h.in index 6c78bd0544..d9eabb9f81 100644 --- a/lib/version.h.in +++ b/lib/version.h.in @@ -39,7 +39,7 @@ #define FRR_SMUX_NAME "@PACKAGE_NAME@" #define FRR_PTM_NAME "@PACKAGE_NAME@" -#define FRR_FULL_NAME "FreeRangeRouting" +#define FRR_FULL_NAME "FRRouting" #define FRR_VERSION "@PACKAGE_VERSION@" GIT_SUFFIX #define FRR_VER_SHORT "@PACKAGE_VERSION@" #define FRR_BUG_ADDRESS "@PACKAGE_BUGREPORT@" diff --git a/ospfd/ospf_dump_api.c b/ospfd/ospf_dump_api.c index 20e7740d32..5ef262ce54 100644 --- a/ospfd/ospf_dump_api.c +++ b/ospfd/ospf_dump_api.c @@ -2,7 +2,7 @@ * OSPFd dump routine (parts used by ospfclient). * Copyright (C) 1999, 2000 Toshiaki Takada * - * This file is part of FreeRangeRouting (FRR). + * This file is part of FRRouting (FRR). * * FRR 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 diff --git a/ospfd/ospf_dump_api.h b/ospfd/ospf_dump_api.h index c3ff1e3f54..1cd8257f0c 100644 --- a/ospfd/ospf_dump_api.h +++ b/ospfd/ospf_dump_api.h @@ -2,7 +2,7 @@ * OSPFd dump routine (parts used by ospfclient). * Copyright (C) 1999 Toshiaki Takada * - * This file is part of FreeRangeRouting (FRR). + * This file is part of FRRouting (FRR). * * FRR 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 diff --git a/redhat/README.rpm_build.md b/redhat/README.rpm_build.md index db3c7d45c8..c266f3dc2e 100644 --- a/redhat/README.rpm_build.md +++ b/redhat/README.rpm_build.md @@ -1,4 +1,4 @@ -Building your own FreeRangeRouting RPM +Building your own FRRouting RPM ====================================== (Tested on CentOS 6, CentOS 7 and Fedora 22.) diff --git a/redhat/frr.spec.in b/redhat/frr.spec.in index c53e8459c9..e0d8f697db 100644 --- a/redhat/frr.spec.in +++ b/redhat/frr.spec.in @@ -8,7 +8,7 @@ # rpms again and again on the same day, so the newer rpms can be installed. # bumping the number each time. -####################### FreeRangeRouting (FRR) configure options ######################### +####################### FRRouting (FRR) configure options ######################### # with-feature options %{!?with_tcp_zebra: %global with_tcp_zebra 0 } %{!?with_pam: %global with_pam 0 } @@ -128,14 +128,14 @@ BuildRoot: %{_tmppath}/%{name}-%{version}-root Obsoletes: bird gated mrt zebra frr-sysvinit %description -FreeRangeRouting is a free software that manages TCP/IP based routing +FRRouting is a free software that manages TCP/IP based routing protocol. It takes multi-server and multi-thread approach to resolve the current complexity of the Internet. -FreeRangeRouting supports BGP4, OSPFv2, OSPFv3, ISIS, RIP, RIPng, PIM +FRRouting supports BGP4, OSPFv2, OSPFv3, ISIS, RIP, RIPng, PIM and LDP -FreeRangeRouting is a fork of Quagga. +FRRouting is a fork of Quagga. %package contrib Summary: contrib tools for frr @@ -303,7 +303,7 @@ if getent group %frr_user >/dev/null; then : ; else \ fi if getent passwd %frr_user >/dev/null ; then : ; else \ /usr/sbin/useradd -u %frr_uid -g %frr_gid \ - -M -r -s /sbin/nologin -c "FreeRangeRouting suite" \ + -M -r -s /sbin/nologin -c "FRRouting suite" \ -d %_localstatedir %frr_user 2> /dev/null || : ; \ fi %if 0%{?vty_group:1} @@ -571,7 +571,7 @@ rm -rf %{buildroot} %changelog * Fri Jan 6 2017 Martin Winter - %{version} -- Renamed to frr for FreeRangeRouting fork of Quagga +- Renamed to frr for FRRouting fork of Quagga * Thu Feb 11 2016 Paul Jakma - remove with_ipv6 conditionals, always build v6 diff --git a/snapcraft/README.snap_build.md b/snapcraft/README.snap_build.md index 341b210f71..b14b10b837 100644 --- a/snapcraft/README.snap_build.md +++ b/snapcraft/README.snap_build.md @@ -1,4 +1,4 @@ -Building your own FreeRangeRouting Snap +Building your own FRRouting Snap ======================================== (Tested on Ubuntu 16.04 with Snap Version 2, does not work on Ubuntu 15.x which uses earlier versions of snaps) @@ -7,7 +7,7 @@ which uses earlier versions of snaps) sudo apt-get install snapcraft -2. Checkout FreeRangeRouting under a **unpriviledged** user account +2. Checkout FRRouting under a **unpriviledged** user account git clone https://github.com/freerangerouting/frr.git cd frr @@ -56,8 +56,8 @@ The Snap will be auto-started and running. Operations ========== -### FreeRangeRouting Daemons -At this time, all FreeRangeRouting daemons are auto-started. +### FRRouting Daemons +At this time, all FRRouting daemons are auto-started. A daemon can be stopped/started with (ie ospf6d) @@ -69,7 +69,7 @@ or disabled/enabled with systemctl disable snap.frr.ospf6d.service systemctl enable snap.frr.ospf6d.service -### FreeRangeRouting Commands +### FRRouting Commands All the commands are prefixed with frr. frr.vtysh -> vtysh diff --git a/snapcraft/README.usage.md b/snapcraft/README.usage.md index 2d2b32b6b7..a8d6bca76c 100644 --- a/snapcraft/README.usage.md +++ b/snapcraft/README.usage.md @@ -1,14 +1,14 @@ -Using the FreeRangeRouting Snap +Using the FRRouting Snap =============================== After installing the Snap, the priviledged plug need to be connected: snap connect frr:network-control ubuntu-core:network-control -Enabling/Disabling FreeRangeRouting Daemons +Enabling/Disabling FRRouting Daemons ------------------------------------------- -By default (at this time), all FreeRangeRouting daemons will be enabled +By default (at this time), all FRRouting daemons will be enabled on installation. If you want to disable a specific daemon, then use the systemctl commands @@ -24,7 +24,7 @@ Commands defined by this snap ----------------------------- - `frr.vtysh`: - FreeRangeRouting VTY Shell (configuration tool) + FRRouting VTY Shell (configuration tool) - `frr.version`: Returns output of `zebra --version` to display version and configured options @@ -62,7 +62,7 @@ FAQ Sourcecode available ==================== -The source for this SNAP is available as part of the FreeRangeRouting +The source for this SNAP is available as part of the FRRouting Source Code Distribution. https://github.com/freerangerouting/frr.git diff --git a/snapcraft/snapcraft.yaml.in b/snapcraft/snapcraft.yaml.in index a703766f0b..a20a1d0392 100644 --- a/snapcraft/snapcraft.yaml.in +++ b/snapcraft/snapcraft.yaml.in @@ -1,11 +1,11 @@ name: frr version: @VERSION@ -summary: FreeRangeRouting BGP/OSPFv2/OSPFv3/ISIS/RIP/RIPng/PIM/LDP routing daemon +summary: FRRouting BGP/OSPFv2/OSPFv3/ISIS/RIP/RIPng/PIM/LDP routing daemon description: BGP/OSPFv2/OSPFv3/ISIS/RIP/RIPng/PIM routing daemon - FreeRangeRouting (FRR) is free software which manages TCP/IP based routing + FRRouting (FRR) is free software which manages TCP/IP based routing protocols. It supports BGP4, BGP4+, OSPFv2, OSPFv3, IS-IS, RIPv1, RIPv2, RIPng, PIM and LDP as well as the IPv6 versions of these. - FreeRangeRouting (frr) is a fork of Quagga. + FRRouting (frr) is a fork of Quagga. confinement: strict grade: devel diff --git a/solaris/README.txt b/solaris/README.txt index 01f725b8fa..589570d881 100644 --- a/solaris/README.txt +++ b/solaris/README.txt @@ -15,13 +15,13 @@ Requirements: i.manifest must be at least version 1.5. Place these scripts in this directory if you are using Solaris 10 GA (which does not ship with - these scripts), or in the solaris/ directory in the FreeRangeRouting source. + these scripts), or in the solaris/ directory in the FRRouting source. Package creation instructions: ------------------------------ -1. Configure and build FreeRangeRouting (frr) in the top level build directory as per normal, eg: +1. Configure and build FRRouting (frr) in the top level build directory as per normal, eg: ./configure --prefix=/usr/local/frr \ --localstatedir=/var/run/frr \ @@ -102,7 +102,7 @@ Install and post-install configuration notes: # # svcs -l ripd fmri svc:/network/routing/frr:ripd - name FreeRangeRouting: ripd, RIPv1/2 IPv4 routing protocol daemon. + name FRRouting: ripd, RIPv1/2 IPv4 routing protocol daemon. enabled true state online next_state none @@ -117,7 +117,7 @@ Install and post-install configuration notes: - Configuration of startup options is by way of SMF properties in a property group named 'frr'. The defaults should automatically be - inline with how you configured FreeRangeRouting in Step 1 above. + inline with how you configured FRRouting in Step 1 above. - By default the VTY interface is disabled. To change this, see below for how to set the 'frr/vty_port' property as appropriate for @@ -176,11 +176,11 @@ Install and post-install configuration notes: - As SMF is dependency aware, restarting network/zebra will restart all the other daemons. - - To upgrade from one set of FreeRangeRouting packages to a newer release, + - To upgrade from one set of FRRouting packages to a newer release, one must first pkgrm the installed packages. When one pkgrm's FRRsmf all property configuration will be lost, and any customisations will have to redone after installing the updated FRRsmf package. - These packages are not supported by Sun Microsystems, report bugs via the - usual FreeRangeRouting channels, ie Issue Tracker. Improvements/contributions of course would be greatly appreciated. + usual FRRouting channels, ie Issue Tracker. Improvements/contributions of course would be greatly appreciated. diff --git a/solaris/depend.daemons.in b/solaris/depend.daemons.in index 64fb03ac19..a8ce943e31 100644 --- a/solaris/depend.daemons.in +++ b/solaris/depend.daemons.in @@ -1,4 +1,4 @@ -P FRRlibs FreeRangeRouting common runtime libraries +P FRRlibs FRRouting common runtime libraries @PACKAGE_VERSION@,REV=@CONFDATE@ P SUNWcsu Core Solaris, (Usr) P SUNWcsr Core Solaris Libraries (Root) diff --git a/solaris/depend.dev.in b/solaris/depend.dev.in index 5d8bf16ed6..1b65724a04 100644 --- a/solaris/depend.dev.in +++ b/solaris/depend.dev.in @@ -1,2 +1,2 @@ -P FRRlibs FreeRangeRouting common runtime libraries +P FRRlibs FRRouting common runtime libraries @PACKAGE_VERSION@,REV=@CONFDATE@ diff --git a/solaris/depend.libs.in b/solaris/depend.libs.in index 6ead0b2867..04f04efd01 100644 --- a/solaris/depend.libs.in +++ b/solaris/depend.libs.in @@ -1,5 +1,5 @@ P SUNWcslr Core Solaris Libraries (Root) P SUNWcsl Core Solaris, (Shared Libs) P SUNWlibmsr Math & Microtasking Libraries (Root) -R FRRdaemons FreeRangeRouting daemons +R FRRdaemons FRRouting daemons R FRRdev diff --git a/solaris/depend.smf.in b/solaris/depend.smf.in index 66b11eba2a..b3b1bd778c 100644 --- a/solaris/depend.smf.in +++ b/solaris/depend.smf.in @@ -1,4 +1,4 @@ -P FRRaemons FreeRangeRouting daemons +P FRRaemons FRRouting daemons @PACKAGE_VERSION@,REV=@CONFDATE@ P SUNWcsu Core Solaris, (Usr) P SUNWcsr Core Solaris Libraries (Root) diff --git a/solaris/frr.init.in b/solaris/frr.init.in index 580fd9b35c..bd9ab85e69 100755 --- a/solaris/frr.init.in +++ b/solaris/frr.init.in @@ -3,20 +3,20 @@ # Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # -# This file is part of FreeRangeRouting. +# This file is part of FRRouting. # -# FreeRangeRouting is free software; you can redistribute it and/or modify +# FRRouting 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. # -# FreeRangeRouting is distributed in the hope that it will be useful, but +# FRRouting 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 FreeRangeRouting; see the file COPYING. If not, write to +# along with FRRouting; see the file COPYING. If not, write to # the Free Software Foundation, Inc., 59 Temple Place - Suite 330, # Boston, MA 02111-1307, USA. # @@ -74,7 +74,7 @@ handle_routeadm_upgrade () { upgrade_config () { DAEMON=$1 - # handle upgrade of SUNWzebra to FreeRangeRouting + # handle upgrade of SUNWzebra to FRRouting if [ -d "/etc/frr" -a ! -f "/etc/frr/${DAEMON}.conf" ] ; then if [ -f "/etc/sfw/zebra/${DAEMON}.conf" ] ; then cp "/etc/sfw/zebra/${DAEMON}.conf" \ @@ -216,7 +216,7 @@ case "${DAEMON}" in ;; esac -# Older FreeRangeRouting SMF packages pass daemon args on the commandline +# Older FRRouting SMF packages pass daemon args on the commandline # Newer SMF routeadm model uses properties for each argument # so we must handle that. if [ smf_present -a -f "$ROUTEADMINCLUDE" ]; then diff --git a/solaris/frr.xml.in b/solaris/frr.xml.in index 5ac7e52721..825c987a41 100644 --- a/solaris/frr.xml.in +++ b/solaris/frr.xml.in @@ -1,20 +1,20 @@ + option name, consult FRRouting documentation --> + frrouting Signed-off-by: Lou Berger --- ChangeLog | 2 +- REPORTING-BUGS | 2 +- configure.ac | 4 ++-- debian/README.Debian | 2 +- debian/copyright | 4 ++-- doc/Building_FRR_on_CentOS6.md | 2 +- doc/Building_FRR_on_CentOS7.md | 2 +- doc/Building_FRR_on_Debian8.md | 2 +- doc/Building_FRR_on_Fedora24.md | 2 +- doc/Building_FRR_on_FreeBSD10.md | 2 +- doc/Building_FRR_on_FreeBSD11.md | 2 +- doc/Building_FRR_on_FreeBSD9.md | 2 +- doc/Building_FRR_on_NetBSD6.md | 2 +- doc/Building_FRR_on_NetBSD7.md | 2 +- doc/Building_FRR_on_OmniOS.md | 2 +- doc/Building_FRR_on_OpenBSD6.md | 2 +- doc/Building_FRR_on_Ubuntu1204.md | 2 +- doc/Building_FRR_on_Ubuntu1404.md | 2 +- doc/Building_FRR_on_Ubuntu1604.md | 2 +- doc/frr.texi | 12 ++++++------ doc/overview.texi | 12 ++++++------ redhat/README.rpm_build.md | 2 +- redhat/frr.spec.in | 4 ++-- snapcraft/README.snap_build.md | 2 +- snapcraft/README.usage.md | 2 +- solaris/frr.xml.in | 24 ++++++++++++------------ solaris/pkginfo.tmpl.in | 4 ++-- 27 files changed, 52 insertions(+), 52 deletions(-) diff --git a/ChangeLog b/ChangeLog index 6793fc25d7..ec7e6cdde8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,4 @@ ChangeLog information for FRRouting is for now recorded in source-code management system. Please see: - http://www.freerangerouting.org/ + http://www.frrouting.org/ diff --git a/REPORTING-BUGS b/REPORTING-BUGS index a37f5c2829..01f25a2051 100644 --- a/REPORTING-BUGS +++ b/REPORTING-BUGS @@ -10,7 +10,7 @@ non-response to requests to reconfirm or supply additional information. Report bugs on Github Issue Tracker at - https://github.com/freerangerouting/frr/issues + https://github.com/frrouting/frr/issues Please supply the following information: 1. Your FRRouting version or if it is from git then the commit reference. diff --git a/configure.ac b/configure.ac index cbddaa63fa..02f1ae239c 100755 --- a/configure.ac +++ b/configure.ac @@ -7,8 +7,8 @@ ## AC_PREREQ(2.60) -AC_INIT(frr, 2.0-rc2, [https://github.com/freerangerouting/frr/issues]) -PACKAGE_URL="https://freerangerouting.org/" +AC_INIT(frr, 2.0-rc2, [https://github.com/frrouting/frr/issues]) +PACKAGE_URL="https://frrouting.org/" PACKAGE_FULLNAME="FRRouting" AC_SUBST(PACKAGE_FULLNAME) diff --git a/debian/README.Debian b/debian/README.Debian index caded52075..4cf35d7e32 100644 --- a/debian/README.Debian +++ b/debian/README.Debian @@ -14,7 +14,7 @@ available forcing you to explicitly type "apt-get install frr" to upgrade it. * What is frr? ================= -http://www.freerangerouting.org/ +http://www.frrouting.org/ FRR is a routing software suite, providing implementations of OSPFv2, OSPFv3, RIP v1 and v2, RIPng, ISIS, PIM, BGP and LDP for Unix platforms, particularly FreeBSD and Linux and also NetBSD, to mention a few. FRR is a fork of Quagga diff --git a/debian/copyright b/debian/copyright index 6a5ed98f91..7b873abd31 100644 --- a/debian/copyright +++ b/debian/copyright @@ -1,7 +1,7 @@ Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ Upstream-Name: Frr -Upstream-Contact: maintainers@freerangerouting.org, security@freerangerouting.org -Source: http://www.freerangerouting.org/ +Upstream-Contact: maintainers@frrouting.org, security@frrouting.org +Source: http://www.frrouting.org/ Files: * Copyright: 1996-2003 by the original Zebra authors: diff --git a/doc/Building_FRR_on_CentOS6.md b/doc/Building_FRR_on_CentOS6.md index 1ff4748230..c0c8efafdd 100644 --- a/doc/Building_FRR_on_CentOS6.md +++ b/doc/Building_FRR_on_CentOS6.md @@ -78,7 +78,7 @@ an example.) You may want to pay special attention to `/usr/lib64` paths and change them if you are not building on a x86_64 architecture - git clone https://github.com/freerangerouting/frr.git frr + git clone https://github.com/frrouting/frr.git frr cd frr git checkout stable/2.0 ./bootstrap.sh diff --git a/doc/Building_FRR_on_CentOS7.md b/doc/Building_FRR_on_CentOS7.md index 1a9bcb8817..570d14dee8 100644 --- a/doc/Building_FRR_on_CentOS7.md +++ b/doc/Building_FRR_on_CentOS7.md @@ -37,7 +37,7 @@ an example.) You may want to pay special attention to `/usr/lib64` paths and change them if you are not building on a x86_64 architecture - git clone https://github.com/freerangerouting/frr.git frr + git clone https://github.com/frrouting/frr.git frr cd frr git checkout stable/2.0 ./bootstrap.sh diff --git a/doc/Building_FRR_on_Debian8.md b/doc/Building_FRR_on_Debian8.md index 4335e76210..81d58827d3 100644 --- a/doc/Building_FRR_on_Debian8.md +++ b/doc/Building_FRR_on_Debian8.md @@ -39,7 +39,7 @@ any packages** (You may prefer different options on configure statement. These are just an example.) - git clone https://github.com/freerangerouting/frr.git frr + git clone https://github.com/frrouting/frr.git frr cd frr git checkout stable/2.0 ./bootstrap.sh diff --git a/doc/Building_FRR_on_Fedora24.md b/doc/Building_FRR_on_Fedora24.md index 0afc5c676a..6c5b78b1eb 100644 --- a/doc/Building_FRR_on_Fedora24.md +++ b/doc/Building_FRR_on_Fedora24.md @@ -30,7 +30,7 @@ an example.) You may want to pay special attention to `/usr/lib64` paths and change them if you are not building on a x86_64 architecture - git clone https://github.com/freerangerouting/frr.git frr + git clone https://github.com/frrouting/frr.git frr cd frr git checkout stable/2.0 ./bootstrap.sh diff --git a/doc/Building_FRR_on_FreeBSD10.md b/doc/Building_FRR_on_FreeBSD10.md index 696b7d5d2e..8b5c919b64 100644 --- a/doc/Building_FRR_on_FreeBSD10.md +++ b/doc/Building_FRR_on_FreeBSD10.md @@ -41,7 +41,7 @@ using any packages** (You may prefer different options on configure statement. These are just an example) - git clone https://github.com/freerangerouting/frr.git frr + git clone https://github.com/frrouting/frr.git frr cd frr git checkout stable/2.0 ./bootstrap.sh diff --git a/doc/Building_FRR_on_FreeBSD11.md b/doc/Building_FRR_on_FreeBSD11.md index d0b8a7bf88..4c8704c6aa 100644 --- a/doc/Building_FRR_on_FreeBSD11.md +++ b/doc/Building_FRR_on_FreeBSD11.md @@ -41,7 +41,7 @@ using any packages** (You may prefer different options on configure statement. These are just an example) - git clone https://github.com/freerangerouting/frr.git frr + git clone https://github.com/frrouting/frr.git frr cd frr git checkout stable/2.0 ./bootstrap.sh diff --git a/doc/Building_FRR_on_FreeBSD9.md b/doc/Building_FRR_on_FreeBSD9.md index d470d0046a..0a866acf90 100644 --- a/doc/Building_FRR_on_FreeBSD9.md +++ b/doc/Building_FRR_on_FreeBSD9.md @@ -41,7 +41,7 @@ using any packages** (You may prefer different options on configure statement. These are just an example) - git clone https://github.com/freerangerouting/frr.git frr + git clone https://github.com/frrouting/frr.git frr cd frr git checkout stable/2.0 ./bootstrap.sh diff --git a/doc/Building_FRR_on_NetBSD6.md b/doc/Building_FRR_on_NetBSD6.md index 03d04ce954..dfc1f2c292 100644 --- a/doc/Building_FRR_on_NetBSD6.md +++ b/doc/Building_FRR_on_NetBSD6.md @@ -45,7 +45,7 @@ Get FRR, compile it and install it (from Git) (You may prefer different options on configure statement. These are just an example) - git clone https://github.com/freerangerouting/frr.git frr + git clone https://github.com/frrouting/frr.git frr cd frr git checkout stable/2.0 ./bootstrap.sh diff --git a/doc/Building_FRR_on_NetBSD7.md b/doc/Building_FRR_on_NetBSD7.md index d9b4b47ea6..99230e385e 100644 --- a/doc/Building_FRR_on_NetBSD7.md +++ b/doc/Building_FRR_on_NetBSD7.md @@ -39,7 +39,7 @@ Get FRR, compile it and install it (from Git) (You may prefer different options on configure statement. These are just an example) - git clone https://github.com/freerangerouting/frr.git frr + git clone https://github.com/frrouting/frr.git frr cd frr git checkout stable/2.0 ./bootstrap.sh diff --git a/doc/Building_FRR_on_OmniOS.md b/doc/Building_FRR_on_OmniOS.md index f158c80a75..7ed22aaae3 100644 --- a/doc/Building_FRR_on_OmniOS.md +++ b/doc/Building_FRR_on_OmniOS.md @@ -87,7 +87,7 @@ any packages** (You may prefer different options on configure statement. These are just an example) - git clone https://github.com/freerangerouting/frr.git frr + git clone https://github.com/frrouting/frr.git frr cd frr git checkout stable/2.0 ./bootstrap.sh diff --git a/doc/Building_FRR_on_OpenBSD6.md b/doc/Building_FRR_on_OpenBSD6.md index 9e13d5ce45..40bf982a47 100644 --- a/doc/Building_FRR_on_OpenBSD6.md +++ b/doc/Building_FRR_on_OpenBSD6.md @@ -40,7 +40,7 @@ any packages** (You may prefer different options on configure statement. These are just an example) - git clone https://github.com/freerangerouting/frr.git frr + git clone https://github.com/frrouting/frr.git frr cd frr git checkout stable/2.0 ./bootstrap.sh diff --git a/doc/Building_FRR_on_Ubuntu1204.md b/doc/Building_FRR_on_Ubuntu1204.md index 3312a2c9c8..6e6374c2f8 100644 --- a/doc/Building_FRR_on_Ubuntu1204.md +++ b/doc/Building_FRR_on_Ubuntu1204.md @@ -72,7 +72,7 @@ any packages** (You may prefer different options on configure statement. These are just an example.) - git clone https://github.com/freerangerouting/frr.git frr + git clone https://github.com/frrouting/frr.git frr cd frr git checkout stable/2.0 ./bootstrap.sh diff --git a/doc/Building_FRR_on_Ubuntu1404.md b/doc/Building_FRR_on_Ubuntu1404.md index ac0a45acdf..6db3f426b4 100644 --- a/doc/Building_FRR_on_Ubuntu1404.md +++ b/doc/Building_FRR_on_Ubuntu1404.md @@ -32,7 +32,7 @@ any packages** (You may prefer different options on configure statement. These are just an example.) - git clone https://github.com/freerangerouting/frr.git frr + git clone https://github.com/frrouting/frr.git frr cd frr git checkout stable/2.0 ./bootstrap.sh diff --git a/doc/Building_FRR_on_Ubuntu1604.md b/doc/Building_FRR_on_Ubuntu1604.md index d1e1a377d0..8e71cc1eee 100644 --- a/doc/Building_FRR_on_Ubuntu1604.md +++ b/doc/Building_FRR_on_Ubuntu1604.md @@ -33,7 +33,7 @@ any packages** (You may prefer different options on configure statement. These are just an example.) - git clone https://github.com/freerangerouting/frr.git frr + git clone https://github.com/frrouting/frr.git frr cd frr git checkout stable/2.0 ./bootstrap.sh diff --git a/doc/frr.texi b/doc/frr.texi index d4a78b7b81..0478ec592a 100644 --- a/doc/frr.texi +++ b/doc/frr.texi @@ -7,7 +7,7 @@ @setfilename frr.info @c Set variables - sourced from defines.texi @include defines.texi -@settitle @uref{http://www.freerangerouting.org,,@value{PACKAGE_NAME}} +@settitle @uref{http://www.frrouting.org,,@value{PACKAGE_NAME}} @c %**end of header @c automake will automatically generate version.texi @@ -48,16 +48,16 @@ This file documents the Frr Software Routing Suite which manages common TCP/IP routing protocols. This is Edition @value{EDITION}, last updated @value{UPDATED} of -@cite{The Frr Manual}, for @uref{http://www.freerangerouting.org/,,@value{PACKAGE_NAME}} +@cite{The Frr Manual}, for @uref{http://www.frrouting.org/,,@value{PACKAGE_NAME}} Version @value{VERSION}. @insertcopying @end ifinfo @titlepage -@title @uref{http://www.freerangerouting.org,,Frr} +@title @uref{http://www.frrouting.org,,Frr} @subtitle A routing software package for TCP/IP networks -@subtitle @uref{http://www.freerangerouting.org,,@value{PACKAGE_NAME}} @value{VERSION} +@subtitle @uref{http://www.frrouting.org,,@value{PACKAGE_NAME}} @value{VERSION} @subtitle @value{UPDATED-MONTH} @author @value{AUTHORS} @@ -72,9 +72,9 @@ Version @value{VERSION}. @node Top @top Frr -- With Virtual Network Control -@uref{http://www.freerangerouting.org,,Frr} is an advanced routing software package +@uref{http://www.frrouting.org,,Frr} is an advanced routing software package that provides a suite of TCP/IP based routing protocols. This is the Manual -for @value{PACKAGE_STRING}. @uref{http://www.freerangerouting.org,,Frr} is a fork of +for @value{PACKAGE_STRING}. @uref{http://www.frrouting.org,,Frr} is a fork of @uref{http://www.quagga.net,,Quagga}. @insertcopying diff --git a/doc/overview.texi b/doc/overview.texi index 370ada3f8a..7ecf3d95c3 100644 --- a/doc/overview.texi +++ b/doc/overview.texi @@ -2,7 +2,7 @@ @chapter Overview @cindex Overview - @uref{http://www.freerangerouting.org,,Frr} is a routing software package that + @uref{http://www.frrouting.org,,Frr} is a routing software package that provides TCP/IP based routing services with routing protocols support such as RIPv1, RIPv2, RIPng, OSPFv2, OSPFv3, IS-IS, BGP-4, and BGP-4+ (@pxref{Supported RFCs}). Frr also supports special BGP Route Reflector and Route Server @@ -275,12 +275,12 @@ November 1995.} The official Frr web-site is located at: -@uref{http://www.freerangerouting.org/} +@uref{http://www.frrouting.org/} and contains further information, as well as links to additional resources. -@uref{http://www.freerangerouting.org/,Frr} is a fork of Quagga, whose +@uref{http://www.frrouting.org/,Frr} is a fork of Quagga, whose web-site is located at: @uref{http://www.quagga.net/}. @@ -298,7 +298,7 @@ comments or suggestions to Frr, please subscribe to: @uref{http://lists.nox.tf/listinfo/frr-users}. -The @uref{http://www.freerangerouting.org/,,Frr} site has further information on +The @uref{http://www.frrouting.org/,,Frr} site has further information on the available mailing lists, see: @uref{http://lists.nox.tf/lists.php} @@ -315,7 +315,7 @@ the available mailing lists, see: If you think you have found a bug, please send a bug report to: -@uref{http://github.com/freerangerouting/frr/issues} +@uref{http://github.com/frrouting/frr/issues} When you send a bug report, please be careful about the points below. @@ -334,4 +334,4 @@ arguments to the configure script please note that too. Bug reports are very important for us to improve the quality of Frr. Frr is still in the development stage, but please don't hesitate to -send a bug report to @uref{http://github.com/freerangerouting/frr/issues}. +send a bug report to @uref{http://github.com/frrouting/frr/issues}. diff --git a/redhat/README.rpm_build.md b/redhat/README.rpm_build.md index c266f3dc2e..6bec5d65cd 100644 --- a/redhat/README.rpm_build.md +++ b/redhat/README.rpm_build.md @@ -12,7 +12,7 @@ Building your own FRRouting RPM 2. Checkout FRR under a **unpriviledged** user account - git clone https://github.com/freerangerouting/frr.git frr + git clone https://github.com/frrouting/frr.git frr 3. Run Bootstrap and make distribution tar.gz diff --git a/redhat/frr.spec.in b/redhat/frr.spec.in index e0d8f697db..6d94b5a5cc 100644 --- a/redhat/frr.spec.in +++ b/redhat/frr.spec.in @@ -100,8 +100,8 @@ Version: %{rpmversion} Release: @CONFDATE@%{release_rev}%{?dist} License: GPLv2+ Group: System Environment/Daemons -Source0: http://www.freerangerouting.org/releases/frr/%{name}-%{frrversion}.tar.gz -URL: http://www.freerangerouting.org +Source0: http://www.frrouting.org/releases/frr/%{name}-%{frrversion}.tar.gz +URL: http://www.frrouting.org Requires: ncurses json-c Requires(pre): /sbin/install-info Requires(preun): /sbin/install-info diff --git a/snapcraft/README.snap_build.md b/snapcraft/README.snap_build.md index b14b10b837..c4db51bd6a 100644 --- a/snapcraft/README.snap_build.md +++ b/snapcraft/README.snap_build.md @@ -9,7 +9,7 @@ which uses earlier versions of snaps) 2. Checkout FRRouting under a **unpriviledged** user account - git clone https://github.com/freerangerouting/frr.git + git clone https://github.com/frrouting/frr.git cd frr 3. Run Bootstrap and make distribution tar.gz diff --git a/snapcraft/README.usage.md b/snapcraft/README.usage.md index a8d6bca76c..aaff59438a 100644 --- a/snapcraft/README.usage.md +++ b/snapcraft/README.usage.md @@ -65,7 +65,7 @@ Sourcecode available The source for this SNAP is available as part of the FRRouting Source Code Distribution. - https://github.com/freerangerouting/frr.git + https://github.com/frrouting/frr.git Instructions for rebuilding the snap are in `README.snap_build.md` diff --git a/solaris/frr.xml.in b/solaris/frr.xml.in index 825c987a41..08a9a11c0f 100644 --- a/solaris/frr.xml.in +++ b/solaris/frr.xml.in @@ -148,8 +148,8 @@ - + @@ -279,8 +279,8 @@ - + @@ -408,8 +408,8 @@ - + @@ -539,8 +539,8 @@ - + @@ -665,8 +665,8 @@ - + @@ -818,8 +818,8 @@ - + diff --git a/solaris/pkginfo.tmpl.in b/solaris/pkginfo.tmpl.in index 02abb0f96b..89a281ceb6 100644 --- a/solaris/pkginfo.tmpl.in +++ b/solaris/pkginfo.tmpl.in @@ -1,9 +1,9 @@ ARCH="@target_cpu@" CATEGORY="system" VERSION="@PACKAGE_VERSION@,REV=@CONFDATE@" -VENDOR="http://www.freerangerouting.org/" +VENDOR="http://www.frrouting.org/" HOTLINE="@PACKAGE_BUGREPORT@" -EMAIL=maintainers@freerangerouting.org +EMAIL=maintainers@frrouting.org DESC="@PACKAGE_NAME@ Routing Protocols" MAXINST=1 CLASSES="none preserve renamenew manifest" From f790d62ad140b98ab05ef96aee349284c4d604fc Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Thu, 30 Mar 2017 12:33:46 -0300 Subject: [PATCH 22/61] ldpd: fix harmless maybe-uninitialized warning Signed-off-by: Renato Westphal --- ldpd/ldp_vty_exec.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ldpd/ldp_vty_exec.c b/ldpd/ldp_vty_exec.c index dfd5af9748..a149b7fe35 100644 --- a/ldpd/ldp_vty_exec.c +++ b/ldpd/ldp_vty_exec.c @@ -1049,7 +1049,7 @@ show_lib_msg(struct vty *vty, struct imsg *imsg, struct show_params *params) static int show_lib_detail_msg(struct vty *vty, struct imsg *imsg, struct show_params *params) { - struct ctl_rt *rt; + struct ctl_rt *rt = NULL; char dstnet[BUFSIZ]; static int upstream, downstream; size_t buflen; @@ -1172,7 +1172,7 @@ static int show_lib_detail_msg_json(struct imsg *imsg, struct show_params *params, json_object *json) { - struct ctl_rt *rt; + struct ctl_rt *rt = NULL; char dstnet[BUFSIZ]; static json_object *json_lib_entry; static json_object *json_adv_labels; From 726329191d8c153a91af70396513ebc71f50e4a1 Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Thu, 30 Mar 2017 20:19:16 -0300 Subject: [PATCH 23/61] ldpd: no need to synchronize pseudowires with LSPs anymore Since commit 595b4be, the l2vpn_pw_ok() function doesn't check if there's a working LSP to the remote end of the pseudowire (we assume that zebra will do that for us). With that said, the l2vpn_sync_pws() function is not necessary anymore. Signed-off-by: Renato Westphal --- ldpd/l2vpn.c | 31 ------------------------------- ldpd/lde.c | 16 ---------------- ldpd/lde.h | 1 - 3 files changed, 48 deletions(-) diff --git a/ldpd/l2vpn.c b/ldpd/l2vpn.c index ca40636e09..bdfcd420eb 100644 --- a/ldpd/l2vpn.c +++ b/ldpd/l2vpn.c @@ -463,37 +463,6 @@ l2vpn_recv_pw_status_wcard(struct lde_nbr *ln, struct notify_msg *nm) } } -void -l2vpn_sync_pws(int af, union ldpd_addr *addr) -{ - struct l2vpn *l2vpn; - struct l2vpn_pw *pw; - struct fec fec; - struct fec_node *fn; - struct fec_nh *fnh; - - RB_FOREACH(l2vpn, l2vpn_head, &ldeconf->l2vpn_tree) { - RB_FOREACH(pw, l2vpn_pw_head, &l2vpn->pw_tree) { - if (af != pw->af || ldp_addrcmp(af, &pw->addr, addr)) - continue; - - l2vpn_pw_fec(pw, &fec); - fn = (struct fec_node *)fec_find(&ft, &fec); - if (fn == NULL) - continue; - fnh = fec_nh_find(fn, AF_INET, (union ldpd_addr *) - &pw->lsr_id, 0, 0); - if (fnh == NULL) - continue; - - if (l2vpn_pw_ok(pw, fnh)) - lde_send_change_klabel(fn, fnh); - else - lde_send_delete_klabel(fn, fnh); - } - } -} - void l2vpn_pw_ctl(pid_t pid) { diff --git a/ldpd/lde.c b/ldpd/lde.c index 53fde32fd9..bc808e6841 100644 --- a/ldpd/lde.c +++ b/ldpd/lde.c @@ -725,10 +725,6 @@ lde_send_change_klabel(struct fec_node *fn, struct fec_nh *fnh) lde_imsg_compose_parent(IMSG_KLABEL_CHANGE, 0, &kr, sizeof(kr)); - - if (fn->fec.u.ipv4.prefixlen == 32) - l2vpn_sync_pws(AF_INET, (union ldpd_addr *) - &fn->fec.u.ipv4.prefix); break; case FEC_TYPE_IPV6: memset(&kr, 0, sizeof(kr)); @@ -743,10 +739,6 @@ lde_send_change_klabel(struct fec_node *fn, struct fec_nh *fnh) lde_imsg_compose_parent(IMSG_KLABEL_CHANGE, 0, &kr, sizeof(kr)); - - if (fn->fec.u.ipv6.prefixlen == 128) - l2vpn_sync_pws(AF_INET6, (union ldpd_addr *) - &fn->fec.u.ipv6.prefix); break; case FEC_TYPE_PWID: if (fn->local_label == NO_LABEL || @@ -792,10 +784,6 @@ lde_send_delete_klabel(struct fec_node *fn, struct fec_nh *fnh) lde_imsg_compose_parent(IMSG_KLABEL_DELETE, 0, &kr, sizeof(kr)); - - if (fn->fec.u.ipv4.prefixlen == 32) - l2vpn_sync_pws(AF_INET, (union ldpd_addr *) - &fn->fec.u.ipv4.prefix); break; case FEC_TYPE_IPV6: memset(&kr, 0, sizeof(kr)); @@ -810,10 +798,6 @@ lde_send_delete_klabel(struct fec_node *fn, struct fec_nh *fnh) lde_imsg_compose_parent(IMSG_KLABEL_DELETE, 0, &kr, sizeof(kr)); - - if (fn->fec.u.ipv6.prefixlen == 128) - l2vpn_sync_pws(AF_INET6, (union ldpd_addr *) - &fn->fec.u.ipv6.prefix); break; case FEC_TYPE_PWID: pw = (struct l2vpn_pw *) fn->data; diff --git a/ldpd/lde.h b/ldpd/lde.h index d1089b44f4..8ee62b02d3 100644 --- a/ldpd/lde.h +++ b/ldpd/lde.h @@ -231,7 +231,6 @@ void l2vpn_send_pw_status_wcard(struct lde_nbr *, uint32_t, void l2vpn_recv_pw_status(struct lde_nbr *, struct notify_msg *); void l2vpn_recv_pw_status_wcard(struct lde_nbr *, struct notify_msg *); -void l2vpn_sync_pws(int, union ldpd_addr *); void l2vpn_pw_ctl(pid_t); void l2vpn_binding_ctl(pid_t); From 3f11a103a6ee10cc9ccf2121fce914cb82ef9f80 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Mon, 11 Jan 2016 16:02:49 +0100 Subject: [PATCH 24/61] lib: make sure SEGV handler cannot lock up Just adding -pthread to gcc options changes libc's behaviour, e.g. making malloc() use proper locking. This means a SEGV inside malloc() (e.g. because malloc bookkeeping structures have been damaged by writing to a broken pointer) can lead to a lockup by the following chain: - random_function() - malloc() --- SEGV - core_handler() - zlog_backtrace_sigsafe() - backtrace() - malloc() This will hang forever waiting for the malloc() lock to be released. Another failure mode is dynamic linking with lazy binding (-z lazy, default). Since backtrace() is seldomly used, this means the call to backtrace() in the core handler can in fact result in the dynamic linker trying to resolve the "backtrace" symbol, which can also deadlock. Add several safeguards to prevent any of this from happening. (Unfortunately, these are not theoretical issues - I found them by running into them headfirst.) Signed-off-by: David Lamparter --- lib/log.c | 11 +++++++++++ lib/sigevent.c | 17 +++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/lib/log.c b/lib/log.c index 69225dbf7a..66320230ce 100644 --- a/lib/log.c +++ b/lib/log.c @@ -734,6 +734,17 @@ openzlog (const char *progname, const char *protoname, u_short instance, openlog (progname, syslog_flags, zl->facility); zlog_default = zl; + +#ifdef HAVE_GLIBC_BACKTRACE + /* work around backtrace() using lazily resolved dynamically linked + * symbols, which will otherwise cause funny breakage in the SEGV handler. + * (particularly, the dynamic linker can call malloc(), which uses locks + * in programs linked with -pthread, thus can deadlock.) */ + void *bt[4]; + backtrace (bt, array_size(bt)); + free (backtrace_symbols (bt, 0)); + backtrace_symbols_fd (bt, 0, 0); +#endif } void diff --git a/lib/sigevent.c b/lib/sigevent.c index 09f07180ce..b2059a17bf 100644 --- a/lib/sigevent.c +++ b/lib/sigevent.c @@ -233,6 +233,18 @@ core_handler(int signo #endif ) { + /* make sure we don't hang in here. default for SIGALRM is terminate. + * - if we're in backtrace for more than a second, abort. */ + struct sigaction sa_default = { .sa_handler = SIG_DFL }; + sigaction (SIGALRM, &sa_default, NULL); + + sigset_t sigset; + sigemptyset (&sigset); + sigaddset (&sigset, SIGALRM); + sigprocmask (SIG_UNBLOCK, &sigset, NULL); + + alarm (1); + zlog_signal(signo, "aborting..." #ifdef SA_SIGINFO , siginfo, program_counter(context) @@ -326,6 +338,11 @@ trap_default_signals(void) #else act.sa_handler = sigmap[i].handler; act.sa_flags = 0; +#endif +#ifdef SA_RESETHAND + /* don't try to print backtraces recursively */ + if (sigmap[i].handler == core_handler) + act.sa_flags |= SA_RESETHAND; #endif } if (sigaction(sigmap[i].sigs[j],&act,NULL) < 0) From fbd0bae6d6dfa0af786c906b419e01bb389ead3e Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Fri, 29 May 2015 02:22:48 +0200 Subject: [PATCH 25/61] build: disable autoconf "-g -O2" default CFLAGS We have AC_C_FLAG and try -Os before -O2. Signed-off-by: David Lamparter --- configure.ac | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/configure.ac b/configure.ac index e46e44a8b7..a8e820a237 100755 --- a/configure.ac +++ b/configure.ac @@ -66,6 +66,10 @@ LIBS="$LIBS -ltcmalloc_minimal" esac],[tcmalloc_enabled=false]) +dnl Thanks autoconf, but we don't want a default -g -O2. We have our own +dnl flag determination logic. +CFLAGS="${CFLAGS:-}" + dnl -------------------- dnl Check CC and friends dnl -------------------- From 8aa42b826c2037ddc68a32712caf2dfbda9981f8 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Sun, 29 Jan 2017 00:51:45 +0100 Subject: [PATCH 26/61] build: bump to C11 Funnily enough, "gnu11" is gcc's default in 5.x if you don't specify anything, yet there is no "AC_PROG_CC_C11" in autoconf. Signed-off-by: David Lamparter --- configure.ac | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/configure.ac b/configure.ac index a8e820a237..b8cebd8d23 100755 --- a/configure.ac +++ b/configure.ac @@ -82,6 +82,7 @@ AM_PROG_CC_C_O dnl remove autoconf default "-g -O2" CFLAGS="$orig_cflags" AC_PROG_CC_C99 +dnl NB: see C11 below AC_PROG_EGREP PKG_PROG_PKG_CONFIG @@ -119,6 +120,13 @@ dnl ICC won't bail on unknown options without -diag-error 10006 dnl need to do this first so we get useful results for the other options AC_C_FLAG([-diag-error 10006]) +dnl AC_PROG_CC_C99 may change CC to include -std=gnu99 or something +ac_cc="$CC" +CC="${CC% -std=gnu99}" +CC="${CC% -std=c99}" + +AC_C_FLAG([-std=gnu11], [CC="$ac_cc"], [CC="$CC -std=gnu11"]) + dnl if the user specified any CFLAGS, we don't add "-g -Os/-O2" here if test "z$orig_cflags" = "z"; then AC_C_FLAG([-g]) From 308252d06dfb76edf1477b96416c2e2aa9f90579 Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Thu, 30 Mar 2017 20:26:17 -0300 Subject: [PATCH 27/61] ldpd: remove the interface vty node ldpd uses a hierarchical configuration model where all commands are defined inside the "mpls ldp" node and its subnodes. The idea is to keep all LDP configuration in a single place to keep things simple. With that said, we can remove the "config-if" node from ldpd because we already have a separate node ("config-ldp-af-if") for LDP-related interface specific commands. Example: vtysh(config)# mpls ldp vtysh(config-ldp)# address-family ipv4 vtysh(config-ldp-af)# interface eth1 vtysh(config-ldp-af-if)# discovery hello ? holdtime Hello holdtime interval Hello interval Signed-off-by: Renato Westphal --- ldpd/ldp_vty.h | 1 - ldpd/ldp_vty_conf.c | 36 ------------------------------------ ldpd/ldpd.c | 1 - vtysh/vtysh.c | 4 ++-- vtysh/vtysh.h | 2 +- 5 files changed, 3 insertions(+), 41 deletions(-) diff --git a/ldpd/ldp_vty.h b/ldpd/ldp_vty.h index 0b05e6fbf1..8510a394ec 100644 --- a/ldpd/ldp_vty.h +++ b/ldpd/ldp_vty.h @@ -80,6 +80,5 @@ int ldp_vty_debug(struct vty *, struct vty_arg *[]); int ldp_vty_show_debugging(struct vty *, struct vty_arg *[]); void ldp_vty_init(void); -void ldp_vty_if_init(void); #endif /* _LDP_VTY_H_ */ diff --git a/ldpd/ldp_vty_conf.c b/ldpd/ldp_vty_conf.c index bab5e17368..dcf5f52436 100644 --- a/ldpd/ldp_vty_conf.c +++ b/ldpd/ldp_vty_conf.c @@ -32,7 +32,6 @@ #include "vty.h" #include "ldp_vty.h" -static int interface_config_write(struct vty *); static void ldp_af_iface_config_write(struct vty *, int); static void ldp_af_config_write(struct vty *, int, struct ldpd_conf *, struct ldpd_af_conf *); @@ -48,13 +47,6 @@ static struct iface *vty_iface; static struct l2vpn *vty_l2vpn; static struct l2vpn_pw *vty_pw; -static struct cmd_node interface_node = -{ - INTERFACE_NODE, - "%s(config-if)# ", - 1 -}; - struct cmd_node ldp_node = { LDP_NODE, @@ -122,26 +114,6 @@ ldp_get_address(const char *str, int *af, union ldpd_addr *addr) return (-1); } -static int -interface_config_write(struct vty *vty) -{ - struct listnode *node; - struct interface *ifp; - int write = 0; - - for (ALL_LIST_ELEMENTS_RO(vrf_iflist (VRF_DEFAULT), node, ifp)) { - vty_out(vty, "!%s", VTY_NEWLINE); - vty_out(vty, "interface %s%s", ifp->name, VTY_NEWLINE); - if (ifp->desc) - vty_out(vty, " description %s%s", ifp->desc, - VTY_NEWLINE); - - write++; - } - - return (write); -} - static void ldp_af_iface_config_write(struct vty *vty, int af) { @@ -1794,14 +1766,6 @@ ldp_vty_l2vpn_pw_pwstatus(struct vty *vty, struct vty_arg *args[]) return (CMD_SUCCESS); } -void -ldp_vty_if_init(void) -{ - /* Install interface node. */ - install_node (&interface_node, interface_config_write); - if_cmd_init (); -} - struct iface * iface_new_api(struct ldpd_conf *conf, const char *name) { diff --git a/ldpd/ldpd.c b/ldpd/ldpd.c index 3023d94469..3b3a07c28c 100644 --- a/ldpd/ldpd.c +++ b/ldpd/ldpd.c @@ -338,7 +338,6 @@ main(int argc, char *argv[]) vrf_init(); access_list_init(); ldp_vty_init(); - ldp_vty_if_init(); ldp_zebra_init(master); /* create base configuration with sane defaults */ diff --git a/vtysh/vtysh.c b/vtysh/vtysh.c index 114022d199..7d5fa8442b 100644 --- a/vtysh/vtysh.c +++ b/vtysh/vtysh.c @@ -1799,7 +1799,7 @@ DEFUNSH (VTYSH_INTERFACE, } /* TODO Implement "no interface command in isisd. */ -DEFSH (VTYSH_ZEBRA|VTYSH_RIPD|VTYSH_RIPNGD|VTYSH_OSPFD|VTYSH_OSPF6D|VTYSH_LDPD, +DEFSH (VTYSH_ZEBRA|VTYSH_RIPD|VTYSH_RIPNGD|VTYSH_OSPFD|VTYSH_OSPF6D, vtysh_no_interface_cmd, "no interface IFNAME", NO_STR @@ -1883,7 +1883,7 @@ DEFUNSH (VTYSH_VRF, /* TODO Implement interface description commands in ripngd, ospf6d * and isisd. */ -DEFSH (VTYSH_ZEBRA|VTYSH_RIPD|VTYSH_OSPFD|VTYSH_LDPD, +DEFSH (VTYSH_ZEBRA|VTYSH_RIPD|VTYSH_OSPFD, vtysh_interface_desc_cmd, "description LINE...", "Interface specific description\n" diff --git a/vtysh/vtysh.h b/vtysh/vtysh.h index 07ba8367de..6d9e21d8a0 100644 --- a/vtysh/vtysh.h +++ b/vtysh/vtysh.h @@ -44,7 +44,7 @@ DECLARE_MGROUP(MVTYSH) * things like prefix lists are not even initialised) */ #define VTYSH_ALL VTYSH_ZEBRA|VTYSH_RIPD|VTYSH_RIPNGD|VTYSH_OSPFD|VTYSH_OSPF6D|VTYSH_LDPD|VTYSH_BGPD|VTYSH_ISISD|VTYSH_PIMD|VTYSH_NHRPD #define VTYSH_RMAP VTYSH_ZEBRA|VTYSH_RIPD|VTYSH_RIPNGD|VTYSH_OSPFD|VTYSH_OSPF6D|VTYSH_BGPD|VTYSH_PIMD -#define VTYSH_INTERFACE VTYSH_ZEBRA|VTYSH_RIPD|VTYSH_RIPNGD|VTYSH_OSPFD|VTYSH_OSPF6D|VTYSH_LDPD|VTYSH_ISISD|VTYSH_PIMD|VTYSH_NHRPD +#define VTYSH_INTERFACE VTYSH_ZEBRA|VTYSH_RIPD|VTYSH_RIPNGD|VTYSH_OSPFD|VTYSH_OSPF6D|VTYSH_ISISD|VTYSH_PIMD|VTYSH_NHRPD #define VTYSH_NS VTYSH_ZEBRA #define VTYSH_VRF VTYSH_ZEBRA From 52b530fc64355933d428e2b88591cbf926b85bc8 Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Thu, 30 Mar 2017 21:58:47 -0300 Subject: [PATCH 28/61] ldpd: fix configuration of non-existing VPLS interfaces and pseudowires If we don't know the ifindex, flags, etc of an interface at the time it's configured, we should make sure that once this information is available the appropriate structures are updated. Signed-off-by: Renato Westphal --- ldpd/interface.c | 7 ++--- ldpd/l2vpn.c | 25 ++++++++++----- ldpd/lde.c | 34 +++++++++++++++++--- ldpd/lde.h | 6 ++-- ldpd/ldp_vty_conf.c | 75 ++++----------------------------------------- ldpd/ldp_zebra.c | 6 ++-- ldpd/ldpd.c | 11 +++++-- ldpd/ldpe.c | 13 +++++--- ldpd/ldpe.h | 2 +- 9 files changed, 80 insertions(+), 99 deletions(-) diff --git a/ldpd/interface.c b/ldpd/interface.c index 17b3237b37..11bce12b09 100644 --- a/ldpd/interface.c +++ b/ldpd/interface.c @@ -49,17 +49,14 @@ iface_compare(struct iface *a, struct iface *b) } struct iface * -if_new(struct kif *kif) +if_new(const char *name) { struct iface *iface; if ((iface = calloc(1, sizeof(*iface))) == NULL) fatal("if_new: calloc"); - strlcpy(iface->name, kif->ifname, sizeof(iface->name)); - LIST_INIT(&iface->addr_list); - if (kif->ifindex) - if_update_info(iface, kif); + strlcpy(iface->name, name, sizeof(iface->name)); /* ipv4 */ iface->ipv4.af = AF_INET; diff --git a/ldpd/l2vpn.c b/ldpd/l2vpn.c index bdfcd420eb..92d865210a 100644 --- a/ldpd/l2vpn.c +++ b/ldpd/l2vpn.c @@ -117,7 +117,7 @@ l2vpn_if_compare(struct l2vpn_if *a, struct l2vpn_if *b) } struct l2vpn_if * -l2vpn_if_new(struct l2vpn *l2vpn, struct kif *kif) +l2vpn_if_new(struct l2vpn *l2vpn, const char *ifname) { struct l2vpn_if *lif; @@ -125,9 +125,7 @@ l2vpn_if_new(struct l2vpn *l2vpn, struct kif *kif) fatal("l2vpn_if_new: calloc"); lif->l2vpn = l2vpn; - strlcpy(lif->ifname, kif->ifname, sizeof(lif->ifname)); - lif->ifindex = kif->ifindex; - lif->flags = kif->flags; + strlcpy(lif->ifname, ifname, sizeof(lif->ifname)); return (lif); } @@ -140,6 +138,14 @@ l2vpn_if_find(struct l2vpn *l2vpn, const char *ifname) return (RB_FIND(l2vpn_if_head, &l2vpn->if_tree, &lif)); } +void +l2vpn_if_update_info(struct l2vpn_if *lif, struct kif *kif) +{ + lif->ifindex = kif->ifindex; + lif->flags = kif->flags; + memcpy(lif->mac, kif->mac, sizeof(lif->mac)); +} + void l2vpn_if_update(struct l2vpn_if *lif) { @@ -174,7 +180,7 @@ l2vpn_pw_compare(struct l2vpn_pw *a, struct l2vpn_pw *b) } struct l2vpn_pw * -l2vpn_pw_new(struct l2vpn *l2vpn, struct kif *kif) +l2vpn_pw_new(struct l2vpn *l2vpn, const char *ifname) { struct l2vpn_pw *pw; @@ -182,8 +188,7 @@ l2vpn_pw_new(struct l2vpn *l2vpn, struct kif *kif) fatal("l2vpn_pw_new: calloc"); pw->l2vpn = l2vpn; - strlcpy(pw->ifname, kif->ifname, sizeof(pw->ifname)); - pw->ifindex = kif->ifindex; + strlcpy(pw->ifname, ifname, sizeof(pw->ifname)); return (pw); } @@ -219,6 +224,12 @@ l2vpn_pw_find_inactive(struct l2vpn *l2vpn, const char *ifname) return (RB_FIND(l2vpn_pw_head, &l2vpn->pw_inactive_tree, &s)); } +void +l2vpn_pw_update_info(struct l2vpn_pw *pw, struct kif *kif) +{ + pw->ifindex = kif->ifindex; +} + void l2vpn_pw_init(struct l2vpn_pw *pw) { diff --git a/ldpd/lde.c b/ldpd/lde.c index bc808e6841..607a9f7b14 100644 --- a/ldpd/lde.c +++ b/ldpd/lde.c @@ -439,13 +439,14 @@ static int lde_dispatch_parent(struct thread *thread) { static struct ldpd_conf *nconf; - struct iface *niface; + struct iface *iface, *niface; struct tnbr *ntnbr; struct nbr_params *nnbrp; - static struct l2vpn *nl2vpn; - struct l2vpn_if *nlif; - struct l2vpn_pw *npw; + static struct l2vpn *l2vpn, *nl2vpn; + struct l2vpn_if *lif, *nlif; + struct l2vpn_pw *pw, *npw; struct imsg imsg; + struct kif *kif; struct kroute *kr; int fd = THREAD_FD(thread); struct imsgev *iev = THREAD_ARG(thread); @@ -468,6 +469,31 @@ lde_dispatch_parent(struct thread *thread) break; switch (imsg.hdr.type) { + case IMSG_IFSTATUS: + if (imsg.hdr.len != IMSG_HEADER_SIZE + + sizeof(struct kif)) + fatalx("IFSTATUS imsg with wrong len"); + kif = imsg.data; + + iface = if_lookup_name(ldeconf, kif->ifname); + if (iface) { + if_update_info(iface, kif); + break; + } + + RB_FOREACH(l2vpn, l2vpn_head, &ldeconf->l2vpn_tree) { + lif = l2vpn_if_find(l2vpn, kif->ifname); + if (lif) { + l2vpn_if_update_info(lif, kif); + break; + } + pw = l2vpn_pw_find(l2vpn, kif->ifname); + if (pw) { + l2vpn_pw_update_info(pw, kif); + break; + } + } + break; case IMSG_NETWORK_ADD: case IMSG_NETWORK_UPDATE: if (imsg.hdr.len != IMSG_HEADER_SIZE + diff --git a/ldpd/lde.h b/ldpd/lde.h index 8ee62b02d3..57791cd1b0 100644 --- a/ldpd/lde.h +++ b/ldpd/lde.h @@ -212,13 +212,15 @@ struct l2vpn *l2vpn_find(struct ldpd_conf *, const char *); void l2vpn_del(struct l2vpn *); void l2vpn_init(struct l2vpn *); void l2vpn_exit(struct l2vpn *); -struct l2vpn_if *l2vpn_if_new(struct l2vpn *, struct kif *); +struct l2vpn_if *l2vpn_if_new(struct l2vpn *, const char *); struct l2vpn_if *l2vpn_if_find(struct l2vpn *, const char *); +void l2vpn_if_update_info(struct l2vpn_if *, struct kif *); void l2vpn_if_update(struct l2vpn_if *); -struct l2vpn_pw *l2vpn_pw_new(struct l2vpn *, struct kif *); +struct l2vpn_pw *l2vpn_pw_new(struct l2vpn *, const char *); struct l2vpn_pw *l2vpn_pw_find(struct l2vpn *, const char *); struct l2vpn_pw *l2vpn_pw_find_active(struct l2vpn *, const char *); struct l2vpn_pw *l2vpn_pw_find_inactive(struct l2vpn *, const char *); +void l2vpn_pw_update_info(struct l2vpn_pw *, struct kif *); void l2vpn_pw_init(struct l2vpn_pw *); void l2vpn_pw_exit(struct l2vpn_pw *); void l2vpn_pw_reset(struct l2vpn_pw *); diff --git a/ldpd/ldp_vty_conf.c b/ldpd/ldp_vty_conf.c index dcf5f52436..4c6cfcd4a3 100644 --- a/ldpd/ldp_vty_conf.c +++ b/ldpd/ldp_vty_conf.c @@ -907,8 +907,6 @@ ldp_vty_interface(struct vty *vty, struct vty_arg *args[]) int af; struct iface *iface; struct iface_af *ia; - struct interface *ifp; - struct kif kif; const char *ifname; int disable; @@ -940,23 +938,12 @@ ldp_vty_interface(struct vty *vty, struct vty_arg *args[]) return (CMD_SUCCESS); } - ifp = if_lookup_by_name(ifname, VRF_DEFAULT); - memset(&kif, 0, sizeof(kif)); - strlcpy(kif.ifname, ifname, sizeof(kif.ifname)); - if (ifp) { - kif.ifindex = ifp->ifindex; - kif.flags = ifp->flags; - } - iface = if_new(&kif); - + iface = if_new(ifname); ia = iface_af_get(iface, af); ia->enabled = 1; RB_INSERT(iface_head, &vty_conf->iface_tree, iface); ldp_reload(vty_conf); } else { - memset(&kif, 0, sizeof(kif)); - strlcpy(kif.ifname, ifname, sizeof(kif.ifname)); - ia = iface_af_get(iface, af); if (!ia->enabled) { ia->enabled = 1; @@ -1505,8 +1492,6 @@ ldp_vty_l2vpn_interface(struct vty *vty, struct vty_arg *args[]) { struct l2vpn *l2vpn; struct l2vpn_if *lif; - struct interface *ifp; - struct kif kif; const char *ifname; int disable; @@ -1535,15 +1520,7 @@ ldp_vty_l2vpn_interface(struct vty *vty, struct vty_arg *args[]) return (CMD_SUCCESS); } - ifp = if_lookup_by_name(ifname, VRF_DEFAULT); - memset(&kif, 0, sizeof(kif)); - strlcpy(kif.ifname, ifname, sizeof(kif.ifname)); - if (ifp) { - kif.ifindex = ifp->ifindex; - kif.flags = ifp->flags; - } - - lif = l2vpn_if_new(l2vpn, &kif); + lif = l2vpn_if_new(l2vpn, ifname); RB_INSERT(l2vpn_if_head, &l2vpn->if_tree, lif); ldp_reload(vty_conf); @@ -1556,8 +1533,6 @@ ldp_vty_l2vpn_pseudowire(struct vty *vty, struct vty_arg *args[]) { struct l2vpn *l2vpn; struct l2vpn_pw *pw; - struct interface *ifp; - struct kif kif; const char *ifname; int disable; @@ -1588,15 +1563,7 @@ ldp_vty_l2vpn_pseudowire(struct vty *vty, struct vty_arg *args[]) return (CMD_SUCCESS); } - ifp = if_lookup_by_name(ifname, VRF_DEFAULT); - memset(&kif, 0, sizeof(kif)); - strlcpy(kif.ifname, ifname, sizeof(kif.ifname)); - if (ifp) { - kif.ifindex = ifp->ifindex; - kif.flags = ifp->flags; - } - - pw = l2vpn_pw_new(l2vpn, &kif); + pw = l2vpn_pw_new(l2vpn, ifname); pw->flags = F_PW_STATUSTLV_CONF|F_PW_CWORD_CONF; RB_INSERT(l2vpn_pw_head, &l2vpn->pw_inactive_tree, pw); @@ -1771,21 +1738,11 @@ iface_new_api(struct ldpd_conf *conf, const char *name) { const char *ifname = name; struct iface *iface; - struct interface *ifp; - struct kif kif; if (ldp_iface_is_configured(conf, ifname)) return NULL; - memset(&kif, 0, sizeof(kif)); - strlcpy(kif.ifname, ifname, sizeof(kif.ifname)); - ifp = if_lookup_by_name(ifname, VRF_DEFAULT); - if (ifp) { - kif.ifindex = ifp->ifindex; - kif.flags = ifp->flags; - } - - iface = if_new(&kif); + iface = if_new(name); RB_INSERT(iface_head, &conf->iface_tree, iface); return (iface); } @@ -1882,21 +1839,11 @@ l2vpn_if_new_api(struct ldpd_conf *conf, struct l2vpn *l2vpn, const char *ifname) { struct l2vpn_if *lif; - struct interface *ifp; - struct kif kif; if (ldp_iface_is_configured(conf, ifname)) return (NULL); - memset(&kif, 0, sizeof(kif)); - strlcpy(kif.ifname, ifname, sizeof(kif.ifname)); - ifp = if_lookup_by_name(ifname, VRF_DEFAULT); - if (ifp) { - kif.ifindex = ifp->ifindex; - kif.flags = ifp->flags; - } - - lif = l2vpn_if_new(l2vpn, &kif); + lif = l2vpn_if_new(l2vpn, ifname); RB_INSERT(l2vpn_if_head, &l2vpn->if_tree, lif); return (lif); } @@ -1913,21 +1860,11 @@ l2vpn_pw_new_api(struct ldpd_conf *conf, struct l2vpn *l2vpn, const char *ifname) { struct l2vpn_pw *pw; - struct interface *ifp; - struct kif kif; if (ldp_iface_is_configured(conf, ifname)) return (NULL); - memset(&kif, 0, sizeof(kif)); - strlcpy(kif.ifname, ifname, sizeof(kif.ifname)); - ifp = if_lookup_by_name(ifname, VRF_DEFAULT); - if (ifp) { - kif.ifindex = ifp->ifindex; - kif.flags = ifp->flags; - } - - pw = l2vpn_pw_new(l2vpn, &kif); + pw = l2vpn_pw_new(l2vpn, ifname); pw->flags = F_PW_STATUSTLV_CONF|F_PW_CWORD_CONF; RB_INSERT(l2vpn_pw_head, &l2vpn->pw_inactive_tree, pw); return (pw); diff --git a/ldpd/ldp_zebra.c b/ldpd/ldp_zebra.c index c41a0dbd91..702b5c5eaa 100644 --- a/ldpd/ldp_zebra.c +++ b/ldpd/ldp_zebra.c @@ -180,7 +180,7 @@ kif_redistribute(const char *ifname) continue; ifp2kif(ifp, &kif); - main_imsg_compose_ldpe(IMSG_IFSTATUS, 0, &kif, sizeof(kif)); + main_imsg_compose_both(IMSG_IFSTATUS, &kif, sizeof(kif)); for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, ifc)) { ifc2kaddr(ifp, ifc, &ka); @@ -222,7 +222,7 @@ ldp_interface_add(int command, struct zclient *zclient, zebra_size_t length, ifp->ifindex, ifp->mtu); ifp2kif(ifp, &kif); - main_imsg_compose_ldpe(IMSG_IFSTATUS, 0, &kif, sizeof(kif)); + main_imsg_compose_both(IMSG_IFSTATUS, &kif, sizeof(kif)); return (0); } @@ -270,7 +270,7 @@ ldp_interface_status_change(int command, struct zclient *zclient, debug_zebra_in("interface %s state update", ifp->name); ifp2kif(ifp, &kif); - main_imsg_compose_ldpe(IMSG_IFSTATUS, 0, &kif, sizeof(kif)); + main_imsg_compose_both(IMSG_IFSTATUS, &kif, sizeof(kif)); link_new = (ifp->flags & IFF_UP) && (ifp->flags & IFF_RUNNING); if (link_new) { diff --git a/ldpd/ldpd.c b/ldpd/ldpd.c index 3b3a07c28c..6c888c534c 100644 --- a/ldpd/ldpd.c +++ b/ldpd/ldpd.c @@ -1660,8 +1660,10 @@ merge_l2vpn(struct ldpd_conf *xconf, struct l2vpn *l2vpn, struct l2vpn *xl) RB_REMOVE(l2vpn_if_head, &xl->if_tree, xf); RB_INSERT(l2vpn_if_head, &l2vpn->if_tree, xf); xf->l2vpn = l2vpn; - if (ldpd_process == PROC_MAIN) - QOBJ_REG (xf, l2vpn_if); + if (ldpd_process == PROC_MAIN) { + QOBJ_REG(xf, l2vpn_if); + kif_redistribute(xf->ifname); + } continue; } @@ -1705,6 +1707,7 @@ merge_l2vpn(struct ldpd_conf *xconf, struct l2vpn *l2vpn, struct l2vpn *xl) break; case PROC_MAIN: QOBJ_REG (xp, l2vpn_pw); + kif_redistribute(xp->ifname); break; } continue; @@ -1792,8 +1795,10 @@ merge_l2vpn(struct ldpd_conf *xconf, struct l2vpn *l2vpn, struct l2vpn *xl) RB_REMOVE(l2vpn_pw_head, &xl->pw_inactive_tree, xp); RB_INSERT(l2vpn_pw_head, &l2vpn->pw_inactive_tree, xp); xp->l2vpn = l2vpn; - if (ldpd_process == PROC_MAIN) + if (ldpd_process == PROC_MAIN) { QOBJ_REG (xp, l2vpn_pw); + kif_redistribute(xp->ifname); + } continue; } diff --git a/ldpd/ldpe.c b/ldpd/ldpe.c index 96a7052ec6..f8e9abab02 100644 --- a/ldpd/ldpe.c +++ b/ldpd/ldpe.c @@ -256,8 +256,8 @@ ldpe_dispatch_main(struct thread *thread) struct tnbr *ntnbr; struct nbr_params *nnbrp; static struct l2vpn *l2vpn, *nl2vpn; - struct l2vpn_if *lif = NULL, *nlif; - struct l2vpn_pw *npw; + struct l2vpn_if *lif, *nlif; + struct l2vpn_pw *pw, *npw; struct imsg imsg; int fd = THREAD_FD(thread); struct imsgev *iev = THREAD_ARG(thread); @@ -305,12 +305,15 @@ ldpe_dispatch_main(struct thread *thread) RB_FOREACH(l2vpn, l2vpn_head, &leconf->l2vpn_tree) { lif = l2vpn_if_find(l2vpn, kif->ifname); if (lif) { - lif->flags = kif->flags; - memcpy(lif->mac, kif->mac, - sizeof(lif->mac)); + l2vpn_if_update_info(lif, kif); l2vpn_if_update(lif); break; } + pw = l2vpn_pw_find(l2vpn, kif->ifname); + if (pw) { + l2vpn_pw_update_info(pw, kif); + break; + } } break; case IMSG_NEWADDR: diff --git a/ldpd/ldpe.h b/ldpd/ldpe.h index 8215d08407..e4b8394aa0 100644 --- a/ldpd/ldpe.h +++ b/ldpd/ldpe.h @@ -214,7 +214,7 @@ void mapping_list_add(struct mapping_head *, struct map *); void mapping_list_clr(struct mapping_head *); /* interface.c */ -struct iface *if_new(struct kif *); +struct iface *if_new(const char *); void if_exit(struct iface *); struct iface *if_lookup(struct ldpd_conf *, unsigned short); struct iface *if_lookup_name(struct ldpd_conf *, const char *); From 7d0eeac1a154b76ff55c1ad53ae97a05a3ca977a Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Thu, 30 Mar 2017 22:15:33 -0300 Subject: [PATCH 29/61] ldpd: extend the ldp_config_normalize() function * remove superfluous parts of the configuration when possible (e.g. interfaces that are disabled for both IPv4 and IPv6); * move the check of whether the pseudowire is active or not from merge_l2vpns() to ldp_config_normalize() where it belongs. Signed-off-by: Renato Westphal --- ldpd/ldpd.c | 67 ++++++++++++++++++++++++++++++++--------------------- 1 file changed, 40 insertions(+), 27 deletions(-) diff --git a/ldpd/ldpd.c b/ldpd/ldpd.c index 6c888c534c..ea9317c41d 100644 --- a/ldpd/ldpd.c +++ b/ldpd/ldpd.c @@ -1000,8 +1000,10 @@ ldp_reload(struct ldpd_conf *xconf) static void ldp_config_normalize(struct ldpd_conf *xconf) { + struct iface *iface, *itmp; + struct nbr_params *nbrp, *ntmp; struct l2vpn *l2vpn; - struct l2vpn_pw *pw; + struct l2vpn_pw *pw, *ptmp; if (!(xconf->flags & F_LDPD_ENABLED)) ldp_config_reset_main(xconf); @@ -1010,22 +1012,49 @@ ldp_config_normalize(struct ldpd_conf *xconf) ldp_config_reset_af(xconf, AF_INET); if (!(xconf->ipv6.flags & F_LDPD_AF_ENABLED)) ldp_config_reset_af(xconf, AF_INET6); + + RB_FOREACH_SAFE(iface, iface_head, &xconf->iface_tree, itmp) { + if (iface->ipv4.enabled || iface->ipv6.enabled) + continue; + + RB_REMOVE(iface_head, &vty_conf->iface_tree, iface); + free(iface); + } + + RB_FOREACH_SAFE(nbrp, nbrp_head, &xconf->nbrp_tree, ntmp) { + if (nbrp->flags & (F_NBRP_KEEPALIVE|F_NBRP_GTSM)) + continue; + if (nbrp->auth.method != AUTH_NONE) + continue; + + RB_REMOVE(nbrp_head, &vty_conf->nbrp_tree, nbrp); + free(nbrp); + } } RB_FOREACH(l2vpn, l2vpn_head, &xconf->l2vpn_tree) { - RB_FOREACH(pw, l2vpn_pw_head, &l2vpn->pw_tree) { - if (pw->flags & F_PW_STATIC_NBR_ADDR) - continue; + RB_FOREACH_SAFE(pw, l2vpn_pw_head, &l2vpn->pw_tree, ptmp) { + if (!(pw->flags & F_PW_STATIC_NBR_ADDR)) { + pw->af = AF_INET; + pw->addr.v4 = pw->lsr_id; + } - pw->af = AF_INET; - pw->addr.v4 = pw->lsr_id; + if (pw->lsr_id.s_addr != INADDR_ANY && pw->pwid != 0) + continue; + RB_REMOVE(l2vpn_pw_head, &l2vpn->pw_tree, pw); + RB_INSERT(l2vpn_pw_head, &l2vpn->pw_inactive_tree, pw); } - RB_FOREACH(pw, l2vpn_pw_head, &l2vpn->pw_inactive_tree) { - if (pw->flags & F_PW_STATIC_NBR_ADDR) - continue; + RB_FOREACH_SAFE(pw, l2vpn_pw_head, &l2vpn->pw_inactive_tree, + ptmp) { + if (!(pw->flags & F_PW_STATIC_NBR_ADDR)) { + pw->af = AF_INET; + pw->addr.v4 = pw->lsr_id; + } - pw->af = AF_INET; - pw->addr.v4 = pw->lsr_id; + if (pw->lsr_id.s_addr == INADDR_ANY || pw->pwid == 0) + continue; + RB_REMOVE(l2vpn_pw_head, &l2vpn->pw_inactive_tree, pw); + RB_INSERT(l2vpn_pw_head, &l2vpn->pw_tree, pw); } } } @@ -1590,22 +1619,6 @@ merge_l2vpns(struct ldpd_conf *conf, struct ldpd_conf *xconf) } } RB_FOREACH_SAFE(xl, l2vpn_head, &xconf->l2vpn_tree, ltmp) { - struct l2vpn_pw *xp, *ptmp; - - /* check if the pseudowires should be enabled or disabled */ - RB_FOREACH_SAFE(xp, l2vpn_pw_head, &xl->pw_tree, ptmp) { - if (xp->lsr_id.s_addr != INADDR_ANY && xp->pwid != 0) - continue; - RB_REMOVE(l2vpn_pw_head, &xl->pw_tree, xp); - RB_INSERT(l2vpn_pw_head, &xl->pw_inactive_tree, xp); - } - RB_FOREACH_SAFE(xp, l2vpn_pw_head, &xl->pw_inactive_tree, ptmp) { - if (xp->lsr_id.s_addr == INADDR_ANY || xp->pwid == 0) - continue; - RB_REMOVE(l2vpn_pw_head, &xl->pw_inactive_tree, xp); - RB_INSERT(l2vpn_pw_head, &xl->pw_tree, xp); - } - /* find new l2vpns */ if ((l2vpn = l2vpn_find(conf, xl->name)) == NULL) { RB_REMOVE(l2vpn_head, &xconf->l2vpn_tree, xl); From 899a4fd2a14bf51b8a37e6d0fadd5dbf9395b427 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Fri, 29 May 2015 09:56:51 +0200 Subject: [PATCH 30/61] build: try to find some kind of atomic ops Either one of: - ISO C11 - gcc __atomic_* - gcc/clang __sync_* Signed-off-by: David Lamparter --- configure.ac | 66 +++++++++++++++++++++++++++ lib/Makefile.am | 1 + lib/frratomic.h | 118 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 185 insertions(+) create mode 100644 lib/frratomic.h diff --git a/configure.ac b/configure.ac index b8cebd8d23..4875a6849d 100755 --- a/configure.ac +++ b/configure.ac @@ -541,6 +541,72 @@ AC_CHECK_HEADERS([stropts.h sys/ksym.h \ linux/version.h asm/types.h \ sys/cdefs.h]) +ac_stdatomic_ok=false +AC_DEFINE(FRR_AUTOCONF_ATOMIC, 1, [did autoconf checks for atomic funcs]) +AC_CHECK_HEADER([stdatomic.h],[ + + AC_MSG_CHECKING([whether _Atomic qualifier works]) + AC_LINK_IFELSE([AC_LANG_SOURCE([[ +#include +int main(int argc, char **argv) { + _Atomic int i = 0; + return i; +} +]])], [ + AC_DEFINE(HAVE_STDATOMIC_H, 1, [found stdatomic.h]) + AC_MSG_RESULT([yes]) + ac_stdatomic_ok=true + ], [ + AC_MSG_RESULT([no]) + ]) +]) + +AS_IF([$ac_stdatomic_ok], [true], [ + AC_MSG_CHECKING([for __atomic_* builtins]) + AC_LINK_IFELSE([AC_LANG_SOURCE([[ +int main(int argc, char **argv) { + volatile int i = 1; + __atomic_store_n (&i, 0, __ATOMIC_RELEASE); + return __atomic_load_n (&i, __ATOMIC_ACQUIRE); +} +]])], [ + AC_DEFINE(HAVE___ATOMIC, 1, [found __atomic builtins]) + AC_MSG_RESULT([yes]) + ], [ + AC_MSG_RESULT([no]) + + dnl FreeBSD 9 has a broken stdatomic.h where _Atomic doesn't work + AC_MSG_CHECKING([for __sync_* builtins]) + AC_LINK_IFELSE([AC_LANG_SOURCE([[ +int main(int argc, char **argv) { + volatile int i = 1; + __sync_fetch_and_sub (&i, 1); + return __sync_val_compare_and_swap (&i, 0, 1); +} +]])], [ + AC_DEFINE(HAVE___SYNC, 1, [found __sync builtins]) + AC_MSG_RESULT([yes]) + + AC_MSG_CHECKING([for __sync_swap builtin]) + AC_LINK_IFELSE([AC_LANG_SOURCE([[ +int main(int argc, char **argv) { + volatile int i = 1; + return __sync_swap (&i, 2); +} +]])], [ + AC_DEFINE(HAVE___SYNC_SWAP, 1, [found __sync_swap builtin]) + AC_MSG_RESULT([yes]) + ], [ + AC_MSG_RESULT([no]) + ]) + + ], [ + AC_MSG_RESULT([no]) + AC_MSG_FAILURE([stdatomic.h unavailable and $CC has neither __atomic nor __sync builtins]) + ]) + ]) +]) + dnl Utility macro to avoid retyping includes all the time m4_define([FRR_INCLUDES], [#ifdef SUNOS_5 diff --git a/lib/Makefile.am b/lib/Makefile.am index 1a8c7af42b..d7a4439d5a 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -38,6 +38,7 @@ BUILT_SOURCES = route_types.h gitversion.h command_parse.h command_lex.h libfrr_la_LIBADD = @LIBCAP@ pkginclude_HEADERS = \ + frratomic.h \ buffer.h checksum.h filter.h getopt.h hash.h \ if.h linklist.h log.h \ graph.h command_match.h \ diff --git a/lib/frratomic.h b/lib/frratomic.h new file mode 100644 index 0000000000..183790aeb0 --- /dev/null +++ b/lib/frratomic.h @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2015-16 David Lamparter, for NetDEF, Inc. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _FRRATOMIC_H +#define _FRRATOMIC_H + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifndef FRR_AUTOCONF_ATOMIC +#error autoconf checks for atomic functions were not properly run +#endif + +/* ISO C11 */ +#ifdef HAVE_STDATOMIC_H +#include + +/* gcc 4.7 and newer */ +#elif defined(HAVE___ATOMIC) + +#define _Atomic volatile + +#define memory_order_relaxed __ATOMIC_RELAXED +#define memory_order_consume __ATOMIC_CONSUME +#define memory_order_acquire __ATOMIC_ACQUIRE +#define memory_order_release __ATOMIC_RELEASE +#define memory_order_acq_rel __ATOMIC_ACQ_REL +#define memory_order_seq_cst __ATOMIC_SEQ_CST + +#define atomic_load_explicit __atomic_load_n +#define atomic_store_explicit __atomic_store_n +#define atomic_exchange_explicit __atomic_exchange_n +#define atomic_fetch_add_explicit __atomic_fetch_add +#define atomic_fetch_sub_explicit __atomic_fetch_sub + +#define atomic_compare_exchange_weak_explicit(atom, expect, desire, mem1, mem2) \ + __atomic_compare_exchange_n(atom, expect, desire, 1, mem1, mem2) + +/* gcc 4.1 and newer, + * clang 3.3 (possibly older) + * + * __sync_swap isn't in gcc's documentation, but clang has it + * + * note __sync_synchronize() + */ +#elif defined(HAVE___SYNC) + +#define _Atomic volatile + +#define memory_order_relaxed 0 +#define memory_order_consume 0 +#define memory_order_acquire 0 +#define memory_order_release 0 +#define memory_order_acq_rel 0 +#define memory_order_seq_cst 0 + +#define atomic_load_explicit(ptr, mem) \ + ({ __sync_synchronize(); \ + typeof(*ptr) rval = __sync_fetch_and_add((ptr), 0); \ + __sync_synchronize(); rval; }) +#define atomic_store_explicit(ptr, val, mem) \ + ({ __sync_synchronize(); \ + *(ptr) = (val); \ + __sync_synchronize(); (void)0; }) +#ifdef HAVE___SYNC_SWAP +#define atomic_exchange_explicit(ptr, val, mem) \ + ({ __sync_synchronize(); \ + typeof(*ptr) rval = __sync_swap((ptr, val), 0); \ + __sync_synchronize(); rval; }) +#else /* !HAVE___SYNC_SWAP */ +#define atomic_exchange_explicit(ptr, val, mem) \ + ({ typeof(ptr) _ptr = (ptr); typeof(val) _val = (val); \ + __sync_synchronize(); \ + typeof(*ptr) old1, old2 = __sync_fetch_and_add(_ptr, 0); \ + do { \ + old1 = old2; \ + old2 = __sync_val_compare_and_swap (_ptr, old1, _val); \ + } while (old1 != old2); \ + __sync_synchronize(); \ + old2; \ + }) +#endif /* !HAVE___SYNC_SWAP */ +#define atomic_fetch_add_explicit(ptr, val, mem) \ + ({ __sync_synchronize(); \ + typeof(*ptr) rval = __sync_fetch_and_add((ptr), (val)); \ + __sync_synchronize(); rval; }) +#define atomic_fetch_sub_explicit(ptr, val, mem) \ + ({ __sync_synchronize(); \ + typeof(*ptr) rval = __sync_fetch_and_sub((ptr), (val)); \ + __sync_synchronize(); rval; }) + +#define atomic_compare_exchange_weak_explicit(atom, expect, desire, mem1, mem2) \ + ({ typeof(atom) _atom = (atom); typeof(expect) _expect = (expect); \ + typeof(desire) _desire = (desire); \ + __sync_synchronize(); \ + typeof(*atom) rval = __sync_val_compare_and_swap(_atom, *_expect, _desire); \ + __sync_synchronize(); \ + bool ret = (rval == *_expect); *_expect = rval; ret; }) + +#else /* !HAVE___ATOMIC && !HAVE_STDATOMIC_H */ +#error no atomic functions... +#endif + +#endif /* _FRRATOMIC_H */ From a31446a88f7751b763d0af2a3d92c9e0887faa61 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Wed, 26 Oct 2016 17:19:56 +0200 Subject: [PATCH 31/61] lib: memtypes: restore atomicity the original version of this code already used _Atomic and atomic_*(). Restore this functionality for future multithreading. Signed-off-by: David Lamparter --- lib/memory.c | 15 +++++++++------ lib/memory.h | 5 +++-- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/lib/memory.c b/lib/memory.c index ad55366f64..28e358dfc1 100644 --- a/lib/memory.c +++ b/lib/memory.c @@ -30,19 +30,22 @@ DEFINE_MTYPE(LIB, TMP, "Temporary memory") static inline void mt_count_alloc (struct memtype *mt, size_t size) { - mt->n_alloc++; + size_t oldsize; - if (mt->size == 0) - mt->size = size; - else if (mt->size != size) - mt->size = SIZE_VAR; + atomic_fetch_add_explicit(&mt->n_alloc, 1, memory_order_relaxed); + + oldsize = atomic_load_explicit(&mt->size, memory_order_relaxed); + if (oldsize == 0) + oldsize = atomic_exchange_explicit(&mt->size, size, memory_order_relaxed); + if (oldsize != 0 && oldsize != size && oldsize != SIZE_VAR) + atomic_store_explicit(&mt->size, SIZE_VAR, memory_order_relaxed); } static inline void mt_count_free (struct memtype *mt) { assert(mt->n_alloc); - mt->n_alloc--; + atomic_fetch_sub_explicit(&mt->n_alloc, 1, memory_order_relaxed); } static inline void * diff --git a/lib/memory.h b/lib/memory.h index 477a6162dc..284a1b13c5 100644 --- a/lib/memory.h +++ b/lib/memory.h @@ -18,6 +18,7 @@ #define _QUAGGA_MEMORY_H #include +#include #define array_size(ar) (sizeof(ar) / sizeof(ar[0])) @@ -26,8 +27,8 @@ struct memtype { struct memtype *next, **ref; const char *name; - size_t n_alloc; - size_t size; + _Atomic size_t n_alloc; + _Atomic size_t size; }; struct memgroup From fa7fe831aace83d919df3792fccd264dc5ce94ea Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Fri, 31 Mar 2017 16:37:23 +0200 Subject: [PATCH 32/61] lib: Linux indentation on memory.[ch] The fact that I originally wrote this in Linux Kernel style and then reindented it to GNU makes me want to gouge my eyes out every time I look at it. Restore original indentation. [This patch is whitespace-only.] Signed-off-by: David Lamparter --- lib/memory.c | 147 +++++++++++++++++++++++---------------------------- lib/memory.h | 42 +++++++-------- 2 files changed, 86 insertions(+), 103 deletions(-) diff --git a/lib/memory.c b/lib/memory.c index 28e358dfc1..c6207adb98 100644 --- a/lib/memory.c +++ b/lib/memory.c @@ -27,122 +27,107 @@ struct memgroup **mg_insert = &mg_first; DEFINE_MGROUP(LIB, "libfrr") DEFINE_MTYPE(LIB, TMP, "Temporary memory") -static inline void -mt_count_alloc (struct memtype *mt, size_t size) +static inline void mt_count_alloc(struct memtype *mt, size_t size) { - size_t oldsize; + size_t oldsize; - atomic_fetch_add_explicit(&mt->n_alloc, 1, memory_order_relaxed); + atomic_fetch_add_explicit(&mt->n_alloc, 1, memory_order_relaxed); - oldsize = atomic_load_explicit(&mt->size, memory_order_relaxed); - if (oldsize == 0) - oldsize = atomic_exchange_explicit(&mt->size, size, memory_order_relaxed); - if (oldsize != 0 && oldsize != size && oldsize != SIZE_VAR) - atomic_store_explicit(&mt->size, SIZE_VAR, memory_order_relaxed); + oldsize = atomic_load_explicit(&mt->size, memory_order_relaxed); + if (oldsize == 0) + oldsize = atomic_exchange_explicit(&mt->size, size, memory_order_relaxed); + if (oldsize != 0 && oldsize != size && oldsize != SIZE_VAR) + atomic_store_explicit(&mt->size, SIZE_VAR, memory_order_relaxed); } -static inline void -mt_count_free (struct memtype *mt) +static inline void mt_count_free(struct memtype *mt) { - assert(mt->n_alloc); - atomic_fetch_sub_explicit(&mt->n_alloc, 1, memory_order_relaxed); + assert(mt->n_alloc); + atomic_fetch_sub_explicit(&mt->n_alloc, 1, memory_order_relaxed); } -static inline void * -mt_checkalloc (struct memtype *mt, void *ptr, size_t size) +static inline void *mt_checkalloc(struct memtype *mt, void *ptr, size_t size) { - if (__builtin_expect(ptr == NULL, 0)) - { - memory_oom (size, mt->name); - return NULL; - } - mt_count_alloc (mt, size); - return ptr; + if (__builtin_expect(ptr == NULL, 0)) { + memory_oom(size, mt->name); + return NULL; + } + mt_count_alloc(mt, size); + return ptr; } -void * -qmalloc (struct memtype *mt, size_t size) +void *qmalloc(struct memtype *mt, size_t size) { - return mt_checkalloc (mt, malloc (size), size); + return mt_checkalloc(mt, malloc(size), size); } -void * -qcalloc (struct memtype *mt, size_t size) +void *qcalloc(struct memtype *mt, size_t size) { - return mt_checkalloc (mt, calloc (size, 1), size); + return mt_checkalloc(mt, calloc(size, 1), size); } -void * -qrealloc (struct memtype *mt, void *ptr, size_t size) +void *qrealloc(struct memtype *mt, void *ptr, size_t size) { - if (ptr) - mt_count_free (mt); - return mt_checkalloc (mt, ptr ? realloc (ptr, size) : malloc (size), size); + if (ptr) + mt_count_free(mt); + return mt_checkalloc(mt, ptr ? realloc(ptr, size) : malloc(size), size); } -void * -qstrdup (struct memtype *mt, const char *str) +void *qstrdup(struct memtype *mt, const char *str) { - return mt_checkalloc (mt, strdup (str), strlen (str) + 1); + return mt_checkalloc(mt, strdup(str), strlen(str) + 1); } -void -qfree (struct memtype *mt, void *ptr) +void qfree(struct memtype *mt, void *ptr) { - if (ptr) - mt_count_free (mt); - free (ptr); + if (ptr) + mt_count_free(mt); + free(ptr); } -int -qmem_walk (qmem_walk_fn *func, void *arg) +int qmem_walk(qmem_walk_fn *func, void *arg) { - struct memgroup *mg; - struct memtype *mt; - int rv; + struct memgroup *mg; + struct memtype *mt; + int rv; - for (mg = mg_first; mg; mg = mg->next) - { - if ((rv = func (arg, mg, NULL))) - return rv; - for (mt = mg->types; mt; mt = mt->next) - if ((rv = func (arg, mg, mt))) - return rv; - } - return 0; + for (mg = mg_first; mg; mg = mg->next) { + if ((rv = func(arg, mg, NULL))) + return rv; + for (mt = mg->types; mt; mt = mt->next) + if ((rv = func(arg, mg, mt))) + return rv; + } + return 0; } -struct exit_dump_args -{ - const char *prefix; - int error; +struct exit_dump_args { + const char *prefix; + int error; }; -static int -qmem_exit_walker (void *arg, struct memgroup *mg, struct memtype *mt) +static int qmem_exit_walker(void *arg, struct memgroup *mg, struct memtype *mt) { - struct exit_dump_args *eda = arg; + struct exit_dump_args *eda = arg; - if (!mt) - { - fprintf (stderr, "%s: showing active allocations in memory group %s\n", - eda->prefix, mg->name); - } - else if (mt->n_alloc) - { - char size[32]; - eda->error++; - snprintf (size, sizeof (size), "%10zu", mt->size); - fprintf (stderr, "%s: memstats: %-30s: %6zu * %s\n", - eda->prefix, mt->name, mt->n_alloc, - mt->size == SIZE_VAR ? "(variably sized)" : size); - } - return 0; + if (!mt) { + fprintf(stderr, "%s: showing active allocations in " + "memory group %s\n", + eda->prefix, mg->name); + + } else if (mt->n_alloc) { + char size[32]; + eda->error++; + snprintf(size, sizeof(size), "%10zu", mt->size); + fprintf(stderr, "%s: memstats: %-30s: %6zu * %s\n", + eda->prefix, mt->name, mt->n_alloc, + mt->size == SIZE_VAR ? "(variably sized)" : size); + } + return 0; } -void -log_memstats_stderr (const char *prefix) +void log_memstats_stderr(const char *prefix) { - struct exit_dump_args eda = { .prefix = prefix, .error = 0 }; - qmem_walk (qmem_exit_walker, &eda); + struct exit_dump_args eda = { .prefix = prefix, .error = 0 }; + qmem_walk(qmem_exit_walker, &eda); } diff --git a/lib/memory.h b/lib/memory.h index 284a1b13c5..9e8803a8b2 100644 --- a/lib/memory.h +++ b/lib/memory.h @@ -23,19 +23,17 @@ #define array_size(ar) (sizeof(ar) / sizeof(ar[0])) #define SIZE_VAR ~0UL -struct memtype -{ - struct memtype *next, **ref; - const char *name; - _Atomic size_t n_alloc; - _Atomic size_t size; +struct memtype { + struct memtype *next, **ref; + const char *name; + _Atomic size_t n_alloc; + _Atomic size_t size; }; -struct memgroup -{ - struct memgroup *next, **ref; - struct memtype *types, **insert; - const char *name; +struct memgroup { + struct memgroup *next, **ref; + struct memtype *types, **insert; + const char *name; }; #if defined(__clang__) @@ -83,14 +81,14 @@ struct memgroup * DEFINE_MGROUP(MYDAEMON, "my daemon memory") * DEFINE_MTYPE(MYDAEMON, MYDAEMON_COMMON, * "this mtype is used in multiple files in mydaemon") - * foo = qmalloc (MTYPE_MYDAEMON_COMMON, sizeof (*foo)) + * foo = qmalloc(MTYPE_MYDAEMON_COMMON, sizeof(*foo)) * * mydaemon_io.c - * bar = qmalloc (MTYPE_MYDAEMON_COMMON, sizeof (*bar)) + * bar = qmalloc(MTYPE_MYDAEMON_COMMON, sizeof(*bar)) * * DEFINE_MTYPE_STATIC(MYDAEMON, MYDAEMON_IO, * "this mtype is used only in this file") - * baz = qmalloc (MTYPE_MYDAEMON_IO, sizeof (*baz)) + * baz = qmalloc(MTYPE_MYDAEMON_IO, sizeof(*baz)) * * Note: Naming conventions (MGROUP_ and MTYPE_ prefixes are enforced * by not having these as part of the macro arguments) @@ -156,15 +154,15 @@ DECLARE_MGROUP(LIB) DECLARE_MTYPE(TMP) -extern void *qmalloc (struct memtype *mt, size_t size) +extern void *qmalloc(struct memtype *mt, size_t size) __attribute__ ((malloc, _ALLOC_SIZE(2), nonnull (1) _RET_NONNULL)); -extern void *qcalloc (struct memtype *mt, size_t size) +extern void *qcalloc(struct memtype *mt, size_t size) __attribute__ ((malloc, _ALLOC_SIZE(2), nonnull (1) _RET_NONNULL)); -extern void *qrealloc (struct memtype *mt, void *ptr, size_t size) +extern void *qrealloc(struct memtype *mt, void *ptr, size_t size) __attribute__ ((_ALLOC_SIZE(3), nonnull (1) _RET_NONNULL)); extern void *qstrdup (struct memtype *mt, const char *str) __attribute__ ((malloc, nonnull (1) _RET_NONNULL)); -extern void qfree (struct memtype *mt, void *ptr) +extern void qfree(struct memtype *mt, void *ptr) __attribute__ ((nonnull (1))); #define XMALLOC(mtype, size) qmalloc(mtype, size) @@ -184,10 +182,10 @@ static inline size_t mtype_stats_alloc(struct memtype *mt) * * return value: 0: continue, !0: abort walk. qmem_walk will return the * last value from qmem_walk_fn. */ -typedef int qmem_walk_fn (void *arg, struct memgroup *mg, struct memtype *mt); -extern int qmem_walk (qmem_walk_fn *func, void *arg); -extern void log_memstats_stderr (const char *); +typedef int qmem_walk_fn(void *arg, struct memgroup *mg, struct memtype *mt); +extern int qmem_walk(qmem_walk_fn *func, void *arg); +extern void log_memstats_stderr(const char *); -extern void memory_oom (size_t size, const char *name); +extern void memory_oom(size_t size, const char *name); #endif /* _QUAGGA_MEMORY_H */ From b31fd749072b0310016dfb53cc2f61d4d6126cea Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Sat, 25 Apr 2015 13:10:36 +0200 Subject: [PATCH 33/61] build: find & use threading library Signed-off-by: David Lamparter --- configure.ac | 14 +- m4/.gitignore | 3 +- m4/ax_pthread.m4 | 332 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 347 insertions(+), 2 deletions(-) create mode 100644 m4/ax_pthread.m4 diff --git a/configure.ac b/configure.ac index 4875a6849d..5b46f77d6d 100755 --- a/configure.ac +++ b/configure.ac @@ -94,7 +94,7 @@ AC_CHECK_PROG([SED],[sed],[sed],[/bin/false]) dnl try and enable CFLAGS that are useful for Quagga dnl - specifically, options to control warnings -AC_USE_SYSTEM_EXTENSIONS() +AC_USE_SYSTEM_EXTENSIONS AC_DEFUN([AC_C_FLAG], [{ AC_LANG_PUSH(C) ac_c_flag_save="$CFLAGS" @@ -182,6 +182,18 @@ AC_LINK_IFELSE( ]) AC_LANG_POP(C) +dnl ---------- +dnl Essentials +dnl ---------- + +AX_PTHREAD([ + CC="$PTHREAD_CC" + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + LIBS="$PTHREAD_LIBS $LIBS" +], [ + AC_MSG_FAILURE([This Quagga version needs pthreads]) +]) + dnl -------------- dnl Check programs dnl -------------- diff --git a/m4/.gitignore b/m4/.gitignore index 3f3bd0a735..798188b0b9 100644 --- a/m4/.gitignore +++ b/m4/.gitignore @@ -4,4 +4,5 @@ Makefile.in .arch-ids *~ *.loT - +!ax_pthread.m4 +!ax_sys_weak_alias.m4 diff --git a/m4/ax_pthread.m4 b/m4/ax_pthread.m4 new file mode 100644 index 0000000000..d383ad5c6d --- /dev/null +++ b/m4/ax_pthread.m4 @@ -0,0 +1,332 @@ +# =========================================================================== +# http://www.gnu.org/software/autoconf-archive/ax_pthread.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_PTHREAD([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]]) +# +# DESCRIPTION +# +# This macro figures out how to build C programs using POSIX threads. It +# sets the PTHREAD_LIBS output variable to the threads library and linker +# flags, and the PTHREAD_CFLAGS output variable to any special C compiler +# flags that are needed. (The user can also force certain compiler +# flags/libs to be tested by setting these environment variables.) +# +# Also sets PTHREAD_CC to any special C compiler that is needed for +# multi-threaded programs (defaults to the value of CC otherwise). (This +# is necessary on AIX to use the special cc_r compiler alias.) +# +# NOTE: You are assumed to not only compile your program with these flags, +# but also link it with them as well. e.g. you should link with +# $PTHREAD_CC $CFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS $LIBS +# +# If you are only building threads programs, you may wish to use these +# variables in your default LIBS, CFLAGS, and CC: +# +# LIBS="$PTHREAD_LIBS $LIBS" +# CFLAGS="$CFLAGS $PTHREAD_CFLAGS" +# CC="$PTHREAD_CC" +# +# In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute constant +# has a nonstandard name, defines PTHREAD_CREATE_JOINABLE to that name +# (e.g. PTHREAD_CREATE_UNDETACHED on AIX). +# +# Also HAVE_PTHREAD_PRIO_INHERIT is defined if pthread is found and the +# PTHREAD_PRIO_INHERIT symbol is defined when compiling with +# PTHREAD_CFLAGS. +# +# ACTION-IF-FOUND is a list of shell commands to run if a threads library +# is found, and ACTION-IF-NOT-FOUND is a list of commands to run it if it +# is not found. If ACTION-IF-FOUND is not specified, the default action +# will define HAVE_PTHREAD. +# +# Please let the authors know if this macro fails on any platform, or if +# you have any other suggestions or comments. This macro was based on work +# by SGJ on autoconf scripts for FFTW (http://www.fftw.org/) (with help +# from M. Frigo), as well as ac_pthread and hb_pthread macros posted by +# Alejandro Forero Cuervo to the autoconf macro repository. We are also +# grateful for the helpful feedback of numerous users. +# +# Updated for Autoconf 2.68 by Daniel Richard G. +# +# LICENSE +# +# Copyright (c) 2008 Steven G. Johnson +# Copyright (c) 2011 Daniel Richard G. +# +# This program 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 3 of the License, or (at your +# option) any later version. +# +# This program 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. If not, see . +# +# As a special exception, the respective Autoconf Macro's copyright owner +# gives unlimited permission to copy, distribute and modify the configure +# scripts that are the output of Autoconf when processing the Macro. You +# need not follow the terms of the GNU General Public License when using +# or distributing such scripts, even though portions of the text of the +# Macro appear in them. The GNU General Public License (GPL) does govern +# all other use of the material that constitutes the Autoconf Macro. +# +# This special exception to the GPL applies to versions of the Autoconf +# Macro released by the Autoconf Archive. When you make and distribute a +# modified version of the Autoconf Macro, you may extend this special +# exception to the GPL to apply to your modified version as well. + +#serial 21 + +AU_ALIAS([ACX_PTHREAD], [AX_PTHREAD]) +AC_DEFUN([AX_PTHREAD], [ +AC_REQUIRE([AC_CANONICAL_HOST]) +AC_LANG_PUSH([C]) +ax_pthread_ok=no + +# We used to check for pthread.h first, but this fails if pthread.h +# requires special compiler flags (e.g. on True64 or Sequent). +# It gets checked for in the link test anyway. + +# First of all, check if the user has set any of the PTHREAD_LIBS, +# etcetera environment variables, and if threads linking works using +# them: +if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then + save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + save_LIBS="$LIBS" + LIBS="$PTHREAD_LIBS $LIBS" + AC_MSG_CHECKING([for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS]) + AC_TRY_LINK_FUNC([pthread_join], [ax_pthread_ok=yes]) + AC_MSG_RESULT([$ax_pthread_ok]) + if test x"$ax_pthread_ok" = xno; then + PTHREAD_LIBS="" + PTHREAD_CFLAGS="" + fi + LIBS="$save_LIBS" + CFLAGS="$save_CFLAGS" +fi + +# We must check for the threads library under a number of different +# names; the ordering is very important because some systems +# (e.g. DEC) have both -lpthread and -lpthreads, where one of the +# libraries is broken (non-POSIX). + +# Create a list of thread flags to try. Items starting with a "-" are +# C compiler flags, and other items are library names, except for "none" +# which indicates that we try without any flags at all, and "pthread-config" +# which is a program returning the flags for the Pth emulation library. + +ax_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config" + +# The ordering *is* (sometimes) important. Some notes on the +# individual items follow: + +# pthreads: AIX (must check this before -lpthread) +# none: in case threads are in libc; should be tried before -Kthread and +# other compiler flags to prevent continual compiler warnings +# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h) +# -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able) +# lthread: LinuxThreads port on FreeBSD (also preferred to -pthread) +# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads) +# -pthreads: Solaris/gcc +# -mthreads: Mingw32/gcc, Lynx/gcc +# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it +# doesn't hurt to check since this sometimes defines pthreads too; +# also defines -D_REENTRANT) +# ... -mt is also the pthreads flag for HP/aCC +# pthread: Linux, etcetera +# --thread-safe: KAI C++ +# pthread-config: use pthread-config program (for GNU Pth library) + +case ${host_os} in + solaris*) + + # On Solaris (at least, for some versions), libc contains stubbed + # (non-functional) versions of the pthreads routines, so link-based + # tests will erroneously succeed. (We need to link with -pthreads/-mt/ + # -lpthread.) (The stubs are missing pthread_cleanup_push, or rather + # a function called by this macro, so we could check for that, but + # who knows whether they'll stub that too in a future libc.) So, + # we'll just look for -pthreads and -lpthread first: + + ax_pthread_flags="-pthreads pthread -mt -pthread $ax_pthread_flags" + ;; + + darwin*) + ax_pthread_flags="-pthread $ax_pthread_flags" + ;; +esac + +# Clang doesn't consider unrecognized options an error unless we specify +# -Werror. We throw in some extra Clang-specific options to ensure that +# this doesn't happen for GCC, which also accepts -Werror. + +AC_MSG_CHECKING([if compiler needs -Werror to reject unknown flags]) +save_CFLAGS="$CFLAGS" +ax_pthread_extra_flags="-Werror" +CFLAGS="$CFLAGS $ax_pthread_extra_flags -Wunknown-warning-option -Wsizeof-array-argument" +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([int foo(void);],[foo()])], + [AC_MSG_RESULT([yes])], + [ax_pthread_extra_flags= + AC_MSG_RESULT([no])]) +CFLAGS="$save_CFLAGS" + +if test x"$ax_pthread_ok" = xno; then +for flag in $ax_pthread_flags; do + + case $flag in + none) + AC_MSG_CHECKING([whether pthreads work without any flags]) + ;; + + -*) + AC_MSG_CHECKING([whether pthreads work with $flag]) + PTHREAD_CFLAGS="$flag" + ;; + + pthread-config) + AC_CHECK_PROG([ax_pthread_config], [pthread-config], [yes], [no]) + if test x"$ax_pthread_config" = xno; then continue; fi + PTHREAD_CFLAGS="`pthread-config --cflags`" + PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`" + ;; + + *) + AC_MSG_CHECKING([for the pthreads library -l$flag]) + PTHREAD_LIBS="-l$flag" + ;; + esac + + save_LIBS="$LIBS" + save_CFLAGS="$CFLAGS" + LIBS="$PTHREAD_LIBS $LIBS" + CFLAGS="$CFLAGS $PTHREAD_CFLAGS $ax_pthread_extra_flags" + + # Check for various functions. We must include pthread.h, + # since some functions may be macros. (On the Sequent, we + # need a special flag -Kthread to make this header compile.) + # We check for pthread_join because it is in -lpthread on IRIX + # while pthread_create is in libc. We check for pthread_attr_init + # due to DEC craziness with -lpthreads. We check for + # pthread_cleanup_push because it is one of the few pthread + # functions on Solaris that doesn't have a non-functional libc stub. + # We try pthread_create on general principles. + AC_LINK_IFELSE([AC_LANG_PROGRAM([#include + static void routine(void *a) { a = 0; } + static void *start_routine(void *a) { return a; }], + [pthread_t th; pthread_attr_t attr; + pthread_create(&th, 0, start_routine, 0); + pthread_join(th, 0); + pthread_attr_init(&attr); + pthread_cleanup_push(routine, 0); + pthread_cleanup_pop(0) /* ; */])], + [ax_pthread_ok=yes], + []) + + LIBS="$save_LIBS" + CFLAGS="$save_CFLAGS" + + AC_MSG_RESULT([$ax_pthread_ok]) + if test "x$ax_pthread_ok" = xyes; then + break; + fi + + PTHREAD_LIBS="" + PTHREAD_CFLAGS="" +done +fi + +# Various other checks: +if test "x$ax_pthread_ok" = xyes; then + save_LIBS="$LIBS" + LIBS="$PTHREAD_LIBS $LIBS" + save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + + # Detect AIX lossage: JOINABLE attribute is called UNDETACHED. + AC_MSG_CHECKING([for joinable pthread attribute]) + attr_name=unknown + for attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do + AC_LINK_IFELSE([AC_LANG_PROGRAM([#include ], + [int attr = $attr; return attr /* ; */])], + [attr_name=$attr; break], + []) + done + AC_MSG_RESULT([$attr_name]) + if test "$attr_name" != PTHREAD_CREATE_JOINABLE; then + AC_DEFINE_UNQUOTED([PTHREAD_CREATE_JOINABLE], [$attr_name], + [Define to necessary symbol if this constant + uses a non-standard name on your system.]) + fi + + AC_MSG_CHECKING([if more special flags are required for pthreads]) + flag=no + case ${host_os} in + aix* | freebsd* | darwin*) flag="-D_THREAD_SAFE";; + osf* | hpux*) flag="-D_REENTRANT";; + solaris*) + if test "$GCC" = "yes"; then + flag="-D_REENTRANT" + else + # TODO: What about Clang on Solaris? + flag="-mt -D_REENTRANT" + fi + ;; + esac + AC_MSG_RESULT([$flag]) + if test "x$flag" != xno; then + PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS" + fi + + AC_CACHE_CHECK([for PTHREAD_PRIO_INHERIT], + [ax_cv_PTHREAD_PRIO_INHERIT], [ + AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include ]], + [[int i = PTHREAD_PRIO_INHERIT;]])], + [ax_cv_PTHREAD_PRIO_INHERIT=yes], + [ax_cv_PTHREAD_PRIO_INHERIT=no]) + ]) + AS_IF([test "x$ax_cv_PTHREAD_PRIO_INHERIT" = "xyes"], + [AC_DEFINE([HAVE_PTHREAD_PRIO_INHERIT], [1], [Have PTHREAD_PRIO_INHERIT.])]) + + LIBS="$save_LIBS" + CFLAGS="$save_CFLAGS" + + # More AIX lossage: compile with *_r variant + if test "x$GCC" != xyes; then + case $host_os in + aix*) + AS_CASE(["x/$CC"], + [x*/c89|x*/c89_128|x*/c99|x*/c99_128|x*/cc|x*/cc128|x*/xlc|x*/xlc_v6|x*/xlc128|x*/xlc128_v6], + [#handle absolute path differently from PATH based program lookup + AS_CASE(["x$CC"], + [x/*], + [AS_IF([AS_EXECUTABLE_P([${CC}_r])],[PTHREAD_CC="${CC}_r"])], + [AC_CHECK_PROGS([PTHREAD_CC],[${CC}_r],[$CC])])]) + ;; + esac + fi +fi + +test -n "$PTHREAD_CC" || PTHREAD_CC="$CC" + +AC_SUBST([PTHREAD_LIBS]) +AC_SUBST([PTHREAD_CFLAGS]) +AC_SUBST([PTHREAD_CC]) + +# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND: +if test x"$ax_pthread_ok" = xyes; then + ifelse([$1],,[AC_DEFINE([HAVE_PTHREAD],[1],[Define if you have POSIX threads libraries and header files.])],[$1]) + : +else + ax_pthread_ok=no + $2 +fi +AC_LANG_POP +])dnl AX_PTHREAD From 1d75a89d8553caab99e58668af30a9803d40d49b Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Thu, 30 Mar 2017 11:33:08 -0300 Subject: [PATCH 34/61] ldpd: do not consume vty_conf when updating the configuration David Lamparter gave the idea of keeping vty_conf as a permanent copy of ldpd_conf in order to simplify the CLI code and facilitate the integration with his cap'n proto framework in the future. Doing this demanded quite some effort but it was worth it as the code looks much better now. Signed-off-by: Renato Westphal --- ldpd/interface.c | 24 +++- ldpd/lde.c | 10 +- ldpd/ldp_vty_conf.c | 232 ++++++++++++-------------------------- ldpd/ldpd.c | 268 ++++++++++++++++++-------------------------- ldpd/ldpd.h | 1 - ldpd/ldpe.c | 10 +- ldpd/ldpe.h | 3 +- 7 files changed, 205 insertions(+), 343 deletions(-) diff --git a/ldpd/interface.c b/ldpd/interface.c index 11bce12b09..b7f473d396 100644 --- a/ldpd/interface.c +++ b/ldpd/interface.c @@ -62,21 +62,35 @@ if_new(const char *name) iface->ipv4.af = AF_INET; iface->ipv4.iface = iface; iface->ipv4.enabled = 0; - iface->ipv4.state = IF_STA_DOWN; - RB_INIT(&iface->ipv4.adj_tree); /* ipv6 */ iface->ipv6.af = AF_INET6; iface->ipv6.iface = iface; iface->ipv6.enabled = 0; - iface->ipv6.state = IF_STA_DOWN; - RB_INIT(&iface->ipv6.adj_tree); return (iface); } void -if_exit(struct iface *iface) +ldpe_if_init(struct iface *iface) +{ + log_debug("%s: interface %s", __func__, iface->name); + + LIST_INIT(&iface->addr_list); + + /* ipv4 */ + iface->ipv4.iface = iface; + iface->ipv4.state = IF_STA_DOWN; + RB_INIT(&iface->ipv4.adj_tree); + + /* ipv6 */ + iface->ipv6.iface = iface; + iface->ipv6.state = IF_STA_DOWN; + RB_INIT(&iface->ipv6.adj_tree); +} + +void +ldpe_if_exit(struct iface *iface) { struct if_addr *if_addr; diff --git a/ldpd/lde.c b/ldpd/lde.c index 607a9f7b14..d8a2924b31 100644 --- a/ldpd/lde.c +++ b/ldpd/lde.c @@ -566,12 +566,6 @@ lde_dispatch_parent(struct thread *thread) fatal(NULL); memcpy(niface, imsg.data, sizeof(struct iface)); - LIST_INIT(&niface->addr_list); - RB_INIT(&niface->ipv4.adj_tree); - RB_INIT(&niface->ipv6.adj_tree); - niface->ipv4.iface = niface; - niface->ipv6.iface = niface; - RB_INSERT(iface_head, &nconf->iface_tree, niface); break; case IMSG_RECONF_TNBR: @@ -604,7 +598,6 @@ lde_dispatch_parent(struct thread *thread) fatal(NULL); memcpy(nlif, imsg.data, sizeof(struct l2vpn_if)); - nlif->l2vpn = nl2vpn; RB_INSERT(l2vpn_if_head, &nl2vpn->if_tree, nlif); break; case IMSG_RECONF_L2VPN_PW: @@ -612,7 +605,6 @@ lde_dispatch_parent(struct thread *thread) fatal(NULL); memcpy(npw, imsg.data, sizeof(struct l2vpn_pw)); - npw->l2vpn = nl2vpn; RB_INSERT(l2vpn_pw_head, &nl2vpn->pw_tree, npw); break; case IMSG_RECONF_L2VPN_IPW: @@ -620,11 +612,11 @@ lde_dispatch_parent(struct thread *thread) fatal(NULL); memcpy(npw, imsg.data, sizeof(struct l2vpn_pw)); - npw->l2vpn = nl2vpn; RB_INSERT(l2vpn_pw_head, &nl2vpn->pw_inactive_tree, npw); break; case IMSG_RECONF_END: merge_config(ldeconf, nconf); + ldp_clear_config(nconf); nconf = NULL; break; case IMSG_DEBUG_UPDATE: diff --git a/ldpd/ldp_vty_conf.c b/ldpd/ldp_vty_conf.c index 4c6cfcd4a3..e4fc7b0054 100644 --- a/ldpd/ldp_vty_conf.c +++ b/ldpd/ldp_vty_conf.c @@ -36,17 +36,11 @@ static void ldp_af_iface_config_write(struct vty *, int); static void ldp_af_config_write(struct vty *, int, struct ldpd_conf *, struct ldpd_af_conf *); static void ldp_l2vpn_pw_config_write(struct vty *, struct l2vpn_pw *); -static void ldp_vty_push_node(struct vty *, int, void *); -static void *ldp_vty_get_node(struct vty *, void *, int); static int ldp_vty_get_af(struct vty *); static int ldp_iface_is_configured(struct ldpd_conf *, const char *); static int ldp_vty_nbr_session_holdtime(struct vty *, struct vty_arg *[]); static int ldp_vty_af_session_holdtime(struct vty *, struct vty_arg *[]); -static struct iface *vty_iface; -static struct l2vpn *vty_l2vpn; -static struct l2vpn_pw *vty_pw; - struct cmd_node ldp_node = { LDP_NODE, @@ -391,94 +385,6 @@ ldp_l2vpn_config_write(struct vty *vty) return (0); } -void -ldp_vty_push_node(struct vty *vty, int node, void *ptr) -{ - if (global.sighup) { - switch (node) { - case LDP_IPV4_IFACE_NODE: - case LDP_IPV6_IFACE_NODE: - vty_iface = ptr; - break; - case LDP_L2VPN_NODE: - vty_l2vpn = ptr; - break; - case LDP_PSEUDOWIRE_NODE: - vty_pw = ptr; - break; - default: - fatalx("ldp_vty_push_node: unexpected node"); - } - vty->node = node; - return; - } - - switch (node) { - case LDP_IPV4_IFACE_NODE: - case LDP_IPV6_IFACE_NODE: - VTY_PUSH_CONTEXT(node, (struct iface *)ptr); - break; - case LDP_L2VPN_NODE: - VTY_PUSH_CONTEXT(node, (struct l2vpn *)ptr); - break; - case LDP_PSEUDOWIRE_NODE: - VTY_PUSH_CONTEXT_SUB(node, (struct l2vpn_pw *)ptr); - break; - default: - fatalx("ldp_vty_push_node: unexpected node"); - } -} - -void * -ldp_vty_get_node(struct vty *vty, void *parent, int node) -{ - struct iface *iface; - struct l2vpn *l2vpn; - struct l2vpn_pw *pw; - - if (global.sighup) { - switch (node) { - case LDP_IPV4_IFACE_NODE: - case LDP_IPV6_IFACE_NODE: - return (vty_iface); - case LDP_L2VPN_NODE: - return (vty_l2vpn); - case LDP_PSEUDOWIRE_NODE: - return (vty_pw); - default: - fatalx("ldp_vty_get_node: unexpected node"); - } - } - - /* - * Since VTY_GET_CONTEXT() returns a pointer to an element of ldpd_conf, - * we have to find the equivalent element inside vty_conf (which should - * always exist as vty_conf is a duplicate of ldpd_conf). - */ - switch (node) { - case LDP_IPV4_IFACE_NODE: - case LDP_IPV6_IFACE_NODE: - iface = VTY_GET_CONTEXT(iface); - if (iface) - return (if_lookup_name(vty_conf, iface->name)); - break; - case LDP_L2VPN_NODE: - l2vpn = VTY_GET_CONTEXT(l2vpn); - if (l2vpn) - return (l2vpn_find(vty_conf, l2vpn->name)); - break; - case LDP_PSEUDOWIRE_NODE: - pw = VTY_GET_CONTEXT_SUB(l2vpn_pw); - if (pw) - return (l2vpn_pw_find(parent, pw->ifname)); - break; - default: - fatalx("ldp_vty_get_node: unexpected node"); - } - - return (NULL); -} - static int ldp_vty_get_af(struct vty *vty) { @@ -656,7 +562,7 @@ ldp_vty_disc_holdtime(struct vty *vty, struct vty_arg *args[]) case LDP_IPV4_IFACE_NODE: case LDP_IPV6_IFACE_NODE: af = ldp_vty_get_af(vty); - iface = ldp_vty_get_node(vty, NULL, vty->node); + iface = VTY_GET_CONTEXT(iface); VTY_CHECK_CONTEXT(iface); ia = iface_af_get(iface, af); @@ -664,6 +570,7 @@ ldp_vty_disc_holdtime(struct vty *vty, struct vty_arg *args[]) ia->hello_holdtime = 0; else ia->hello_holdtime = secs; + ldp_reload(vty_conf); break; default: @@ -756,7 +663,7 @@ ldp_vty_disc_interval(struct vty *vty, struct vty_arg *args[]) case LDP_IPV4_IFACE_NODE: case LDP_IPV6_IFACE_NODE: af = ldp_vty_get_af(vty); - iface = ldp_vty_get_node(vty, NULL, vty->node); + iface = VTY_GET_CONTEXT(iface); VTY_CHECK_CONTEXT(iface); ia = iface_af_get(iface, af); @@ -764,6 +671,7 @@ ldp_vty_disc_interval(struct vty *vty, struct vty_arg *args[]) ia->hello_interval = 0; else ia->hello_interval = secs; + ldp_reload(vty_conf); break; default: @@ -825,14 +733,14 @@ ldp_vty_nbr_session_holdtime(struct vty *vty, struct vty_arg *args[]) return (CMD_WARNING); } - nbrp = nbr_params_find(vty_conf, lsr_id); - secs = strtol(seconds_str, &ep, 10); if (*ep != '\0' || secs < MIN_KEEPALIVE || secs > MAX_KEEPALIVE) { vty_out(vty, "%% Invalid holdtime%s", VTY_NEWLINE); return (CMD_SUCCESS); } + nbrp = nbr_params_find(vty_conf, lsr_id); + if (disable) { if (nbrp == NULL) return (CMD_SUCCESS); @@ -843,6 +751,7 @@ ldp_vty_nbr_session_holdtime(struct vty *vty, struct vty_arg *args[]) if (nbrp == NULL) { nbrp = nbr_params_new(lsr_id); RB_INSERT(nbrp_head, &vty_conf->nbrp_tree, nbrp); + QOBJ_REG(nbrp, nbr_params); } else if (nbrp->keepalive == secs) return (CMD_SUCCESS); @@ -927,7 +836,9 @@ ldp_vty_interface(struct vty *vty, struct vty_arg *args[]) ia->enabled = 0; ia->hello_holdtime = 0; ia->hello_interval = 0; + ldp_reload(vty_conf); + return (CMD_SUCCESS); } @@ -942,6 +853,8 @@ ldp_vty_interface(struct vty *vty, struct vty_arg *args[]) ia = iface_af_get(iface, af); ia->enabled = 1; RB_INSERT(iface_head, &vty_conf->iface_tree, iface); + QOBJ_REG(iface, iface); + ldp_reload(vty_conf); } else { ia = iface_af_get(iface, af); @@ -953,10 +866,10 @@ ldp_vty_interface(struct vty *vty, struct vty_arg *args[]) switch (af) { case AF_INET: - ldp_vty_push_node(vty, LDP_IPV4_IFACE_NODE, iface); + VTY_PUSH_CONTEXT(LDP_IPV4_IFACE_NODE, iface); break; case AF_INET6: - ldp_vty_push_node(vty, LDP_IPV6_IFACE_NODE, iface); + VTY_PUSH_CONTEXT(LDP_IPV6_IFACE_NODE, iface); break; default: break; @@ -1024,9 +937,12 @@ ldp_vty_neighbor_targeted(struct vty *vty, struct vty_arg *args[]) if (tnbr == NULL) return (CMD_SUCCESS); + QOBJ_UNREG(tnbr); RB_REMOVE(tnbr_head, &vty_conf->tnbr_tree, tnbr); free(tnbr); + ldp_reload(vty_conf); + return (CMD_SUCCESS); } @@ -1036,6 +952,7 @@ ldp_vty_neighbor_targeted(struct vty *vty, struct vty_arg *args[]) tnbr = tnbr_new(af, &addr); tnbr->flags |= F_TNBR_CONFIGURED; RB_INSERT(tnbr_head, &vty_conf->tnbr_tree, tnbr); + QOBJ_REG(tnbr, tnbr); ldp_reload(vty_conf); @@ -1290,6 +1207,7 @@ ldp_vty_neighbor_password(struct vty *vty, struct vty_arg *args[]) if (nbrp == NULL) { nbrp = nbr_params_new(lsr_id); RB_INSERT(nbrp_head, &vty_conf->nbrp_tree, nbrp); + QOBJ_REG(nbrp, nbr_params); } else if (nbrp->auth.method == AUTH_MD5SIG && strcmp(nbrp->auth.md5key, password_str) == 0) return (CMD_SUCCESS); @@ -1350,6 +1268,7 @@ ldp_vty_neighbor_ttl_security(struct vty *vty, struct vty_arg *args[]) if (nbrp == NULL) { nbrp = nbr_params_new(lsr_id); RB_INSERT(nbrp_head, &vty_conf->nbrp_tree, nbrp); + QOBJ_REG(nbrp, nbr_params); } nbrp->flags |= F_NBRP_GTSM; @@ -1371,6 +1290,8 @@ int ldp_vty_l2vpn(struct vty *vty, struct vty_arg *args[]) { struct l2vpn *l2vpn; + struct l2vpn_if *lif; + struct l2vpn_pw *pw; const char *name_str; int disable; @@ -1383,23 +1304,34 @@ ldp_vty_l2vpn(struct vty *vty, struct vty_arg *args[]) if (l2vpn == NULL) return (CMD_SUCCESS); + RB_FOREACH(lif, l2vpn_if_head, &l2vpn->if_tree) + QOBJ_UNREG(lif); + RB_FOREACH(pw, l2vpn_pw_head, &l2vpn->pw_tree) + QOBJ_UNREG(pw); + RB_FOREACH(pw, l2vpn_pw_head, &l2vpn->pw_inactive_tree) + QOBJ_UNREG(pw); + QOBJ_UNREG(l2vpn); RB_REMOVE(l2vpn_head, &vty_conf->l2vpn_tree, l2vpn); l2vpn_del(l2vpn); + ldp_reload(vty_conf); + return (CMD_SUCCESS); } if (l2vpn) { - ldp_vty_push_node(vty, LDP_L2VPN_NODE, l2vpn); + VTY_PUSH_CONTEXT(LDP_L2VPN_NODE, l2vpn); return (CMD_SUCCESS); } l2vpn = l2vpn_new(name_str); l2vpn->type = L2VPN_TYPE_VPLS; RB_INSERT(l2vpn_head, &vty_conf->l2vpn_tree, l2vpn); + QOBJ_REG(l2vpn, l2vpn); + + VTY_PUSH_CONTEXT(LDP_L2VPN_NODE, l2vpn); ldp_reload(vty_conf); - ldp_vty_push_node(vty, LDP_L2VPN_NODE, l2vpn); return (CMD_SUCCESS); } @@ -1407,16 +1339,13 @@ ldp_vty_l2vpn(struct vty *vty, struct vty_arg *args[]) int ldp_vty_l2vpn_bridge(struct vty *vty, struct vty_arg *args[]) { - struct l2vpn *l2vpn; + VTY_DECLVAR_CONTEXT(l2vpn, l2vpn); const char *ifname; int disable; disable = (vty_get_arg_value(args, "no")) ? 1 : 0; ifname = vty_get_arg_value(args, "ifname"); - l2vpn = ldp_vty_get_node(vty, NULL, LDP_L2VPN_NODE); - VTY_CHECK_CONTEXT(l2vpn); - if (disable) memset(l2vpn->br_ifname, 0, sizeof(l2vpn->br_ifname)); else @@ -1430,7 +1359,7 @@ ldp_vty_l2vpn_bridge(struct vty *vty, struct vty_arg *args[]) int ldp_vty_l2vpn_mtu(struct vty *vty, struct vty_arg *args[]) { - struct l2vpn *l2vpn; + VTY_DECLVAR_CONTEXT(l2vpn, l2vpn); char *ep; int mtu; const char *mtu_str; @@ -1445,9 +1374,6 @@ ldp_vty_l2vpn_mtu(struct vty *vty, struct vty_arg *args[]) return (CMD_WARNING); } - l2vpn = ldp_vty_get_node(vty, NULL, LDP_L2VPN_NODE); - VTY_CHECK_CONTEXT(l2vpn); - if (disable) l2vpn->mtu = DEFAULT_L2VPN_MTU; else @@ -1461,7 +1387,7 @@ ldp_vty_l2vpn_mtu(struct vty *vty, struct vty_arg *args[]) int ldp_vty_l2vpn_pwtype(struct vty *vty, struct vty_arg *args[]) { - struct l2vpn *l2vpn; + VTY_DECLVAR_CONTEXT(l2vpn, l2vpn); int pw_type; const char *type_str; int disable; @@ -1474,9 +1400,6 @@ ldp_vty_l2vpn_pwtype(struct vty *vty, struct vty_arg *args[]) else pw_type = PW_TYPE_ETHERNET_TAGGED; - l2vpn = ldp_vty_get_node(vty, NULL, LDP_L2VPN_NODE); - VTY_CHECK_CONTEXT(l2vpn); - if (disable) l2vpn->pw_type = DEFAULT_PW_TYPE; else @@ -1490,7 +1413,7 @@ ldp_vty_l2vpn_pwtype(struct vty *vty, struct vty_arg *args[]) int ldp_vty_l2vpn_interface(struct vty *vty, struct vty_arg *args[]) { - struct l2vpn *l2vpn; + VTY_DECLVAR_CONTEXT(l2vpn, l2vpn); struct l2vpn_if *lif; const char *ifname; int disable; @@ -1498,17 +1421,18 @@ ldp_vty_l2vpn_interface(struct vty *vty, struct vty_arg *args[]) disable = (vty_get_arg_value(args, "no")) ? 1 : 0; ifname = vty_get_arg_value(args, "ifname"); - l2vpn = ldp_vty_get_node(vty, NULL, LDP_L2VPN_NODE); - VTY_CHECK_CONTEXT(l2vpn); lif = l2vpn_if_find(l2vpn, ifname); if (disable) { if (lif == NULL) return (CMD_SUCCESS); + QOBJ_UNREG(lif); RB_REMOVE(l2vpn_if_head, &l2vpn->if_tree, lif); free(lif); + ldp_reload(vty_conf); + return (CMD_SUCCESS); } @@ -1522,6 +1446,7 @@ ldp_vty_l2vpn_interface(struct vty *vty, struct vty_arg *args[]) lif = l2vpn_if_new(l2vpn, ifname); RB_INSERT(l2vpn_if_head, &l2vpn->if_tree, lif); + QOBJ_REG(lif, l2vpn_if); ldp_reload(vty_conf); @@ -1531,7 +1456,7 @@ ldp_vty_l2vpn_interface(struct vty *vty, struct vty_arg *args[]) int ldp_vty_l2vpn_pseudowire(struct vty *vty, struct vty_arg *args[]) { - struct l2vpn *l2vpn; + VTY_DECLVAR_CONTEXT(l2vpn, l2vpn); struct l2vpn_pw *pw; const char *ifname; int disable; @@ -1539,22 +1464,26 @@ ldp_vty_l2vpn_pseudowire(struct vty *vty, struct vty_arg *args[]) disable = (vty_get_arg_value(args, "no")) ? 1 : 0; ifname = vty_get_arg_value(args, "ifname"); - l2vpn = ldp_vty_get_node(vty, NULL, LDP_L2VPN_NODE); - VTY_CHECK_CONTEXT(l2vpn); pw = l2vpn_pw_find(l2vpn, ifname); if (disable) { if (pw == NULL) return (CMD_SUCCESS); - RB_REMOVE(l2vpn_pw_head, &l2vpn->pw_inactive_tree, pw); + QOBJ_UNREG(pw); + if (pw->lsr_id.s_addr == INADDR_ANY || pw->pwid == 0) + RB_REMOVE(l2vpn_pw_head, &l2vpn->pw_inactive_tree, pw); + else + RB_REMOVE(l2vpn_pw_head, &l2vpn->pw_tree, pw); free(pw); + ldp_reload(vty_conf); + return (CMD_SUCCESS); } if (pw) { - ldp_vty_push_node(vty, LDP_PSEUDOWIRE_NODE, pw); + VTY_PUSH_CONTEXT_SUB(LDP_PSEUDOWIRE_NODE, pw); return (CMD_SUCCESS); } @@ -1566,9 +1495,11 @@ ldp_vty_l2vpn_pseudowire(struct vty *vty, struct vty_arg *args[]) pw = l2vpn_pw_new(l2vpn, ifname); pw->flags = F_PW_STATUSTLV_CONF|F_PW_CWORD_CONF; RB_INSERT(l2vpn_pw_head, &l2vpn->pw_inactive_tree, pw); + QOBJ_REG(pw, l2vpn_pw); + + VTY_PUSH_CONTEXT_SUB(LDP_PSEUDOWIRE_NODE, pw); ldp_reload(vty_conf); - ldp_vty_push_node(vty, LDP_PSEUDOWIRE_NODE, pw); return (CMD_SUCCESS); } @@ -1576,19 +1507,13 @@ ldp_vty_l2vpn_pseudowire(struct vty *vty, struct vty_arg *args[]) int ldp_vty_l2vpn_pw_cword(struct vty *vty, struct vty_arg *args[]) { - struct l2vpn *l2vpn; - struct l2vpn_pw *pw; + VTY_DECLVAR_CONTEXT_SUB(l2vpn_pw, pw); const char *preference_str; int disable; disable = (vty_get_arg_value(args, "no")) ? 1 : 0; preference_str = vty_get_arg_value(args, "preference"); - l2vpn = ldp_vty_get_node(vty, NULL, LDP_L2VPN_NODE); - VTY_CHECK_CONTEXT(l2vpn); - pw = ldp_vty_get_node(vty, l2vpn, LDP_PSEUDOWIRE_NODE); - VTY_CHECK_CONTEXT(pw); - if (disable) pw->flags |= F_PW_CWORD_CONF; else { @@ -1606,8 +1531,7 @@ ldp_vty_l2vpn_pw_cword(struct vty *vty, struct vty_arg *args[]) int ldp_vty_l2vpn_pw_nbr_addr(struct vty *vty, struct vty_arg *args[]) { - struct l2vpn *l2vpn; - struct l2vpn_pw *pw; + VTY_DECLVAR_CONTEXT_SUB(l2vpn_pw, pw); int af; union ldpd_addr addr; const char *addr_str; @@ -1622,11 +1546,6 @@ ldp_vty_l2vpn_pw_nbr_addr(struct vty *vty, struct vty_arg *args[]) return (CMD_WARNING); } - l2vpn = ldp_vty_get_node(vty, NULL, LDP_L2VPN_NODE); - VTY_CHECK_CONTEXT(l2vpn); - pw = ldp_vty_get_node(vty, l2vpn, LDP_PSEUDOWIRE_NODE); - VTY_CHECK_CONTEXT(pw); - if (disable) { pw->af = AF_UNSPEC; memset(&pw->addr, 0, sizeof(pw->addr)); @@ -1645,8 +1564,7 @@ ldp_vty_l2vpn_pw_nbr_addr(struct vty *vty, struct vty_arg *args[]) int ldp_vty_l2vpn_pw_nbr_id(struct vty *vty, struct vty_arg *args[]) { - struct l2vpn *l2vpn; - struct l2vpn_pw *pw; + VTY_DECLVAR_CONTEXT_SUB(l2vpn_pw, pw); struct in_addr lsr_id; const char *lsr_id_str; int disable; @@ -1660,11 +1578,6 @@ ldp_vty_l2vpn_pw_nbr_id(struct vty *vty, struct vty_arg *args[]) return (CMD_WARNING); } - l2vpn = ldp_vty_get_node(vty, NULL, LDP_L2VPN_NODE); - VTY_CHECK_CONTEXT(l2vpn); - pw = ldp_vty_get_node(vty, l2vpn, LDP_PSEUDOWIRE_NODE); - VTY_CHECK_CONTEXT(pw); - if (disable) pw->lsr_id.s_addr = INADDR_ANY; else @@ -1678,8 +1591,7 @@ ldp_vty_l2vpn_pw_nbr_id(struct vty *vty, struct vty_arg *args[]) int ldp_vty_l2vpn_pw_pwid(struct vty *vty, struct vty_arg *args[]) { - struct l2vpn *l2vpn; - struct l2vpn_pw *pw; + VTY_DECLVAR_CONTEXT_SUB(l2vpn_pw, pw); char *ep; uint32_t pwid; const char *pwid_str; @@ -1694,11 +1606,6 @@ ldp_vty_l2vpn_pw_pwid(struct vty *vty, struct vty_arg *args[]) return (CMD_WARNING); } - l2vpn = ldp_vty_get_node(vty, NULL, LDP_L2VPN_NODE); - VTY_CHECK_CONTEXT(l2vpn); - pw = ldp_vty_get_node(vty, l2vpn, LDP_PSEUDOWIRE_NODE); - VTY_CHECK_CONTEXT(pw); - if (disable) pw->pwid = 0; else @@ -1712,17 +1619,11 @@ ldp_vty_l2vpn_pw_pwid(struct vty *vty, struct vty_arg *args[]) int ldp_vty_l2vpn_pw_pwstatus(struct vty *vty, struct vty_arg *args[]) { - struct l2vpn *l2vpn; - struct l2vpn_pw *pw; + VTY_DECLVAR_CONTEXT_SUB(l2vpn_pw, pw); int disable; disable = (vty_get_arg_value(args, "no")) ? 1 : 0; - l2vpn = ldp_vty_get_node(vty, NULL, LDP_L2VPN_NODE); - VTY_CHECK_CONTEXT(l2vpn); - pw = ldp_vty_get_node(vty, l2vpn, LDP_PSEUDOWIRE_NODE); - VTY_CHECK_CONTEXT(pw); - if (disable) pw->flags |= F_PW_STATUSTLV_CONF; else @@ -1744,12 +1645,14 @@ iface_new_api(struct ldpd_conf *conf, const char *name) iface = if_new(name); RB_INSERT(iface_head, &conf->iface_tree, iface); + QOBJ_REG(iface, iface); return (iface); } void iface_del_api(struct ldpd_conf *conf, struct iface *iface) { + QOBJ_UNREG(iface); RB_REMOVE(iface_head, &conf->iface_tree, iface); free(iface); } @@ -1768,12 +1671,14 @@ tnbr_new_api(struct ldpd_conf *conf, int af, union ldpd_addr *addr) tnbr = tnbr_new(af, addr); tnbr->flags |= F_TNBR_CONFIGURED; RB_INSERT(tnbr_head, &conf->tnbr_tree, tnbr); + QOBJ_REG(tnbr, tnbr); return (tnbr); } void tnbr_del_api(struct ldpd_conf *conf, struct tnbr *tnbr) { + QOBJ_UNREG(tnbr); RB_REMOVE(tnbr_head, &conf->tnbr_tree, tnbr); free(tnbr); } @@ -1788,12 +1693,14 @@ nbrp_new_api(struct ldpd_conf *conf, struct in_addr lsr_id) nbrp = nbr_params_new(lsr_id); RB_INSERT(nbrp_head, &conf->nbrp_tree, nbrp); + QOBJ_REG(nbrp, nbr_params); return (nbrp); } void nbrp_del_api(struct ldpd_conf *conf, struct nbr_params *nbrp) { + QOBJ_UNREG(nbrp); RB_REMOVE(nbrp_head, &conf->nbrp_tree, nbrp); free(nbrp); } @@ -1809,6 +1716,7 @@ l2vpn_new_api(struct ldpd_conf *conf, const char *name) l2vpn = l2vpn_new(name); l2vpn->type = L2VPN_TYPE_VPLS; RB_INSERT(l2vpn_head, &conf->l2vpn_tree, l2vpn); + QOBJ_REG(l2vpn, l2vpn); return (l2vpn); } @@ -1819,17 +1727,21 @@ l2vpn_del_api(struct ldpd_conf *conf, struct l2vpn *l2vpn) struct l2vpn_pw *pw; while ((lif = RB_ROOT(&l2vpn->if_tree)) != NULL) { + QOBJ_UNREG(lif); RB_REMOVE(l2vpn_if_head, &l2vpn->if_tree, lif); free(lif); } while ((pw = RB_ROOT(&l2vpn->pw_tree)) != NULL) { + QOBJ_UNREG(pw); RB_REMOVE(l2vpn_pw_head, &l2vpn->pw_tree, pw); free(pw); } while ((pw = RB_ROOT(&l2vpn->pw_inactive_tree)) != NULL) { + QOBJ_UNREG(pw); RB_REMOVE(l2vpn_pw_head, &l2vpn->pw_inactive_tree, pw); free(pw); } + QOBJ_UNREG(l2vpn); RB_REMOVE(l2vpn_head, &conf->l2vpn_tree, l2vpn); free(l2vpn); } @@ -1845,12 +1757,14 @@ l2vpn_if_new_api(struct ldpd_conf *conf, struct l2vpn *l2vpn, lif = l2vpn_if_new(l2vpn, ifname); RB_INSERT(l2vpn_if_head, &l2vpn->if_tree, lif); + QOBJ_REG(lif, l2vpn_if); return (lif); } void l2vpn_if_del_api(struct l2vpn *l2vpn, struct l2vpn_if *lif) { + QOBJ_UNREG(lif); RB_REMOVE(l2vpn_if_head, &l2vpn->if_tree, lif); free(lif); } @@ -1867,12 +1781,14 @@ l2vpn_pw_new_api(struct ldpd_conf *conf, struct l2vpn *l2vpn, pw = l2vpn_pw_new(l2vpn, ifname); pw->flags = F_PW_STATUSTLV_CONF|F_PW_CWORD_CONF; RB_INSERT(l2vpn_pw_head, &l2vpn->pw_inactive_tree, pw); + QOBJ_REG(pw, l2vpn_pw); return (pw); } void l2vpn_pw_del_api(struct l2vpn *l2vpn, struct l2vpn_pw *pw) { + QOBJ_UNREG(pw); RB_REMOVE(l2vpn_pw_head, &l2vpn->pw_inactive_tree, pw); free(pw); } diff --git a/ldpd/ldpd.c b/ldpd/ldpd.c index ea9317c41d..9729499e28 100644 --- a/ldpd/ldpd.c +++ b/ldpd/ldpd.c @@ -56,6 +56,7 @@ static int main_imsg_send_config(struct ldpd_conf *); static void ldp_config_normalize(struct ldpd_conf *); static void ldp_config_reset_main(struct ldpd_conf *); static void ldp_config_reset_af(struct ldpd_conf *, int); +static void ldp_config_reset_l2vpns(struct ldpd_conf *); static void merge_global(struct ldpd_conf *, struct ldpd_conf *); static void merge_af(int, struct ldpd_af_conf *, struct ldpd_af_conf *); @@ -131,9 +132,8 @@ sighup(void) log_info("SIGHUP received"); /* reset vty_conf */ - ldp_clear_config(vty_conf); - vty_conf = config_new_empty(); ldp_config_reset_main(vty_conf); + ldp_config_reset_l2vpns(vty_conf); /* read configuration file without applying any changes */ global.sighup = 1; @@ -343,14 +343,15 @@ main(int argc, char *argv[]) /* create base configuration with sane defaults */ ldpd_conf = config_new_empty(); ldp_config_reset_main(ldpd_conf); - QOBJ_REG(ldpd_conf, ldpd_conf); /* * Create vty_conf as a duplicate of the main configuration. All * configuration requests (e.g. CLI) act on vty_conf and then call * ldp_reload() to merge the changes into ldpd_conf. */ - vty_conf = ldp_dup_config(ldpd_conf); + vty_conf = config_new_empty(); + ldp_config_reset_main(vty_conf); + QOBJ_REG(vty_conf, ldpd_conf); /* read configuration file and daemonize */ frr_config_fork(); @@ -415,7 +416,11 @@ ldpd_shutdown(void) close(iev_lde->ibuf.fd); config_clear(ldpd_conf); - QOBJ_UNREG(ldpd_conf); + + ldp_config_reset_main(vty_conf); + ldp_config_reset_l2vpns(vty_conf); + QOBJ_UNREG(vty_conf); + free(vty_conf); log_debug("waiting for children to terminate"); do { @@ -992,8 +997,6 @@ ldp_reload(struct ldpd_conf *xconf) merge_config(ldpd_conf, xconf); - vty_conf = ldp_dup_config(ldpd_conf); - return (0); } @@ -1017,6 +1020,7 @@ ldp_config_normalize(struct ldpd_conf *xconf) if (iface->ipv4.enabled || iface->ipv6.enabled) continue; + QOBJ_UNREG(iface); RB_REMOVE(iface_head, &vty_conf->iface_tree, iface); free(iface); } @@ -1027,6 +1031,7 @@ ldp_config_normalize(struct ldpd_conf *xconf) if (nbrp->auth.method != AUTH_NONE) continue; + QOBJ_UNREG(nbrp); RB_REMOVE(nbrp_head, &vty_conf->nbrp_tree, nbrp); free(nbrp); } @@ -1066,11 +1071,13 @@ ldp_config_reset_main(struct ldpd_conf *conf) struct nbr_params *nbrp; while ((iface = RB_ROOT(&conf->iface_tree)) != NULL) { + QOBJ_UNREG(iface); RB_REMOVE(iface_head, &conf->iface_tree, iface); free(iface); } while ((nbrp = RB_ROOT(&conf->nbrp_tree)) != NULL) { + QOBJ_UNREG(nbrp); RB_REMOVE(nbrp_head, &conf->nbrp_tree, nbrp); free(nbrp); } @@ -1103,6 +1110,7 @@ ldp_config_reset_af(struct ldpd_conf *conf, int af) if (tnbr->af != af) continue; + QOBJ_UNREG(tnbr); RB_REMOVE(tnbr_head, &conf->tnbr_tree, tnbr); free(tnbr); } @@ -1117,70 +1125,33 @@ ldp_config_reset_af(struct ldpd_conf *conf, int af) af_conf->flags = 0; } -struct ldpd_conf * -ldp_dup_config(struct ldpd_conf *conf) +static void +ldp_config_reset_l2vpns(struct ldpd_conf *conf) { - struct ldpd_conf *xconf; - struct iface *iface, *xi; - struct tnbr *tnbr, *xt; - struct nbr_params *nbrp, *xn; - struct l2vpn *l2vpn, *xl; - struct l2vpn_if *lif, *xf; - struct l2vpn_pw *pw, *xp; + struct l2vpn *l2vpn; + struct l2vpn_if *lif; + struct l2vpn_pw *pw; -#define COPY(a, b) do { \ - a = calloc(1, sizeof(*a)); \ - if (a == NULL) \ - fatal(__func__); \ - *a = *b; \ - } while (0) - - COPY(xconf, conf); - RB_INIT(&xconf->iface_tree); - RB_INIT(&xconf->tnbr_tree); - RB_INIT(&xconf->nbrp_tree); - RB_INIT(&xconf->l2vpn_tree); - - RB_FOREACH(iface, iface_head, &conf->iface_tree) { - COPY(xi, iface); - xi->ipv4.iface = xi; - xi->ipv6.iface = xi; - RB_INSERT(iface_head, &xconf->iface_tree, xi); - } - RB_FOREACH(tnbr, tnbr_head, &conf->tnbr_tree) { - COPY(xt, tnbr); - RB_INSERT(tnbr_head, &xconf->tnbr_tree, xt); - } - RB_FOREACH(nbrp, nbrp_head, &conf->nbrp_tree) { - COPY(xn, nbrp); - RB_INSERT(nbrp_head, &xconf->nbrp_tree, xn); - } - RB_FOREACH(l2vpn, l2vpn_head, &conf->l2vpn_tree) { - COPY(xl, l2vpn); - RB_INIT(&xl->if_tree); - RB_INIT(&xl->pw_tree); - RB_INIT(&xl->pw_inactive_tree); - RB_INSERT(l2vpn_head, &xconf->l2vpn_tree, xl); - - RB_FOREACH(lif, l2vpn_if_head, &l2vpn->if_tree) { - COPY(xf, lif); - xf->l2vpn = xl; - RB_INSERT(l2vpn_if_head, &xl->if_tree, xf); + while ((l2vpn = RB_ROOT(&conf->l2vpn_tree)) != NULL) { + while ((lif = RB_ROOT(&l2vpn->if_tree)) != NULL) { + QOBJ_UNREG(lif); + RB_REMOVE(l2vpn_if_head, &l2vpn->if_tree, lif); + free(lif); } - RB_FOREACH(pw, l2vpn_pw_head, &l2vpn->pw_tree) { - COPY(xp, pw); - xp->l2vpn = xl; - RB_INSERT(l2vpn_pw_head, &xl->pw_tree, xp); + while ((pw = RB_ROOT(&l2vpn->pw_tree)) != NULL) { + QOBJ_UNREG(pw); + RB_REMOVE(l2vpn_pw_head, &l2vpn->pw_tree, pw); + free(pw); } - RB_FOREACH(pw, l2vpn_pw_head, &l2vpn->pw_inactive_tree) { - COPY(xp, pw); - xp->l2vpn = xl; - RB_INSERT(l2vpn_pw_head, &xl->pw_inactive_tree, xp); + while ((pw = RB_ROOT(&l2vpn->pw_inactive_tree)) != NULL) { + QOBJ_UNREG(pw); + RB_REMOVE(l2vpn_pw_head, &l2vpn->pw_inactive_tree, pw); + free(pw); } + QOBJ_UNREG(l2vpn); + RB_REMOVE(l2vpn_head, &conf->l2vpn_tree, l2vpn); + free(l2vpn); } -#undef COPY - - return (xconf); } void @@ -1211,6 +1182,13 @@ ldp_clear_config(struct ldpd_conf *xconf) free(xconf); } +#define COPY(a, b) do { \ + a = malloc(sizeof(*a)); \ + if (a == NULL) \ + fatal(__func__); \ + *a = *b; \ + } while (0) + void merge_config(struct ldpd_conf *conf, struct ldpd_conf *xconf) { @@ -1221,7 +1199,6 @@ merge_config(struct ldpd_conf *conf, struct ldpd_conf *xconf) merge_tnbrs(conf, xconf); merge_nbrps(conf, xconf); merge_l2vpns(conf, xconf); - free(xconf); } static void @@ -1365,31 +1342,34 @@ merge_ifaces(struct ldpd_conf *conf, struct ldpd_conf *xconf) RB_FOREACH_SAFE(iface, iface_head, &conf->iface_tree, itmp) { /* find deleted interfaces */ if ((xi = if_lookup_name(xconf, iface->name)) == NULL) { - RB_REMOVE(iface_head, &conf->iface_tree, iface); - switch (ldpd_process) { - case PROC_LDE_ENGINE: - break; case PROC_LDP_ENGINE: - if_exit(iface); + ldpe_if_exit(iface); break; + case PROC_LDE_ENGINE: case PROC_MAIN: - QOBJ_UNREG (iface); break; } + RB_REMOVE(iface_head, &conf->iface_tree, iface); free(iface); } } RB_FOREACH_SAFE(xi, iface_head, &xconf->iface_tree, itmp) { /* find new interfaces */ if ((iface = if_lookup_name(conf, xi->name)) == NULL) { - RB_REMOVE(iface_head, &xconf->iface_tree, xi); - RB_INSERT(iface_head, &conf->iface_tree, xi); + COPY(iface, xi); + RB_INSERT(iface_head, &conf->iface_tree, iface); - if (ldpd_process == PROC_MAIN) { - QOBJ_REG (xi, iface); + switch (ldpd_process) { + case PROC_LDP_ENGINE: + ldpe_if_init(iface); + break; + case PROC_LDE_ENGINE: + break; + case PROC_MAIN: /* resend addresses to activate new interfaces */ - kif_redistribute(xi->name); + kif_redistribute(iface->name); + break; } continue; } @@ -1397,8 +1377,6 @@ merge_ifaces(struct ldpd_conf *conf, struct ldpd_conf *xconf) /* update existing interfaces */ merge_iface_af(&iface->ipv4, &xi->ipv4); merge_iface_af(&iface->ipv6, &xi->ipv6); - RB_REMOVE(iface_head, &xconf->iface_tree, xi); - free(xi); } } @@ -1426,17 +1404,13 @@ merge_tnbrs(struct ldpd_conf *conf, struct ldpd_conf *xconf) /* find deleted tnbrs */ if ((xt = tnbr_find(xconf, tnbr->af, &tnbr->addr)) == NULL) { switch (ldpd_process) { - case PROC_LDE_ENGINE: - RB_REMOVE(tnbr_head, &conf->tnbr_tree, tnbr); - free(tnbr); - break; case PROC_LDP_ENGINE: tnbr->flags &= ~F_TNBR_CONFIGURED; tnbr_check(conf, tnbr); break; + case PROC_LDE_ENGINE: case PROC_MAIN: RB_REMOVE(tnbr_head, &conf->tnbr_tree, tnbr); - QOBJ_UNREG (tnbr); free(tnbr); break; } @@ -1445,17 +1419,15 @@ merge_tnbrs(struct ldpd_conf *conf, struct ldpd_conf *xconf) RB_FOREACH_SAFE(xt, tnbr_head, &xconf->tnbr_tree, ttmp) { /* find new tnbrs */ if ((tnbr = tnbr_find(conf, xt->af, &xt->addr)) == NULL) { - RB_REMOVE(tnbr_head, &xconf->tnbr_tree, xt); - RB_INSERT(tnbr_head, &conf->tnbr_tree, xt); + COPY(tnbr, xt); + RB_INSERT(tnbr_head, &conf->tnbr_tree, tnbr); switch (ldpd_process) { - case PROC_LDE_ENGINE: - break; case PROC_LDP_ENGINE: - tnbr_update(xt); + tnbr_update(tnbr); break; + case PROC_LDE_ENGINE: case PROC_MAIN: - QOBJ_REG (xt, tnbr); break; } continue; @@ -1464,8 +1436,6 @@ merge_tnbrs(struct ldpd_conf *conf, struct ldpd_conf *xconf) /* update existing tnbrs */ if (!(tnbr->flags & F_TNBR_CONFIGURED)) tnbr->flags |= F_TNBR_CONFIGURED; - RB_REMOVE(tnbr_head, &xconf->tnbr_tree, xt); - free(xt); } } @@ -1480,8 +1450,6 @@ merge_nbrps(struct ldpd_conf *conf, struct ldpd_conf *xconf) /* find deleted nbrps */ if ((xn = nbr_params_find(xconf, nbrp->lsr_id)) == NULL) { switch (ldpd_process) { - case PROC_LDE_ENGINE: - break; case PROC_LDP_ENGINE: nbr = nbr_find_ldpid(nbrp->lsr_id.s_addr); if (nbr) { @@ -1499,8 +1467,8 @@ merge_nbrps(struct ldpd_conf *conf, struct ldpd_conf *xconf) nbr_establish_connection(nbr); } break; + case PROC_LDE_ENGINE: case PROC_MAIN: - QOBJ_UNREG (nbrp); break; } RB_REMOVE(nbrp_head, &conf->nbrp_tree, nbrp); @@ -1510,33 +1478,31 @@ merge_nbrps(struct ldpd_conf *conf, struct ldpd_conf *xconf) RB_FOREACH_SAFE(xn, nbrp_head, &xconf->nbrp_tree, ntmp) { /* find new nbrps */ if ((nbrp = nbr_params_find(conf, xn->lsr_id)) == NULL) { - RB_REMOVE(nbrp_head, &xconf->nbrp_tree, xn); - RB_INSERT(nbrp_head, &conf->nbrp_tree, xn); + COPY(nbrp, xn); + RB_INSERT(nbrp_head, &conf->nbrp_tree, nbrp); switch (ldpd_process) { - case PROC_LDE_ENGINE: - break; case PROC_LDP_ENGINE: - nbr = nbr_find_ldpid(xn->lsr_id.s_addr); + nbr = nbr_find_ldpid(nbrp->lsr_id.s_addr); if (nbr) { session_shutdown(nbr, S_SHUTDOWN, 0, 0); - nbr->auth.method = xn->auth.method; + nbr->auth.method = nbrp->auth.method; #ifdef __OpenBSD__ - if (pfkey_establish(nbr, xn) == -1) + if (pfkey_establish(nbr, nbrp) == -1) fatalx("pfkey setup failed"); #else sock_set_md5sig( (ldp_af_global_get(&global, nbr->af))->ldp_session_socket, nbr->af, &nbr->raddr, - xn->auth.md5key); + nbrp->auth.md5key); #endif if (nbr_session_active_role(nbr)) nbr_establish_connection(nbr); } break; + case PROC_LDE_ENGINE: case PROC_MAIN: - QOBJ_REG (xn, nbr_params); break; } continue; @@ -1581,8 +1547,6 @@ merge_nbrps(struct ldpd_conf *conf, struct ldpd_conf *xconf) nbr_establish_connection(nbr); } } - RB_REMOVE(nbrp_head, &xconf->nbrp_tree, xn); - free(xn); } } @@ -1590,14 +1554,10 @@ static void merge_l2vpns(struct ldpd_conf *conf, struct ldpd_conf *xconf) { struct l2vpn *l2vpn, *ltmp, *xl; - struct l2vpn_if *lif; - struct l2vpn_pw *pw; RB_FOREACH_SAFE(l2vpn, l2vpn_head, &conf->l2vpn_tree, ltmp) { /* find deleted l2vpns */ if ((xl = l2vpn_find(xconf, l2vpn->name)) == NULL) { - RB_REMOVE(l2vpn_head, &conf->l2vpn_tree, l2vpn); - switch (ldpd_process) { case PROC_LDE_ENGINE: l2vpn_exit(l2vpn); @@ -1606,42 +1566,35 @@ merge_l2vpns(struct ldpd_conf *conf, struct ldpd_conf *xconf) ldpe_l2vpn_exit(l2vpn); break; case PROC_MAIN: - RB_FOREACH(lif, l2vpn_if_head, &l2vpn->if_tree) - QOBJ_UNREG (lif); - RB_FOREACH(pw, l2vpn_pw_head, &l2vpn->pw_tree) - QOBJ_UNREG (pw); - RB_FOREACH(pw, l2vpn_pw_head, &l2vpn->pw_inactive_tree) - QOBJ_UNREG (pw); - QOBJ_UNREG (l2vpn); break; } + RB_REMOVE(l2vpn_head, &conf->l2vpn_tree, l2vpn); l2vpn_del(l2vpn); } } RB_FOREACH_SAFE(xl, l2vpn_head, &xconf->l2vpn_tree, ltmp) { /* find new l2vpns */ if ((l2vpn = l2vpn_find(conf, xl->name)) == NULL) { - RB_REMOVE(l2vpn_head, &xconf->l2vpn_tree, xl); - RB_INSERT(l2vpn_head, &conf->l2vpn_tree, xl); + COPY(l2vpn, xl); + RB_INSERT(l2vpn_head, &conf->l2vpn_tree, l2vpn); + RB_INIT(&l2vpn->if_tree); + RB_INIT(&l2vpn->pw_tree); + RB_INIT(&l2vpn->pw_inactive_tree); switch (ldpd_process) { case PROC_LDE_ENGINE: - l2vpn_init(xl); + l2vpn_init(l2vpn); break; case PROC_LDP_ENGINE: - ldpe_l2vpn_init(xl); + ldpe_l2vpn_init(l2vpn); break; case PROC_MAIN: - QOBJ_REG (xl, l2vpn); break; } - continue; } /* update existing l2vpns */ merge_l2vpn(conf, l2vpn, xl); - RB_REMOVE(l2vpn_head, &xconf->l2vpn_tree, xl); - free(xl); } } @@ -1661,8 +1614,6 @@ merge_l2vpn(struct ldpd_conf *xconf, struct l2vpn *l2vpn, struct l2vpn *xl) RB_FOREACH_SAFE(lif, l2vpn_if_head, &l2vpn->if_tree, ftmp) { /* find deleted interfaces */ if ((xf = l2vpn_if_find(xl, lif->ifname)) == NULL) { - if (ldpd_process == PROC_MAIN) - QOBJ_UNREG (lif); RB_REMOVE(l2vpn_if_head, &l2vpn->if_tree, lif); free(lif); } @@ -1670,18 +1621,19 @@ merge_l2vpn(struct ldpd_conf *xconf, struct l2vpn *l2vpn, struct l2vpn *xl) RB_FOREACH_SAFE(xf, l2vpn_if_head, &xl->if_tree, ftmp) { /* find new interfaces */ if ((lif = l2vpn_if_find(l2vpn, xf->ifname)) == NULL) { - RB_REMOVE(l2vpn_if_head, &xl->if_tree, xf); - RB_INSERT(l2vpn_if_head, &l2vpn->if_tree, xf); - xf->l2vpn = l2vpn; - if (ldpd_process == PROC_MAIN) { - QOBJ_REG(xf, l2vpn_if); - kif_redistribute(xf->ifname); - } - continue; - } + COPY(lif, xf); + RB_INSERT(l2vpn_if_head, &l2vpn->if_tree, lif); + lif->l2vpn = l2vpn; - RB_REMOVE(l2vpn_if_head, &xl->if_tree, xf); - free(xf); + switch (ldpd_process) { + case PROC_LDP_ENGINE: + case PROC_LDE_ENGINE: + break; + case PROC_MAIN: + kif_redistribute(lif->ifname); + break; + } + } } /* merge active pseudowires */ @@ -1696,7 +1648,6 @@ merge_l2vpn(struct ldpd_conf *xconf, struct l2vpn *l2vpn, struct l2vpn *xl) ldpe_l2vpn_pw_exit(pw); break; case PROC_MAIN: - QOBJ_UNREG (pw); break; } @@ -1707,20 +1658,19 @@ merge_l2vpn(struct ldpd_conf *xconf, struct l2vpn *l2vpn, struct l2vpn *xl) RB_FOREACH_SAFE(xp, l2vpn_pw_head, &xl->pw_tree, ptmp) { /* find new active pseudowires */ if ((pw = l2vpn_pw_find_active(l2vpn, xp->ifname)) == NULL) { - RB_REMOVE(l2vpn_pw_head, &xl->pw_tree, xp); - RB_INSERT(l2vpn_pw_head, &l2vpn->pw_tree, xp); - xp->l2vpn = l2vpn; + COPY(pw, xp); + RB_INSERT(l2vpn_pw_head, &l2vpn->pw_tree, pw); + pw->l2vpn = l2vpn; switch (ldpd_process) { case PROC_LDE_ENGINE: - l2vpn_pw_init(xp); + l2vpn_pw_init(pw); break; case PROC_LDP_ENGINE: - ldpe_l2vpn_pw_init(xp); + ldpe_l2vpn_pw_init(pw); break; case PROC_MAIN: - QOBJ_REG (xp, l2vpn_pw); - kif_redistribute(xp->ifname); + kif_redistribute(pw->ifname); break; } continue; @@ -1787,9 +1737,6 @@ merge_l2vpn(struct ldpd_conf *xconf, struct l2vpn *l2vpn, struct l2vpn *xl) l2vpn->pw_type = previous_pw_type; l2vpn->mtu = previous_mtu; } - - RB_REMOVE(l2vpn_pw_head, &xl->pw_tree, xp); - free(xp); } /* merge inactive pseudowires */ @@ -1797,20 +1744,23 @@ merge_l2vpn(struct ldpd_conf *xconf, struct l2vpn *l2vpn, struct l2vpn *xl) /* find deleted inactive pseudowires */ if ((xp = l2vpn_pw_find_inactive(xl, pw->ifname)) == NULL) { RB_REMOVE(l2vpn_pw_head, &l2vpn->pw_inactive_tree, pw); - if (ldpd_process == PROC_MAIN) - QOBJ_UNREG (pw); free(pw); } } RB_FOREACH_SAFE(xp, l2vpn_pw_head, &xl->pw_inactive_tree, ptmp) { /* find new inactive pseudowires */ if ((pw = l2vpn_pw_find_inactive(l2vpn, xp->ifname)) == NULL) { - RB_REMOVE(l2vpn_pw_head, &xl->pw_inactive_tree, xp); - RB_INSERT(l2vpn_pw_head, &l2vpn->pw_inactive_tree, xp); - xp->l2vpn = l2vpn; - if (ldpd_process == PROC_MAIN) { - QOBJ_REG (xp, l2vpn_pw); - kif_redistribute(xp->ifname); + COPY(pw, xp); + RB_INSERT(l2vpn_pw_head, &l2vpn->pw_inactive_tree, pw); + pw->l2vpn = l2vpn; + + switch (ldpd_process) { + case PROC_LDE_ENGINE: + case PROC_LDP_ENGINE: + break; + case PROC_MAIN: + kif_redistribute(pw->ifname); + break; } continue; } @@ -1823,9 +1773,6 @@ merge_l2vpn(struct ldpd_conf *xconf, struct l2vpn *l2vpn, struct l2vpn *xl) strlcpy(pw->ifname, xp->ifname, sizeof(pw->ifname)); pw->ifindex = xp->ifindex; pw->flags = xp->flags; - - RB_REMOVE(l2vpn_pw_head, &xl->pw_inactive_tree, xp); - free(xp); } l2vpn->pw_type = xl->pw_type; @@ -1869,5 +1816,6 @@ config_clear(struct ldpd_conf *conf) xconf->trans_pref = conf->trans_pref; xconf->flags = conf->flags; merge_config(conf, xconf); + free(xconf); free(conf); } diff --git a/ldpd/ldpd.h b/ldpd/ldpd.h index a0474a5a2d..d2fc5aa3af 100644 --- a/ldpd/ldpd.h +++ b/ldpd/ldpd.h @@ -706,7 +706,6 @@ struct ldpd_af_global *ldp_af_global_get(struct ldpd_global *, int); int ldp_is_dual_stack(struct ldpd_conf *); in_addr_t ldp_rtr_id_get(struct ldpd_conf *); int ldp_reload(struct ldpd_conf *); -struct ldpd_conf *ldp_dup_config(struct ldpd_conf *); void ldp_clear_config(struct ldpd_conf *); void merge_config(struct ldpd_conf *, struct ldpd_conf *); struct ldpd_conf *config_new_empty(void); diff --git a/ldpd/ldpe.c b/ldpd/ldpe.c index f8e9abab02..1bec3d2a95 100644 --- a/ldpd/ldpe.c +++ b/ldpd/ldpe.c @@ -452,12 +452,6 @@ ldpe_dispatch_main(struct thread *thread) fatal(NULL); memcpy(niface, imsg.data, sizeof(struct iface)); - LIST_INIT(&niface->addr_list); - RB_INIT(&niface->ipv4.adj_tree); - RB_INIT(&niface->ipv6.adj_tree); - niface->ipv4.iface = niface; - niface->ipv6.iface = niface; - RB_INSERT(iface_head, &nconf->iface_tree, niface); break; case IMSG_RECONF_TNBR: @@ -490,7 +484,6 @@ ldpe_dispatch_main(struct thread *thread) fatal(NULL); memcpy(nlif, imsg.data, sizeof(struct l2vpn_if)); - nlif->l2vpn = nl2vpn; RB_INSERT(l2vpn_if_head, &nl2vpn->if_tree, nlif); break; case IMSG_RECONF_L2VPN_PW: @@ -498,7 +491,6 @@ ldpe_dispatch_main(struct thread *thread) fatal(NULL); memcpy(npw, imsg.data, sizeof(struct l2vpn_pw)); - npw->l2vpn = nl2vpn; RB_INSERT(l2vpn_pw_head, &nl2vpn->pw_tree, npw); break; case IMSG_RECONF_L2VPN_IPW: @@ -506,11 +498,11 @@ ldpe_dispatch_main(struct thread *thread) fatal(NULL); memcpy(npw, imsg.data, sizeof(struct l2vpn_pw)); - npw->l2vpn = nl2vpn; RB_INSERT(l2vpn_pw_head, &nl2vpn->pw_inactive_tree, npw); break; case IMSG_RECONF_END: merge_config(leconf, nconf); + ldp_clear_config(nconf); nconf = NULL; global.conf_seqnum++; break; diff --git a/ldpd/ldpe.h b/ldpd/ldpe.h index e4b8394aa0..a3f41a8b9f 100644 --- a/ldpd/ldpe.h +++ b/ldpd/ldpe.h @@ -215,7 +215,8 @@ void mapping_list_clr(struct mapping_head *); /* interface.c */ struct iface *if_new(const char *); -void if_exit(struct iface *); +void ldpe_if_init(struct iface *); +void ldpe_if_exit(struct iface *); struct iface *if_lookup(struct ldpd_conf *, unsigned short); struct iface *if_lookup_name(struct ldpd_conf *, const char *); void if_update_info(struct iface *, struct kif *); From e43223bcc38e0eb68c65c1d37c82739716bc0523 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 31 Mar 2017 16:28:22 -0400 Subject: [PATCH 35/61] pimd: Cleanup unused variable write There exists a common pattern in pim where we were setting a variable to a value in the error case when we would no longer need it. Signed-off-by: Donald Sharp --- pimd/pim_igmp.c | 4 +--- pimd/pim_mroute.c | 6 ++---- pimd/pim_pim.c | 6 ++---- 3 files changed, 5 insertions(+), 11 deletions(-) diff --git a/pimd/pim_igmp.c b/pimd/pim_igmp.c index e6582e2b17..ee88e7d8ea 100644 --- a/pimd/pim_igmp.c +++ b/pimd/pim_igmp.c @@ -876,10 +876,8 @@ pim_igmp_read (struct thread *t) if (errno == EINTR) continue; if (errno == EWOULDBLOCK || errno == EAGAIN) - { - cont = 0; break; - } + goto done; } } diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c index 90e30ea3d6..2fb243b9bd 100644 --- a/pimd/pim_mroute.c +++ b/pimd/pim_mroute.c @@ -577,10 +577,8 @@ static int mroute_read(struct thread *t) if (errno == EINTR) continue; if (errno == EWOULDBLOCK || errno == EAGAIN) - { - cont = 0; - break; - } + break; + if (PIM_DEBUG_MROUTE) zlog_warn("%s: failure reading fd=%d: errno=%d: %s", __PRETTY_FUNCTION__, fd, errno, safe_strerror(errno)); diff --git a/pimd/pim_pim.c b/pimd/pim_pim.c index f82687245d..b2f858b7d9 100644 --- a/pimd/pim_pim.c +++ b/pimd/pim_pim.c @@ -310,10 +310,8 @@ static int pim_sock_read(struct thread *t) if (errno == EINTR) continue; if (errno == EWOULDBLOCK || errno == EAGAIN) - { - cont = 0; - break; - } + break; + if (PIM_DEBUG_PIM_PACKETS) zlog_debug ("Received errno: %d %s", errno, safe_strerror (errno)); goto done; From 8cb129e9868eb5edb7bfe98917fad9931de6144b Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 31 Mar 2017 16:38:29 -0400 Subject: [PATCH 36/61] pimd: Cleanup api and stop crash There is no need for a function that calls another function. Additionally, nexthop_updates from zebra can be either ZEBRA_NEXTHOP_UPDATE -or- ZEBRA_IMPORT_CHECK_UPDATE If we were to receive a IMPORT_CHECK_UPDATE the code would cause a immediate crash. Fix this Signed-off-by: Donald Sharp --- pimd/pim_nht.c | 21 ++++++++++++++++----- pimd/pim_nht.h | 4 ++-- pimd/pim_zebra.c | 10 +--------- 3 files changed, 19 insertions(+), 16 deletions(-) diff --git a/pimd/pim_nht.c b/pimd/pim_nht.c index c9ae673224..5395c08392 100644 --- a/pimd/pim_nht.c +++ b/pimd/pim_nht.c @@ -462,10 +462,13 @@ pim_update_upstream_nh (struct pim_nexthop_cache *pnc) return 0; } -/* This API is used to parse Registered address nexthop update coming from Zebra */ -void -pim_parse_nexthop_update (struct zclient *zclient, int command, - vrf_id_t vrf_id) +/* + * This API is used to parse Registered address nexthop update + * coming from Zebra + */ +int +pim_parse_nexthop_update (int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf_id) { struct stream *s; struct prefix p; @@ -512,9 +515,16 @@ pim_parse_nexthop_update (struct zclient *zclient, int command, zlog_debug ("%s: NHT addr %s is not in local cached DB.", __PRETTY_FUNCTION__, buf); } - return; + return 0; } } + else + { + /* + * We do not currently handle ZEBRA_IMPORT_CHECK_UPDATE + */ + return 0; + } pnc->last_update = pim_time_monotonic_sec (); distance = stream_getc (s); @@ -644,4 +654,5 @@ pim_parse_nexthop_update (struct zclient *zclient, int command, if (listcount (pnc->upstream_list)) pim_update_upstream_nh (pnc); + return 0; } diff --git a/pimd/pim_nht.h b/pimd/pim_nht.h index 6e6602b3be..5348ec3704 100644 --- a/pimd/pim_nht.h +++ b/pimd/pim_nht.h @@ -48,8 +48,8 @@ struct pim_nexthop_cache struct list *upstream_list; }; -void pim_parse_nexthop_update (struct zclient *zclient, int command, - vrf_id_t vrf_id); +int pim_parse_nexthop_update (int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf_id); int pim_find_or_track_nexthop (struct prefix *addr, struct pim_upstream *up, struct rp_info *rp); void pim_delete_tracked_nexthop (struct prefix *addr, struct pim_upstream *up, diff --git a/pimd/pim_zebra.c b/pimd/pim_zebra.c index cd7c3db59a..4e18c478d6 100644 --- a/pimd/pim_zebra.c +++ b/pimd/pim_zebra.c @@ -602,14 +602,6 @@ void sched_rpf_cache_refresh(void) 0, qpim_rpf_cache_refresh_delay_msec); } -static int -pim_zebra_nexthop_update (int command, struct zclient *zclient, - zebra_size_t length, vrf_id_t vrf_id) -{ - pim_parse_nexthop_update (zclient, command, vrf_id); - return 0; -} - static void pim_zebra_connected (struct zclient *zclient) { @@ -637,7 +629,7 @@ void pim_zebra_init(void) zclient->interface_down = pim_zebra_if_state_down; zclient->interface_address_add = pim_zebra_if_address_add; zclient->interface_address_delete = pim_zebra_if_address_del; - zclient->nexthop_update = pim_zebra_nexthop_update; + zclient->nexthop_update = pim_parse_nexthop_update; zclient_init(zclient, ZEBRA_ROUTE_PIM, 0); if (PIM_DEBUG_PIM_TRACE) { From ff3745c26abdfbebeebf14ffe55361666771e1a7 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 31 Mar 2017 16:43:36 -0400 Subject: [PATCH 37/61] pimd: Remove impossible conditions from test It is impossible for the list->cmp function to ever be handed NULL values as the arguments. Clean up this in the code. Additionally consolidate the exact same two functions into 1 function. Signed-off-by: Donald Sharp --- pimd/pim_nht.c | 36 ------------------------------------ pimd/pim_rp.c | 16 ++-------------- pimd/pim_rp.h | 2 ++ 3 files changed, 4 insertions(+), 50 deletions(-) diff --git a/pimd/pim_nht.c b/pimd/pim_nht.c index 5395c08392..fe96d01a06 100644 --- a/pimd/pim_nht.c +++ b/pimd/pim_nht.c @@ -111,42 +111,6 @@ pim_nexthop_cache_find (struct pim_rpf *rpf) } -static int -pim_rp_list_cmp (void *v1, void *v2) -{ - struct rp_info *rp1 = (struct rp_info *) v1; - struct rp_info *rp2 = (struct rp_info *) v2; - - if (rp1 == rp2) - return 0; - - if (!rp1 && rp2) - return -1; - - if (rp1 && !rp2) - return 1; - - /* - * Sort by RP IP address - */ - if (rp1->rp.rpf_addr.u.prefix4.s_addr < rp2->rp.rpf_addr.u.prefix4.s_addr) - return -1; - - if (rp1->rp.rpf_addr.u.prefix4.s_addr > rp2->rp.rpf_addr.u.prefix4.s_addr) - return 1; - - /* - * Sort by group IP address - */ - if (rp1->group.u.prefix4.s_addr < rp2->group.u.prefix4.s_addr) - return -1; - - if (rp1->group.u.prefix4.s_addr > rp2->group.u.prefix4.s_addr) - return 1; - - return -1; -} - struct pim_nexthop_cache * pim_nexthop_cache_add (struct pim_rpf *rpf_addr) { diff --git a/pimd/pim_rp.c b/pimd/pim_rp.c index 6c83811d9a..78bbd14405 100644 --- a/pimd/pim_rp.c +++ b/pimd/pim_rp.c @@ -54,21 +54,12 @@ pim_rp_info_free (struct rp_info *rp_info) XFREE (MTYPE_PIM_RP, rp_info); } -static int +int pim_rp_list_cmp (void *v1, void *v2) { struct rp_info *rp1 = (struct rp_info *)v1; struct rp_info *rp2 = (struct rp_info *)v2; - if (rp1 == rp2) - return 0; - - if (!rp1 && rp2) - return -1; - - if (rp1 && !rp2) - return 1; - /* * Sort by RP IP address */ @@ -87,10 +78,7 @@ pim_rp_list_cmp (void *v1, void *v2) if (rp1->group.u.prefix4.s_addr > rp2->group.u.prefix4.s_addr) return 1; - if (rp1 == tail) - return 1; - - return -1; + return 0; } void diff --git a/pimd/pim_rp.h b/pimd/pim_rp.h index e5580cfa63..84ab9be482 100644 --- a/pimd/pim_rp.h +++ b/pimd/pim_rp.h @@ -61,4 +61,6 @@ struct pim_rpf *pim_rp_g (struct in_addr group); #define RP(G) pim_rp_g ((G)) void pim_rp_show_information (struct vty *vty, u_char uj); + +int pim_rp_list_cmp (void *v1, void *v2); #endif From 19f4e33afa182dde18c4c7bdde7426816ce2a36a Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 31 Mar 2017 16:50:08 -0400 Subject: [PATCH 38/61] pimd: Fix incorrect indentation Signed-off-by: Donald Sharp --- pimd/pim_register.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pimd/pim_register.c b/pimd/pim_register.c index effc212722..65a3e8714f 100644 --- a/pimd/pim_register.c +++ b/pimd/pim_register.c @@ -54,7 +54,7 @@ pim_register_join (struct pim_upstream *up) { if (PIM_DEBUG_PIM_EVENTS) zlog_debug ("%s register setup skipped as group is SSM", up->sg_str); - return; + return; } pim_channel_add_oif (up->channel_oil, pim_regiface, PIM_OIF_FLAG_PROTO_PIM); From 6ca7dd9045d720374a490e21b13393095fd4a9b0 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 31 Mar 2017 16:56:26 -0400 Subject: [PATCH 39/61] pimd: Cleanup termination to avoid possible null ptr deref When terminating pim, there existed( albeit small ) the chance to cause a crash. Cleanup the termination to not have that chance. Signed-off-by: Donald Sharp --- pimd/pimd.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/pimd/pimd.c b/pimd/pimd.c index 72fe0e7046..bdbd251e20 100644 --- a/pimd/pimd.c +++ b/pimd/pimd.c @@ -108,8 +108,14 @@ pim_vrf_enable (struct vrf *vrf) { pimg = pim_instance_init (VRF_DEFAULT, AFI_IP); if (pimg == NULL) - zlog_err ("%s %s: pim class init failure ", __FILE__, - __PRETTY_FUNCTION__); + { + zlog_err ("%s %s: pim class init failure ", __FILE__, + __PRETTY_FUNCTION__); + /* + * We will crash and burn otherwise + */ + exit(1); + } } return 0; } @@ -194,12 +200,18 @@ static void pim_instance_terminate (void) { /* Traverse and cleanup rpf_hash */ - if (pimg && pimg->rpf_hash) + if (pimg->rpf_hash) { hash_clean (pimg->rpf_hash, (void *) pim_rp_list_hash_clean); hash_free (pimg->rpf_hash); + pimg->rpf_hash = NULL; + } + + if (pimg->ssm_info) + { + pim_ssm_terminate (pimg->ssm_info); + pimg->ssm_info = NULL; } - pim_ssm_terminate (pimg->ssm_info); XFREE (MTYPE_PIM_PIM_INSTANCE, pimg); } From 7f03a6f6d2334a33a5d94a612941e5ceb5832fc7 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 31 Mar 2017 17:00:26 -0400 Subject: [PATCH 40/61] nhrpd: Fix value set but never used. The nbma_addr value is set but never used. Signed-off-by: Donald Sharp --- nhrpd/nhrp_peer.c | 1 - 1 file changed, 1 deletion(-) diff --git a/nhrpd/nhrp_peer.c b/nhrpd/nhrp_peer.c index 73b6aaccf6..4c1d97a489 100644 --- a/nhrpd/nhrp_peer.c +++ b/nhrpd/nhrp_peer.c @@ -425,7 +425,6 @@ static void nhrp_handle_registration_request(struct nhrp_packet_parser *p) nbma_natoa = NULL; if (natted) { nbma_natoa = nbma_addr; - nbma_addr = &p->peer->vc->remote.nbma; } holdtime = htons(cie->holding_time); From 7e5b53972233b6aea593397ed8fb8f55068eadaf Mon Sep 17 00:00:00 2001 From: Mike Tancsa Date: Fri, 31 Mar 2017 17:50:35 -0300 Subject: [PATCH 41/61] lib: fix usage of getgrouplist() in *BSD On BSD systems, the getgrouplist() function returns 0 if successful and -1 on error. Linux in the other hand returns *ngroups (the number of groups of which user is a member) on success and -1 on error. Given this difference, the most portable way to use getgrouplist() is use its return value only for checking if it succeeded or not. Signed-off-by: Renato Westphal --- lib/privs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/privs.c b/lib/privs.c index 376d6f3365..decd4bb7db 100644 --- a/lib/privs.c +++ b/lib/privs.c @@ -731,7 +731,7 @@ zprivs_init(struct zebra_privs_t *zprivs) if (zprivs->user) { ngroups = sizeof(groups); - if ( (ngroups = getgrouplist (zprivs->user, zprivs_state.zgid, groups, &ngroups )) < 0 ) + if (getgrouplist (zprivs->user, zprivs_state.zgid, groups, &ngroups) < 0) { /* cant use log.h here as it depends on vty */ fprintf (stderr, "privs_init: could not getgrouplist for user %s\n", From 264f864625263921936d5e2b3e1ae55c3a76a4f4 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Sat, 1 Apr 2017 08:42:19 -0400 Subject: [PATCH 42/61] isisd: Fix some various clang warnings Signed-off-by: Donald Sharp --- isisd/isis_pfpacket.c | 12 ++++++++---- isisd/isis_spf.c | 4 ---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/isisd/isis_pfpacket.c b/isisd/isis_pfpacket.c index 6ec7771ec2..dd07a9c6f5 100644 --- a/isisd/isis_pfpacket.c +++ b/isisd/isis_pfpacket.c @@ -279,6 +279,10 @@ isis_recv_pdu_bcast (struct isis_circuit *circuit, u_char * ssnpa) bytesread = recvfrom (circuit->fd, discard_buff, sizeof (discard_buff), MSG_DONTWAIT, (struct sockaddr *) &s_addr, (socklen_t *) &addr_len); + + if (bytesread < 0) + zlog_warn ("isis_recv_pdu_bcast(): recvfrom() failed"); + return ISIS_WARNING; } /* @@ -322,10 +326,10 @@ isis_recv_pdu_p2p (struct isis_circuit *circuit, u_char * ssnpa) addr_len = sizeof (s_addr); /* we can read directly to the stream */ - bytesread = stream_recvfrom (circuit->rcv_stream, circuit->fd, - circuit->interface->mtu, 0, - (struct sockaddr *) &s_addr, - (socklen_t *) &addr_len); + stream_recvfrom (circuit->rcv_stream, circuit->fd, + circuit->interface->mtu, 0, + (struct sockaddr *) &s_addr, + (socklen_t *) &addr_len); if (s_addr.sll_pkttype == PACKET_OUTGOING) { diff --git a/isisd/isis_spf.c b/isisd/isis_spf.c index db46078f20..554fa563ad 100644 --- a/isisd/isis_spf.c +++ b/isisd/isis_spf.c @@ -68,7 +68,6 @@ remove_excess_adjs (struct list *adjs) if (candidate->sys_type < adj->sys_type) { excess = node; - candidate = adj; continue; } if (candidate->sys_type > adj->sys_type) @@ -78,7 +77,6 @@ remove_excess_adjs (struct list *adjs) if (comp > 0) { excess = node; - candidate = adj; continue; } if (comp < 0) @@ -87,7 +85,6 @@ remove_excess_adjs (struct list *adjs) if (candidate->circuit->circuit_id > adj->circuit->circuit_id) { excess = node; - candidate = adj; continue; } @@ -98,7 +95,6 @@ remove_excess_adjs (struct list *adjs) if (comp > 0) { excess = node; - candidate = adj; continue; } } From 3e71b5d907e9a58049e188cd88ad86614c5ad4f6 Mon Sep 17 00:00:00 2001 From: Martin Winter Date: Sat, 1 Apr 2017 22:22:47 -0700 Subject: [PATCH 43/61] Release: FRR-2.0 Signed-off-by: Martin Winter --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 02f1ae239c..63fbc304fc 100755 --- a/configure.ac +++ b/configure.ac @@ -7,7 +7,7 @@ ## AC_PREREQ(2.60) -AC_INIT(frr, 2.0-rc2, [https://github.com/frrouting/frr/issues]) +AC_INIT(frr, 2.0, [https://github.com/frrouting/frr/issues]) PACKAGE_URL="https://frrouting.org/" PACKAGE_FULLNAME="FRRouting" AC_SUBST(PACKAGE_FULLNAME) From f257ff2cdb28303b3c1d8135bc9897f62adae4f2 Mon Sep 17 00:00:00 2001 From: Quentin Young Date: Sun, 2 Apr 2017 23:21:09 +0000 Subject: [PATCH 44/61] lib: fix proto_redistnum() oversight from #257 proto_redistnum() now accepts full protocol strings and not partial names per #10 Signed-off-by: Quentin Young --- lib/log.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/log.c b/lib/log.c index 69225dbf7a..c7d4ca2d97 100644 --- a/lib/log.c +++ b/lib/log.c @@ -1059,7 +1059,7 @@ proto_redistnum(int afi, const char *s) return ZEBRA_ROUTE_VNC; else if (strmatch (s, "vnc-direct")) return ZEBRA_ROUTE_VNC_DIRECT; - else if (strncmp (s, "n", 1) == 0) + else if (strmatch (s, "nhrp")) return ZEBRA_ROUTE_NHRP; } if (afi == AFI_IP6) @@ -1084,7 +1084,7 @@ proto_redistnum(int afi, const char *s) return ZEBRA_ROUTE_VNC; else if (strmatch (s, "vnc-direct")) return ZEBRA_ROUTE_VNC_DIRECT; - else if (strncmp (s, "n", 1) == 0) + else if (strmatch (s, "nhrp")) return ZEBRA_ROUTE_NHRP; } return -1; From 2d7f0d76c6298e1a59646bcb028412f678dbceee Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 30 Mar 2017 15:37:22 -0400 Subject: [PATCH 45/61] lib, zebra: Add ability to pass interface speed up from zebra This is a prepatory commit for future improvements. Add a change to the zapi to pass the interface speed up. Signed-off-by: Donald Sharp --- lib/if.h | 3 +++ lib/zclient.c | 3 +++ zebra/zserv.c | 1 + 3 files changed, 7 insertions(+) diff --git a/lib/if.h b/lib/if.h index 49f2a52478..d7ec495636 100644 --- a/lib/if.h +++ b/lib/if.h @@ -229,6 +229,9 @@ struct interface /* Interface metric */ uint32_t metric; + /* Interface Speed */ + uint32_t speed; + /* Interface MTU. */ unsigned int mtu; /* IPv4 MTU */ unsigned int mtu6; /* IPv6 MTU - probably, but not neccessarily same as mtu */ diff --git a/lib/zclient.c b/lib/zclient.c index 4455644345..71b95ae7db 100644 --- a/lib/zclient.c +++ b/lib/zclient.c @@ -1003,6 +1003,8 @@ zebra_router_id_update_read (struct stream *s, struct prefix *rid) * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | metric | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | speed | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | ifmtu | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | ifmtu6 | @@ -1185,6 +1187,7 @@ zebra_interface_if_set_value (struct stream *s, struct interface *ifp) ifp->ptm_enable = stream_getc (s); ifp->ptm_status = stream_getc (s); ifp->metric = stream_getl (s); + ifp->speed = stream_getl (s); ifp->mtu = stream_getl (s); ifp->mtu6 = stream_getl (s); ifp->bandwidth = stream_getl (s); diff --git a/zebra/zserv.c b/zebra/zserv.c index f9205a12c8..85fdd53122 100644 --- a/zebra/zserv.c +++ b/zebra/zserv.c @@ -167,6 +167,7 @@ zserv_encode_interface (struct stream *s, struct interface *ifp) stream_putc (s, ifp->ptm_enable); stream_putc (s, ifp->ptm_status); stream_putl (s, ifp->metric); + stream_putl (s, ifp->speed); stream_putl (s, ifp->mtu); stream_putl (s, ifp->mtu6); stream_putl (s, ifp->bandwidth); From 535fe877a9b70084db581e4897452fb4a8dd4e85 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 30 Mar 2017 15:51:29 -0400 Subject: [PATCH 46/61] zebra: Retrieve interface speed when creating interface When we get notification from the kernel about the creation of a new interface, retrieve the speed of it from the kernel Signed-off-by: Donald Sharp --- zebra/if_netlink.c | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/zebra/if_netlink.c b/zebra/if_netlink.c index 0a1cafd87e..b1d4dd81d9 100644 --- a/zebra/if_netlink.c +++ b/zebra/if_netlink.c @@ -22,6 +22,8 @@ #include #include +#include +#include #include "linklist.h" #include "if.h" @@ -298,6 +300,45 @@ netlink_vrf_change (struct nlmsghdr *h, struct rtattr *tb, const char *name) } } +static int +get_iflink_speed (const char *ifname) +{ + struct ifreq ifdata; + struct ethtool_cmd ecmd; + int sd; + int rc; + + /* initialize struct */ + memset(&ifdata, 0, sizeof(ifdata)); + + /* set interface name */ + strcpy(ifdata.ifr_name, ifname); + + /* initialize ethtool interface */ + memset(&ecmd, 0, sizeof(ecmd)); + ecmd.cmd = ETHTOOL_GSET; /* ETHTOOL_GLINK */ + ifdata.ifr_data = (__caddr_t) &ecmd; + + /* use ioctl to get IP address of an interface */ + sd = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP); + if(sd < 0) { + zlog_debug ("Failure to read interface %s speed: %d %s", + ifname, errno, safe_strerror(errno)); + return 0; + } + + /* Get the current link state for the interface */ + rc = ioctl(sd, SIOCETHTOOL, (char *)&ifdata); + if(rc < 0) { + zlog_debug ("IOCTL failure to read interface %s speed: %d %s", + ifname, errno, safe_strerror(errno)); + } + + close(sd); + + return (ecmd.speed_hi << 16 ) | ecmd.speed; +} + /* Called from interface_lookup_netlink(). This function is only used during bootstrap. */ static int @@ -382,6 +423,7 @@ netlink_interface (struct sockaddr_nl *snl, struct nlmsghdr *h, SET_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK); ifp->mtu6 = ifp->mtu = *(uint32_t *) RTA_DATA (tb[IFLA_MTU]); ifp->metric = 0; + ifp->speed = get_iflink_speed (name); ifp->ptm_status = ZEBRA_PTM_STATUS_UNKNOWN; /* Hardware type and address. */ From 6f4c7f7476b0124e024f51f32392792efd116b4d Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 30 Mar 2017 16:54:15 -0400 Subject: [PATCH 47/61] zebra: Display new speed information in 'show int..' command Signed-off-by: Donald Sharp --- zebra/interface.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zebra/interface.c b/zebra/interface.c index e9c54a629b..adcc78095b 100644 --- a/zebra/interface.c +++ b/zebra/interface.c @@ -1056,8 +1056,8 @@ if_dump_vty (struct vty *vty, struct interface *ifp) return; } - vty_out (vty, " index %d metric %d mtu %d ", - ifp->ifindex, ifp->metric, ifp->mtu); + vty_out (vty, " index %d metric %d mtu %d speed %d ", + ifp->ifindex, ifp->metric, ifp->mtu, ifp->speed); if (ifp->mtu6 != ifp->mtu) vty_out (vty, "mtu6 %d ", ifp->mtu6); vty_out (vty, "%s flags: %s%s", VTY_NEWLINE, From eaa1ae0db4841d20d74943cf2c569ecff663c926 Mon Sep 17 00:00:00 2001 From: Quentin Young Date: Mon, 3 Apr 2017 20:17:12 +0000 Subject: [PATCH 48/61] ospfd, ospf6d: fix distance commands OSPF distance commands were broken in a variety of ways. Fix 'em. * `distance ospf` and `distance ospf6` were accepted commands * Inconsistent doc strings * Make use of {keyword|tokens} * Add ability to reset specific distance without specifying a value Ex: ~# no distance ospf6 intra Signed-off-by: Quentin Young --- ospf6d/ospf6_top.c | 120 +++++---------------------------------------- ospfd/ospf_vty.c | 72 +++++++++------------------ 2 files changed, 35 insertions(+), 157 deletions(-) diff --git a/ospf6d/ospf6_top.c b/ospf6d/ospf6_top.c index 74e49a21bb..32dad36d9e 100644 --- a/ospf6d/ospf6_top.c +++ b/ospf6d/ospf6_top.c @@ -470,21 +470,9 @@ DEFUN (no_ospf6_distance, DEFUN (ospf6_distance_ospf6, ospf6_distance_ospf6_cmd, - "distance ospf6 ", + "distance ospf6 {intra-area (1-255)|inter-area (1-255)|external (1-255)}", "Administrative distance\n" - "OSPF6 distance\n" - "Intra-area routes\n" - "Distance for intra-area routes\n" - "Inter-area routes\n" - "Distance for inter-area routes\n" - "External routes\n" - "Distance for external routes\n" - "Intra-area routes\n" - "Distance for intra-area routes\n" - "Inter-area routes\n" - "Distance for inter-area routes\n" - "External routes\n" - "Distance for external routes\n" + "OSPF6 administrative distance\n" "Intra-area routes\n" "Distance for intra-area routes\n" "Inter-area routes\n" @@ -493,53 +481,23 @@ DEFUN (ospf6_distance_ospf6, "Distance for external routes\n") { VTY_DECLVAR_CONTEXT(ospf6, o); - - char *intra, *inter, *external; - intra = inter = external = NULL; - int idx = 0; - if (argv_find (argv, argc, "intra-area", &idx)) - intra = argv[++idx]->arg; - if (argv_find (argv, argc, "intra-area", &idx)) - { - vty_out (vty, "%% Cannot specify intra-area distance twice%s", VTY_NEWLINE); - return CMD_WARNING; - } + if (argv_find (argv, argc, "intra-area", &idx)) + o->distance_intra = atoi(argv[idx + 1]->arg); idx = 0; if (argv_find (argv, argc, "inter-area", &idx)) - inter = argv[++idx]->arg; - if (argv_find (argv, argc, "inter-area", &idx)) - { - vty_out (vty, "%% Cannot specify inter-area distance twice%s", VTY_NEWLINE); - return CMD_WARNING; - } - + o->distance_inter = atoi(argv[idx + 1]->arg); idx = 0; if (argv_find (argv, argc, "external", &idx)) - external = argv[++idx]->arg; - if (argv_find (argv, argc, "external", &idx)) - { - vty_out (vty, "%% Cannot specify external distance twice%s", VTY_NEWLINE); - return CMD_WARNING; - } - - - if (intra) - o->distance_intra = atoi (intra); - - if (inter) - o->distance_inter = atoi (inter); - - if (external) - o->distance_external = atoi (external); + o->distance_external = atoi(argv[idx + 1]->arg); return CMD_SUCCESS; } DEFUN (no_ospf6_distance_ospf6, no_ospf6_distance_ospf6_cmd, - "no distance ospf6 [ ]", + "no distance ospf6 [{intra-area [(1-255)]|inter-area [(1-255)]|external [(1-255)]}]", NO_STR "Administrative distance\n" "OSPF6 distance\n" @@ -548,70 +506,16 @@ DEFUN (no_ospf6_distance_ospf6, "Inter-area routes\n" "Distance for inter-area routes\n" "External routes\n" - "Distance for external routes\n" - "Intra-area routes\n" - "Distance for intra-area routes\n" - "Inter-area routes\n" - "Distance for inter-area routes\n" - "External routes\n" - "Distance for external routes\n" - "Intra-area routes\n" - "Distance for intra-area routes\n" - "Inter-area routes\n" - "Distance for inter-area routes\n" - "External routes\n" "Distance for external routes\n") { VTY_DECLVAR_CONTEXT(ospf6, o); - - char *intra, *inter, *external; - intra = inter = external = NULL; - - if (argc == 3) - { - /* If no arguments are given, clear all distance information */ - o->distance_intra = 0; - o->distance_inter = 0; - o->distance_external = 0; - return CMD_SUCCESS; - } - int idx = 0; - if (argv_find (argv, argc, "intra-area", &idx)) - intra = argv[++idx]->arg; - if (argv_find (argv, argc, "intra-area", &idx)) - { - vty_out (vty, "%% Cannot specify intra-area distance twice%s", VTY_NEWLINE); - return CMD_WARNING; - } - idx = 0; - if (argv_find (argv, argc, "inter-area", &idx)) - inter = argv[++idx]->arg; - if (argv_find (argv, argc, "inter-area", &idx)) - { - vty_out (vty, "%% Cannot specify inter-area distance twice%s", VTY_NEWLINE); - return CMD_WARNING; - } - - idx = 0; - if (argv_find (argv, argc, "external", &idx)) - external = argv[++idx]->arg; - if (argv_find (argv, argc, "external", &idx)) - { - vty_out (vty, "%% Cannot specify external distance twice%s", VTY_NEWLINE); - return CMD_WARNING; - } - if (argc < 3) /* should not happen */ - return CMD_WARNING; - - if (intra) - o->distance_intra = 0; - - if (inter) - o->distance_inter = 0; - - if (external) + if (argv_find (argv, argc, "intra-area", &idx) || argc == 3) + idx = o->distance_intra = 0; + if (argv_find (argv, argc, "inter-area", &idx) || argc == 3) + idx = o->distance_inter = 0; + if (argv_find (argv, argc, "external", &idx) || argc == 3) o->distance_external = 0; return CMD_SUCCESS; diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c index c51e176c74..121ef018b2 100644 --- a/ospfd/ospf_vty.c +++ b/ospfd/ospf_vty.c @@ -7458,7 +7458,7 @@ DEFUN (no_ospf_default_metric, DEFUN (ospf_distance, ospf_distance_cmd, "distance (1-255)", - "Define an administrative distance\n" + "Administrative distance\n" "OSPF Administrative distance\n") { VTY_DECLVAR_CONTEXT(ospf, ospf); @@ -7473,7 +7473,7 @@ DEFUN (no_ospf_distance, no_ospf_distance_cmd, "no distance (1-255)", NO_STR - "Define an administrative distance\n" + "Administrative distance\n" "OSPF Administrative distance\n") { VTY_DECLVAR_CONTEXT(ospf, ospf); @@ -7485,10 +7485,10 @@ DEFUN (no_ospf_distance, DEFUN (no_ospf_distance_ospf, no_ospf_distance_ospf_cmd, - "no distance ospf []", + "no distance ospf [{intra-area [(1-255)]|inter-area [(1-255)]|external [(1-255)]}]", NO_STR - "Define an administrative distance\n" - "OSPF Administrative distance\n" + "Administrative distance\n" + "OSPF administrative distance\n" "Intra-area routes\n" "Distance for intra-area routes\n" "Inter-area routes\n" @@ -7497,42 +7497,26 @@ DEFUN (no_ospf_distance_ospf, "Distance for external routes\n") { VTY_DECLVAR_CONTEXT(ospf, ospf); - int idx_area_distance = 3; + int idx = 0; if (!ospf) return CMD_SUCCESS; - if (argc < 3) - return CMD_WARNING; - - if (!ospf) - return CMD_SUCCESS; - - if (argv[idx_area_distance]->arg != NULL) - ospf->distance_intra = 0; - - if (argv[1] != NULL) - ospf->distance_inter = 0; - - if (argv[2] != NULL) + if (argv_find (argv, argc, "intra-area", &idx) || argc == 3) + idx = ospf->distance_intra = 0; + if (argv_find (argv, argc, "inter-area", &idx) || argc == 3) + idx = ospf->distance_inter = 0; + if (argv_find (argv, argc, "external", &idx) || argc == 3) ospf->distance_external = 0; - if (argv[idx_area_distance]->arg || argv[1] || argv[2]) - return CMD_SUCCESS; - - /* If no arguments are given, clear all distance information */ - ospf->distance_intra = 0; - ospf->distance_inter = 0; - ospf->distance_external = 0; - return CMD_SUCCESS; } DEFUN (ospf_distance_ospf, ospf_distance_ospf_cmd, - "distance ospf []", - "Define an administrative distance\n" - "OSPF Administrative distance\n" + "distance ospf {intra-area (1-255)|inter-area (1-255)|external (1-255)}", + "Administrative distance\n" + "OSPF administrative distance\n" "Intra-area routes\n" "Distance for intra-area routes\n" "Inter-area routes\n" @@ -7541,26 +7525,16 @@ DEFUN (ospf_distance_ospf, "Distance for external routes\n") { VTY_DECLVAR_CONTEXT(ospf, ospf); - int idx_area_distance = 2; + int idx = 0; - if (argc < 3) /* should not happen */ - return CMD_WARNING; - - if (!argv[idx_area_distance]->arg && !argv[1] && !argv[2]) - { - vty_out(vty, "%% Command incomplete. (Arguments required)%s", - VTY_NEWLINE); - return CMD_WARNING; - } - - if (strcmp (argv[idx_area_distance]->text, "intra") == 0) - ospf->distance_intra = atoi(argv[idx_area_distance+1]->arg); - - if (strcmp (argv[idx_area_distance]->text, "inter") == 0) - ospf->distance_inter = atoi(argv[idx_area_distance+1]->arg); - - if (strcmp (argv[idx_area_distance]->text, "external") == 0) - ospf->distance_external = atoi(argv[idx_area_distance+1]->arg); + if (argv_find (argv, argc, "intra-area", &idx)) + ospf->distance_intra = atoi(argv[idx + 1]->arg); + idx = 0; + if (argv_find (argv, argc, "inter-area", &idx)) + ospf->distance_inter = atoi(argv[idx + 1]->arg); + idx = 0; + if (argv_find (argv, argc, "external", &idx)) + ospf->distance_external = atoi(argv[idx + 1]->arg); return CMD_SUCCESS; } From 45a39399d7b6a5fc6bed721e58871d2a30cfe91a Mon Sep 17 00:00:00 2001 From: Lou Berger Date: Mon, 3 Apr 2017 17:30:31 -0400 Subject: [PATCH 49/61] doc: fix some omissions in centos instructions Signed-off-by: Lou Berger --- doc/Building_FRR_on_CentOS6.md | 2 +- doc/Building_FRR_on_CentOS7.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/Building_FRR_on_CentOS6.md b/doc/Building_FRR_on_CentOS6.md index 3829962d4a..b18e53470b 100644 --- a/doc/Building_FRR_on_CentOS6.md +++ b/doc/Building_FRR_on_CentOS6.md @@ -18,7 +18,7 @@ Add packages: sudo yum install git autoconf automake libtool make gawk readline-devel \ texinfo net-snmp-devel groff pkgconfig json-c-devel pam-devel \ - flex c-ares-devel epel-release + flex c-ares-devel epel-release rpm-build libcap-devel texi2html Install newer version of bison (CentOS 6 package source is too old) from CentOS 7 diff --git a/doc/Building_FRR_on_CentOS7.md b/doc/Building_FRR_on_CentOS7.md index 41c88b5593..e24c73a175 100644 --- a/doc/Building_FRR_on_CentOS7.md +++ b/doc/Building_FRR_on_CentOS7.md @@ -15,7 +15,7 @@ Add packages: sudo yum install git autoconf automake libtool make gawk readline-devel \ texinfo net-snmp-devel groff pkgconfig json-c-devel pam-devel \ - bison flex pytest c-ares-devel python-devel + bison flex pytest c-ares-devel python-devel rpm-build To build from git (in difference to building from distribution tar.gz as created by `make dist`), the python development libraries are needed. (Make sure you've installed EPEL libraries as shown above for this to work) From 208bf70046b20489eb2f81fa03d91d14d2fdc9a5 Mon Sep 17 00:00:00 2001 From: Lou Berger Date: Mon, 3 Apr 2017 17:32:03 -0400 Subject: [PATCH 50/61] redhat/frr.spec.in: fix typo Signed-off-by: Lou Berger --- redhat/frr.spec.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/redhat/frr.spec.in b/redhat/frr.spec.in index bb23931b13..b86d115507 100644 --- a/redhat/frr.spec.in +++ b/redhat/frr.spec.in @@ -73,7 +73,7 @@ %{!?frr_gid: %global frr_gid 92 } %{!?vty_gid: %global vty_gid 85 } -%define daemon_list zebra ripd ospfd bgpd isisd pimd ripngd ospfd6d +%define daemon_list zebra ripd ospfd bgpd isisd pimd ripngd ospf6d %if %{with_ldpd} %define daemon_ldpd ldpd From eb649b7ff38df75fb2b5fc20a552b9a6d1f78063 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Mon, 3 Apr 2017 18:28:26 -0400 Subject: [PATCH 51/61] lib, zebra: Fix CR comments lib -> Add a bit of documentation about what units we are in. zebra -> Fix failure case to be a bit better. Signed-off-by: Donald Sharp --- lib/if.h | 2 +- zebra/if_netlink.c | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/if.h b/lib/if.h index d7ec495636..e8e84ffc88 100644 --- a/lib/if.h +++ b/lib/if.h @@ -229,7 +229,7 @@ struct interface /* Interface metric */ uint32_t metric; - /* Interface Speed */ + /* Interface Speed in Mb/s */ uint32_t speed; /* Interface MTU. */ diff --git a/zebra/if_netlink.c b/zebra/if_netlink.c index b1d4dd81d9..28538fabdf 100644 --- a/zebra/if_netlink.c +++ b/zebra/if_netlink.c @@ -330,8 +330,10 @@ get_iflink_speed (const char *ifname) /* Get the current link state for the interface */ rc = ioctl(sd, SIOCETHTOOL, (char *)&ifdata); if(rc < 0) { - zlog_debug ("IOCTL failure to read interface %s speed: %d %s", - ifname, errno, safe_strerror(errno)); + zlog_debug("IOCTL failure to read interface %s speed: %d %s", + ifname, errno, safe_strerror(errno)); + ecmd.speed_hi = 0; + ecmd.speed = 0; } close(sd); From 10dad4242a63a221fdd0b51499a10a026658642d Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Mon, 3 Apr 2017 21:14:18 -0300 Subject: [PATCH 52/61] zebra: fix v4/v6 typos in some show commands This fixes a few problems like this one: vtysh# show ipv6 route ospf6 Unknown route type Also, replace SAFI_UNICAST with SAFI_MULTICAST in the "show ipv6 mroute vrf all" command. Signed-off-by: Renato Westphal --- zebra/zebra_vty.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c index ffc075f43f..35aa69cc97 100644 --- a/zebra/zebra_vty.c +++ b/zebra/zebra_vty.c @@ -3143,7 +3143,7 @@ DEFUN (show_ipv6_route_protocol, VRF_GET_ID (vrf_id, argv[idx]->arg); char *proto = argv[argc - 1]->text; - type = proto_redistnum (AFI_IP, proto); + type = proto_redistnum (AFI_IP6, proto); if (type < 0) { @@ -3431,7 +3431,7 @@ DEFUN (show_ipv6_route_vrf_all_tag, RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) { if ((zvrf = vrf->info) == NULL || - (table = zvrf->table[AFI_IP][SAFI_UNICAST]) == NULL) + (table = zvrf->table[AFI_IP6][SAFI_UNICAST]) == NULL) continue; /* Show all IPv6 routes with matching tag value. */ @@ -3541,7 +3541,7 @@ DEFUN (show_ipv6_route_vrf_all_protocol, int vrf_header = 1; char *proto = argv[argc - 1]->text; - type = proto_redistnum (AFI_IP, proto); + type = proto_redistnum (AFI_IP6, proto); if (type < 0) { @@ -3705,7 +3705,7 @@ DEFUN (show_ipv6_mroute_vrf_all, RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) { if ((zvrf = vrf->info) == NULL || - (table = zvrf->table[AFI_IP6][SAFI_UNICAST]) == NULL) + (table = zvrf->table[AFI_IP6][SAFI_MULTICAST]) == NULL) continue; /* Show all IPv6 route. */ From 97d2cd8d0c54279407cef16f070231912ef85a00 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Tue, 4 Apr 2017 07:50:31 -0400 Subject: [PATCH 53/61] zebra: Fix printf formatting Signed-off-by: Donald Sharp --- zebra/interface.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zebra/interface.c b/zebra/interface.c index adcc78095b..1d015e8588 100644 --- a/zebra/interface.c +++ b/zebra/interface.c @@ -1056,7 +1056,7 @@ if_dump_vty (struct vty *vty, struct interface *ifp) return; } - vty_out (vty, " index %d metric %d mtu %d speed %d ", + vty_out (vty, " index %d metric %d mtu %d speed %u ", ifp->ifindex, ifp->metric, ifp->mtu, ifp->speed); if (ifp->mtu6 != ifp->mtu) vty_out (vty, "mtu6 %d ", ifp->mtu6); From 2a8e27afb8bbddeedb6eba2521a921ca1a510bd8 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Tue, 4 Apr 2017 16:12:59 +0200 Subject: [PATCH 54/61] vtysh: handle "show modules" like "show memory" Preface with line identifying which daemon it applies to. [Also fixes a missed "plugin" -> "module" replace.] Signed-off-by: David Lamparter --- lib/memory_vty.c | 2 +- vtysh/vtysh.c | 43 +++++++++++++++++++++++++++++-------------- 2 files changed, 30 insertions(+), 15 deletions(-) diff --git a/lib/memory_vty.c b/lib/memory_vty.c index 01a41fe02e..6d63bc2d53 100644 --- a/lib/memory_vty.c +++ b/lib/memory_vty.c @@ -121,7 +121,7 @@ DEFUN (show_modules, struct frrmod_runtime *plug = frrmod_list; vty_out (vty, "%-12s %-25s %s%s%s", - "Plugin Name", "Version", "Description", + "Module Name", "Version", "Description", VTY_NEWLINE, VTY_NEWLINE); while (plug) { diff --git a/vtysh/vtysh.c b/vtysh/vtysh.c index 114022d199..1182944f8f 100644 --- a/vtysh/vtysh.c +++ b/vtysh/vtysh.c @@ -2010,6 +2010,24 @@ DEFUNSH (VTYSH_ZEBRA, return CMD_SUCCESS; } +static int +show_per_daemon (const char *line, const char *headline) +{ + unsigned int i; + int ret = CMD_SUCCESS; + + for (i = 0; i < array_size(vtysh_client); i++) + if ( vtysh_client[i].fd >= 0 ) + { + fprintf (stdout, headline, + vtysh_client[i].name); + ret = vtysh_client_execute (&vtysh_client[i], line, stdout); + fprintf (stdout,"\n"); + } + + return ret; +} + /* Memory */ DEFUN (vtysh_show_memory, vtysh_show_memory_cmd, @@ -2017,20 +2035,16 @@ DEFUN (vtysh_show_memory, SHOW_STR "Memory statistics\n") { - unsigned int i; - int ret = CMD_SUCCESS; - char line[] = "show memory\n"; - - for (i = 0; i < array_size(vtysh_client); i++) - if ( vtysh_client[i].fd >= 0 ) - { - fprintf (stdout, "Memory statistics for %s:\n", - vtysh_client[i].name); - ret = vtysh_client_execute (&vtysh_client[i], line, stdout); - fprintf (stdout,"\n"); - } - - return ret; + return show_per_daemon ("show memory\n", "Memory statistics for %s:\n"); +} + +DEFUN (vtysh_show_modules, + vtysh_show_modules_cmd, + "show modules", + SHOW_STR + "Loaded modules\n") +{ + return show_per_daemon ("show modules\n", "Module information for %s:\n"); } /* Logging commands. */ @@ -3388,6 +3402,7 @@ vtysh_init_vty (void) #endif install_element (VIEW_NODE, &vtysh_show_memory_cmd); + install_element (VIEW_NODE, &vtysh_show_modules_cmd); install_element (VIEW_NODE, &vtysh_show_work_queues_cmd); install_element (VIEW_NODE, &vtysh_show_work_queues_daemon_cmd); From b394fc99bc4b555aa3c78521439b28f1ff8886ef Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Tue, 4 Apr 2017 18:37:47 +0200 Subject: [PATCH 55/61] build: remove wildcards from snapcraft/Makefile.am automake does not support globs. Signed-off-by: David Lamparter --- snapcraft/Makefile.am | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/snapcraft/Makefile.am b/snapcraft/Makefile.am index 8cc4e0b4c6..75f768e942 100644 --- a/snapcraft/Makefile.am +++ b/snapcraft/Makefile.am @@ -1,5 +1,25 @@ EXTRA_DIST = snapcraft.yaml \ - README.* \ - scripts/Makefile scripts/*-service \ - defaults/*.conf.default \ - helpers snap + README.snap_build.md \ + README.usage.md \ + scripts/Makefile \ + scripts/bgpd-service \ + scripts/isisd-service \ + scripts/ldpd-service \ + scripts/ospf6d-service \ + scripts/ospfd-service \ + scripts/pimd-service \ + scripts/ripd-service \ + scripts/ripngd-service \ + scripts/zebra-service \ + defaults/bgpd.conf.default \ + defaults/isisd.conf.default \ + defaults/ldpd.conf.default \ + defaults/ospf6d.conf.default \ + defaults/ospfd.conf.default \ + defaults/pimd.conf.default \ + defaults/ripd.conf.default \ + defaults/ripngd.conf.default \ + defaults/vtysh.conf.default \ + defaults/zebra.conf.default \ + helpers \ + snap From ee4330959627607144c4d01b32aedb49600e366a Mon Sep 17 00:00:00 2001 From: Daniel Walton Date: Tue, 4 Apr 2017 18:11:04 +0000 Subject: [PATCH 56/61] zebra: "debug zebra nht" is not in the config Signed-off-by: Daniel Walton Reviewed-by: Donald Sharp --- zebra/debug.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/zebra/debug.c b/zebra/debug.c index 2e9fef292b..f21778276e 100644 --- a/zebra/debug.c +++ b/zebra/debug.c @@ -399,6 +399,11 @@ config_write_debug (struct vty *vty) vty_out (vty, "debug zebra fpm%s", VTY_NEWLINE); write++; } + if (IS_ZEBRA_DEBUG_NHT) + { + vty_out (vty, "debug zebra nht%s", VTY_NEWLINE); + write++; + } if (IS_ZEBRA_DEBUG_MPLS) { vty_out (vty, "debug zebra mpls%s", VTY_NEWLINE); From 7994b01d26100c642b97939d5ce8e04320c27fa4 Mon Sep 17 00:00:00 2001 From: Daniel Walton Date: Tue, 4 Apr 2017 18:13:43 +0000 Subject: [PATCH 57/61] ospfd: "no log-adjacency-changes detail" disables log-adjacency-changes Signed-off-by: Daniel Walton Reviewed-by: Donald Sharp --- ospf6d/ospf6_top.c | 1 - ospfd/ospf_vty.c | 1 - 2 files changed, 2 deletions(-) diff --git a/ospf6d/ospf6_top.c b/ospf6d/ospf6_top.c index 32dad36d9e..bbb2a5e42d 100644 --- a/ospf6d/ospf6_top.c +++ b/ospf6d/ospf6_top.c @@ -391,7 +391,6 @@ DEFUN (no_ospf6_log_adjacency_changes_detail, VTY_DECLVAR_CONTEXT(ospf6, ospf6); UNSET_FLAG(ospf6->config_flags, OSPF6_LOG_ADJACENCY_DETAIL); - UNSET_FLAG(ospf6->config_flags, OSPF6_LOG_ADJACENCY_CHANGES); return CMD_SUCCESS; } diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c index 121ef018b2..64ccea36b2 100644 --- a/ospfd/ospf_vty.c +++ b/ospfd/ospf_vty.c @@ -2137,7 +2137,6 @@ DEFUN (no_ospf_log_adjacency_changes_detail, { VTY_DECLVAR_CONTEXT(ospf, ospf); - UNSET_FLAG(ospf->config, OSPF_LOG_ADJACENCY_CHANGES); UNSET_FLAG(ospf->config, OSPF_LOG_ADJACENCY_DETAIL); return CMD_SUCCESS; } From 2ce26af10059f532c753d0504675cb307f1da64f Mon Sep 17 00:00:00 2001 From: Daniel Walton Date: Tue, 4 Apr 2017 18:51:32 +0000 Subject: [PATCH 58/61] tools: quagga-reload.py fails to change max-paths Signed-off-by: Daniel Walton Reviewed-by: Donald Sharp --- tools/frr-reload.py | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/tools/frr-reload.py b/tools/frr-reload.py index 4c26300099..c91392da15 100755 --- a/tools/frr-reload.py +++ b/tools/frr-reload.py @@ -988,6 +988,21 @@ if __name__ == '__main__': # the "neighbor 1.1.1.1 route-map FOO out" line...so we compare the # configs again to put this line back. + # There are many keywords in quagga that can only appear one time under + # a context, take "bgp router-id" for example. If the config that we are + # reloading against has the following: + # + # router bgp 10 + # bgp router-id 1.1.1.1 + # bgp router-id 2.2.2.2 + # + # The final config needs to contain "bgp router-id 2.2.2.2". On the + # first pass we will add "bgp router-id 2.2.2.2" but then on the second + # pass we will see that "bgp router-id 1.1.1.1" is missing and add that + # back which cancels out the "bgp router-id 2.2.2.2". The fix is for the + # second pass to include all of the "adds" from the first pass. + lines_to_add_first_pass = [] + for x in range(2): running = Config() running.load_from_show_running() @@ -995,6 +1010,11 @@ if __name__ == '__main__': (lines_to_add, lines_to_del) = compare_context_objects(newconf, running) + if x == 0: + lines_to_add_first_pass = lines_to_add + else: + lines_to_add.extend(lines_to_add_first_pass) + # Only do deletes on the first pass. The reason being if we # configure a bgp neighbor via "neighbor swp1 interface" quagga # will automatically add: From a263892613216ae4c58fa769c4aada70dcdd9e2c Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Tue, 4 Apr 2017 21:25:19 +0200 Subject: [PATCH 59/61] build: fix CFLAGS for snmp modules The SNMP modules include , which won't be found in off-searchpath directories without SNMP_CFLAGS. Unfortunately in my tests the files were on the search path even without the flags. (SNMP_LIBS is not needed because only libfrrsnmp calls into net-snmp functions.) Signed-off-by: David Lamparter --- bgpd/Makefile.am | 1 + ospf6d/Makefile.am | 1 + ospfd/Makefile.am | 1 + ripd/Makefile.am | 1 + zebra/Makefile.am | 1 + 5 files changed, 5 insertions(+) diff --git a/bgpd/Makefile.am b/bgpd/Makefile.am index af6c8faf03..b6ed9a4d6d 100644 --- a/bgpd/Makefile.am +++ b/bgpd/Makefile.am @@ -107,6 +107,7 @@ module_LTLIBRARIES += bgpd_snmp.la endif bgpd_snmp_la_SOURCES = bgp_snmp.c +bgpd_snmp_la_CFLAGS = $(WERROR) $(SNMP_CFLAGS) bgpd_snmp_la_LDFLAGS = -avoid-version -module -shared -export-dynamic bgpd_snmp_la_LIBADD = ../lib/libfrrsnmp.la diff --git a/ospf6d/Makefile.am b/ospf6d/Makefile.am index 933a97ca8f..75dd8ffe46 100644 --- a/ospf6d/Makefile.am +++ b/ospf6d/Makefile.am @@ -35,6 +35,7 @@ if SNMP module_LTLIBRARIES += ospf6d_snmp.la endif ospf6d_snmp_la_SOURCES = ospf6_snmp.c +ospf6d_snmp_la_CFLAGS = $(WERROR) $(SNMP_CFLAGS) ospf6d_snmp_la_LDFLAGS = -avoid-version -module -shared -export-dynamic ospf6d_snmp_la_LIBADD = ../lib/libfrrsnmp.la diff --git a/ospfd/Makefile.am b/ospfd/Makefile.am index e9d0ed2192..c6a5ec91d2 100644 --- a/ospfd/Makefile.am +++ b/ospfd/Makefile.am @@ -38,6 +38,7 @@ if SNMP module_LTLIBRARIES += ospfd_snmp.la endif ospfd_snmp_la_SOURCES = ospf_snmp.c +ospfd_snmp_la_CFLAGS = $(WERROR) $(SNMP_CFLAGS) ospfd_snmp_la_LDFLAGS = -avoid-version -module -shared -export-dynamic ospfd_snmp_la_LIBADD = ../lib/libfrrsnmp.la diff --git a/ripd/Makefile.am b/ripd/Makefile.am index 827869121c..9c034f0c38 100644 --- a/ripd/Makefile.am +++ b/ripd/Makefile.am @@ -28,6 +28,7 @@ if SNMP module_LTLIBRARIES += ripd_snmp.la endif ripd_snmp_la_SOURCES = rip_snmp.c +ripd_snmp_la_CFLAGS = $(WERROR) $(SNMP_CFLAGS) ripd_snmp_la_LDFLAGS = -avoid-version -module -shared -export-dynamic ripd_snmp_la_LIBADD = ../lib/libfrrsnmp.la diff --git a/zebra/Makefile.am b/zebra/Makefile.am index af7a513d2f..3e0de3b463 100644 --- a/zebra/Makefile.am +++ b/zebra/Makefile.am @@ -61,6 +61,7 @@ if SNMP module_LTLIBRARIES += zebra_snmp.la endif zebra_snmp_la_SOURCES = zebra_snmp.c +zebra_snmp_la_CFLAGS = $(WERROR) $(SNMP_CFLAGS) zebra_snmp_la_LDFLAGS = -avoid-version -module -shared -export-dynamic zebra_snmp_la_LIBADD = ../lib/libfrrsnmp.la From be0f843102ae00a33f04fd6a403506c3767692b7 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Tue, 4 Apr 2017 15:20:52 -0400 Subject: [PATCH 60/61] vtysh: Fix build for non-snmp case The snmp code is being included in the build of the vtysh_cmd.c irrelevant of whether or not it is needed. Be a bit smarter about what files to include. Signed-off-by: Donald Sharp Signed-off-by: David Lamparter --- vtysh/Makefile.am | 52 +++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 46 insertions(+), 6 deletions(-) diff --git a/vtysh/Makefile.am b/vtysh/Makefile.am index d02ec9661f..544b467e32 100644 --- a/vtysh/Makefile.am +++ b/vtysh/Makefile.am @@ -44,27 +44,67 @@ vtysh_scan += $(top_srcdir)/pimd/pim_cmd.c endif if BGPD -vtysh_scan += $(top_srcdir)/bgpd/*.c +vtysh_scan += $(top_srcdir)/bgpd/bgp_bfd.c +vtysh_scan += $(top_srcdir)/bgpd/bgp_debug.c +vtysh_scan += $(top_srcdir)/bgpd/bgp_dump.c +vtysh_scan += $(top_srcdir)/bgpd/bgp_encap.c +vtysh_scan += $(top_srcdir)/bgpd/bgp_evpn_vty.c +vtysh_scan += $(top_srcdir)/bgpd/bgp_filter.c +vtysh_scan += $(top_srcdir)/bgpd/bgp_mplsvpn.c +vtysh_scan += $(top_srcdir)/bgpd/bgp_route.c +vtysh_scan += $(top_srcdir)/bgpd/bgp_routemap.c +vtysh_scan += $(top_srcdir)/bgpd/bgp_vty.c endif if ISISD -vtysh_scan += $(top_srcdir)/isisd/*.c +vtysh_scan += $(top_srcdir)/isisd/isis_redist.c +vtysh_scan += $(top_srcdir)/isisd/isis_spf.c +vtysh_scan += $(top_srcdir)/isisd/isis_te.c +vtysh_scan += $(top_srcdir)/isisd/isis_vty.c +vtysh_scan += $(top_srcdir)/isisd/isisd.c endif if OSPFD -vtysh_scan += $(top_srcdir)/ospfd/*.c +vtysh_scan += $(top_srcdir)/ospfd/ospf_bfd.c +vtysh_scan += $(top_srcdir)/ospfd/ospf_dump.c +vtysh_scan += $(top_srcdir)/ospfd/ospf_opaque.c +vtysh_scan += $(top_srcdir)/ospfd/ospf_ri.c +vtysh_scan += $(top_srcdir)/ospfd/ospf_routemap.c +vtysh_scan += $(top_srcdir)/ospfd/ospf_te.c +vtysh_scan += $(top_srcdir)/ospfd/ospf_vty.c endif if OSPF6D -vtysh_scan += $(top_srcdir)/ospf6d/*.c +vtysh_scan += $(top_srcdir)/ospf6d/ospf6_abr.c +vtysh_scan += $(top_srcdir)/ospf6d/ospf6_area.c +vtysh_scan += $(top_srcdir)/ospf6d/ospf6_bfd.c +vtysh_scan += $(top_srcdir)/ospf6d/ospf6_flood.c +vtysh_scan += $(top_srcdir)/ospf6d/ospf6_interface.c +vtysh_scan += $(top_srcdir)/ospf6d/ospf6_intra.c +vtysh_scan += $(top_srcdir)/ospf6d/ospf6_lsa.c +vtysh_scan += $(top_srcdir)/ospf6d/ospf6_message.c +vtysh_scan += $(top_srcdir)/ospf6d/ospf6_neighbor.c +vtysh_scan += $(top_srcdir)/ospf6d/ospf6_route.c +vtysh_scan += $(top_srcdir)/ospf6d/ospf6_spf.c +vtysh_scan += $(top_srcdir)/ospf6d/ospf6_top.c +vtysh_scan += $(top_srcdir)/ospf6d/ospf6_zebra.c +vtysh_scan += $(top_srcdir)/ospf6d/ospf6d.c endif if RIPD -vtysh_scan += $(top_srcdir)/ripd/*.c +vtysh_scan += $(top_srcdir)/ripd/rip_debug.c +vtysh_scan += $(top_srcdir)/ripd/rip_interface.c +vtysh_scan += $(top_srcdir)/ripd/rip_offset.c +vtysh_scan += $(top_srcdir)/ripd/rip_zebra.c +vtysh_scan += $(top_srcdir)/ripd/ripd.c endif if RIPNGD -vtysh_scan += $(top_srcdir)/ripngd/*.c +vtysh_scan += $(top_srcdir)/ripngd/ripng_debug.c +vtysh_scan += $(top_srcdir)/ripngd/ripng_interface.c +vtysh_scan += $(top_srcdir)/ripngd/ripng_offset.c +vtysh_scan += $(top_srcdir)/ripngd/ripng_zebra.c +vtysh_scan += $(top_srcdir)/ripngd/ripngd.c endif if NHRPD From e879fd94d9c01ddc80e7d12fea3a7945e7e44a0d Mon Sep 17 00:00:00 2001 From: Phil Huang Date: Wed, 5 Apr 2017 16:00:56 +0800 Subject: [PATCH 61/61] Remove superfluous path and correct groupname Signed-off-by: Phil Huang --- doc/Building_FRR_on_Ubuntu1204.md | 24 ++++++++++++------------ doc/Building_FRR_on_Ubuntu1404.md | 22 +++++++++++----------- doc/Building_FRR_on_Ubuntu1604.md | 24 ++++++++++++------------ 3 files changed, 35 insertions(+), 35 deletions(-) diff --git a/doc/Building_FRR_on_Ubuntu1204.md b/doc/Building_FRR_on_Ubuntu1204.md index 82404097c5..154907d9df 100644 --- a/doc/Building_FRR_on_Ubuntu1204.md +++ b/doc/Building_FRR_on_Ubuntu1204.md @@ -102,20 +102,20 @@ an example.) ### Create empty FRR configuration files sudo mkdir /var/log/frr - sudo chown frr:fee /var/log/frr + sudo chown frr:frr /var/log/frr sudo mkdir /etc/frr - sudo touch /etc/frr/etc/zebra.conf - sudo touch /etc/frr/etc/bgpd.conf - sudo touch /etc/frr/etc/ospfd.conf - sudo touch /etc/frr/etc/ospf6d.conf - sudo touch /etc/frr/etc/isisd.conf - sudo touch /etc/frr/etc/ripd.conf - sudo touch /etc/frr/etc/ripngd.conf - sudo touch /etc/frr/etc/pimd.conf - sudo touch /etc/frr/etc/ldpd.conf + sudo touch /etc/frr/zebra.conf + sudo touch /etc/frr/bgpd.conf + sudo touch /etc/frr/ospfd.conf + sudo touch /etc/frr/ospf6d.conf + sudo touch /etc/frr/isisd.conf + sudo touch /etc/frr/ripd.conf + sudo touch /etc/frr/ripngd.conf + sudo touch /etc/frr/pimd.conf + sudo touch /etc/frr/ldpd.conf sudo chown frr:frr /etc/frr/ - sudo touch /etc/frr/etc/vtysh.conf - sudo chown frr:frrvty /etc/frr/etc/vtysh.conf + sudo touch /etc/frr/vtysh.conf + sudo chown frr:frrvty /etc/frr/vtysh.conf sudo chmod 640 /etc/frr/*.conf ### Enable IP & IPv6 forwarding diff --git a/doc/Building_FRR_on_Ubuntu1404.md b/doc/Building_FRR_on_Ubuntu1404.md index 0d7c6f76fe..33ef896a9a 100644 --- a/doc/Building_FRR_on_Ubuntu1404.md +++ b/doc/Building_FRR_on_Ubuntu1404.md @@ -62,19 +62,19 @@ an example.) ### Create empty FRR configuration files sudo mkdir /var/log/frr - sudo chown frr:fee /var/log/frr + sudo chown frr:frr /var/log/frr sudo mkdir /etc/frr - sudo touch /etc/frr/etc/zebra.conf - sudo touch /etc/frr/etc/bgpd.conf - sudo touch /etc/frr/etc/ospfd.conf - sudo touch /etc/frr/etc/ospf6d.conf - sudo touch /etc/frr/etc/isisd.conf - sudo touch /etc/frr/etc/ripd.conf - sudo touch /etc/frr/etc/ripngd.conf - sudo touch /etc/frr/etc/pimd.conf + sudo touch /etc/frr/zebra.conf + sudo touch /etc/frr/bgpd.conf + sudo touch /etc/frr/ospfd.conf + sudo touch /etc/frr/ospf6d.conf + sudo touch /etc/frr/isisd.conf + sudo touch /etc/frr/ripd.conf + sudo touch /etc/frr/ripngd.conf + sudo touch /etc/frr/pimd.conf sudo chown frr:frr /etc/frr/ - sudo touch /etc/frr/etc/vtysh.conf - sudo chown frr:frrvty /etc/frr/etc/vtysh.conf + sudo touch /etc/frr/vtysh.conf + sudo chown frr:frrvty /etc/frr/vtysh.conf sudo chmod 640 /etc/frr/*.conf ### Enable IP & IPv6 forwarding diff --git a/doc/Building_FRR_on_Ubuntu1604.md b/doc/Building_FRR_on_Ubuntu1604.md index b6e18088f0..18724859fb 100644 --- a/doc/Building_FRR_on_Ubuntu1604.md +++ b/doc/Building_FRR_on_Ubuntu1604.md @@ -63,20 +63,20 @@ an example.) ### Create empty FRR configuration files sudo mkdir /var/log/frr - sudo chown frr:fee /var/log/frr + sudo chown frr:frr /var/log/frr sudo mkdir /etc/frr - sudo touch /etc/frr/etc/zebra.conf - sudo touch /etc/frr/etc/bgpd.conf - sudo touch /etc/frr/etc/ospfd.conf - sudo touch /etc/frr/etc/ospf6d.conf - sudo touch /etc/frr/etc/isisd.conf - sudo touch /etc/frr/etc/ripd.conf - sudo touch /etc/frr/etc/ripngd.conf - sudo touch /etc/frr/etc/pimd.conf - sudo touch /etc/frr/etc/ldpd.conf + sudo touch /etc/frr/zebra.conf + sudo touch /etc/frr/bgpd.conf + sudo touch /etc/frr/ospfd.conf + sudo touch /etc/frr/ospf6d.conf + sudo touch /etc/frr/isisd.conf + sudo touch /etc/frr/ripd.conf + sudo touch /etc/frr/ripngd.conf + sudo touch /etc/frr/pimd.conf + sudo touch /etc/frr/ldpd.conf sudo chown frr:frr /etc/frr/ - sudo touch /etc/frr/etc/vtysh.conf - sudo chown frr:frrvty /etc/frr/etc/vtysh.conf + sudo touch /etc/frr/vtysh.conf + sudo chown frr:frrvty /etc/frr/vtysh.conf sudo chmod 640 /etc/frr/*.conf ### Enable IP & IPv6 forwarding