diff --git a/Makefile.am b/Makefile.am index 494fcd4d56..f204f8a724 100644 --- a/Makefile.am +++ b/Makefile.am @@ -5,7 +5,7 @@ include common.am AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/lib -I$(top_builddir) -I$(top_builddir)/lib AM_CFLAGS = $(WERROR) -DEFS = @DEFS@ -DSYSCONFDIR=\"$(sysconfdir)/\" +DEFS = @DEFS@ -DSYSCONFDIR=\"$(sysconfdir)/\" -DCONFDATE=$(CONFDATE) LIBCAP = @LIBCAP@ EXTRA_DIST = @@ -25,6 +25,14 @@ pkginclude_HEADERS = nodist_pkginclude_HEADERS = dist_examples_DATA = +## libtool, the self-made GNU scourge +## ... this should fix relinking +## ... and AUTOMAKE_DUMMY is needed to prevent automake from treating this +## as overriding the normal targets... +$(AUTOMAKE_DUMMY)install-moduleLTLIBRARIES: install-libLTLIBRARIES +$(AUTOMAKE_DUMMY)install-binPROGRAMS: install-libLTLIBRARIES +$(AUTOMAKE_DUMMY)install-sbinPROGRAMS: install-libLTLIBRARIES + include lib/subdir.am include zebra/subdir.am include qpb/subdir.am diff --git a/bgpd/bgp_main.c b/bgpd/bgp_main.c index 3bf9ea02d5..fa8c45b004 100644 --- a/bgpd/bgp_main.c +++ b/bgpd/bgp_main.c @@ -219,9 +219,6 @@ static __attribute__((__noreturn__)) void bgp_exit(int status) memset(bm, 0, sizeof(*bm)); frr_fini(); - - if (bgp_debug_count()) - log_memstats_stderr("bgpd"); exit(status); } diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 2256b069cb..beb1e2a2a0 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -20,6 +20,7 @@ */ #include +#include #include "prefix.h" #include "linklist.h" @@ -9349,6 +9350,7 @@ static const char *table_stats_strs[] = { struct bgp_table_stats { struct bgp_table *table; unsigned long long counts[BGP_STATS_MAX]; + double total_space; }; #if 0 @@ -9417,8 +9419,8 @@ static int bgp_table_stats_walker(struct thread *t) ts->counts[BGP_STATS_UNAGGREGATEABLE]++; /* announced address space */ if (space) - ts->counts[BGP_STATS_SPACE] += - 1 << (space - rn->p.prefixlen); + ts->total_space += pow(2.0, + space - rn->p.prefixlen); } else if (prn->info) ts->counts[BGP_STATS_MAX_AGGREGATEABLE]++; @@ -9528,31 +9530,26 @@ static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi, break; case BGP_STATS_SPACE: vty_out(vty, "%-30s: ", table_stats_strs[i]); - vty_out(vty, "%12llu\n", ts.counts[i]); - if (ts.counts[BGP_STATS_MAXBITLEN] < 9) - break; - vty_out(vty, "%30s: ", "%% announced "); - vty_out(vty, "%12.2f\n", - 100 * (float)ts.counts[BGP_STATS_SPACE] - / (float)((uint64_t)1UL - << ts.counts - [BGP_STATS_MAXBITLEN])); - vty_out(vty, "%30s: ", "/8 equivalent "); - vty_out(vty, "%12.2f\n", - (float)ts.counts[BGP_STATS_SPACE] - / (float)(1UL - << (ts.counts - [BGP_STATS_MAXBITLEN] - - 8))); - if (ts.counts[BGP_STATS_MAXBITLEN] < 25) - break; - vty_out(vty, "%30s: ", "/24 equivalent "); - vty_out(vty, "%12.2f", - (float)ts.counts[BGP_STATS_SPACE] - / (float)(1UL - << (ts.counts - [BGP_STATS_MAXBITLEN] - - 24))); + vty_out(vty, "%12g\n", ts.total_space); + + if (afi == AFI_IP6) { + vty_out(vty, "%30s: ", "/32 equivalent "); + vty_out(vty, "%12g\n", + ts.total_space * pow(2.0, -128+32)); + vty_out(vty, "%30s: ", "/48 equivalent "); + vty_out(vty, "%12g\n", + ts.total_space * pow(2.0, -128+48)); + } else { + vty_out(vty, "%30s: ", "% announced "); + vty_out(vty, "%12.2f\n", + ts.total_space * 100. * pow(2.0, -32)); + vty_out(vty, "%30s: ", "/8 equivalent "); + vty_out(vty, "%12.2f\n", + ts.total_space * pow(2.0, -32+8)); + vty_out(vty, "%30s: ", "/24 equivalent "); + vty_out(vty, "%12.2f\n", + ts.total_space * pow(2.0, -32+24)); + } break; default: vty_out(vty, "%-30s: ", table_stats_strs[i]); diff --git a/common.am b/common.am index b115a871b9..c0094b1b88 100644 --- a/common.am +++ b/common.am @@ -13,8 +13,7 @@ CLIPPY_DEPS = $(HOSTTOOLS)lib/clippy $(top_srcdir)/python/clidef.py SUFFIXES = _clippy.c .proto .pb-c.c .pb-c.h .pb.h .c_clippy.c: @{ test -x $(top_builddir)/$(HOSTTOOLS)lib/clippy || $(MAKE) -C $(top_builddir)/$(HOSTTOOLS) lib/clippy; } - $(AM_V_CLIPPY)$(top_builddir)/$(HOSTTOOLS)lib/clippy $(top_srcdir)/python/clidef.py $< > $@.tmp - @{ test -f $@ && diff $@.tmp $@ >/dev/null 2>/dev/null; } && rm $@.tmp || mv $@.tmp $@ + $(AM_V_CLIPPY)$(top_builddir)/$(HOSTTOOLS)lib/clippy $(top_srcdir)/python/clidef.py -o $@ $< ## automake's "ylwrap" is a great piece of GNU software... not. .l.c: diff --git a/git-reindent-branch.py b/git-reindent-branch.py index b0dd8db6de..c207f5946f 100644 --- a/git-reindent-branch.py +++ b/git-reindent-branch.py @@ -11,14 +11,28 @@ def run(cmd): proc.wait() return rv +clangfmt = run(['git', 'show', 'master:.clang-format']) + argp = argparse.ArgumentParser(description = 'git whitespace-fixing tool') argp.add_argument('branch', metavar='BRANCH', type = str, nargs = '?', default = 'HEAD') args = argp.parse_args() branch = args.branch commit = run(['git', 'rev-list', '-n', '1', branch, '--']).strip() -beforeid = run(['git', 'rev-list', '-n', '1', 'reindent-master-before', '--']).strip() -afterid = run(['git', 'rev-list', '-n', '1', 'reindent-master-after', '--']).strip() + +# frr-3.1-dev = first commit that is on master but not on stable/3.0 +masterid = run(['git', 'rev-list', '-n', '1', 'frr-3.1-dev', '--']).strip() +masterbase = run(['git', 'merge-base', commit, masterid]).strip() + +if masterbase == masterid: + refbranch = 'master' +else: + refbranch = '3.0' + +sys.stderr.write('autodetected base: %s (can be 3.0 or master)\n' % refbranch) + +beforeid = run(['git', 'rev-list', '-n', '1', 'reindent-%s-before' % refbranch, '--']).strip() +afterid = run(['git', 'rev-list', '-n', '1', 'reindent-%s-after' % refbranch, '--']).strip() beforebase = run(['git', 'merge-base', commit, beforeid]).strip() afterbase = run(['git', 'merge-base', commit, afterid]).strip() @@ -28,10 +42,10 @@ if afterbase == afterid: sys.exit(1) if beforebase != beforeid: - sys.stderr.write('you need to rebase your branch onto the tag "reindent-master-before"\n') + sys.stderr.write('you need to rebase your branch onto the tag "reindent-%s-before"\n' % refbranch) sys.exit(1) -revs = run(['git', 'rev-list', 'reindent-master-before..%s' % commit]).strip().split('\n') +revs = run(['git', 'rev-list', 'reindent-%s-before..%s' % (refbranch, commit)]).strip().split('\n') revs.reverse() srcdir = os.getcwd() @@ -39,9 +53,12 @@ tmpdir = tempfile.mkdtemp('frrindent') os.chdir(tmpdir) sys.stderr.write('using temporary directory %s; %d revisions\n' % (tmpdir, len(revs))) -run(['git', 'clone', '-s', '-b', 'reindent-master-after', srcdir, 'repo']) +run(['git', 'clone', '-s', '-b', 'reindent-%s-after' % refbranch, srcdir, 'repo']) os.chdir('repo') +with open('.clang-format', 'w') as fd: + fd.write(clangfmt) + prev = beforeid for rev in revs: filestat = run(['git', 'diff', '-z', '--name-status', prev, rev]).rstrip('\0').split('\0') diff --git a/lib/command.c b/lib/command.c index 45b5593a3e..c86025a3bd 100644 --- a/lib/command.c +++ b/lib/command.c @@ -42,6 +42,7 @@ #include "command_graph.h" #include "qobj.h" #include "defaults.h" +#include "libfrr.h" DEFINE_MTYPE(LIB, HOST, "Host config") DEFINE_MTYPE(LIB, STRVEC, "String vector") @@ -359,21 +360,23 @@ void install_element(enum node_type ntype, struct cmd_element *cmd) return; } - cnode = vector_slot(cmdvec, ntype); + cnode = vector_lookup(cmdvec, ntype); if (cnode == NULL) { fprintf(stderr, - "Command node %d doesn't exist, please check it\n", - ntype); - fprintf(stderr, - "Have you called install_node before this install_element?\n"); + "%s[%s]:\n" + "\tnode %d (%s) does not exist.\n" + "\tplease call install_node() before install_element()\n", + cmd->name, cmd->string, ntype, node_names[ntype]); exit(EXIT_FAILURE); } if (hash_lookup(cnode->cmd_hash, cmd) != NULL) { fprintf(stderr, - "Multiple command installs to node %d of command:\n%s\n", - ntype, cmd->string); + "%s[%s]:\n" + "\tnode %d (%s) already has this command installed.\n" + "\tduplicate install_element call?\n", + cmd->name, cmd->string, ntype, node_names[ntype]); return; } @@ -406,21 +409,23 @@ void uninstall_element(enum node_type ntype, struct cmd_element *cmd) return; } - cnode = vector_slot(cmdvec, ntype); + cnode = vector_lookup(cmdvec, ntype); if (cnode == NULL) { fprintf(stderr, - "Command node %d doesn't exist, please check it\n", - ntype); - fprintf(stderr, - "Have you called install_node before this install_element?\n"); + "%s[%s]:\n" + "\tnode %d (%s) does not exist.\n" + "\tplease call install_node() before uninstall_element()\n", + cmd->name, cmd->string, ntype, node_names[ntype]); exit(EXIT_FAILURE); } if (hash_release(cnode->cmd_hash, cmd) == NULL) { fprintf(stderr, - "Trying to uninstall non-installed command (node %d):\n%s\n", - ntype, cmd->string); + "%s[%s]:\n" + "\tnode %d (%s) does not have this command installed.\n" + "\tduplicate uninstall_element call?\n", + cmd->name, cmd->string, ntype, node_names[ntype]); return; } @@ -555,6 +560,9 @@ static int config_write_host(struct vty *vty) else if (!host.motd) vty_out(vty, "no banner motd\n"); + if (debug_memstats_at_exit) + vty_out(vty, "!\ndebug memstats-at-exit\n"); + return 1; } @@ -2366,6 +2374,17 @@ DEFUN (no_config_log_timestamp_precision, return CMD_SUCCESS; } +DEFUN (debug_memstats, + debug_memstats_cmd, + "[no] debug memstats-at-exit", + NO_STR + DEBUG_STR + "Print memory type statistics at exit\n") +{ + debug_memstats_at_exit = !!strcmp(argv[0]->text, "no"); + return CMD_SUCCESS; +} + int cmd_banner_motd_file(const char *file) { int success = CMD_SUCCESS; @@ -2527,6 +2546,7 @@ void cmd_init(int terminal) /* Each node's basic commands. */ install_element(VIEW_NODE, &show_version_cmd); install_element(ENABLE_NODE, &show_startup_config_cmd); + install_element(ENABLE_NODE, &debug_memstats_cmd); if (terminal) { install_element(VIEW_NODE, &config_list_cmd); @@ -2560,6 +2580,7 @@ void 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); + install_element(CONFIG_NODE, &debug_memstats_cmd); if (terminal > 0) { install_element(CONFIG_NODE, &password_cmd); diff --git a/lib/compiler.h b/lib/compiler.h new file mode 100644 index 0000000000..49a2f2a422 --- /dev/null +++ b/lib/compiler.h @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2015-2017 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 _FRR_COMPILER_H +#define _FRR_COMPILER_H + +/* function attributes, use like + * void prototype(void) __attribute__((_CONSTRUCTOR(100))); + */ +#if defined(__clang__) +# if __clang_major__ > 3 || (__clang_major__ == 3 && __clang_minor__ >= 5) +# define _RET_NONNULL , returns_nonnull +# endif +# define _CONSTRUCTOR(x) constructor(x) +#elif defined(__GNUC__) +# if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9) +# define _RET_NONNULL , returns_nonnull +# endif +# if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3) +# define _CONSTRUCTOR(x) constructor(x) +# define _DESTRUCTOR(x) destructor(x) +# define _ALLOC_SIZE(x) alloc_size(x) +# endif +#endif + +#ifdef __sun +/* Solaris doesn't do constructor priorities due to linker restrictions */ +# undef _CONSTRUCTOR +# undef _DESTRUCTOR +#endif + +/* fallback versions */ +#ifndef _RET_NONNULL +# define _RET_NONNULL +#endif +#ifndef _CONSTRUCTOR +# define _CONSTRUCTOR(x) constructor +#endif +#ifndef _DESTRUCTOR +# define _DESTRUCTOR(x) destructor +#endif +#ifndef _ALLOC_SIZE +# define _ALLOC_SIZE(x) +#endif + +/* + * for warnings on macros, put in the macro content like this: + * #define MACRO BLA CPP_WARN("MACRO has been deprecated") + */ +#define CPP_STR(X) #X + +#if defined(__ICC) +#define CPP_NOTICE(text) _Pragma(CPP_STR(message __FILE__ ": " text)) +#define CPP_WARN(text) CPP_NOTICE(text) + +#elif (defined(__GNUC__) \ + && (__GNUC__ >= 5 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8))) \ + || (defined(__clang__) \ + && (__clang_major__ >= 4 \ + || (__clang_major__ == 3 && __clang_minor__ >= 5))) +#define CPP_WARN(text) _Pragma(CPP_STR(GCC warning text)) +#define CPP_NOTICE(text) _Pragma(CPP_STR(message text)) + +#else +#define CPP_WARN(text) +#endif + +#endif /* _FRR_COMPILER_H */ diff --git a/lib/grammar_sandbox.c b/lib/grammar_sandbox.c index 96ecfa44d3..3c6396f347 100644 --- a/lib/grammar_sandbox.c +++ b/lib/grammar_sandbox.c @@ -404,7 +404,8 @@ DEFUN (grammar_findambig, nodegraph = cnode->cmdgraph; if (!nodegraph) continue; - vty_out(vty, "scanning node %d\n", scannode - 1); + vty_out(vty, "scanning node %d (%s)\n", + scannode - 1, node_names[scannode - 1]); } commands = cmd_graph_permutations(nodegraph); diff --git a/lib/libfrr.c b/lib/libfrr.c index 255f91ec71..9944fdd1e1 100644 --- a/lib/libfrr.c +++ b/lib/libfrr.c @@ -52,6 +52,8 @@ char frr_zclientpath[256]; static char pidfile_default[256]; static char vtypath_default[256]; +bool debug_memstats_at_exit = 0; + static char comb_optstr[256]; static struct option comb_lo[64]; static struct option *comb_next_lo = &comb_lo[0]; @@ -639,7 +641,10 @@ static void frr_daemon_wait(int fd) exit(0); /* child failed one way or another ... */ - if (WIFEXITED(exitstat)) + if (WIFEXITED(exitstat) && WEXITSTATUS(exitstat) == 0) + /* can happen in --terminal case if exit is fast enough */ + (void)0; + else if (WIFEXITED(exitstat)) fprintf(stderr, "%s failed to start, exited %d\n", di->name, WEXITSTATUS(exitstat)); else if (WIFSIGNALED(exitstat)) @@ -841,6 +846,10 @@ void frr_early_fini(void) void frr_fini(void) { + FILE *fp; + char filename[128]; + int have_leftovers; + hook_call(frr_fini); /* memory_init -> nothing needed */ @@ -851,4 +860,28 @@ void frr_fini(void) thread_master_free(master); closezlog(); /* frrmod_init -> nothing needed / hooks */ + + if (!debug_memstats_at_exit) + return; + + have_leftovers = log_memstats(stderr, di->name); + + /* in case we decide at runtime that we want exit-memstats for + * a daemon, but it has no stderr because it's daemonized + * (only do this if we actually have something to print though) + */ + if (!have_leftovers) + return; + + snprintf(filename, sizeof(filename), + "/tmp/frr-memstats-%s-%llu-%llu", + di->name, + (unsigned long long)getpid(), + (unsigned long long)time(NULL)); + + fp = fopen(filename, "w"); + if (fp) { + log_memstats(fp, di->name); + fclose(fp); + } } diff --git a/lib/libfrr.h b/lib/libfrr.h index 8a15d168a1..f7d69eecb3 100644 --- a/lib/libfrr.h +++ b/lib/libfrr.h @@ -121,4 +121,6 @@ extern const char frr_moduledir[]; extern char frr_protoname[]; extern char frr_protonameinst[]; +extern bool debug_memstats_at_exit; + #endif /* _ZEBRA_FRR_H */ diff --git a/lib/log.c b/lib/log.c index 0ea52ed401..ea2e804cda 100644 --- a/lib/log.c +++ b/lib/log.c @@ -701,7 +701,7 @@ void _zlog_assert_failed(const char *assertion, const char *file, assertion, file, line, (function ? function : "?")); zlog_backtrace(LOG_CRIT); zlog_thread_info(LOG_CRIT); - log_memstats_stderr("log"); + log_memstats(stderr, "log"); abort(); } diff --git a/lib/memory.c b/lib/memory.c index 0ccc204002..c684c7605c 100644 --- a/lib/memory.c +++ b/lib/memory.c @@ -104,6 +104,7 @@ int qmem_walk(qmem_walk_fn *func, void *arg) } struct exit_dump_args { + FILE *fp; const char *prefix; int error; }; @@ -113,7 +114,7 @@ static int qmem_exit_walker(void *arg, struct memgroup *mg, struct memtype *mt) struct exit_dump_args *eda = arg; if (!mt) { - fprintf(stderr, + fprintf(eda->fp, "%s: showing active allocations in " "memory group %s\n", eda->prefix, mg->name); @@ -122,15 +123,16 @@ static int qmem_exit_walker(void *arg, struct memgroup *mg, struct memtype *mt) char size[32]; eda->error++; snprintf(size, sizeof(size), "%10zu", mt->size); - fprintf(stderr, "%s: memstats: %-30s: %6zu * %s\n", + fprintf(eda->fp, "%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) +int log_memstats(FILE *fp, const char *prefix) { - struct exit_dump_args eda = {.prefix = prefix, .error = 0}; + struct exit_dump_args eda = { .fp = fp, .prefix = prefix, .error = 0 }; qmem_walk(qmem_exit_walker, &eda); + return eda.error; } diff --git a/lib/memory.h b/lib/memory.h index d5facad583..6de370514a 100644 --- a/lib/memory.h +++ b/lib/memory.h @@ -18,7 +18,9 @@ #define _QUAGGA_MEMORY_H #include +#include #include +#include "compiler.h" #define array_size(ar) (sizeof(ar) / sizeof(ar[0])) @@ -36,41 +38,6 @@ struct memgroup { const char *name; }; -#if defined(__clang__) -#if __clang_major__ > 3 || (__clang_major__ == 3 && __clang_minor__ >= 5) -# define _RET_NONNULL , returns_nonnull -#endif -# define _CONSTRUCTOR(x) constructor(x) -#elif defined(__GNUC__) -#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9) -# define _RET_NONNULL , returns_nonnull -#endif -#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3) -# define _CONSTRUCTOR(x) constructor(x) -# define _DESTRUCTOR(x) destructor(x) -# define _ALLOC_SIZE(x) alloc_size(x) -#endif -#endif - -#ifdef __sun -/* Solaris doesn't do constructor priorities due to linker restrictions */ -#undef _CONSTRUCTOR -#undef _DESTRUCTOR -#endif - -#ifndef _RET_NONNULL -# define _RET_NONNULL -#endif -#ifndef _CONSTRUCTOR -# define _CONSTRUCTOR(x) constructor -#endif -#ifndef _DESTRUCTOR -# define _DESTRUCTOR(x) destructor -#endif -#ifndef _ALLOC_SIZE -# define _ALLOC_SIZE(x) -#endif - /* macro usage: * * mydaemon.h @@ -194,7 +161,8 @@ static inline size_t mtype_stats_alloc(struct memtype *mt) * 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 *); +extern int log_memstats(FILE *fp, const char *); +#define log_memstats_stderr(prefix) log_memstats(stderr, prefix) extern void memory_oom(size_t size, const char *name); diff --git a/lib/plist.c b/lib/plist.c index b0cf42ca49..ebd628d724 100644 --- a/lib/plist.c +++ b/lib/plist.c @@ -122,6 +122,14 @@ const char *prefix_list_name(struct prefix_list *plist) return plist->name; } +afi_t prefix_list_afi(struct prefix_list *plist) +{ + if (plist->master == &prefix_master_ipv4 + || plist->master == &prefix_master_orf_v4) + return AFI_IP; + return AFI_IP6; +} + /* Lookup prefix_list from list of prefix_list by name. */ static struct prefix_list *prefix_list_lookup_do(afi_t afi, int orf, const char *name) diff --git a/lib/plist.h b/lib/plist.h index 73d8da509a..3eba3046ae 100644 --- a/lib/plist.h +++ b/lib/plist.h @@ -48,6 +48,7 @@ extern void prefix_list_add_hook(void (*func)(struct prefix_list *)); extern void prefix_list_delete_hook(void (*func)(struct prefix_list *)); extern const char *prefix_list_name(struct prefix_list *); +extern afi_t prefix_list_afi(struct prefix_list *); extern struct prefix_list *prefix_list_lookup(afi_t, const char *); extern enum prefix_list_type prefix_list_apply(struct prefix_list *, void *); diff --git a/lib/prefix.c b/lib/prefix.c index 2f61eb6e8b..10f77bda87 100644 --- a/lib/prefix.c +++ b/lib/prefix.c @@ -1263,5 +1263,6 @@ unsigned prefix_hash_key(void *pp) * padding and unused prefix bytes. */ memset(©, 0, sizeof(copy)); prefix_copy(©, (struct prefix *)pp); - return jhash(©, sizeof(copy), 0x55aa5a5a); + return jhash(©, offsetof(struct prefix, u.prefix) + + PSIZE(copy.prefixlen), 0x55aa5a5a); } diff --git a/lib/prefix.h b/lib/prefix.h index bc4abb492a..eab4ac2bb7 100644 --- a/lib/prefix.h +++ b/lib/prefix.h @@ -33,28 +33,13 @@ #endif #include "sockunion.h" #include "ipaddr.h" +#include "compiler.h" #ifndef ETH_ALEN #define ETH_ALEN 6 #endif /* for compatibility */ -#if defined(__ICC) -#define CPP_WARN_STR(X) #X -#define CPP_WARN(text) _Pragma(CPP_WARN_STR(message __FILE__ ": " text)) - -#elif (defined(__GNUC__) \ - && (__GNUC__ >= 5 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8))) \ - || (defined(__clang__) \ - && (__clang_major__ >= 4 \ - || (__clang_major__ == 3 && __clang_minor__ >= 5))) -#define CPP_WARN_STR(X) #X -#define CPP_WARN(text) _Pragma(CPP_WARN_STR(GCC warning text)) - -#else -#define CPP_WARN(text) -#endif - #ifdef ETHER_ADDR_LEN #undef ETHER_ADDR_LEN #endif diff --git a/lib/sigevent.c b/lib/sigevent.c index 2a04fa23cb..d55f368dfb 100644 --- a/lib/sigevent.c +++ b/lib/sigevent.c @@ -245,7 +245,7 @@ core_handler(int signo #endif ); /* dump memory stats on core */ - log_memstats_stderr("core_handler"); + log_memstats(stderr, "core_handler"); abort(); } diff --git a/lib/subdir.am b/lib/subdir.am index 8545184228..d6349ba22d 100644 --- a/lib/subdir.am +++ b/lib/subdir.am @@ -85,6 +85,7 @@ pkginclude_HEADERS += \ lib/command.h \ lib/command_graph.h \ lib/command_match.h \ + lib/compiler.h \ lib/csv.h \ lib/distribute.h \ lib/event_counter.h \ diff --git a/lib/vty.h b/lib/vty.h index dcb8da225d..9acd62af3c 100644 --- a/lib/vty.h +++ b/lib/vty.h @@ -25,6 +25,7 @@ #include "log.h" #include "sockunion.h" #include "qobj.h" +#include "compiler.h" #define VTY_BUFSIZ 4096 #define VTY_MAXHIST 20 @@ -182,23 +183,11 @@ struct vty_arg { /* Integrated configuration file. */ #define INTEGRATE_DEFAULT_CONFIG "frr.conf" -/* for compatibility */ -#if defined(__ICC) -#define CPP_WARN_STR(X) #X -#define CPP_WARN(text) _Pragma(CPP_WARN_STR(message __FILE__ ": " text)) - -#elif (defined(__GNUC__) \ - && (__GNUC__ >= 5 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8))) \ - || (defined(__clang__) \ - && (__clang_major__ >= 4 \ - || (__clang_major__ == 3 && __clang_minor__ >= 5))) -#define CPP_WARN_STR(X) #X -#define CPP_WARN(text) _Pragma(CPP_WARN_STR(GCC warning text)) - -#else -#define CPP_WARN(text) +#if CONFDATE > 20180401 +CPP_NOTICE("It's probably time to remove VTY_NEWLINE compatibility foo.") #endif +/* for compatibility */ #define VNL "\n" CPP_WARN("VNL has been replaced with \\n.") #define VTYNL "\n" CPP_WARN("VTYNL has been replaced with \\n.") #define VTY_NEWLINE "\n" CPP_WARN("VTY_NEWLINE has been replaced with \\n.") diff --git a/ospf6d/ospf6_abr.c b/ospf6d/ospf6_abr.c index f198ac4af6..36528d063c 100644 --- a/ospf6d/ospf6_abr.c +++ b/ospf6d/ospf6_abr.c @@ -386,27 +386,20 @@ int ospf6_abr_originate_summary_to_area(struct ospf6_route *route, } /* Check filter-list */ - if (PREFIX_NAME_OUT(area)) { - if (PREFIX_LIST_OUT(area) == NULL) - PREFIX_LIST_OUT(area) = prefix_list_lookup( - AFI_IP6, PREFIX_NAME_OUT(area)); - - if (PREFIX_LIST_OUT(area)) - if (prefix_list_apply(PREFIX_LIST_OUT(area), - &route->prefix) - != PREFIX_PERMIT) { - if (is_debug) { - inet_ntop(AF_INET, - &(ADV_ROUTER_IN_PREFIX( - &route->prefix)), - buf, sizeof(buf)); - zlog_debug( - "prefix %s was denied by filter-list out", - buf); - } - return 0; + if (PREFIX_LIST_OUT(area)) + if (prefix_list_apply(PREFIX_LIST_OUT(area), &route->prefix) + != PREFIX_PERMIT) { + if (is_debug) { + inet_ntop(AF_INET, + &(ADV_ROUTER_IN_PREFIX( + &route->prefix)), + buf, sizeof(buf)); + zlog_debug( + "prefix %s was denied by filter-list out", + buf); } - } + return 0; + } /* the route is going to be originated. store it in area's summary_table */ @@ -873,22 +866,16 @@ void ospf6_abr_examin_summary(struct ospf6_lsa *lsa, struct ospf6_area *oa) } /* Check input prefix-list */ - if (PREFIX_NAME_IN(oa)) { - if (PREFIX_LIST_IN(oa) == NULL) - PREFIX_LIST_IN(oa) = - prefix_list_lookup(AFI_IP6, PREFIX_NAME_IN(oa)); - - if (PREFIX_LIST_IN(oa)) - if (prefix_list_apply(PREFIX_LIST_IN(oa), &prefix) - != PREFIX_PERMIT) { - if (is_debug) - zlog_debug( - "Prefix was denied by prefix-list"); - if (old) - ospf6_route_remove(old, table); - return; - } - } + if (PREFIX_LIST_IN(oa)) + if (prefix_list_apply(PREFIX_LIST_IN(oa), &prefix) + != PREFIX_PERMIT) { + if (is_debug) + zlog_debug( + "Prefix was denied by prefix-list"); + if (old) + ospf6_route_remove(old, table); + return; + } /* (5),(6): the path preference is handled by the sorting in the routing table. Always install the path by substituting diff --git a/ospf6d/ospf6_area.c b/ospf6d/ospf6_area.c index a4cc0bf420..649d7a1000 100644 --- a/ospf6d/ospf6_area.c +++ b/ospf6d/ospf6_area.c @@ -45,6 +45,8 @@ #include "ospf6_asbr.h" #include "ospf6d.h" +DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_PLISTNAME, "Prefix list name") + int ospf6_area_cmp(void *va, void *vb) { struct ospf6_area *oa = (struct ospf6_area *)va; @@ -579,17 +581,15 @@ DEFUN (area_filter_list, plist = prefix_list_lookup(AFI_IP6, plistname); if (strmatch(inout, "in")) { PREFIX_LIST_IN(area) = plist; - if (PREFIX_NAME_IN(area)) - free(PREFIX_NAME_IN(area)); - - PREFIX_NAME_IN(area) = strdup(plistname); + XFREE(MTYPE_OSPF6_PLISTNAME, PREFIX_NAME_IN(area)); + PREFIX_NAME_IN(area) = XSTRDUP(MTYPE_OSPF6_PLISTNAME, + plistname); ospf6_abr_reimport(area); } else { PREFIX_LIST_OUT(area) = plist; - if (PREFIX_NAME_OUT(area)) - free(PREFIX_NAME_OUT(area)); - - PREFIX_NAME_OUT(area) = strdup(plistname); + XFREE(MTYPE_OSPF6_PLISTNAME, PREFIX_NAME_OUT(area)); + PREFIX_NAME_OUT(area) = XSTRDUP(MTYPE_OSPF6_PLISTNAME, + plistname); ospf6_abr_enable_area(area); } @@ -622,27 +622,34 @@ DEFUN (no_area_filter_list, return CMD_SUCCESS; PREFIX_LIST_IN(area) = NULL; - if (PREFIX_NAME_IN(area)) - free(PREFIX_NAME_IN(area)); - - PREFIX_NAME_IN(area) = NULL; + XFREE(MTYPE_OSPF6_PLISTNAME, PREFIX_NAME_IN(area)); ospf6_abr_reimport(area); } else { if (PREFIX_NAME_OUT(area)) if (!strmatch(PREFIX_NAME_OUT(area), plistname)) return CMD_SUCCESS; - PREFIX_LIST_OUT(area) = NULL; - if (PREFIX_NAME_OUT(area)) - free(PREFIX_NAME_OUT(area)); - - PREFIX_NAME_OUT(area) = NULL; + XFREE(MTYPE_OSPF6_PLISTNAME, PREFIX_NAME_OUT(area)); ospf6_abr_enable_area(area); } return CMD_SUCCESS; } +void ospf6_area_plist_update(struct prefix_list *plist, int add) +{ + struct ospf6_area *oa; + struct listnode *n; + const char *name = prefix_list_name(plist); + + for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, n, oa)) { + if (!strcmp(PREFIX_NAME_IN(oa), name)) + PREFIX_LIST_IN(oa) = add ? plist : NULL; + if (!strcmp(PREFIX_NAME_OUT(oa), name)) + PREFIX_LIST_OUT(oa) = add ? plist : NULL; + } +} + DEFUN (area_import_list, area_import_list_cmd, "area A.B.C.D import-list NAME", diff --git a/ospf6d/ospf6_area.h b/ospf6d/ospf6_area.h index 4bc24a6dd8..d212d92387 100644 --- a/ospf6d/ospf6_area.h +++ b/ospf6d/ospf6_area.h @@ -122,6 +122,7 @@ extern void ospf6_area_disable(struct ospf6_area *); extern void ospf6_area_show(struct vty *, struct ospf6_area *); +extern void ospf6_area_plist_update(struct prefix_list *plist, int add); extern void ospf6_area_config_write(struct vty *vty); extern void ospf6_area_init(void); diff --git a/ospf6d/ospf6d.c b/ospf6d/ospf6d.c index f6b9e0ec14..84a56fb505 100644 --- a/ospf6d/ospf6d.c +++ b/ospf6d/ospf6d.c @@ -24,6 +24,7 @@ #include "linklist.h" #include "vty.h" #include "command.h" +#include "plist.h" #include "ospf6_proto.h" #include "ospf6_network.h" @@ -1139,6 +1140,20 @@ DEFUN (show_ipv6_ospf6_linkstate_detail, return CMD_SUCCESS; } +static void ospf6_plist_add(struct prefix_list *plist) +{ + if (prefix_list_afi(plist) != AFI_IP6) + return; + ospf6_area_plist_update(plist, 1); +} + +static void ospf6_plist_del(struct prefix_list *plist) +{ + if (prefix_list_afi(plist) != AFI_IP6) + return; + ospf6_area_plist_update(plist, 0); +} + /* Install ospf related commands. */ void ospf6_init(void) { @@ -1154,6 +1169,9 @@ void ospf6_init(void) ospf6_asbr_init(); ospf6_abr_init(); + prefix_list_add_hook(ospf6_plist_add); + prefix_list_delete_hook(ospf6_plist_del); + ospf6_bfd_init(); install_node(&debug_node, config_write_ospf6_debug); diff --git a/python/clidef.py b/python/clidef.py index 8e3c7595b7..aa6cd18b8b 100644 --- a/python/clidef.py +++ b/python/clidef.py @@ -257,4 +257,4 @@ if __name__ == '__main__': process_file(args.cfile, ofd, dumpfd, args.all_defun) if args.o is not None: - clippy.wrdiff(args.o, ofd) + clippy.wrdiff(args.o, ofd, [args.cfile, os.path.realpath(__file__)]) diff --git a/python/clippy/__init__.py b/python/clippy/__init__.py index 82aa9495d4..41aeae6b4d 100644 --- a/python/clippy/__init__.py +++ b/python/clippy/__init__.py @@ -16,6 +16,7 @@ # with this program; see the file COPYING; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +import os, stat import _clippy from _clippy import parse, Graph, GraphNode @@ -47,7 +48,7 @@ def dump(graph): for i, depth in graph_iterate(graph): print('\t%s%s %r' % (' ' * (depth * 2), i.type, i.text)) -def wrdiff(filename, buf): +def wrdiff(filename, buf, reffiles = []): '''write buffer to file if contents changed''' expl = '' @@ -57,8 +58,16 @@ def wrdiff(filename, buf): try: old = open(filename, 'r').read() except: pass if old == buf: + for reffile in reffiles: + # ensure output timestamp is newer than inputs, for make + reftime = os.stat(reffile)[stat.ST_MTIME] + outtime = os.stat(filename)[stat.ST_MTIME] + if outtime <= reftime: + os.utime(filename, (reftime + 1, reftime + 1)) # sys.stderr.write('%s unchanged, not written\n' % (filename)) return - with open('.new.' + filename, 'w') as out: + + newname = '%s.new-%d' % (filename, os.getpid()) + with open(newname, 'w') as out: out.write(buf) - os.rename('.new.' + filename, filename) + os.rename(newname, filename) diff --git a/tests/isisd/test_fuzz_isis_tlv.c b/tests/isisd/test_fuzz_isis_tlv.c index 6727e663f5..e61e9639ee 100644 --- a/tests/isisd/test_fuzz_isis_tlv.c +++ b/tests/isisd/test_fuzz_isis_tlv.c @@ -23,7 +23,7 @@ static bool atexit_registered; static void show_meminfo_at_exit(void) { - log_memstats_stderr("isis fuzztest"); + log_memstats(stderr, "isis fuzztest"); } static int comp_line(const void *p1, const void *p2) diff --git a/tests/lib/cli/common_cli.c b/tests/lib/cli/common_cli.c index 77f1610fe2..0fd2f80a39 100644 --- a/tests/lib/cli/common_cli.c +++ b/tests/lib/cli/common_cli.c @@ -53,7 +53,7 @@ static void vty_do_exit(int isexit) thread_master_free(master); closezlog(); - log_memstats_stderr("testcli"); + log_memstats(stderr, "testcli"); if (!isexit) exit(0); } diff --git a/zebra/zebra_fpm.c b/zebra/zebra_fpm.c index b88bce9e82..8c0700ac8b 100644 --- a/zebra/zebra_fpm.c +++ b/zebra/zebra_fpm.c @@ -1589,8 +1589,10 @@ static int fpm_remote_srv_write(struct vty *vty) in.s_addr = zfpm_g->fpm_server; - if (zfpm_g->fpm_server != FPM_DEFAULT_IP - || zfpm_g->fpm_port != FPM_DEFAULT_PORT) + if ((zfpm_g->fpm_server != FPM_DEFAULT_IP + && zfpm_g->fpm_server != INADDR_ANY) + || (zfpm_g->fpm_port != FPM_DEFAULT_PORT + && zfpm_g->fpm_port != 0)) vty_out(vty, "fpm connection ip %s port %d\n", inet_ntoa(in), zfpm_g->fpm_port);