From 08c4c73be6073282e73a9d7074212df39e27aa5c Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Tue, 8 Aug 2017 09:00:28 +0200 Subject: [PATCH 001/130] lib: hooks: support priority ordering & reversing Allow registering callbacks with a priority value used to order them relative to each other. Plus a reverse variant that just flips the direction on priorities. Signed-off-by: David Lamparter --- lib/hook.c | 16 ++++++++++++---- lib/hook.h | 51 ++++++++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 58 insertions(+), 9 deletions(-) diff --git a/lib/hook.c b/lib/hook.c index 2c877cbf45..1468c4d329 100644 --- a/lib/hook.c +++ b/lib/hook.c @@ -26,17 +26,25 @@ 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 frrmod_runtime *module, const char *funcname, + int priority) { - struct hookent *he = XCALLOC(MTYPE_HOOK_ENTRY, sizeof(*he)); + struct hookent *he = XCALLOC(MTYPE_HOOK_ENTRY, sizeof(*he)), **pos; he->hookfn = funcptr; he->hookarg = arg; he->has_arg = has_arg; he->module = module; he->fnname = funcname; + he->priority = priority; - he->next = hook->entries; - hook->entries = he; + for (pos = &hook->entries; *pos; pos = &(*pos)->next) + if (hook->reverse + ? (*pos)->priority < priority + : (*pos)->priority >= priority) + break; + + he->next = *pos; + *pos = he; } void _hook_unregister(struct hook *hook, void *funcptr, void *arg, bool has_arg) diff --git a/lib/hook.h b/lib/hook.h index 4a5cee2fd3..5f45e113e7 100644 --- a/lib/hook.h +++ b/lib/hook.h @@ -74,6 +74,29 @@ * hook_register_arg (some_update_event, event_handler, addonptr); * * (addonptr isn't typesafe, but that should be manageable.) + * + * Hooks also support a "priority" value for ordering registered calls + * relative to each other. The priority is a signed integer where lower + * values are called earlier. There is also "Koohs", which is hooks with + * reverse priority ordering (for cleanup/deinit hooks, so you can use the + * same priority value). + * + * Recommended priority value ranges are: + * + * -999 ... 0 ... 999 - main executable / daemon, or library + * -1999 ... -1000 - modules registering calls that should run before + * the daemon's bits + * 1000 ... 1999 - modules calls that should run after daemon's + * + * Note: the default value is 1000, based on the following 2 expectations: + * - most hook_register() usage will be in loadable modules + * - usage of hook_register() in the daemon itself may need relative ordering + * to itself, making an explicit value the expected case + * + * The priority value is passed as extra argument on hook_register_prio() / + * hook_register_arg_prio(). Whether a hook runs in reverse is determined + * solely by the code defining / calling the hook. (DECLARE_KOOH is actually + * the same thing as DECLARE_HOOK, it's just there to make it obvious.) */ /* TODO: @@ -94,6 +117,7 @@ struct hookent { void *hookfn; /* actually a function pointer */ void *hookarg; bool has_arg; + int priority; struct frrmod_runtime *module; const char *fnname; }; @@ -101,8 +125,11 @@ struct hookent { struct hook { const char *name; struct hookent *entries; + bool reverse; }; +#define HOOK_DEFAULT_PRIORITY 1000 + /* subscribe/add callback function to a hook * * always use hook_register(), which uses the static inline helper from @@ -110,14 +137,21 @@ struct hook { */ extern void _hook_register(struct hook *hook, void *funcptr, void *arg, bool has_arg, struct frrmod_runtime *module, - const char *funcname); + const char *funcname, int priority); #define hook_register(hookname, func) \ _hook_register(&_hook_##hookname, _hook_typecheck_##hookname(func), \ - NULL, false, THIS_MODULE, #func) + NULL, false, THIS_MODULE, #func, HOOK_DEFAULT_PRIORITY) #define hook_register_arg(hookname, func, arg) \ _hook_register(&_hook_##hookname, \ _hook_typecheck_arg_##hookname(func), arg, true, \ - THIS_MODULE, #func) + THIS_MODULE, #func, HOOK_DEFAULT_PRIORITY) +#define hook_register_prio(hookname, prio, func) \ + _hook_register(&_hook_##hookname, _hook_typecheck_##hookname(func), \ + NULL, false, THIS_MODULE, #func, prio) +#define hook_register_arg_prio(hookname, prio, func, arg) \ + _hook_register(&_hook_##hookname, \ + _hook_typecheck_arg_##hookname(func), \ + arg, true, THIS_MODULE, #func, prio) extern void _hook_unregister(struct hook *hook, void *funcptr, void *arg, bool has_arg); @@ -156,12 +190,14 @@ extern void _hook_unregister(struct hook *hook, void *funcptr, void *arg, { \ return (void *)funcptr; \ } +#define DECLARE_KOOH(hookname, arglist, passlist) \ + DECLARE_HOOK(hookname, arglist, passlist) /* use in source file - contains hook-related definitions. */ -#define DEFINE_HOOK(hookname, arglist, passlist) \ +#define DEFINE_HOOK_INT(hookname, arglist, passlist, rev) \ struct hook _hook_##hookname = { \ - .name = #hookname, .entries = NULL, \ + .name = #hookname, .entries = NULL, .reverse = rev, \ }; \ static int hook_call_##hookname arglist \ { \ @@ -184,4 +220,9 @@ extern void _hook_unregister(struct hook *hook, void *funcptr, void *arg, return hooksum; \ } +#define DEFINE_HOOK(hookname, arglist, passlist) \ + DEFINE_HOOK_INT(hookname, arglist, passlist, false) +#define DEFINE_KOOH(hookname, arglist, passlist) \ + DEFINE_HOOK_INT(hookname, arglist, passlist, true) + #endif /* _FRR_HOOK_H */ From 03951374770da5be620e48768588928fbd809c83 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Sun, 6 Aug 2017 08:28:16 +0200 Subject: [PATCH 002/130] *: centralize some exit cleanup into libfrr Start creating a counterpart to frr_init and frr_late_init. Unfortunately, some daemons don't do any exit handling, this doesn't change that just yet. Signed-off-by: David Lamparter --- bgpd/bgp_main.c | 12 ++++-------- ldpd/ldpd.c | 8 +++----- lib/libfrr.c | 21 +++++++++++++++++++++ lib/libfrr.h | 8 ++++++++ nhrpd/nhrp_main.c | 9 ++------- ospf6d/ospf6_main.c | 10 +++------- zebra/main.c | 8 +++----- 7 files changed, 44 insertions(+), 32 deletions(-) diff --git a/bgpd/bgp_main.c b/bgpd/bgp_main.c index 25a562ed68..a80dff271d 100644 --- a/bgpd/bgp_main.c +++ b/bgpd/bgp_main.c @@ -172,6 +172,8 @@ static __attribute__((__noreturn__)) void bgp_exit(int status) /* it only makes sense for this to be called on a clean exit */ assert(status == 0); + frr_early_fini(); + bfd_gbl_exit(); bgp_close(); @@ -214,22 +216,16 @@ static __attribute__((__noreturn__)) void bgp_exit(int status) community_list_terminate(bgp_clist); bgp_vrf_terminate(); - cmd_terminate(); - vty_terminate(); #if ENABLE_BGP_VNC vnc_zebra_destroy(); #endif bgp_zebra_destroy(); - /* reverse bgp_master_init */ - if (bm->master) - thread_master_free(bm->master); - - closezlog(); - list_delete(bm->bgp); memset(bm, 0, sizeof(*bm)); + frr_fini(); + if (bgp_debug_count()) log_memstats_stderr("bgpd"); exit(status); diff --git a/ldpd/ldpd.c b/ldpd/ldpd.c index 80af2b14e5..0a586ec1c5 100644 --- a/ldpd/ldpd.c +++ b/ldpd/ldpd.c @@ -392,6 +392,8 @@ ldpd_shutdown(void) pid_t pid; int status; + frr_early_fini(); + /* close pipes */ msgbuf_clear(&iev_ldpe->ibuf.w); close(iev_ldpe->ibuf.fd); @@ -423,13 +425,9 @@ ldpd_shutdown(void) vrf_terminate(); access_list_reset(); - cmd_terminate(); - vty_terminate(); ldp_zebra_destroy(); - zprivs_terminate(&ldpd_privs); - thread_master_free(master); - closezlog(); + frr_fini(); exit(0); } diff --git a/lib/libfrr.c b/lib/libfrr.c index a5c87e6edc..255f91ec71 100644 --- a/lib/libfrr.c +++ b/lib/libfrr.c @@ -37,6 +37,8 @@ #include "network.h" DEFINE_HOOK(frr_late_init, (struct thread_master * tm), (tm)) +DEFINE_KOOH(frr_early_fini, (), ()) +DEFINE_KOOH(frr_fini, (), ()) const char frr_sysconfdir[] = SYSCONFDIR; const char frr_vtydir[] = DAEMON_VTY_DIR; @@ -831,3 +833,22 @@ void frr_run(struct thread_master *master) while (thread_fetch(master, &thread)) thread_call(&thread); } + +void frr_early_fini(void) +{ + hook_call(frr_early_fini); +} + +void frr_fini(void) +{ + hook_call(frr_fini); + + /* memory_init -> nothing needed */ + vty_terminate(); + cmd_terminate(); + zprivs_terminate(di->privs); + /* signal_init -> nothing needed */ + thread_master_free(master); + closezlog(); + /* frrmod_init -> nothing needed / hooks */ +} diff --git a/lib/libfrr.h b/lib/libfrr.h index 1710fc9a84..8a15d168a1 100644 --- a/lib/libfrr.h +++ b/lib/libfrr.h @@ -104,6 +104,14 @@ extern void frr_run(struct thread_master *master); extern bool frr_zclient_addr(struct sockaddr_storage *sa, socklen_t *sa_len, const char *path); +/* these two are before the protocol daemon does its own shutdown + * it's named this way being the counterpart to frr_late_init */ +DECLARE_KOOH(frr_early_fini, (), ()) +extern void frr_early_fini(void); +/* and these two are after the daemon did its own cleanup */ +DECLARE_KOOH(frr_fini, (), ()) +extern void frr_fini(void); + extern char config_default[256]; extern char frr_zclientpath[256]; extern const char frr_sysconfdir[]; diff --git a/nhrpd/nhrp_main.c b/nhrpd/nhrp_main.c index 012d5cd87c..3a7186c1d7 100644 --- a/nhrpd/nhrp_main.c +++ b/nhrpd/nhrp_main.c @@ -81,6 +81,7 @@ static void nhrp_sigusr1(void) static void nhrp_request_stop(void) { debugf(NHRP_DEBUG_COMMON, "Exiting..."); + frr_early_fini(); nhrp_shortcut_terminate(); nhrp_nhs_terminate(); @@ -89,15 +90,9 @@ static void nhrp_request_stop(void) evmgr_terminate(); nhrp_vc_terminate(); vrf_terminate(); - /* memory_terminate(); */ - /* vty_terminate(); */ - cmd_terminate(); - /* signal_terminate(); */ - zprivs_terminate(&nhrpd_privs); debugf(NHRP_DEBUG_COMMON, "Done."); - - closezlog(); + frr_fini(); exit(0); } diff --git a/ospf6d/ospf6_main.c b/ospf6d/ospf6_main.c index 28bb956c40..e582737f94 100644 --- a/ospf6d/ospf6_main.c +++ b/ospf6d/ospf6_main.c @@ -82,6 +82,8 @@ static void __attribute__((noreturn)) ospf6_exit(int status) struct listnode *node; struct interface *ifp; + frr_early_fini(); + if (ospf6) ospf6_delete(ospf6); @@ -96,19 +98,13 @@ static void __attribute__((noreturn)) ospf6_exit(int status) ospf6_lsa_terminate(); vrf_terminate(); - vty_terminate(); - cmd_terminate(); if (zclient) { zclient_stop(zclient); zclient_free(zclient); } - if (master) - thread_master_free(master); - - closezlog(); - + frr_fini(); exit(status); } diff --git a/zebra/main.c b/zebra/main.c index 538c2f0663..c3a7d3635f 100644 --- a/zebra/main.c +++ b/zebra/main.c @@ -125,6 +125,7 @@ static void sigint(void) zlog_notice("Terminating on signal"); + frr_early_fini(); #ifdef HAVE_IRDP irdp_finish(); #endif @@ -147,17 +148,14 @@ static void sigint(void) access_list_reset(); prefix_list_reset(); route_map_finish(); - cmd_terminate(); - vty_terminate(); - zprivs_terminate(&zserv_privs); + list_delete(zebrad.client_list); work_queue_free(zebrad.ribq); if (zebrad.lsp_process_q) work_queue_free(zebrad.lsp_process_q); meta_queue_free(zebrad.mq); - thread_master_free(zebrad.master); - closezlog(); + frr_fini(); exit(0); } From 2a6a7a656d0d1e0afff091515737cdee2a3dbfe8 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Tue, 8 Aug 2017 10:30:37 +0200 Subject: [PATCH 003/130] doc: sample code-doc in .rst+sphinx Signed-off-by: David Lamparter --- doc/code/.gitignore | 3 + doc/code/Makefile | 216 +++++++++++++++++++++++++++++++ doc/code/conf.py | 293 ++++++++++++++++++++++++++++++++++++++++++ doc/code/hooks.rst | 171 ++++++++++++++++++++++++ doc/code/index.rst | 18 +++ doc/code/library.rst | 10 ++ doc/code/memtypes.rst | 117 +++++++++++++++++ 7 files changed, 828 insertions(+) create mode 100644 doc/code/.gitignore create mode 100644 doc/code/Makefile create mode 100644 doc/code/conf.py create mode 100644 doc/code/hooks.rst create mode 100644 doc/code/index.rst create mode 100644 doc/code/library.rst create mode 100644 doc/code/memtypes.rst diff --git a/doc/code/.gitignore b/doc/code/.gitignore new file mode 100644 index 0000000000..0505537159 --- /dev/null +++ b/doc/code/.gitignore @@ -0,0 +1,3 @@ +/_templates +/_build +!/Makefile diff --git a/doc/code/Makefile b/doc/code/Makefile new file mode 100644 index 0000000000..056b78e68e --- /dev/null +++ b/doc/code/Makefile @@ -0,0 +1,216 @@ +# Makefile for Sphinx documentation +# + +# You can set these variables from the command line. +SPHINXOPTS = +SPHINXBUILD = sphinx-build +PAPER = +BUILDDIR = _build + +# User-friendly check for sphinx-build +ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1) +$(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/) +endif + +# Internal variables. +PAPEROPT_a4 = -D latex_paper_size=a4 +PAPEROPT_letter = -D latex_paper_size=letter +ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . +# the i18n builder cannot share the environment and doctrees with the others +I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . + +.PHONY: help +help: + @echo "Please use \`make ' where is one of" + @echo " html to make standalone HTML files" + @echo " dirhtml to make HTML files named index.html in directories" + @echo " singlehtml to make a single large HTML file" + @echo " pickle to make pickle files" + @echo " json to make JSON files" + @echo " htmlhelp to make HTML files and a HTML help project" + @echo " qthelp to make HTML files and a qthelp project" + @echo " applehelp to make an Apple Help Book" + @echo " devhelp to make HTML files and a Devhelp project" + @echo " epub to make an epub" + @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" + @echo " latexpdf to make LaTeX files and run them through pdflatex" + @echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx" + @echo " text to make text files" + @echo " man to make manual pages" + @echo " texinfo to make Texinfo files" + @echo " info to make Texinfo files and run them through makeinfo" + @echo " gettext to make PO message catalogs" + @echo " changes to make an overview of all changed/added/deprecated items" + @echo " xml to make Docutils-native XML files" + @echo " pseudoxml to make pseudoxml-XML files for display purposes" + @echo " linkcheck to check all external links for integrity" + @echo " doctest to run all doctests embedded in the documentation (if enabled)" + @echo " coverage to run coverage check of the documentation (if enabled)" + +.PHONY: clean +clean: + rm -rf $(BUILDDIR)/* + +.PHONY: html +html: + $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." + +.PHONY: dirhtml +dirhtml: + $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." + +.PHONY: singlehtml +singlehtml: + $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml + @echo + @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." + +.PHONY: pickle +pickle: + $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle + @echo + @echo "Build finished; now you can process the pickle files." + +.PHONY: json +json: + $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json + @echo + @echo "Build finished; now you can process the JSON files." + +.PHONY: htmlhelp +htmlhelp: + $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp + @echo + @echo "Build finished; now you can run HTML Help Workshop with the" \ + ".hhp project file in $(BUILDDIR)/htmlhelp." + +.PHONY: qthelp +qthelp: + $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp + @echo + @echo "Build finished; now you can run "qcollectiongenerator" with the" \ + ".qhcp project file in $(BUILDDIR)/qthelp, like this:" + @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/FRR.qhcp" + @echo "To view the help file:" + @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/FRR.qhc" + +.PHONY: applehelp +applehelp: + $(SPHINXBUILD) -b applehelp $(ALLSPHINXOPTS) $(BUILDDIR)/applehelp + @echo + @echo "Build finished. The help book is in $(BUILDDIR)/applehelp." + @echo "N.B. You won't be able to view it unless you put it in" \ + "~/Library/Documentation/Help or install it in your application" \ + "bundle." + +.PHONY: devhelp +devhelp: + $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp + @echo + @echo "Build finished." + @echo "To view the help file:" + @echo "# mkdir -p $$HOME/.local/share/devhelp/FRR" + @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/FRR" + @echo "# devhelp" + +.PHONY: epub +epub: + $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub + @echo + @echo "Build finished. The epub file is in $(BUILDDIR)/epub." + +.PHONY: latex +latex: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo + @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." + @echo "Run \`make' in that directory to run these through (pdf)latex" \ + "(use \`make latexpdf' here to do that automatically)." + +.PHONY: latexpdf +latexpdf: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo "Running LaTeX files through pdflatex..." + $(MAKE) -C $(BUILDDIR)/latex all-pdf + @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." + +.PHONY: latexpdfja +latexpdfja: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo "Running LaTeX files through platex and dvipdfmx..." + $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja + @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." + +.PHONY: text +text: + $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text + @echo + @echo "Build finished. The text files are in $(BUILDDIR)/text." + +.PHONY: man +man: + $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man + @echo + @echo "Build finished. The manual pages are in $(BUILDDIR)/man." + +.PHONY: texinfo +texinfo: + $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo + @echo + @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." + @echo "Run \`make' in that directory to run these through makeinfo" \ + "(use \`make info' here to do that automatically)." + +.PHONY: info +info: + $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo + @echo "Running Texinfo files through makeinfo..." + make -C $(BUILDDIR)/texinfo info + @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." + +.PHONY: gettext +gettext: + $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale + @echo + @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." + +.PHONY: changes +changes: + $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes + @echo + @echo "The overview file is in $(BUILDDIR)/changes." + +.PHONY: linkcheck +linkcheck: + $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck + @echo + @echo "Link check complete; look for any errors in the above output " \ + "or in $(BUILDDIR)/linkcheck/output.txt." + +.PHONY: doctest +doctest: + $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest + @echo "Testing of doctests in the sources finished, look at the " \ + "results in $(BUILDDIR)/doctest/output.txt." + +.PHONY: coverage +coverage: + $(SPHINXBUILD) -b coverage $(ALLSPHINXOPTS) $(BUILDDIR)/coverage + @echo "Testing of coverage in the sources finished, look at the " \ + "results in $(BUILDDIR)/coverage/python.txt." + +.PHONY: xml +xml: + $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml + @echo + @echo "Build finished. The XML files are in $(BUILDDIR)/xml." + +.PHONY: pseudoxml +pseudoxml: + $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml + @echo + @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml." diff --git a/doc/code/conf.py b/doc/code/conf.py new file mode 100644 index 0000000000..38be7f2fca --- /dev/null +++ b/doc/code/conf.py @@ -0,0 +1,293 @@ +# -*- coding: utf-8 -*- +# +# FRR documentation build configuration file, created by +# sphinx-quickstart on Tue Jan 31 16:00:52 2017. +# +# This file is execfile()d with the current directory set to its +# containing dir. +# +# Note that not all possible configuration values are present in this +# autogenerated file. +# +# All configuration values have a default; values that are commented out +# serve to show the default. + +import sys +import os +import re + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +#sys.path.insert(0, os.path.abspath('.')) + +# -- General configuration ------------------------------------------------ + +# If your documentation needs a minimal Sphinx version, state it here. +#needs_sphinx = '1.0' + +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom +# ones. +extensions = ['sphinx.ext.todo'] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# The suffix(es) of source filenames. +# You can specify multiple suffix as a list of string: +# source_suffix = ['.rst', '.md'] +source_suffix = '.rst' + +# The encoding of source files. +#source_encoding = 'utf-8-sig' + +# The master toctree document. +master_doc = 'index' + +# General information about the project. +project = u'FRR' +copyright = u'2017, FRR' +author = u'FRR' + +# The version info for the project you're documenting, acts as replacement for +# |version| and |release|, also used in various other places throughout the +# built documents. + +# The short X.Y version. +version = u'?.?' +# The full version, including alpha/beta/rc tags. +release = u'?.?-?' + +val = re.compile('^S\["([^"]+)"\]="(.*)"$') +with open('../../config.status', 'r') as cfgstatus: + for ln in cfgstatus.readlines(): + m = val.match(ln) + if m is None: continue + if m.group(1) == 'PACKAGE_VERSION': + release = m.group(2) + version = release.split('-')[0] + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +# +# This is also used if you do content translation via gettext catalogs. +# Usually you set "language" from the command line for these cases. +language = None + +# There are two options for replacing |today|: either, you set today to some +# non-false value, then it is used: +#today = '' +# Else, today_fmt is used as the format for a strftime call. +#today_fmt = '%B %d, %Y' + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +exclude_patterns = ['_build'] + +# The reST default role (used for this markup: `text`) to use for all +# documents. +#default_role = None + +# If true, '()' will be appended to :func: etc. cross-reference text. +#add_function_parentheses = True + +# If true, the current module name will be prepended to all description +# unit titles (such as .. function::). +#add_module_names = True + +# If true, sectionauthor and moduleauthor directives will be shown in the +# output. They are ignored by default. +#show_authors = False + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = 'sphinx' + +# A list of ignored prefixes for module index sorting. +#modindex_common_prefix = [] + +# If true, keep warnings as "system message" paragraphs in the built documents. +#keep_warnings = False + +# If true, `todo` and `todoList` produce output, else they produce nothing. +todo_include_todos = True + + +# -- Options for HTML output ---------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +html_theme = 'sphinx_rtd_theme' + +# Theme options are theme-specific and customize the look and feel of a theme +# further. For a list of options available for each theme, see the +# documentation. +#html_theme_options = {} + +# Add any paths that contain custom themes here, relative to this directory. +#html_theme_path = [] + +# The name for this set of Sphinx documents. If None, it defaults to +# " v documentation". +#html_title = None + +# A shorter title for the navigation bar. Default is the same as html_title. +#html_short_title = None + +# The name of an image file (relative to this directory) to place at the top +# of the sidebar. +#html_logo = None + +# The name of an image file (within the static path) to use as favicon of the +# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 +# pixels large. +#html_favicon = None + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ['_static'] + +# Add any extra paths that contain custom files (such as robots.txt or +# .htaccess) here, relative to this directory. These files are copied +# directly to the root of the documentation. +#html_extra_path = [] + +# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, +# using the given strftime format. +#html_last_updated_fmt = '%b %d, %Y' + +# If true, SmartyPants will be used to convert quotes and dashes to +# typographically correct entities. +#html_use_smartypants = True + +# Custom sidebar templates, maps document names to template names. +#html_sidebars = {} + +# Additional templates that should be rendered to pages, maps page names to +# template names. +#html_additional_pages = {} + +# If false, no module index is generated. +#html_domain_indices = True + +# If false, no index is generated. +#html_use_index = True + +# If true, the index is split into individual pages for each letter. +#html_split_index = False + +# If true, links to the reST sources are added to the pages. +#html_show_sourcelink = True + +# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. +#html_show_sphinx = True + +# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. +#html_show_copyright = True + +# If true, an OpenSearch description file will be output, and all pages will +# contain a tag referring to it. The value of this option must be the +# base URL from which the finished HTML is served. +#html_use_opensearch = '' + +# This is the file name suffix for HTML files (e.g. ".xhtml"). +#html_file_suffix = None + +# Language to be used for generating the HTML full-text search index. +# Sphinx supports the following languages: +# 'da', 'de', 'en', 'es', 'fi', 'fr', 'hu', 'it', 'ja' +# 'nl', 'no', 'pt', 'ro', 'ru', 'sv', 'tr' +#html_search_language = 'en' + +# A dictionary with options for the search language support, empty by default. +# Now only 'ja' uses this config value +#html_search_options = {'type': 'default'} + +# The name of a javascript file (relative to the configuration directory) that +# implements a search results scorer. If empty, the default will be used. +#html_search_scorer = 'scorer.js' + +# Output file base name for HTML help builder. +htmlhelp_basename = 'FRRdoc' + +# -- Options for LaTeX output --------------------------------------------- + +latex_elements = { +# The paper size ('letterpaper' or 'a4paper'). +#'papersize': 'letterpaper', + +# The font size ('10pt', '11pt' or '12pt'). +#'pointsize': '10pt', + +# Additional stuff for the LaTeX preamble. +#'preamble': '', + +# Latex figure (float) alignment +#'figure_align': 'htbp', +} + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, +# author, documentclass [howto, manual, or own class]). +latex_documents = [ + (master_doc, 'FRR.tex', u'FRR Documentation', + u'FRR', 'manual'), +] + +# The name of an image file (relative to this directory) to place at the top of +# the title page. +#latex_logo = None + +# For "manual" documents, if this is true, then toplevel headings are parts, +# not chapters. +#latex_use_parts = False + +# If true, show page references after internal links. +#latex_show_pagerefs = False + +# If true, show URL addresses after external links. +#latex_show_urls = False + +# Documents to append as an appendix to all manuals. +#latex_appendices = [] + +# If false, no module index is generated. +#latex_domain_indices = True + + +# -- Options for manual page output --------------------------------------- + +# One entry per manual page. List of tuples +# (source start file, name, description, authors, manual section). +man_pages = [ + (master_doc, 'frr', u'FRR Documentation', + [author], 1) +] + +# If true, show URL addresses after external links. +#man_show_urls = False + + +# -- Options for Texinfo output ------------------------------------------- + +# Grouping the document tree into Texinfo files. List of tuples +# (source start file, target name, title, author, +# dir menu entry, description, category) +texinfo_documents = [ + (master_doc, 'FRR', u'FRR Documentation', + author, 'FRR', 'One line description of project.', + 'Miscellaneous'), +] + +# Documents to append as an appendix to all manuals. +#texinfo_appendices = [] + +# If false, no module index is generated. +#texinfo_domain_indices = True + +# How to display URL addresses: 'footnote', 'no', or 'inline'. +#texinfo_show_urls = 'footnote' + +# If true, do not generate a @detailmenu in the "Top" node's menu. +#texinfo_no_detailmenu = False diff --git a/doc/code/hooks.rst b/doc/code/hooks.rst new file mode 100644 index 0000000000..0afa297aa7 --- /dev/null +++ b/doc/code/hooks.rst @@ -0,0 +1,171 @@ +.. highlight:: c + +Hooks +===== + +Libfrr provides type-safe subscribable hook points where other pieces of +code can add one or more callback functions. "type-safe" in this case +applies to the function pointers used for subscriptions. The +implementations checks (at compile-time) wheter a callback to be added has +the appropriate function signature (parameters) for the hook. + +Example: + +.. code-block:: c + :caption: mydaemon.h + + #include "hook.h" + DECLARE_HOOK(some_update_event, (struct eventinfo *info), (info)) + +.. code-block:: c + :caption: mydaemon.c + + #include "mydaemon.h" + DEFINE_HOOK(some_update_event, (struct eventinfo *info), (info)) + ... + hook_call(some_update_event, info); + +.. code-block:: c + :caption: mymodule.c + + #include "mydaemon.h" + static int event_handler(struct eventinfo *info); + ... + hook_register(some_update_event, event_handler); + +Do not use parameter names starting with "hook", these can collide with +names used by the hook code itself. + + +Return values +------------- + +Callbacks to be placed on hooks always return "int" for now; hook_call will +sum up the return values from each called function. (The default is 0 if no +callbacks are registered.) + +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). + +There is no built-in way to abort executing a chain after a failure of one +of the callbacks. If this is needed, the hook can use an extra +``bool *aborted`` argument. + + +Priorities +---------- + +Hooks support a "priority" value for ordering registered calls +relative to each other. The priority is a signed integer where lower +values are called earlier. There are also "Koohs", which is hooks with +reverse priority ordering (for cleanup/deinit hooks, so you can use the +same priority value). + +Recommended priority value ranges are: + +======================== =================================================== +Range Usage +------------------------ --------------------------------------------------- + -999 ... 0 ... 999 main executable / daemon, or library + +-1999 ... -1000 modules registering calls that should run before + the daemon's bits + +1000 ... 1999 modules' calls that should run after daemon's + (includes default value: 1000) +======================== =================================================== + +Note: the default value is 1000, based on the following 2 expectations: + +- most hook_register() usage will be in loadable modules +- usage of hook_register() in the daemon itself may need relative ordering + to itself, making an explicit value the expected case + +The priority value is passed as extra argument on hook_register_prio() / +hook_register_arg_prio(). Whether a hook runs in reverse is determined +solely by the code defining / calling the hook. (DECLARE_KOOH is actually +the same thing as DECLARE_HOOK, it's just there to make it obvious.) + + +Definition +---------- + +.. c:macro:: DECLARE_HOOK(name, arglist, passlist) +.. c:macro:: DECLARE_KOOH(name, arglist, passlist) + + :param name: Name of the hook to be defined + :param arglist: Function definition style parameter list in braces. + :param passlist: List of the same parameters without their types. + + 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). + + This macro must be placed in a header file; this header file must be + included to register a callback on the hook. + + Examples: + + .. code-block:: c + + DECLARE_HOOK(foo, (), ()) + DECLARE_HOOK(bar, (int arg), (arg)) + DECLARE_HOOK(baz, (const void *x, in_addr_t y), (x, y)) + +.. c:macro:: DEFINE_HOOK(name, arglist, passlist) + + Implements an hook. Each ``DECLARE_HOOK`` must have be accompanied by + exactly one ``DEFINE_HOOK``, which needs to be placed in a source file. + **The hook can only be called from this source file.** This is intentional + to avoid overloading and/or misusing hooks for distinct purposes. + + The compiled source file will include a global symbol with the name of the + hook prefixed by `_hook_`. Trying to register a callback for a hook that + doesn't exist will therefore result in a linker error, or a module + load-time error for dynamic modules. + +.. c:macro:: DEFINE_KOOH(name, arglist, passlist) + + Same as ``DEFINE_HOOK``, but the sense of priorities / order of callbacks + is reversed. This should be used for cleanup hooks. + +.. c:function:: int hook_call(name, ...) + + Calls the specified named hook. Parameters to the hook are passed right + after the hook name, e.g.: + + .. code-block:: c + + hook_call(foo); + hook_call(bar, 0); + hook_call(baz, NULL, INADDR_ANY); + + Returns the sum of return values from all callbacks. The ``DEFINE_HOOK`` + statement for the hook must be placed in the file before any ``hook_call`` + use of the hook. + + +Callback registration +--------------------- + +.. c:function:: void hook_register(name, int (*callback)(...)) +.. c:function:: void hook_register_prio(name, int priority, int (*callback)(...)) +.. c:function:: void hook_register_arg(name, int (*callback)(void *arg, ...), void *arg) +.. c:function:: void hook_register_arg_prio(name, int priority, int (*callback)(void *arg, ...), void *arg) + + Register a callback with an hook. If the caller needs to pass an extra + argument to the callback, the _arg variant can be used and the extra + parameter will be passed as first argument to the callback. There is no + typechecking for this argument. + + The priority value is used as described above. The variants without a + priority parameter use 1000 as priority value. + +.. c:function:: void hook_unregister(name, int (*callback)(...)) +.. c:function:: void hook_unregister_arg(name, int (*callback)(void *arg, ...), void *arg) + + Removes a previously registered callback from a hook. Note that there + is no _prio variant of these calls. The priority value is only used during + registration. diff --git a/doc/code/index.rst b/doc/code/index.rst new file mode 100644 index 0000000000..79647d0b92 --- /dev/null +++ b/doc/code/index.rst @@ -0,0 +1,18 @@ +Welcome to FRR's documentation! +=============================== + +Contents: + +.. toctree:: + :maxdepth: 2 + + library + + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` + diff --git a/doc/code/library.rst b/doc/code/library.rst new file mode 100644 index 0000000000..dd46021db8 --- /dev/null +++ b/doc/code/library.rst @@ -0,0 +1,10 @@ +libfrr library facilities +========================= + +.. toctree:: + :maxdepth: 2 + + memtypes + hooks + + diff --git a/doc/code/memtypes.rst b/doc/code/memtypes.rst new file mode 100644 index 0000000000..62d211e864 --- /dev/null +++ b/doc/code/memtypes.rst @@ -0,0 +1,117 @@ +.. highlight:: c + +Memtypes +======== + +FRR includes wrappers arround ``malloc()`` and ``free()`` that count the number +of objects currently allocated, for each of a defined ``MTYPE``. + +To this extent, there are `memory groups` and `memory types`. Each memory +type must belong to a memory group, this is used just to provide some basic +structure. + +Example: + +.. code-block:: c + :caption: mydaemon.h + + DECLARE_MGROUP(MYDAEMON) + DECLARE_MTYPE(MYNEIGHBOR) + +.. code-block:: c + :caption: mydaemon.c + + DEFINE_MGROUP( MYDAEMON, "My daemon's memory") + DEFINE_MTYPE( MYDAEMON, MYNEIGHBOR, "Neighbor entry") + DEFINE_MTYPE_STATIC(MYDAEMON, MYNEIGHBORNAME, "Neighbor name") + + struct neigh *neighbor_new(const char *name) + { + struct neigh *n = XMALLOC(MYNEIGHBOR, sizeof(*n)); + n->name = XSTRDUP(MYNEIGHBORNAME, name); + return n; + } + + void neighbor_free(struct neigh *n) + { + XFREE(MYNEIGHBORNAME, n->name); + XFREE(MYNEIGHBOR, n); + } + + +Definition +---------- + +.. c:macro:: DECLARE_MGROUP(name) + + This macro forward-declares a memory group and should be placed in a + ``.h`` file. It expands to an ``extern struct memgroup`` statement. + +.. c:macro:: DEFINE_MGROUP(mname, description) + + Defines/implements a memory group. Must be placed into exactly one ``.c`` + file (multiple inclusion will result in a link-time symbol conflict). + + Contains additional logic (constructor and destructor) to register the + memory group in a global list. + +.. c:macro:: DECLARE_MTYPE(name) + + Forward-declares a memory type and makes ``MTYPE_name`` available for use. + Note that the ``MTYPE_`` prefix must not be included in the name, it is + automatically prefixed. + + ``MTYPE_name`` is created as a `static const` symbol, i.e. a compile-time + constant. It refers to an ``extern struct memtype _mt_name``, where `name` + is replaced with the actual name. + +.. c:macro:: DEFINE_MTYPE(group, name, description) + + Define/implement a memory type, must be placed into exactly one ``.c`` + file (multiple inclusion will result in a link-time symbol conflict). + + Like ``DEFINE_MGROUP``, this contains actual code to register the MTYPE + under its group. + +.. c:macro:: DEFINE_MTYPE_STATIC(group, name, description) + + Same as ``DEFINE_MTYPE``, but the ``DEFINE_MTYPE_STATIC`` variant places + the C ``static`` keyword on the definition, restricting the MTYPE's + availability to the current source file. This should be appropriate in + >80% of cases. + + .. todo:: + + Daemons currently have ``daemon_memory.[ch]`` files listing all of + their MTYPEs. This is not how it should be, most of these types + should be moved into the appropriate files where they are used. + Only a few MTYPEs should remain non-static after that. + + +Usage +----- + +.. c:function:: void *XMALLOC(struct memtype *mtype, size_t size) + +.. c:function:: void *XCALLOC(struct memtype *mtype, size_t size) + +.. c:function:: void *XSTRDUP(struct memtype *mtype, size_t size) + + Allocation wrappers for malloc/calloc/realloc/strdup, taking an extra + mtype parameter. + +.. c:function:: void *XREALLOC(struct memtype *mtype, void *ptr, size_t size) + + Wrapper around realloc() with MTYPE tracking. Note that ``ptr`` may + be NULL, in which case the function does the same as XMALLOC (regardless + of whether the system realloc() supports this.) + +.. c:function:: void XFREE(struct memtype *mtype, void *ptr) + + Wrapper around free(), again taking an extra mtype parameter. This is + actually a macro, with the following additional properties: + + - the macro contains ``ptr = NULL`` + - if ptr is NULL, no operation is performed (as is guaranteed by system + implementations.) Do not surround XFREE with ``if (ptr != NULL)`` + checks. From ce19a04aea80f45ca1da80e28bf3a1253138c691 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Tue, 8 Aug 2017 10:50:43 +0200 Subject: [PATCH 004/130] lib: replace if_add_hook with hook_* logic This allows modules to register their own additional hooks on interface creation/deletion. Signed-off-by: David Lamparter --- babeld/babel_interface.c | 4 ++-- bgpd/bgp_main.c | 3 --- eigrpd/eigrp_interface.c | 4 ++-- isisd/isis_circuit.c | 4 ++-- lib/if.c | 35 +++++------------------------------ lib/if.h | 17 ++++++++++++----- nhrpd/nhrp_interface.c | 4 ++-- ospfd/ospf_interface.c | 4 ++-- ripd/rip_interface.c | 4 ++-- ripngd/ripng_interface.c | 4 ++-- zebra/interface.c | 4 ++-- 11 files changed, 33 insertions(+), 54 deletions(-) diff --git a/babeld/babel_interface.c b/babeld/babel_interface.c index 1ae33b3a27..9fa32ee6fa 100644 --- a/babeld/babel_interface.c +++ b/babeld/babel_interface.c @@ -1256,8 +1256,8 @@ void babel_if_init () { /* initialize interface list */ - if_add_hook (IF_NEW_HOOK, babel_if_new_hook); - if_add_hook (IF_DELETE_HOOK, babel_if_delete_hook); + hook_register_prio(if_add, 0, babel_if_new_hook); + hook_register_prio(if_del, 0, babel_if_delete_hook); babel_enable_if = vector_init (1); diff --git a/bgpd/bgp_main.c b/bgpd/bgp_main.c index a80dff271d..d1359402df 100644 --- a/bgpd/bgp_main.c +++ b/bgpd/bgp_main.c @@ -178,9 +178,6 @@ static __attribute__((__noreturn__)) void bgp_exit(int status) bgp_close(); - if (retain_mode) - if_add_hook(IF_DELETE_HOOK, NULL); - /* reverse bgp_master_init */ for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) bgp_delete(bgp); diff --git a/eigrpd/eigrp_interface.c b/eigrpd/eigrp_interface.c index 7f05e14703..22b6fa394f 100644 --- a/eigrpd/eigrp_interface.c +++ b/eigrpd/eigrp_interface.c @@ -150,8 +150,8 @@ struct list *eigrp_iflist; void eigrp_if_init() { /* Initialize Zebra interface data structure. */ - if_add_hook(IF_NEW_HOOK, eigrp_if_new_hook); - if_add_hook(IF_DELETE_HOOK, eigrp_if_delete_hook); + hook_register_prio(if_add, 0, eigrp_if_new_hook); + hook_register_prio(if_del, 0, eigrp_if_delete_hook); } int eigrp_if_new_hook(struct interface *ifp) diff --git a/isisd/isis_circuit.c b/isisd/isis_circuit.c index 9622dcdbc4..a1aa87e396 100644 --- a/isisd/isis_circuit.c +++ b/isisd/isis_circuit.c @@ -1336,8 +1336,8 @@ int isis_if_delete_hook(struct interface *ifp) void isis_circuit_init() { /* Initialize Zebra interface data structure */ - if_add_hook(IF_NEW_HOOK, isis_if_new_hook); - if_add_hook(IF_DELETE_HOOK, isis_if_delete_hook); + hook_register_prio(if_add, 0, isis_if_new_hook); + hook_register_prio(if_del, 0, isis_if_delete_hook); /* Install interface node */ install_node(&interface_node, isis_interface_config_write); diff --git a/lib/if.c b/lib/if.c index 4e4534851c..43c382beaa 100644 --- a/lib/if.c +++ b/lib/if.c @@ -42,17 +42,12 @@ DEFINE_MTYPE_STATIC(LIB, IF_LINK_PARAMS, "Informational Link Parameters") DEFINE_QOBJ_TYPE(interface) +DEFINE_HOOK(if_add, (struct interface *ifp), (ifp)) +DEFINE_KOOH(if_del, (struct interface *ifp), (ifp)) + /* List of interfaces in only the default VRF */ int ptm_enable = 0; -/* One for each program. This structure is needed to store hooks. */ -struct if_master { - int (*if_new_hook)(struct interface *); - int (*if_delete_hook)(struct interface *); -} if_master = { - 0, -}; - /* Compare interface names, returning an integer greater than, equal to, or * less than 0, (following the strcmp convention), according to the * relationship between ifp1 and ifp2. Interface names consist of an @@ -150,10 +145,7 @@ struct interface *if_create(const char *name, int namelen, vrf_id_t vrf_id) SET_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION); QOBJ_REG(ifp, interface); - - if (if_master.if_new_hook) - (*if_master.if_new_hook)(ifp); - + hook_call(if_add, ifp); return ifp; } @@ -182,9 +174,7 @@ void if_update_to_new_vrf(struct interface *ifp, vrf_id_t vrf_id) /* Delete interface structure. */ void if_delete_retain(struct interface *ifp) { - if (if_master.if_delete_hook) - (*if_master.if_delete_hook)(ifp); - + hook_call(if_del, ifp); QOBJ_UNREG(ifp); /* Free connected address list */ @@ -209,21 +199,6 @@ void if_delete(struct interface *ifp) XFREE(MTYPE_IF, ifp); } -/* Add hook to interface master. */ -void if_add_hook(int type, int (*func)(struct interface *ifp)) -{ - switch (type) { - case IF_NEW_HOOK: - if_master.if_new_hook = func; - break; - case IF_DELETE_HOOK: - if_master.if_delete_hook = func; - break; - default: - break; - } -} - /* Interface existance check by index. */ struct interface *if_lookup_by_index(ifindex_t ifindex, vrf_id_t vrf_id) { diff --git a/lib/if.h b/lib/if.h index f80ac19179..a592e0ff85 100644 --- a/lib/if.h +++ b/lib/if.h @@ -25,6 +25,7 @@ #include "linklist.h" #include "memory.h" #include "qobj.h" +#include "hook.h" DECLARE_MTYPE(IF) DECLARE_MTYPE(CONNECTED_LABEL) @@ -283,6 +284,17 @@ struct interface { }; DECLARE_QOBJ_TYPE(interface) +/* called from the library code whenever interfaces are created/deleted + * note: interfaces may not be fully realized at that point; also they + * may not exist in the system (ifindex = IFINDEX_INTERNAL) + * + * priority values are important here, daemons should be at 0 while modules + * can use 1000+ so they run after the daemon has initialised daemon-specific + * interface data + */ +DECLARE_HOOK(if_add, (struct interface *ifp), (ifp)) +DECLARE_KOOH(if_del, (struct interface *ifp), (ifp)) + /* Connected address structure. */ struct connected { /* Attached interface. */ @@ -355,10 +367,6 @@ struct nbr_connected { ? (C)->destination \ : (C)->address) -/* Interface hook sort. */ -#define IF_NEW_HOOK 0 -#define IF_DELETE_HOOK 1 - /* There are some interface flags which are only supported by some operating system. */ @@ -442,7 +450,6 @@ extern int if_is_loopback(struct interface *); extern int if_is_broadcast(struct interface *); extern int if_is_pointopoint(struct interface *); extern int if_is_multicast(struct interface *); -extern void if_add_hook(int, int (*)(struct interface *)); extern void if_init(struct list **); extern void if_cmd_init(void); extern void if_terminate(struct list **); diff --git a/nhrpd/nhrp_interface.c b/nhrpd/nhrp_interface.c index 58ad167549..a46962c91a 100644 --- a/nhrpd/nhrp_interface.c +++ b/nhrpd/nhrp_interface.c @@ -48,8 +48,8 @@ static int nhrp_if_delete_hook(struct interface *ifp) void nhrp_interface_init(void) { - if_add_hook(IF_NEW_HOOK, nhrp_if_new_hook); - if_add_hook(IF_DELETE_HOOK, nhrp_if_delete_hook); + hook_register_prio(if_add, 0, nhrp_if_new_hook); + hook_register_prio(if_del, 0, nhrp_if_delete_hook); } void nhrp_interface_update_mtu(struct interface *ifp, afi_t afi) diff --git a/ospfd/ospf_interface.c b/ospfd/ospf_interface.c index 4ea8ec26f2..54639afd6c 100644 --- a/ospfd/ospf_interface.c +++ b/ospfd/ospf_interface.c @@ -1163,6 +1163,6 @@ void ospf_if_init() { /* Initialize Zebra interface data structure. */ om->iflist = vrf_iflist(VRF_DEFAULT); - if_add_hook(IF_NEW_HOOK, ospf_if_new_hook); - if_add_hook(IF_DELETE_HOOK, ospf_if_delete_hook); + hook_register_prio(if_add, 0, ospf_if_new_hook); + hook_register_prio(if_del, 0, ospf_if_delete_hook); } diff --git a/ripd/rip_interface.c b/ripd/rip_interface.c index a170471123..00b6d1cadd 100644 --- a/ripd/rip_interface.c +++ b/ripd/rip_interface.c @@ -1877,8 +1877,8 @@ static int rip_interface_delete_hook(struct interface *ifp) void rip_if_init(void) { /* Default initial size of interface vector. */ - if_add_hook(IF_NEW_HOOK, rip_interface_new_hook); - if_add_hook(IF_DELETE_HOOK, rip_interface_delete_hook); + hook_register_prio(if_add, 0, rip_interface_new_hook); + hook_register_prio(if_del, 0, rip_interface_delete_hook); /* RIP network init. */ rip_enable_interface = vector_init(1); diff --git a/ripngd/ripng_interface.c b/ripngd/ripng_interface.c index c762d8ace7..02fab68254 100644 --- a/ripngd/ripng_interface.c +++ b/ripngd/ripng_interface.c @@ -1121,8 +1121,8 @@ static struct cmd_node interface_node = { void ripng_if_init() { /* Interface initialize. */ - if_add_hook(IF_NEW_HOOK, ripng_if_new_hook); - if_add_hook(IF_DELETE_HOOK, ripng_if_delete_hook); + hook_register_prio(if_add, 0, ripng_if_new_hook); + hook_register_prio(if_del, 0, ripng_if_delete_hook); /* RIPng enable network init. */ ripng_enable_network = route_table_init(); diff --git a/zebra/interface.c b/zebra/interface.c index c4d0363994..48158c82c4 100644 --- a/zebra/interface.c +++ b/zebra/interface.c @@ -2930,8 +2930,8 @@ static int if_config_write(struct vty *vty) void zebra_if_init(void) { /* Initialize interface and new hook. */ - if_add_hook(IF_NEW_HOOK, if_zebra_new_hook); - if_add_hook(IF_DELETE_HOOK, if_zebra_delete_hook); + hook_register_prio(if_add, 0, if_zebra_new_hook); + hook_register_prio(if_del, 0, if_zebra_delete_hook); /* Install configuration write function. */ install_node(&interface_node, if_config_write); From 2eb27eecf011a06c01e58a735d8bf087d7519979 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Sun, 6 Aug 2017 08:08:39 +0200 Subject: [PATCH 005/130] zebra: start detangling rtadv & irdp Replace some cross-dependencies with hooks & move bits to where they belong. Signed-off-by: David Lamparter --- zebra/interface.c | 93 ++++-------------------------------------- zebra/interface.h | 16 ++++---- zebra/irdp.h | 4 +- zebra/irdp_interface.c | 7 +++- zebra/irdp_main.c | 9 +++- zebra/main.c | 3 -- zebra/rtadv.c | 77 +++++++++++++++++++++++++++++++++- zebra/rtadv.h | 2 - 8 files changed, 107 insertions(+), 104 deletions(-) diff --git a/zebra/interface.c b/zebra/interface.c index 48158c82c4..c17e408ea0 100644 --- a/zebra/interface.c +++ b/zebra/interface.c @@ -52,11 +52,10 @@ #define ZEBRA_PTM_SUPPORT -#if defined(HAVE_RTADV) -/* Order is intentional. Matches RFC4191. This array is also used for - command matching, so only modify with care. */ -const char *rtadv_pref_strs[] = {"medium", "high", "INVALID", "low", 0}; -#endif /* HAVE_RTADV */ +DEFINE_HOOK(zebra_if_extra_info, (struct vty *vty, struct interface *ifp), + (vty, ifp)) +DEFINE_HOOK(zebra_if_config_wr, (struct vty *vty, struct interface *ifp), + (vty, ifp)) static void if_down_del_nbr_connected(struct interface *ifp); @@ -996,74 +995,6 @@ static void nbr_connected_dump_vty(struct vty *vty, vty_out(vty, "\n"); } -#if defined(HAVE_RTADV) -/* Dump interface ND information to vty. */ -static void nd_dump_vty(struct vty *vty, struct interface *ifp) -{ - struct zebra_if *zif; - struct rtadvconf *rtadv; - int interval; - - zif = (struct zebra_if *)ifp->info; - rtadv = &zif->rtadv; - - if (rtadv->AdvSendAdvertisements) { - vty_out(vty, - " ND advertised reachable time is %d milliseconds\n", - rtadv->AdvReachableTime); - vty_out(vty, - " ND advertised retransmit interval is %d milliseconds\n", - rtadv->AdvRetransTimer); - vty_out(vty, " ND router advertisements sent: %d rcvd: %d\n", - zif->ra_sent, zif->ra_rcvd); - interval = rtadv->MaxRtrAdvInterval; - if (interval % 1000) - vty_out(vty, - " ND router advertisements are sent every " - "%d milliseconds\n", - interval); - else - vty_out(vty, - " ND router advertisements are sent every " - "%d seconds\n", - interval / 1000); - if (rtadv->AdvDefaultLifetime != -1) - vty_out(vty, - " ND router advertisements live for %d seconds\n", - rtadv->AdvDefaultLifetime); - else - vty_out(vty, - " ND router advertisements lifetime tracks ra-interval\n"); - vty_out(vty, - " ND router advertisement default router preference is " - "%s\n", - rtadv_pref_strs[rtadv->DefaultPreference]); - if (rtadv->AdvManagedFlag) - vty_out(vty, - " Hosts use DHCP to obtain routable addresses.\n"); - else - vty_out(vty, - " Hosts use stateless autoconfig for addresses.\n"); - if (rtadv->AdvHomeAgentFlag) { - vty_out(vty, - " ND router advertisements with Home Agent flag bit set.\n"); - if (rtadv->HomeAgentLifetime != -1) - vty_out(vty, - " Home Agent lifetime is %u seconds\n", - rtadv->HomeAgentLifetime); - else - vty_out(vty, - " Home Agent lifetime tracks ra-lifetime\n"); - vty_out(vty, " Home Agent preference is %u\n", - rtadv->HomeAgentPreference); - } - if (rtadv->AdvIntervalOption) - vty_out(vty, - " ND router advertisements with Adv. Interval option.\n"); - } -} -#endif /* HAVE_RTADV */ - static const char *zebra_ziftype_2str(zebra_iftype_t zif_type) { switch (zif_type) { @@ -1277,12 +1208,8 @@ static void if_dump_vty(struct vty *vty, struct interface *ifp) inet_ntoa(iflp->rmt_ip), iflp->rmt_as); } -#ifdef RTADV - nd_dump_vty(vty, ifp); -#endif /* RTADV */ -#if defined(HAVE_RTADV) - nd_dump_vty(vty, ifp); -#endif /* HAVE_RTADV */ + hook_call(zebra_if_extra_info, vty, ifp); + if (listhead(ifp->nbr_connected)) vty_out(vty, " Neighbor address(s):\n"); for (ALL_LIST_ELEMENTS_RO(ifp->nbr_connected, node, nbr_connected)) @@ -2911,13 +2838,7 @@ static int if_config_write(struct vty *vty) : "no "); } -#if defined(HAVE_RTADV) - rtadv_config_write(vty, ifp); -#endif /* HAVE_RTADV */ - -#ifdef HAVE_IRDP - irdp_config_write(vty, ifp); -#endif /* IRDP */ + hook_call(zebra_if_config_wr, vty, ifp); link_params_config_write(vty, ifp); diff --git a/zebra/interface.h b/zebra/interface.h index 970c3c5292..7b56dcd4a4 100644 --- a/zebra/interface.h +++ b/zebra/interface.h @@ -23,10 +23,7 @@ #include "redistribute.h" #include "vrf.h" - -#ifdef HAVE_IRDP -#include "zebra/irdp.h" -#endif +#include "hook.h" #include "zebra/zebra_l2.h" @@ -202,6 +199,8 @@ typedef enum { ZEBRA_IF_SLAVE_OTHER, /* Something else - e.g., bond slave */ } zebra_slave_iftype_t; +struct irdp_interface; + /* `zebra' daemon local interface structure. */ struct zebra_if { /* Shutdown configuration. */ @@ -227,9 +226,7 @@ struct zebra_if { unsigned int ra_sent, ra_rcvd; #endif /* HAVE_RTADV */ -#ifdef HAVE_IRDP - struct irdp_interface irdp; -#endif + struct irdp_interface *irdp; #ifdef HAVE_STRUCT_SOCKADDR_DL union { @@ -273,6 +270,11 @@ struct zebra_if { struct interface *link; }; +DECLARE_HOOK(zebra_if_extra_info, (struct vty *vty, struct interface *ifp), + (vty, ifp)) +DECLARE_HOOK(zebra_if_config_wr, (struct vty *vty, struct interface *ifp), + (vty, ifp)) + static inline void zebra_if_set_ziftype(struct interface *ifp, zebra_iftype_t zif_type, zebra_slave_iftype_t zif_slave_type) diff --git a/zebra/irdp.h b/zebra/irdp.h index 01308b915b..f8f7811248 100644 --- a/zebra/irdp.h +++ b/zebra/irdp.h @@ -139,9 +139,9 @@ struct Adv { }; extern void irdp_init(void); +extern void irdp_if_init(void); extern int irdp_sock_init(void); -extern void irdp_finish(void); -extern void irdp_config_write(struct vty *, struct interface *); +extern int irdp_config_write(struct vty *, struct interface *); extern int irdp_send_thread(struct thread *t_advert); extern void irdp_advert_off(struct interface *ifp); extern void process_solicit(struct interface *ifp); diff --git a/zebra/irdp_interface.c b/zebra/irdp_interface.c index 5682e12e6f..032090adf2 100644 --- a/zebra/irdp_interface.c +++ b/zebra/irdp_interface.c @@ -316,7 +316,7 @@ static void irdp_if_no_shutdown(struct interface *ifp) /* Write configuration to user */ -void irdp_config_write(struct vty *vty, struct interface *ifp) +int irdp_config_write(struct vty *vty, struct interface *ifp) { struct zebra_if *zi = ifp->info; struct irdp_interface *irdp = &zi->irdp; @@ -348,6 +348,7 @@ void irdp_config_write(struct vty *vty, struct interface *ifp) vty_out(vty, " ip irdp maxadvertinterval %ld\n", irdp->MaxAdvertInterval); } + return 0; } @@ -678,8 +679,10 @@ DEFUN (ip_irdp_debug_disable, return CMD_SUCCESS; } -void irdp_init() +void irdp_if_init() { + hook_register(zebra_if_config_wr, irdp_config_write); + install_element(INTERFACE_NODE, &ip_irdp_broadcast_cmd); install_element(INTERFACE_NODE, &ip_irdp_multicast_cmd); install_element(INTERFACE_NODE, &no_ip_irdp_cmd); diff --git a/zebra/irdp_main.c b/zebra/irdp_main.c index 6220c9d81b..e463608af1 100644 --- a/zebra/irdp_main.c +++ b/zebra/irdp_main.c @@ -301,7 +301,7 @@ void process_solicit(struct interface *ifp) &irdp->t_advertise); } -void irdp_finish() +static int irdp_finish(void) { struct vrf *vrf; struct listnode *node, *nnode; @@ -328,4 +328,11 @@ void irdp_finish() } } +void irdp_init(void) +{ + irdp_if_init(); + + hook_register(frr_early_fini, irdp_finish); +} + #endif /* HAVE_IRDP */ diff --git a/zebra/main.c b/zebra/main.c index c3a7d3635f..72f96add86 100644 --- a/zebra/main.c +++ b/zebra/main.c @@ -126,9 +126,6 @@ static void sigint(void) zlog_notice("Terminating on signal"); frr_early_fini(); -#ifdef HAVE_IRDP - irdp_finish(); -#endif zebra_ptm_finish(); list_delete_all_node(zebrad.client_list); diff --git a/zebra/rtadv.c b/zebra/rtadv.c index b8cf2d490a..2182d6618c 100644 --- a/zebra/rtadv.c +++ b/zebra/rtadv.c @@ -62,6 +62,10 @@ extern struct zebra_privs_t zserv_privs; #define ALLNODE "ff02::1" #define ALLROUTER "ff02::2" +/* Order is intentional. Matches RFC4191. This array is also used for + command matching, so only modify with care. */ +const char *rtadv_pref_strs[] = {"medium", "high", "INVALID", "low", 0}; + enum rtadv_event { RTADV_START, RTADV_STOP, @@ -1456,9 +1460,76 @@ DEFUN (no_ipv6_nd_mtu, return CMD_SUCCESS; } +/* Dump interface ND information to vty. */ +static int nd_dump_vty(struct vty *vty, struct interface *ifp) +{ + struct zebra_if *zif; + struct rtadvconf *rtadv; + int interval; + + zif = (struct zebra_if *)ifp->info; + rtadv = &zif->rtadv; + + if (rtadv->AdvSendAdvertisements) { + vty_out(vty, + " ND advertised reachable time is %d milliseconds\n", + rtadv->AdvReachableTime); + vty_out(vty, + " ND advertised retransmit interval is %d milliseconds\n", + rtadv->AdvRetransTimer); + vty_out(vty, " ND router advertisements sent: %d rcvd: %d\n", + zif->ra_sent, zif->ra_rcvd); + interval = rtadv->MaxRtrAdvInterval; + if (interval % 1000) + vty_out(vty, + " ND router advertisements are sent every " + "%d milliseconds\n", + interval); + else + vty_out(vty, + " ND router advertisements are sent every " + "%d seconds\n", + interval / 1000); + if (rtadv->AdvDefaultLifetime != -1) + vty_out(vty, + " ND router advertisements live for %d seconds\n", + rtadv->AdvDefaultLifetime); + else + vty_out(vty, + " ND router advertisements lifetime tracks ra-interval\n"); + vty_out(vty, + " ND router advertisement default router preference is " + "%s\n", + rtadv_pref_strs[rtadv->DefaultPreference]); + if (rtadv->AdvManagedFlag) + vty_out(vty, + " Hosts use DHCP to obtain routable addresses.\n"); + else + vty_out(vty, + " Hosts use stateless autoconfig for addresses.\n"); + if (rtadv->AdvHomeAgentFlag) { + vty_out(vty, + " ND router advertisements with Home Agent flag bit set.\n"); + if (rtadv->HomeAgentLifetime != -1) + vty_out(vty, + " Home Agent lifetime is %u seconds\n", + rtadv->HomeAgentLifetime); + else + vty_out(vty, + " Home Agent lifetime tracks ra-lifetime\n"); + vty_out(vty, " Home Agent preference is %u\n", + rtadv->HomeAgentPreference); + } + if (rtadv->AdvIntervalOption) + vty_out(vty, + " ND router advertisements with Adv. Interval option.\n"); + } + return 0; +} + /* Write configuration about router advertisement. */ -void rtadv_config_write(struct vty *vty, struct interface *ifp) +static int rtadv_config_write(struct vty *vty, struct interface *ifp) { struct zebra_if *zif; struct listnode *node; @@ -1539,6 +1610,7 @@ void rtadv_config_write(struct vty *vty, struct interface *ifp) vty_out(vty, " router-address"); vty_out(vty, "\n"); } + return 0; } @@ -1600,6 +1672,9 @@ void rtadv_terminate(struct zebra_ns *zns) void rtadv_cmd_init(void) { + hook_register(zebra_if_extra_info, nd_dump_vty); + hook_register(zebra_if_config_wr, rtadv_config_write); + install_element(INTERFACE_NODE, &ipv6_nd_suppress_ra_cmd); install_element(INTERFACE_NODE, &no_ipv6_nd_suppress_ra_cmd); install_element(INTERFACE_NODE, &ipv6_nd_ra_interval_cmd); diff --git a/zebra/rtadv.h b/zebra/rtadv.h index 029c97cddc..dcaeb3ed28 100644 --- a/zebra/rtadv.h +++ b/zebra/rtadv.h @@ -55,8 +55,6 @@ struct rtadv_prefix { #endif }; -extern void rtadv_config_write(struct vty *, struct interface *); - /* RFC4584 Extension to Sockets API for Mobile IPv6 */ #ifndef ND_OPT_ADV_INTERVAL From ead4ee99acd63d2342e9e9dda7a8f5a103a6f550 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Sun, 6 Aug 2017 08:57:42 +0200 Subject: [PATCH 006/130] zebra: irdp: manage separate IRDP struct This allocates the per-interface IRDP data as needed; so the pointer in zebra_if is now really opaque. Signed-off-by: David Lamparter --- zebra/irdp_interface.c | 117 +++++++++++++++++++---------------------- zebra/irdp_main.c | 25 ++++++--- zebra/irdp_packet.c | 4 +- 3 files changed, 75 insertions(+), 71 deletions(-) diff --git a/zebra/irdp_interface.c b/zebra/irdp_interface.c index 032090adf2..3465bdebbf 100644 --- a/zebra/irdp_interface.c +++ b/zebra/irdp_interface.c @@ -63,6 +63,25 @@ extern int irdp_sock; +DEFINE_MTYPE_STATIC(ZEBRA, IRDP_IF, "IRDP interface data") + +static struct irdp_interface *irdp_if_get(struct interface *ifp) +{ + struct zebra_if *zi = ifp->info; + if (!zi->irdp) + zi->irdp = XCALLOC(MTYPE_IRDP_IF, sizeof(*zi->irdp)); + return zi->irdp; +} + +static int irdp_if_delete(struct interface *ifp) +{ + struct zebra_if *zi = ifp->info; + if (!zi) + return 0; + XFREE(MTYPE_IRDP_IF, zi->irdp); + return 0; +} + static const char *inet_2a(u_int32_t a, char *b) { sprintf(b, "%u.%u.%u.%u", (a)&0xFF, (a >> 8) & 0xFF, (a >> 16) & 0xFF, @@ -117,10 +136,13 @@ static int if_group(struct interface *ifp, int sock, u_int32_t group, static int if_add_group(struct interface *ifp) { struct zebra_if *zi = ifp->info; - struct irdp_interface *irdp = &zi->irdp; + struct irdp_interface *irdp = zi->irdp; int ret; char b1[INET_ADDRSTRLEN]; + if (!irdp) + return -1; + ret = if_group(ifp, irdp_sock, INADDR_ALLRTRS_GROUP, IP_ADD_MEMBERSHIP); if (ret < 0) { return ret; @@ -135,10 +157,13 @@ static int if_add_group(struct interface *ifp) static int if_drop_group(struct interface *ifp) { struct zebra_if *zi = ifp->info; - struct irdp_interface *irdp = &zi->irdp; + struct irdp_interface *irdp = zi->irdp; int ret; char b1[INET_ADDRSTRLEN]; + if (!irdp) + return -1; + ret = if_group(ifp, irdp_sock, INADDR_ALLRTRS_GROUP, IP_DROP_MEMBERSHIP); if (ret < 0) @@ -150,11 +175,8 @@ static int if_drop_group(struct interface *ifp) return 0; } -static void if_set_defaults(struct interface *ifp) +static void if_set_defaults(struct irdp_interface *irdp) { - struct zebra_if *zi = ifp->info; - struct irdp_interface *irdp = &zi->irdp; - irdp->MaxAdvertInterval = IRDP_MAXADVERTINTERVAL; irdp->MinAdvertInterval = IRDP_MINADVERTINTERVAL; irdp->Preference = IRDP_PREFERENCE; @@ -176,11 +198,13 @@ static void irdp_if_start(struct interface *ifp, int multicast, int set_defaults) { struct zebra_if *zi = ifp->info; - struct irdp_interface *irdp = &zi->irdp; + struct irdp_interface *irdp = zi->irdp; struct listnode *node; struct connected *ifc; u_int32_t timer, seed; + assert(irdp); + if (irdp->flags & IF_ACTIVE) { zlog_warn("IRDP: Interface is already active %s", ifp->name); return; @@ -215,7 +239,7 @@ static void irdp_if_start(struct interface *ifp, int multicast, } if (set_defaults) - if_set_defaults(ifp); + if_set_defaults(irdp); irdp->irdp_sent = 0; @@ -254,7 +278,7 @@ static void irdp_if_start(struct interface *ifp, int multicast, static void irdp_if_stop(struct interface *ifp) { struct zebra_if *zi = ifp->info; - struct irdp_interface *irdp = &zi->irdp; + struct irdp_interface *irdp = zi->irdp; if (irdp == NULL) { zlog_warn("Interface %s structure is NULL", ifp->name); @@ -281,8 +305,10 @@ static void irdp_if_stop(struct interface *ifp) static void irdp_if_shutdown(struct interface *ifp) { struct zebra_if *zi = ifp->info; - struct irdp_interface *irdp = &zi->irdp; + struct irdp_interface *irdp = zi->irdp; + if (!irdp) + return; if (irdp->flags & IF_SHUTDOWN) { zlog_warn("IRDP: Interface is already shutdown %s", ifp->name); return; @@ -300,8 +326,7 @@ static void irdp_if_shutdown(struct interface *ifp) static void irdp_if_no_shutdown(struct interface *ifp) { - struct zebra_if *zi = ifp->info; - struct irdp_interface *irdp = &zi->irdp; + struct irdp_interface *irdp = irdp_if_get(ifp); if (!(irdp->flags & IF_SHUTDOWN)) { zlog_warn("IRDP: Interface is not shutdown %s", ifp->name); @@ -319,11 +344,14 @@ static void irdp_if_no_shutdown(struct interface *ifp) int irdp_config_write(struct vty *vty, struct interface *ifp) { struct zebra_if *zi = ifp->info; - struct irdp_interface *irdp = &zi->irdp; + struct irdp_interface *irdp = zi->irdp; struct Adv *adv; struct listnode *node; char b1[INET_ADDRSTRLEN]; + if (!irdp) + return 0; + if (irdp->flags & IF_ACTIVE || irdp->flags & IF_SHUTDOWN) { if (irdp->flags & IF_SHUTDOWN) @@ -360,6 +388,7 @@ DEFUN (ip_irdp_multicast, "Use multicast mode\n") { VTY_DECLVAR_CONTEXT(interface, ifp); + irdp_if_get(ifp); irdp_if_start(ifp, TRUE, TRUE); return CMD_SUCCESS; @@ -373,6 +402,7 @@ DEFUN (ip_irdp_broadcast, "Use broadcast mode\n") { VTY_DECLVAR_CONTEXT(interface, ifp); + irdp_if_get(ifp); irdp_if_start(ifp, FALSE, TRUE); return CMD_SUCCESS; @@ -428,11 +458,7 @@ DEFUN (ip_irdp_holdtime, { int idx_number = 3; VTY_DECLVAR_CONTEXT(interface, ifp); - struct zebra_if *zi; - struct irdp_interface *irdp; - - zi = ifp->info; - irdp = &zi->irdp; + struct irdp_interface *irdp = irdp_if_get(ifp); irdp->Lifetime = atoi(argv[idx_number]->arg); return CMD_SUCCESS; @@ -448,11 +474,7 @@ DEFUN (ip_irdp_minadvertinterval, { int idx_number = 3; VTY_DECLVAR_CONTEXT(interface, ifp); - struct zebra_if *zi; - struct irdp_interface *irdp; - - zi = ifp->info; - irdp = &zi->irdp; + struct irdp_interface *irdp = irdp_if_get(ifp); if ((unsigned)atoi(argv[idx_number]->arg) <= irdp->MaxAdvertInterval) { irdp->MinAdvertInterval = atoi(argv[idx_number]->arg); @@ -475,11 +497,7 @@ DEFUN (ip_irdp_maxadvertinterval, { int idx_number = 3; VTY_DECLVAR_CONTEXT(interface, ifp); - struct zebra_if *zi; - struct irdp_interface *irdp; - - zi = ifp->info; - irdp = &zi->irdp; + struct irdp_interface *irdp = irdp_if_get(ifp); if (irdp->MinAdvertInterval <= (unsigned)atoi(argv[idx_number]->arg)) { irdp->MaxAdvertInterval = atoi(argv[idx_number]->arg); @@ -507,11 +525,7 @@ DEFUN (ip_irdp_preference, { int idx_number = 3; VTY_DECLVAR_CONTEXT(interface, ifp); - struct zebra_if *zi; - struct irdp_interface *irdp; - - zi = ifp->info; - irdp = &zi->irdp; + struct irdp_interface *irdp = irdp_if_get(ifp); irdp->Preference = atoi(argv[idx_number]->arg); return CMD_SUCCESS; @@ -530,17 +544,13 @@ DEFUN (ip_irdp_address_preference, int idx_ipv4 = 3; int idx_number = 5; VTY_DECLVAR_CONTEXT(interface, ifp); + struct irdp_interface *irdp = irdp_if_get(ifp); struct listnode *node; struct in_addr ip; int pref; int ret; - struct zebra_if *zi; - struct irdp_interface *irdp; struct Adv *adv; - zi = ifp->info; - irdp = &zi->irdp; - ret = inet_aton(argv[idx_ipv4]->arg, &ip); if (!ret) return CMD_WARNING_CONFIG_FAILED; @@ -572,16 +582,12 @@ DEFUN (no_ip_irdp_address_preference, { int idx_ipv4 = 4; VTY_DECLVAR_CONTEXT(interface, ifp); + struct irdp_interface *irdp = irdp_if_get(ifp); struct listnode *node, *nnode; struct in_addr ip; int ret; - struct zebra_if *zi; - struct irdp_interface *irdp; struct Adv *adv; - zi = ifp->info; - irdp = &zi->irdp; - ret = inet_aton(argv[idx_ipv4]->arg, &ip); if (!ret) return CMD_WARNING_CONFIG_FAILED; @@ -605,11 +611,7 @@ DEFUN (ip_irdp_debug_messages, "Enable debugging for IRDP messages\n") { VTY_DECLVAR_CONTEXT(interface, ifp); - struct zebra_if *zi; - struct irdp_interface *irdp; - - zi = ifp->info; - irdp = &zi->irdp; + struct irdp_interface *irdp = irdp_if_get(ifp); irdp->flags |= IF_DEBUG_MESSAGES; @@ -625,11 +627,7 @@ DEFUN (ip_irdp_debug_misc, "Enable debugging for miscellaneous IRDP events\n") { VTY_DECLVAR_CONTEXT(interface, ifp); - struct zebra_if *zi; - struct irdp_interface *irdp; - - zi = ifp->info; - irdp = &zi->irdp; + struct irdp_interface *irdp = irdp_if_get(ifp); irdp->flags |= IF_DEBUG_MISC; @@ -645,11 +643,7 @@ DEFUN (ip_irdp_debug_packet, "Enable debugging for IRDP packets\n") { VTY_DECLVAR_CONTEXT(interface, ifp); - struct zebra_if *zi; - struct irdp_interface *irdp; - - zi = ifp->info; - irdp = &zi->irdp; + struct irdp_interface *irdp = irdp_if_get(ifp); irdp->flags |= IF_DEBUG_PACKET; @@ -666,11 +660,7 @@ DEFUN (ip_irdp_debug_disable, "Disable debugging for all IRDP events\n") { VTY_DECLVAR_CONTEXT(interface, ifp); - struct zebra_if *zi; - struct irdp_interface *irdp; - - zi = ifp->info; - irdp = &zi->irdp; + struct irdp_interface *irdp = irdp_if_get(ifp); irdp->flags &= ~IF_DEBUG_PACKET; irdp->flags &= ~IF_DEBUG_MESSAGES; @@ -682,6 +672,7 @@ DEFUN (ip_irdp_debug_disable, void irdp_if_init() { hook_register(zebra_if_config_wr, irdp_config_write); + hook_register(if_del, irdp_if_delete); install_element(INTERFACE_NODE, &ip_irdp_broadcast_cmd); install_element(INTERFACE_NODE, &ip_irdp_multicast_cmd); diff --git a/zebra/irdp_main.c b/zebra/irdp_main.c index e463608af1..73c6d8141a 100644 --- a/zebra/irdp_main.c +++ b/zebra/irdp_main.c @@ -52,6 +52,7 @@ #include "zclient.h" #include "thread.h" #include "privs.h" +#include "libfrr.h" #include "zebra/interface.h" #include "zebra/rtadv.h" #include "zebra/rib.h" @@ -143,7 +144,7 @@ static int make_advertisement_packet(struct interface *ifp, struct prefix *p, struct stream *s) { struct zebra_if *zi = ifp->info; - struct irdp_interface *irdp = &zi->irdp; + struct irdp_interface *irdp = zi->irdp; int size; int pref; u_int16_t checksum; @@ -175,11 +176,13 @@ static int make_advertisement_packet(struct interface *ifp, struct prefix *p, static void irdp_send(struct interface *ifp, struct prefix *p, struct stream *s) { struct zebra_if *zi = ifp->info; - struct irdp_interface *irdp = &zi->irdp; + struct irdp_interface *irdp = zi->irdp; char buf[PREFIX_STRLEN]; u_int32_t dst; u_int32_t ttl = 1; + if (!irdp) + return; if (!(ifp->flags & IFF_UP)) return; @@ -211,11 +214,14 @@ int irdp_send_thread(struct thread *t_advert) u_int32_t timer, tmp; struct interface *ifp = THREAD_ARG(t_advert); struct zebra_if *zi = ifp->info; - struct irdp_interface *irdp = &zi->irdp; + struct irdp_interface *irdp = zi->irdp; struct prefix *p; struct listnode *node, *nnode; struct connected *ifc; + if (!irdp) + return 0; + irdp->flags &= ~IF_SOLICIT; if (ifp->connected) @@ -250,12 +256,15 @@ int irdp_send_thread(struct thread *t_advert) void irdp_advert_off(struct interface *ifp) { struct zebra_if *zi = ifp->info; - struct irdp_interface *irdp = &zi->irdp; + struct irdp_interface *irdp = zi->irdp; struct listnode *node, *nnode; int i; struct connected *ifc; struct prefix *p; + if (!irdp) + return; + if (irdp->t_advertise) thread_cancel(irdp->t_advertise); irdp->t_advertise = NULL; @@ -279,9 +288,12 @@ void irdp_advert_off(struct interface *ifp) void process_solicit(struct interface *ifp) { struct zebra_if *zi = ifp->info; - struct irdp_interface *irdp = &zi->irdp; + struct irdp_interface *irdp = zi->irdp; u_int32_t timer; + if (!irdp) + return; + /* When SOLICIT is active we reject further incoming solicits this keeps down the answering rate so we don't have think about DoS attacks here. */ @@ -317,7 +329,7 @@ static int irdp_finish(void) if (!zi) continue; - irdp = &zi->irdp; + irdp = zi->irdp; if (!irdp) continue; @@ -326,6 +338,7 @@ static int irdp_finish(void) irdp_advert_off(ifp); } } + return 0; } void irdp_init(void) diff --git a/zebra/irdp_packet.c b/zebra/irdp_packet.c index 3bd093d97b..a64eac2ea4 100644 --- a/zebra/irdp_packet.c +++ b/zebra/irdp_packet.c @@ -84,7 +84,7 @@ static void parse_irdp_packet(char *p, int len, struct interface *ifp) if (!zi) return; - irdp = &zi->irdp; + irdp = zi->irdp; if (!irdp) return; @@ -240,7 +240,7 @@ int irdp_read_raw(struct thread *r) if (!zi) return ret; - irdp = &zi->irdp; + irdp = zi->irdp; if (!irdp) return ret; From 8dc1f7fc888a59c5b723befdd0dbeff5587afa56 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Sun, 6 Aug 2017 09:19:14 +0200 Subject: [PATCH 007/130] zebra: irdp: convert into module Signed-off-by: David Lamparter --- configure.ac | 38 ++++++++++++++++++++++---------------- zebra/irdp.h | 1 - zebra/irdp_interface.c | 4 ---- zebra/irdp_main.c | 19 +++++++++++++++---- zebra/irdp_packet.c | 5 ----- zebra/main.c | 3 --- zebra/subdir.am | 13 ++++++++++--- 7 files changed, 47 insertions(+), 36 deletions(-) diff --git a/configure.ac b/configure.ac index 574992342f..710a71f636 100755 --- a/configure.ac +++ b/configure.ac @@ -344,7 +344,7 @@ AC_ARG_ENABLE(shell_access, AC_ARG_ENABLE(rtadv, AS_HELP_STRING([--disable-rtadv], [disable IPV6 router advertisement feature])) AC_ARG_ENABLE(irdp, - AS_HELP_STRING([--enable-irdp], [enable IRDP server support in zebra])) + AS_HELP_STRING([--disable-irdp], [enable IRDP server support in zebra (default if supported)])) AC_ARG_ENABLE(capabilities, AS_HELP_STRING([--disable-capabilities], [disable using POSIX capabilities])) AC_ARG_ENABLE(rusage, @@ -570,10 +570,6 @@ else AC_MSG_RESULT(no) fi -if test "${enable_irdp}" = "yes"; then - AC_DEFINE(HAVE_IRDP,, IRDP ) -fi - if test x"${enable_user}" = x"no"; then enable_user="" else @@ -1479,17 +1475,27 @@ AC_CHECK_MEMBERS([struct sockaddr.sa_len, dnl --------------------------- dnl IRDP/pktinfo/icmphdr checks dnl --------------------------- -AC_CHECK_TYPES([struct in_pktinfo], - [AC_CHECK_TYPES([struct icmphdr], - [if test "${enable_irdp}" != "no"; then - AC_DEFINE(HAVE_IRDP,, IRDP) - fi], - [if test "${enable_irdp}" = "yes"; then - AC_MSG_ERROR(['IRDP requires in_pktinfo at the moment!']) - fi], [FRR_INCLUDES])], - [if test "${enable_irdp}" = "yes"; then - AC_MSG_ERROR(['IRDP requires in_pktinfo at the moment!']) - fi], [FRR_INCLUDES]) + +AC_CHECK_TYPES([struct in_pktinfo], [ + AC_CHECK_TYPES([struct icmphdr], [ + IRDP=true + ], [ + IRDP=false + ], [FRR_INCLUDES]) +], [ + IRDP=false +], [FRR_INCLUDES]) + +case "${enable_irdp}" in +yes) + $IRDP || AC_MSG_ERROR(['IRDP requires in_pktinfo at the moment!']) + ;; +no) + IRDP=false + ;; +esac + +AM_CONDITIONAL(IRDP, $IRDP) dnl ----------------------- dnl checking for IP_PKTINFO diff --git a/zebra/irdp.h b/zebra/irdp.h index f8f7811248..ea190b574d 100644 --- a/zebra/irdp.h +++ b/zebra/irdp.h @@ -138,7 +138,6 @@ struct Adv { int pref; }; -extern void irdp_init(void); extern void irdp_if_init(void); extern int irdp_sock_init(void); extern int irdp_config_write(struct vty *, struct interface *); diff --git a/zebra/irdp_interface.c b/zebra/irdp_interface.c index 3465bdebbf..34c78e2a48 100644 --- a/zebra/irdp_interface.c +++ b/zebra/irdp_interface.c @@ -35,8 +35,6 @@ #include -#ifdef HAVE_IRDP - #include "if.h" #include "vty.h" #include "sockunion.h" @@ -691,5 +689,3 @@ void irdp_if_init() install_element(INTERFACE_NODE, &ip_irdp_debug_packet_cmd); install_element(INTERFACE_NODE, &ip_irdp_debug_disable_cmd); } - -#endif /* HAVE_IRDP */ diff --git a/zebra/irdp_main.c b/zebra/irdp_main.c index 73c6d8141a..9dfa854725 100644 --- a/zebra/irdp_main.c +++ b/zebra/irdp_main.c @@ -35,8 +35,6 @@ #include -#ifdef HAVE_IRDP - #include "if.h" #include "vty.h" #include "sockunion.h" @@ -53,6 +51,7 @@ #include "thread.h" #include "privs.h" #include "libfrr.h" +#include "version.h" #include "zebra/interface.h" #include "zebra/rtadv.h" #include "zebra/rib.h" @@ -341,11 +340,23 @@ static int irdp_finish(void) return 0; } -void irdp_init(void) +static int irdp_init(struct thread_master *master) { irdp_if_init(); hook_register(frr_early_fini, irdp_finish); + return 0; } -#endif /* HAVE_IRDP */ +static int irdp_module_init(void) +{ + hook_register(frr_late_init, irdp_init); + return 0; +} + +FRR_MODULE_SETUP( + .name = "zebra_irdp", + .version = FRR_VERSION, + .description = "zebra IRDP module", + .init = irdp_module_init, +) diff --git a/zebra/irdp_packet.c b/zebra/irdp_packet.c index a64eac2ea4..0832245536 100644 --- a/zebra/irdp_packet.c +++ b/zebra/irdp_packet.c @@ -36,8 +36,6 @@ #include -#ifdef HAVE_IRDP - #include "if.h" #include "vty.h" #include "sockunion.h" @@ -353,6 +351,3 @@ void send_packet(struct interface *ifp, struct stream *s, u_int32_t dst, } /* printf("TX on %s idx %d\n", ifp->name, ifp->ifindex); */ } - - -#endif /* HAVE_IRDP */ diff --git a/zebra/main.c b/zebra/main.c index 72f96add86..bc7276817d 100644 --- a/zebra/main.c +++ b/zebra/main.c @@ -292,9 +292,6 @@ int main(int argc, char **argv) #if defined(HAVE_RTADV) rtadv_cmd_init(); #endif -#ifdef HAVE_IRDP - irdp_init(); -#endif /* PTM socket */ #ifdef ZEBRA_PTM_SUPPORT zebra_ptm_init(); diff --git a/zebra/subdir.am b/zebra/subdir.am index 0391cab9fd..3474823623 100644 --- a/zebra/subdir.am +++ b/zebra/subdir.am @@ -6,6 +6,9 @@ if ZEBRA sbin_PROGRAMS += zebra/zebra dist_examples_DATA += zebra/zebra.conf.sample +if IRDP +module_LTLIBRARIES += zebra/zebra_irdp.la +endif if SNMP module_LTLIBRARIES += zebra/zebra_snmp.la endif @@ -30,9 +33,6 @@ zebra_zebra_SOURCES = \ zebra/ipforward_proc.c \ zebra/ipforward_solaris.c \ zebra/ipforward_sysctl.c \ - zebra/irdp_interface.c \ - zebra/irdp_main.c \ - zebra/irdp_packet.c \ zebra/kernel_netlink.c \ zebra/kernel_socket.c \ zebra/label_manager.c \ @@ -106,6 +106,13 @@ noinst_HEADERS += \ zebra/zserv.h \ # end +zebra_zebra_irdp_la_SOURCES = \ + zebra/irdp_interface.c \ + zebra/irdp_main.c \ + zebra/irdp_packet.c \ + # end +zebra_zebra_irdp_la_LDFLAGS = -avoid-version -module -shared -export-dynamic + zebra_zebra_snmp_la_SOURCES = zebra/zebra_snmp.c zebra_zebra_snmp_la_CFLAGS = $(WERROR) $(SNMP_CFLAGS) zebra_zebra_snmp_la_LDFLAGS = -avoid-version -module -shared -export-dynamic From 0ed9196b0c196ad1b240a77709d1452a2fa42c80 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Tue, 15 Aug 2017 14:19:16 +0200 Subject: [PATCH 008/130] redhat: ship IRDP module No point in configuring IRDP (it's always available on Linux), just ship the module and let the user decide whether to enable it by way of module loading. Signed-off-by: David Lamparter --- redhat/frr.spec.in | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/redhat/frr.spec.in b/redhat/frr.spec.in index 12cdcf04fe..cc0632b562 100644 --- a/redhat/frr.spec.in +++ b/redhat/frr.spec.in @@ -13,7 +13,6 @@ %{!?with_pam: %global with_pam 0 } %{!?with_ospfclient: %global with_ospfclient 1 } %{!?with_ospfapi: %global with_ospfapi 1 } -%{!?with_irdp: %global with_irdp 1 } %{!?with_rtadv: %global with_rtadv 1 } %{!?with_ldpd: %global with_ldpd 1 } %{!?with_nhrpd: %global with_nhrpd 1 } @@ -221,6 +220,7 @@ developing OSPF-API and frr applications. --libexecdir=%{_libexecdir} \ --localstatedir=%{_localstatedir} \ --disable-werror \ + --enable-irdp \ %if !%{with_shared} --disable-shared \ %endif @@ -238,11 +238,6 @@ developing OSPF-API and frr applications. %else --enable-ospfapi=no \ %endif -%if %{with_irdp} - --enable-irdp=yes \ -%else - --enable-irdp=no \ -%endif %if %{with_rtadv} --enable-rtadv=yes \ %else @@ -325,6 +320,9 @@ rm -rf %{buildroot}/usr/share/info/dir # Remove debian init script if it was installed rm -f %{buildroot}%{_sbindir}/frr +# kill bogus libtool files for modules +rm -f %{buildroot}%{_libdir}/frr/modules/*.la + # install /etc sources %if "%{initsystem}" == "systemd" mkdir -p %{buildroot}%{_unitdir} @@ -554,6 +552,7 @@ rm -rf %{buildroot} %{_libdir}/lib*.so.0 %attr(755,root,root) %{_libdir}/lib*.so.0.* %endif +%attr(755,root,root) %{_libdir}/frr/modules/zebra_irdp.so %{_bindir}/* %config(noreplace) /etc/frr/[!v]*.conf* %config(noreplace) %attr(750,%frr_user,%frr_user) /etc/frr/daemons From b4e84315e441add32c07658e55a319a87b7fbf33 Mon Sep 17 00:00:00 2001 From: Daniel Walton Date: Wed, 16 Aug 2017 18:40:12 +0000 Subject: [PATCH 009/130] ospfd: "show ip ospf neighbor" options not passed Signed-off-by: Daniel Walton --- ospfd/ospf_vty.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c index 13d4780db3..9c18582ea8 100644 --- a/ospfd/ospf_vty.c +++ b/ospfd/ospf_vty.c @@ -4032,12 +4032,13 @@ DEFUN (show_ip_ospf_neighbor_int, JSON_STR) { struct ospf *ospf; + int idx_ifname = 4; u_char uj = use_json(argc, argv); if ((ospf = ospf_lookup()) == NULL || !ospf->oi_running) return CMD_SUCCESS; - return show_ip_ospf_neighbor_int_common(vty, ospf, 0, argv, uj); + return show_ip_ospf_neighbor_int_common(vty, ospf, idx_ifname, argv, uj); } DEFUN (show_ip_ospf_instance_neighbor_int, @@ -4052,6 +4053,7 @@ DEFUN (show_ip_ospf_instance_neighbor_int, JSON_STR) { int idx_number = 3; + int idx_ifname = 5; struct ospf *ospf; u_short instance = 0; u_char uj = use_json(argc, argv); @@ -4064,7 +4066,7 @@ DEFUN (show_ip_ospf_instance_neighbor_int, if (!ospf->oi_running) return CMD_SUCCESS; - return show_ip_ospf_neighbor_int_common(vty, ospf, 1, argv, uj); + return show_ip_ospf_neighbor_int_common(vty, ospf, idx_ifname, argv, uj); } static void show_ip_ospf_nbr_nbma_detail_sub(struct vty *vty, @@ -4422,12 +4424,13 @@ DEFUN (show_ip_ospf_neighbor_id, JSON_STR) { struct ospf *ospf; + int idx_router_id = 4; u_char uj = use_json(argc, argv); if ((ospf = ospf_lookup()) == NULL || !ospf->oi_running) return CMD_SUCCESS; - return show_ip_ospf_neighbor_id_common(vty, ospf, 0, argv, uj); + return show_ip_ospf_neighbor_id_common(vty, ospf, idx_router_id, argv, uj); } DEFUN (show_ip_ospf_instance_neighbor_id, @@ -4442,6 +4445,7 @@ DEFUN (show_ip_ospf_instance_neighbor_id, JSON_STR) { int idx_number = 3; + int idx_router_id = 5; struct ospf *ospf; u_short instance = 0; u_char uj = use_json(argc, argv); @@ -4454,7 +4458,7 @@ DEFUN (show_ip_ospf_instance_neighbor_id, if (!ospf->oi_running) return CMD_SUCCESS; - return show_ip_ospf_neighbor_id_common(vty, ospf, 1, argv, uj); + return show_ip_ospf_neighbor_id_common(vty, ospf, idx_router_id, argv, uj); } static int show_ip_ospf_neighbor_detail_common(struct vty *vty, @@ -4725,12 +4729,13 @@ DEFUN (show_ip_ospf_neighbor_int_detail, JSON_STR) { struct ospf *ospf; + int idx_ifname = 4; u_char uj = use_json(argc, argv); if ((ospf = ospf_lookup()) == NULL || !ospf->oi_running) return CMD_SUCCESS; - return show_ip_ospf_neighbor_int_detail_common(vty, ospf, 0, argv, uj); + return show_ip_ospf_neighbor_int_detail_common(vty, ospf, idx_ifname, argv, uj); } DEFUN (show_ip_ospf_instance_neighbor_int_detail, @@ -4746,6 +4751,7 @@ DEFUN (show_ip_ospf_instance_neighbor_int_detail, JSON_STR) { int idx_number = 3; + int idx_ifname = 5; struct ospf *ospf; u_short instance = 0; u_char uj = use_json(argc, argv); @@ -4758,7 +4764,7 @@ DEFUN (show_ip_ospf_instance_neighbor_int_detail, if (!ospf->oi_running) return CMD_SUCCESS; - return show_ip_ospf_neighbor_int_detail_common(vty, ospf, 1, argv, uj); + return show_ip_ospf_neighbor_int_detail_common(vty, ospf, idx_ifname, argv, uj); } /* Show functions */ From 596074af62ebe33bcccfd910c7ca727ce4bbf409 Mon Sep 17 00:00:00 2001 From: Daniel Walton Date: Wed, 16 Aug 2017 20:22:59 +0000 Subject: [PATCH 010/130] vtysh: vtysh -f FOO should exit non-zero if it hits an error Signed-off-by: Daniel Walton Today if we hit an error while apply the contents of file FOO that error does not bubble up to a non-zero exit. --- tools/frr-reload.py | 18 +++++------------- vtysh/vtysh.c | 1 + 2 files changed, 6 insertions(+), 13 deletions(-) diff --git a/tools/frr-reload.py b/tools/frr-reload.py index 43496d4cbf..8556f0b46e 100755 --- a/tools/frr-reload.py +++ b/tools/frr-reload.py @@ -1162,19 +1162,11 @@ if __name__ == '__main__': for line in lines_to_configure: fh.write(line + '\n') - output = subprocess.check_output(['/usr/bin/vtysh', '-f', filename]) - - # exit non-zero if we see these errors - for x in ('BGP instance name and AS number mismatch', - 'BGP instance is already running', - '% not a local address'): - for line in output.splitlines(): - if x in line: - msg = "ERROR: %s" % x - log.error(msg) - print msg - reload_ok = False - + try: + subprocess.check_output(['/usr/bin/vtysh', '-f', filename]) + except subprocess.CalledProcessError as e: + log.warning("frr-reload.py failed due to\n%s" % e.output) + reload_ok = False os.unlink(filename) # Make these changes persistent diff --git a/vtysh/vtysh.c b/vtysh/vtysh.c index f971c171bc..f7bfd9e42e 100644 --- a/vtysh/vtysh.c +++ b/vtysh/vtysh.c @@ -752,6 +752,7 @@ int vtysh_config_from_file(struct vty *vty, FILE *fp) lineno, cmd_stat, vtysh_client[i].name, vty->buf); + retcode = cmd_stat; break; } } From 3bbde7327a20efe80a58574a784290206c8efc93 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 17 Aug 2017 09:48:21 -0400 Subject: [PATCH 011/130] eigrpd: Remove extra newline in debug Signed-off-by: Donald Sharp --- eigrpd/eigrp_fsm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eigrpd/eigrp_fsm.c b/eigrpd/eigrp_fsm.c index 8e2a26447e..ba2d1f7e8d 100644 --- a/eigrpd/eigrp_fsm.c +++ b/eigrpd/eigrp_fsm.c @@ -333,7 +333,7 @@ int eigrp_get_fsm_event(struct eigrp_fsm_action_message *msg) */ int eigrp_fsm_event(struct eigrp_fsm_action_message *msg, int event) { - zlog_info("EIGRP AS: %d State: %d Event: %d Network: %s\n", + zlog_info("EIGRP AS: %d State: %d Event: %d Network: %s", msg->eigrp->AS, msg->prefix->state, event, eigrp_topology_ip_string(msg->prefix)); (*(NSM[msg->prefix->state][event].func))(msg); From 907b430346b16f670a497e357ba48b01a3240144 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 17 Aug 2017 09:53:51 -0400 Subject: [PATCH 012/130] eigrpd: Store nbr in packet data Store the neighbor information( if available ) in the packet data that we are sending. This will allow in a future commit the ability to fixup the outgoing ack we are sending. Signed-off-by: Donald Sharp --- eigrpd/eigrp_hello.c | 2 +- eigrpd/eigrp_packet.c | 5 +++-- eigrpd/eigrp_packet.h | 2 +- eigrpd/eigrp_query.c | 2 +- eigrpd/eigrp_reply.c | 2 +- eigrpd/eigrp_siaquery.c | 2 +- eigrpd/eigrp_siareply.c | 2 +- eigrpd/eigrp_structs.h | 2 ++ eigrpd/eigrp_update.c | 10 +++++----- 9 files changed, 16 insertions(+), 13 deletions(-) diff --git a/eigrpd/eigrp_hello.c b/eigrpd/eigrp_hello.c index b7c2f7f18d..4654ead434 100644 --- a/eigrpd/eigrp_hello.c +++ b/eigrpd/eigrp_hello.c @@ -614,7 +614,7 @@ static struct eigrp_packet *eigrp_hello_encode(struct eigrp_interface *ei, u_int16_t length = EIGRP_HEADER_LEN; // allocate a new packet to be sent - ep = eigrp_packet_new(ei->ifp->mtu); + ep = eigrp_packet_new(ei->ifp->mtu, NULL); if (ep) { // encode common header feilds diff --git a/eigrpd/eigrp_packet.c b/eigrpd/eigrp_packet.c index dfc7463025..84c1b1c590 100644 --- a/eigrpd/eigrp_packet.c +++ b/eigrpd/eigrp_packet.c @@ -826,13 +826,14 @@ void eigrp_fifo_reset(struct eigrp_fifo *fifo) fifo->count = 0; } -struct eigrp_packet *eigrp_packet_new(size_t size) +struct eigrp_packet *eigrp_packet_new(size_t size, struct eigrp_neighbor *nbr) { struct eigrp_packet *new; new = XCALLOC(MTYPE_EIGRP_PACKET, sizeof(struct eigrp_packet)); new->s = stream_new(size); new->retrans_counter = 0; + new->nbr = nbr; return new; } @@ -1121,7 +1122,7 @@ struct eigrp_packet *eigrp_packet_duplicate(struct eigrp_packet *old, { struct eigrp_packet *new; - new = eigrp_packet_new(nbr->ei->ifp->mtu); + new = eigrp_packet_new(nbr->ei->ifp->mtu, nbr); new->length = old->length; new->retrans_counter = old->retrans_counter; new->dst = old->dst; diff --git a/eigrpd/eigrp_packet.h b/eigrpd/eigrp_packet.h index 2f607e5cab..890fc33c0f 100644 --- a/eigrpd/eigrp_packet.h +++ b/eigrpd/eigrp_packet.h @@ -36,7 +36,7 @@ extern int eigrp_read(struct thread *); extern int eigrp_write(struct thread *); -extern struct eigrp_packet *eigrp_packet_new(size_t); +extern struct eigrp_packet *eigrp_packet_new(size_t, struct eigrp_neighbor *); extern struct eigrp_packet *eigrp_packet_duplicate(struct eigrp_packet *, struct eigrp_neighbor *); extern void eigrp_packet_free(struct eigrp_packet *); diff --git a/eigrpd/eigrp_query.c b/eigrpd/eigrp_query.c index 653eae258f..92bc792c6a 100644 --- a/eigrpd/eigrp_query.c +++ b/eigrpd/eigrp_query.c @@ -159,7 +159,7 @@ void eigrp_send_query(struct eigrp_interface *ei) char has_tlv; bool ep_saved = false; - ep = eigrp_packet_new(ei->ifp->mtu); + ep = eigrp_packet_new(ei->ifp->mtu, NULL); /* Prepare EIGRP INIT UPDATE header */ eigrp_packet_header_init(EIGRP_OPC_QUERY, ei, ep->s, 0, diff --git a/eigrpd/eigrp_reply.c b/eigrpd/eigrp_reply.c index 4eb08c60d0..c96c3008ca 100644 --- a/eigrpd/eigrp_reply.c +++ b/eigrpd/eigrp_reply.c @@ -114,7 +114,7 @@ void eigrp_send_reply(struct eigrp_neighbor *nbr, struct eigrp_prefix_entry *pe) * End of filtering */ - ep = eigrp_packet_new(nbr->ei->ifp->mtu); + ep = eigrp_packet_new(nbr->ei->ifp->mtu, nbr); /* Prepare EIGRP INIT UPDATE header */ eigrp_packet_header_init(EIGRP_OPC_REPLY, nbr->ei, ep->s, 0, diff --git a/eigrpd/eigrp_siaquery.c b/eigrpd/eigrp_siaquery.c index f16f49a330..a5df2381ca 100644 --- a/eigrpd/eigrp_siaquery.c +++ b/eigrpd/eigrp_siaquery.c @@ -123,7 +123,7 @@ void eigrp_send_siaquery(struct eigrp_neighbor *nbr, struct eigrp_packet *ep; u_int16_t length = EIGRP_HEADER_LEN; - ep = eigrp_packet_new(nbr->ei->ifp->mtu); + ep = eigrp_packet_new(nbr->ei->ifp->mtu, nbr); /* Prepare EIGRP INIT UPDATE header */ eigrp_packet_header_init(EIGRP_OPC_SIAQUERY, nbr->ei, ep->s, 0, diff --git a/eigrpd/eigrp_siareply.c b/eigrpd/eigrp_siareply.c index 9a768566d3..0b684b498b 100644 --- a/eigrpd/eigrp_siareply.c +++ b/eigrpd/eigrp_siareply.c @@ -122,7 +122,7 @@ void eigrp_send_siareply(struct eigrp_neighbor *nbr, struct eigrp_packet *ep; u_int16_t length = EIGRP_HEADER_LEN; - ep = eigrp_packet_new(nbr->ei->ifp->mtu); + ep = eigrp_packet_new(nbr->ei->ifp->mtu, nbr); /* Prepare EIGRP INIT UPDATE header */ eigrp_packet_header_init(EIGRP_OPC_SIAREPLY, nbr->ei, ep->s, 0, diff --git a/eigrpd/eigrp_structs.h b/eigrpd/eigrp_structs.h index fd3e4b2014..0c15436d4f 100644 --- a/eigrpd/eigrp_structs.h +++ b/eigrpd/eigrp_structs.h @@ -311,6 +311,8 @@ struct eigrp_packet { /* EIGRP packet length. */ u_int16_t length; + + struct eigrp_neighbor *nbr; }; struct eigrp_fifo { diff --git a/eigrpd/eigrp_update.c b/eigrpd/eigrp_update.c index e0169c514b..3c82fdfde8 100644 --- a/eigrpd/eigrp_update.c +++ b/eigrpd/eigrp_update.c @@ -463,7 +463,7 @@ void eigrp_update_send_init(struct eigrp_neighbor *nbr) struct eigrp_packet *ep; u_int16_t length = EIGRP_HEADER_LEN; - ep = eigrp_packet_new(nbr->ei->ifp->mtu); + ep = eigrp_packet_new(nbr->ei->ifp->mtu, nbr); /* Prepare EIGRP INIT UPDATE header */ if (IS_DEBUG_EIGRP_PACKET(0, RECV)) @@ -546,7 +546,7 @@ void eigrp_update_send_EOT(struct eigrp_neighbor *nbr) struct prefix_ipv4 *dest_addr; u_int32_t seq_no = nbr->ei->eigrp->sequence_number; - ep = eigrp_packet_new(nbr->ei->ifp->mtu); + ep = eigrp_packet_new(nbr->ei->ifp->mtu, nbr); /* Prepare EIGRP EOT UPDATE header */ eigrp_packet_header_init(EIGRP_OPC_UPDATE, nbr->ei, ep->s, EIGRP_EOT_FLAG, @@ -571,7 +571,7 @@ void eigrp_update_send_EOT(struct eigrp_neighbor *nbr) seq_no++; length = EIGRP_HEADER_LEN; - ep = eigrp_packet_new(nbr->ei->ifp->mtu); + ep = eigrp_packet_new(nbr->ei->ifp->mtu, nbr); eigrp_packet_header_init(EIGRP_OPC_UPDATE, nbr->ei, ep->s, EIGRP_EOT_FLAG, seq_no, nbr->recv_sequence_number); @@ -635,7 +635,7 @@ void eigrp_update_send(struct eigrp_interface *ei) u_int16_t length = EIGRP_HEADER_LEN; - ep = eigrp_packet_new(ei->ifp->mtu); + ep = eigrp_packet_new(ei->ifp->mtu, NULL); /* Prepare EIGRP INIT UPDATE header */ eigrp_packet_header_init(EIGRP_OPC_UPDATE, ei, ep->s, 0, @@ -835,7 +835,7 @@ static void eigrp_update_send_GR_part(struct eigrp_neighbor *nbr) } } - ep = eigrp_packet_new(nbr->ei->ifp->mtu); + ep = eigrp_packet_new(nbr->ei->ifp->mtu, nbr); /* Prepare EIGRP Graceful restart UPDATE header */ eigrp_packet_header_init(EIGRP_OPC_UPDATE, nbr->ei, ep->s, flags, From ef9329ac02539642b04e2c0baf6d401525ce5621 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20Ter=C3=A4s?= Date: Thu, 17 Aug 2017 16:55:43 +0300 Subject: [PATCH 013/130] nhrpd: use hop count 1 for registration requests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cisco has a bug that it rejects packets with zero hop count. Use one to avoid potential forwarding of registration requests. Fixes #951 Signed-off-by: Timo Teräs --- nhrpd/nhrp_nhs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nhrpd/nhrp_nhs.c b/nhrpd/nhrp_nhs.c index 76c591fd79..0bada33502 100644 --- a/nhrpd/nhrp_nhs.c +++ b/nhrpd/nhrp_nhs.c @@ -171,7 +171,7 @@ static int nhrp_reg_send_req(struct thread *t) zb = zbuf_alloc(1400); hdr = nhrp_packet_push(zb, NHRP_PACKET_REGISTRATION_REQUEST, &nifp->nbma, &if_ad->addr, dst_proto); - hdr->hop_count = 0; + hdr->hop_count = 1; if (!(if_ad->flags & NHRP_IFF_REG_NO_UNIQUE)) hdr->flags |= htons(NHRP_FLAG_REGISTRATION_UNIQUE); From 9c273c6d28345cb6c3d88aef2ab69a0eec264be3 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 17 Aug 2017 10:02:54 -0400 Subject: [PATCH 014/130] eigrpd: Rework ack sent to neighbor EIGRP schedules and builds packets to send in the future. Before those packets are being sent, we are receiving update information from our peer. At that time we need to reach into the built packet and reset the outgoing ack to a better value. Signed-off-by: Donald Sharp --- eigrpd/eigrp_packet.c | 63 ++++++++++++++++++++++--------------------- 1 file changed, 32 insertions(+), 31 deletions(-) diff --git a/eigrpd/eigrp_packet.c b/eigrpd/eigrp_packet.c index 84c1b1c590..9f3de10141 100644 --- a/eigrpd/eigrp_packet.c +++ b/eigrpd/eigrp_packet.c @@ -299,18 +299,6 @@ int eigrp_check_sha256_digest(struct stream *s, return 1; } -/* - * eigrp_packet_dump - * - * This routing dumps the contents of the IP packet either received or - * built by EIGRP. - */ -static void eigrp_packet_dump(struct stream *s) -{ - // not yet... - return; -} - int eigrp_write(struct thread *thread) { struct eigrp *eigrp = THREAD_ARG(thread); @@ -322,6 +310,7 @@ int eigrp_write(struct thread *thread) struct msghdr msg; struct iovec iov[2]; u_int16_t opcode = 0; + u_int32_t seqno, ack; int ret; int flags = 0; @@ -357,6 +346,25 @@ int eigrp_write(struct thread *thread) memset(&iph, 0, sizeof(struct ip)); memset(&sa_dst, 0, sizeof(sa_dst)); + /* + * We build and schedule packets to go out + * in the future. In the mean time we may + * process some update packets from the + * neighbor, thus making it necessary + * to update the ack we are using for + * this outgoing packet. + */ + eigrph = (struct eigrp_header *)STREAM_DATA(ep->s); + opcode = eigrph->opcode; + seqno = ntohl(eigrph->sequence); + ack = ntohl(eigrph->ack); + if (ep->nbr && (ack != ep->nbr->recv_sequence_number)) { + eigrph->ack = htonl(ep->nbr->recv_sequence_number); + ack = ep->nbr->recv_sequence_number; + eigrph->checksum = 0; + eigrp_packet_checksum(ei, ep->s, ep->length); + } + sa_dst.sin_family = AF_INET; #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN sa_dst.sin_len = sizeof(sa_dst); @@ -412,8 +420,9 @@ int eigrp_write(struct thread *thread) if (IS_DEBUG_EIGRP_TRANSMIT(0, SEND)) { eigrph = (struct eigrp_header *)STREAM_DATA(ep->s); opcode = eigrph->opcode; - zlog_debug("Sending [%s] to [%s] via [%s] ret [%d].", + zlog_debug("Sending [%s][%d/%d] to [%s] via [%s] ret [%d].", lookup_msg(eigrp_packet_type_str, opcode, NULL), + seqno, ack, inet_ntoa(ep->dst), IF_NAME(ei), ret); } @@ -425,18 +434,6 @@ int eigrp_write(struct thread *thread) iph.ip_len, ei->ifp->name, ei->ifp->mtu, safe_strerror(errno)); - /* Show debug sending packet. */ - if (IS_DEBUG_EIGRP_TRANSMIT(0, SEND) - && (IS_DEBUG_EIGRP_TRANSMIT(0, PACKET_DETAIL))) { - zlog_debug( - "-----------------------------------------------------"); - eigrp_ip_header_dump(&iph); - stream_set_getp(ep->s, 0); - eigrp_packet_dump(ep->s); - zlog_debug( - "-----------------------------------------------------"); - } - /* Now delete packet from queue. */ eigrp_packet_delete(ei); @@ -615,12 +612,16 @@ int eigrp_read(struct thread *thread) start of the eigrp TLVs */ opcode = eigrph->opcode; - if (IS_DEBUG_EIGRP_TRANSMIT(0, RECV)) - zlog_debug( - "Received [%s] length [%u] via [%s] src [%s] dst [%s]", - lookup_msg(eigrp_packet_type_str, opcode, NULL), length, - IF_NAME(ei), inet_ntoa(iph->ip_src), - inet_ntoa(iph->ip_dst)); + if (IS_DEBUG_EIGRP_TRANSMIT(0, RECV)) { + char src[100], dst[100]; + + strcpy(src, inet_ntoa(iph->ip_src)); + strcpy(dst, inet_ntoa(iph->ip_dst)); + zlog_debug("Received [%s][%d/%d] length [%u] via [%s] src [%s] dst [%s]", + lookup_msg(eigrp_packet_type_str, opcode, NULL), + ntohl(eigrph->sequence), ntohl(eigrph->ack), length, + IF_NAME(ei), src, dst); + } /* Read rest of the packet and call each sort of packet routine. */ stream_forward_getp(ibuf, EIGRP_HEADER_LEN); From c6e7b9524852848c72afa7973eb51da19c2dd147 Mon Sep 17 00:00:00 2001 From: Daniel Walton Date: Thu, 17 Aug 2017 15:04:25 +0000 Subject: [PATCH 015/130] pimd: "No Path to RP address specified" should exit 0 Signed-off-by: Daniel Walton This could happen if routing isn't up yet but the command did take so we should exit 0 here. Testing: root@cel-redxp-10[frr-dwalton76]# vtysh -c 'conf t' -c' ip pim rp 11.11.11.11' % No Path to RP address specified: 11.11.11.11 root@cel-redxp-10[frr-dwalton76]# echo $? 0 root@cel-redxp-10[frr-dwalton76]# --- pimd/pim_cmd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index d7e94d11dd..fdc19e6294 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -5066,7 +5066,7 @@ static int pim_rp_cmd_worker(struct pim_instance *pim, struct vty *vty, if (result == PIM_RP_NO_PATH) { vty_out(vty, "%% No Path to RP address specified: %s\n", rp); - return CMD_WARNING_CONFIG_FAILED; + return CMD_WARNING; } if (result == PIM_GROUP_OVERLAP) { From 01dccc0b19e2d568d3a69531aaea1bfbd848c39d Mon Sep 17 00:00:00 2001 From: Jorge Boncompte Date: Mon, 7 Aug 2017 19:15:38 +0200 Subject: [PATCH 016/130] lib: inline route_node_lock()/route_node_unlock() Avoid function calls. Signed-off-by: Jorge Boncompte --- lib/table.c | 20 +------------------- lib/table.h | 20 ++++++++++++++++++-- 2 files changed, 19 insertions(+), 21 deletions(-) diff --git a/lib/table.c b/lib/table.c index 833adb9a37..67cf6aeec3 100644 --- a/lib/table.c +++ b/lib/table.c @@ -31,7 +31,6 @@ DEFINE_MTYPE(LIB, ROUTE_TABLE, "Route table") DEFINE_MTYPE(LIB, ROUTE_NODE, "Route node") -static void route_node_delete(struct route_node *); static void route_table_free(struct route_table *); static int route_table_hash_cmp(const void *a, const void *b) @@ -187,23 +186,6 @@ static void set_link(struct route_node *node, struct route_node *new) new->parent = node; } -/* Lock node. */ -struct route_node *route_lock_node(struct route_node *node) -{ - node->lock++; - return node; -} - -/* Unlock node. */ -void route_unlock_node(struct route_node *node) -{ - assert(node->lock > 0); - node->lock--; - - if (node->lock == 0) - route_node_delete(node); -} - /* Find matched prefix. */ struct route_node *route_node_match(const struct route_table *table, union prefixconstptr pu) @@ -348,7 +330,7 @@ struct route_node *route_node_get(struct route_table *const table, } /* Delete node from the routing table. */ -static void route_node_delete(struct route_node *node) +void route_node_delete(struct route_node *node) { struct route_node *child; struct route_node *parent; diff --git a/lib/table.h b/lib/table.h index b7b402a591..ece40d86b3 100644 --- a/lib/table.h +++ b/lib/table.h @@ -182,7 +182,6 @@ route_table_init_with_delegate(route_table_delegate_t *); extern route_table_delegate_t *route_table_get_default_delegate(void); extern void route_table_finish(struct route_table *); -extern void route_unlock_node(struct route_node *node); extern struct route_node *route_top(struct route_table *); extern struct route_node *route_next(struct route_node *); extern struct route_node *route_next_until(struct route_node *, @@ -193,7 +192,6 @@ extern struct route_node *route_node_lookup(const struct route_table *, union prefixconstptr); extern struct route_node *route_node_lookup_maynull(const struct route_table *, union prefixconstptr); -extern struct route_node *route_lock_node(struct route_node *node); extern struct route_node *route_node_match(const struct route_table *, union prefixconstptr); extern struct route_node *route_node_match_ipv4(const struct route_table *, @@ -205,6 +203,7 @@ extern unsigned long route_table_count(const struct route_table *); extern struct route_node *route_node_create(route_table_delegate_t *, struct route_table *); +extern void route_node_delete(struct route_node *); extern void route_node_destroy(route_table_delegate_t *, struct route_table *, struct route_node *); @@ -225,6 +224,23 @@ extern void route_table_iter_cleanup(route_table_iter_t *iter); * Inline functions. */ +/* Lock node. */ +static inline struct route_node *route_lock_node(struct route_node *node) +{ + node->lock++; + return node; +} + +/* Unlock node. */ +static inline void route_unlock_node(struct route_node *node) +{ + assert(node->lock > 0); + node->lock--; + + if (node->lock == 0) + route_node_delete(node); +} + /* * route_table_iter_next * From cd85bc2e0bd8657cb2555fe8d631a2b0d916588e Mon Sep 17 00:00:00 2001 From: Jorge Boncompte Date: Mon, 7 Aug 2017 11:47:51 +0200 Subject: [PATCH 017/130] lib: standardize use of queue.h The simple queue implementation in OpenBSD and FreeBSD are called diferently, standardize in the use of the FreeBSD version and map the missing names only if we compile on OpenBSD. Signed-off-by: Jorge Boncompte --- ldpd/control.h | 2 +- ldpd/lde.h | 2 +- ldpd/ldpd.h | 2 +- ldpd/ldpe.h | 2 +- lib/freebsd-queue.h | 679 ++++++++++++++++++++++++++++++++++++++++++ lib/imsg-buffer.c | 2 +- lib/imsg.c | 2 +- lib/queue.h | 701 ++++---------------------------------------- lib/subdir.am | 3 +- 9 files changed, 736 insertions(+), 659 deletions(-) create mode 100644 lib/freebsd-queue.h diff --git a/ldpd/control.h b/ldpd/control.h index 0e66a1636a..23edb5f24d 100644 --- a/ldpd/control.h +++ b/ldpd/control.h @@ -19,7 +19,7 @@ #ifndef _CONTROL_H_ #define _CONTROL_H_ -#include "openbsd-queue.h" +#include "queue.h" struct ctl_conn { TAILQ_ENTRY(ctl_conn) entry; diff --git a/ldpd/lde.h b/ldpd/lde.h index 43f1d36481..94077d1631 100644 --- a/ldpd/lde.h +++ b/ldpd/lde.h @@ -21,7 +21,7 @@ #ifndef _LDE_H_ #define _LDE_H_ -#include "openbsd-queue.h" +#include "queue.h" #include "openbsd-tree.h" #include "if.h" diff --git a/ldpd/ldpd.h b/ldpd/ldpd.h index 31d0bc69b1..5580ea5d67 100644 --- a/ldpd/ldpd.h +++ b/ldpd/ldpd.h @@ -22,7 +22,7 @@ #ifndef _LDPD_H_ #define _LDPD_H_ -#include "openbsd-queue.h" +#include "queue.h" #include "openbsd-tree.h" #include "imsg.h" #include "thread.h" diff --git a/ldpd/ldpe.h b/ldpd/ldpe.h index 74f6b852b0..ccff1e803d 100644 --- a/ldpd/ldpe.h +++ b/ldpd/ldpe.h @@ -21,7 +21,7 @@ #ifndef _LDPE_H_ #define _LDPE_H_ -#include "openbsd-queue.h" +#include "queue.h" #include "openbsd-tree.h" #ifdef __OpenBSD__ #include diff --git a/lib/freebsd-queue.h b/lib/freebsd-queue.h new file mode 100644 index 0000000000..658b602ba3 --- /dev/null +++ b/lib/freebsd-queue.h @@ -0,0 +1,679 @@ +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)queue.h 8.5 (Berkeley) 8/20/94 + * $FreeBSD$ + */ + +#ifndef _SYS_QUEUE_H_ +#define _SYS_QUEUE_H_ + +/* + * This file defines four types of data structures: singly-linked lists, + * singly-linked tail queues, lists and tail queues. + * + * A singly-linked list is headed by a single forward pointer. The elements + * are singly linked for minimum space and pointer manipulation overhead at + * the expense of O(n) removal for arbitrary elements. New elements can be + * added to the list after an existing element or at the head of the list. + * Elements being removed from the head of the list should use the explicit + * macro for this purpose for optimum efficiency. A singly-linked list may + * only be traversed in the forward direction. Singly-linked lists are ideal + * for applications with large datasets and few or no removals or for + * implementing a LIFO queue. + * + * A singly-linked tail queue is headed by a pair of pointers, one to the + * head of the list and the other to the tail of the list. The elements are + * singly linked for minimum space and pointer manipulation overhead at the + * expense of O(n) removal for arbitrary elements. New elements can be added + * to the list after an existing element, at the head of the list, or at the + * end of the list. Elements being removed from the head of the tail queue + * should use the explicit macro for this purpose for optimum efficiency. + * A singly-linked tail queue may only be traversed in the forward direction. + * Singly-linked tail queues are ideal for applications with large datasets + * and few or no removals or for implementing a FIFO queue. + * + * A list is headed by a single forward pointer (or an array of forward + * pointers for a hash table header). The elements are doubly linked + * so that an arbitrary element can be removed without a need to + * traverse the list. New elements can be added to the list before + * or after an existing element or at the head of the list. A list + * may only be traversed in the forward direction. + * + * A tail queue is headed by a pair of pointers, one to the head of the + * list and the other to the tail of the list. The elements are doubly + * linked so that an arbitrary element can be removed without a need to + * traverse the list. New elements can be added to the list before or + * after an existing element, at the head of the list, or at the end of + * the list. A tail queue may be traversed in either direction. + * + * For details on the use of these macros, see the queue(3) manual page. + * + * + * SLIST LIST STAILQ TAILQ + * _HEAD + + + + + * _HEAD_INITIALIZER + + + + + * _ENTRY + + + + + * _INIT + + + + + * _EMPTY + + + + + * _FIRST + + + + + * _NEXT + + + + + * _PREV - - - + + * _LAST - - + + + * _FOREACH + + + + + * _FOREACH_SAFE + + + + + * _FOREACH_REVERSE - - - + + * _FOREACH_REVERSE_SAFE - - - + + * _INSERT_HEAD + + + + + * _INSERT_BEFORE - + - + + * _INSERT_AFTER + + + + + * _INSERT_TAIL - - + + + * _CONCAT - - + + + * _REMOVE_AFTER + - + - + * _REMOVE_HEAD + - + - + * _REMOVE + + + + + * _SWAP + + + + + * + */ +#ifdef QUEUE_MACRO_DEBUG +/* Store the last 2 places the queue element or head was altered */ +struct qm_trace { + char *lastfile; + int lastline; + char *prevfile; + int prevline; +}; + +#define TRACEBUF struct qm_trace trace; +#define TRASHIT(x) do {(x) = (void *)-1;} while (0) +#define QMD_SAVELINK(name, link) void **name = (void *)&(link) + +#define QMD_TRACE_HEAD(head) \ + do { \ + (head)->trace.prevline = (head)->trace.lastline; \ + (head)->trace.prevfile = (head)->trace.lastfile; \ + (head)->trace.lastline = __LINE__; \ + (head)->trace.lastfile = __FILE__; \ + } while (0) + +#define QMD_TRACE_ELEM(elem) \ + do { \ + (elem)->trace.prevline = (elem)->trace.lastline; \ + (elem)->trace.prevfile = (elem)->trace.lastfile; \ + (elem)->trace.lastline = __LINE__; \ + (elem)->trace.lastfile = __FILE__; \ + } while (0) + +#else +#define QMD_TRACE_ELEM(elem) +#define QMD_TRACE_HEAD(head) +#define QMD_SAVELINK(name, link) +#define TRACEBUF +#define TRASHIT(x) +#endif /* QUEUE_MACRO_DEBUG */ + +/* + * Singly-linked List declarations. + */ +#define SLIST_HEAD(name, type) \ + struct name { \ + struct type *slh_first; /* first element */ \ + } + +#define SLIST_HEAD_INITIALIZER(head) \ + { \ + NULL \ + } + +#define SLIST_ENTRY(type) \ + struct { \ + struct type *sle_next; /* next element */ \ + } + +/* + * Singly-linked List functions. + */ +#define SLIST_EMPTY(head) ((head)->slh_first == NULL) + +#define SLIST_FIRST(head) ((head)->slh_first) + +#define SLIST_FOREACH(var, head, field) \ + for ((var) = SLIST_FIRST((head)); (var); \ + (var) = SLIST_NEXT((var), field)) + +#define SLIST_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = SLIST_FIRST((head)); \ + (var) && ((tvar) = SLIST_NEXT((var), field), 1); (var) = (tvar)) + +#define SLIST_FOREACH_PREVPTR(var, varp, head, field) \ + for ((varp) = &SLIST_FIRST((head)); ((var) = *(varp)) != NULL; \ + (varp) = &SLIST_NEXT((var), field)) + +#define SLIST_INIT(head) \ + do { \ + SLIST_FIRST((head)) = NULL; \ + } while (0) + +#define SLIST_INSERT_AFTER(slistelm, elm, field) \ + do { \ + SLIST_NEXT((elm), field) = SLIST_NEXT((slistelm), field); \ + SLIST_NEXT((slistelm), field) = (elm); \ + } while (0) + +#define SLIST_INSERT_HEAD(head, elm, field) \ + do { \ + SLIST_NEXT((elm), field) = SLIST_FIRST((head)); \ + SLIST_FIRST((head)) = (elm); \ + } while (0) + +#define SLIST_NEXT(elm, field) ((elm)->field.sle_next) + +#define SLIST_REMOVE(head, elm, type, field) \ + do { \ + QMD_SAVELINK(oldnext, (elm)->field.sle_next); \ + if (SLIST_FIRST((head)) == (elm)) { \ + SLIST_REMOVE_HEAD((head), field); \ + } else { \ + struct type *curelm = SLIST_FIRST((head)); \ + while (SLIST_NEXT(curelm, field) != (elm)) \ + curelm = SLIST_NEXT(curelm, field); \ + SLIST_REMOVE_AFTER(curelm, field); \ + } \ + TRASHIT(*oldnext); \ + } while (0) + +#define SLIST_REMOVE_AFTER(elm, field) \ + do { \ + SLIST_NEXT(elm, field) = \ + SLIST_NEXT(SLIST_NEXT(elm, field), field); \ + } while (0) + +#define SLIST_REMOVE_HEAD(head, field) \ + do { \ + SLIST_FIRST((head)) = SLIST_NEXT(SLIST_FIRST((head)), field); \ + } while (0) + +#define SLIST_SWAP(head1, head2, type) \ + do { \ + struct type *swap_first = SLIST_FIRST(head1); \ + SLIST_FIRST(head1) = SLIST_FIRST(head2); \ + SLIST_FIRST(head2) = swap_first; \ + } while (0) + +/* + * Singly-linked Tail queue declarations. + */ +#define STAILQ_HEAD(name, type) \ + struct name { \ + struct type *stqh_first; /* first element */ \ + struct type **stqh_last; /* addr of last next element */ \ + } + +#define STAILQ_HEAD_INITIALIZER(head) \ + { \ + NULL, &(head).stqh_first \ + } + +#define STAILQ_ENTRY(type) \ + struct { \ + struct type *stqe_next; /* next element */ \ + } + +/* + * Singly-linked Tail queue functions. + */ +#define STAILQ_CONCAT(head1, head2) \ + do { \ + if (!STAILQ_EMPTY((head2))) { \ + *(head1)->stqh_last = (head2)->stqh_first; \ + (head1)->stqh_last = (head2)->stqh_last; \ + STAILQ_INIT((head2)); \ + } \ + } while (0) + +#define STAILQ_EMPTY(head) ((head)->stqh_first == NULL) + +#define STAILQ_FIRST(head) ((head)->stqh_first) + +#define STAILQ_FOREACH(var, head, field) \ + for ((var) = STAILQ_FIRST((head)); (var); \ + (var) = STAILQ_NEXT((var), field)) + + +#define STAILQ_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = STAILQ_FIRST((head)); \ + (var) && ((tvar) = STAILQ_NEXT((var), field), 1); (var) = (tvar)) + +#define STAILQ_INIT(head) \ + do { \ + STAILQ_FIRST((head)) = NULL; \ + (head)->stqh_last = &STAILQ_FIRST((head)); \ + } while (0) + +#define STAILQ_INSERT_AFTER(head, tqelm, elm, field) \ + do { \ + if ((STAILQ_NEXT((elm), field) = STAILQ_NEXT((tqelm), field)) \ + == NULL) \ + (head)->stqh_last = &STAILQ_NEXT((elm), field); \ + STAILQ_NEXT((tqelm), field) = (elm); \ + } while (0) + +#define STAILQ_INSERT_HEAD(head, elm, field) \ + do { \ + if ((STAILQ_NEXT((elm), field) = STAILQ_FIRST((head))) \ + == NULL) \ + (head)->stqh_last = &STAILQ_NEXT((elm), field); \ + STAILQ_FIRST((head)) = (elm); \ + } while (0) + +#define STAILQ_INSERT_TAIL(head, elm, field) \ + do { \ + STAILQ_NEXT((elm), field) = NULL; \ + *(head)->stqh_last = (elm); \ + (head)->stqh_last = &STAILQ_NEXT((elm), field); \ + } while (0) + +#define STAILQ_LAST(head, type, field) \ + (STAILQ_EMPTY((head)) \ + ? NULL \ + : ((struct type *)(void *)((char *)((head)->stqh_last) \ + - __offsetof(struct type, \ + field)))) + +#define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next) + +#define STAILQ_REMOVE(head, elm, type, field) \ + do { \ + QMD_SAVELINK(oldnext, (elm)->field.stqe_next); \ + if (STAILQ_FIRST((head)) == (elm)) { \ + STAILQ_REMOVE_HEAD((head), field); \ + } else { \ + struct type *curelm = STAILQ_FIRST((head)); \ + while (STAILQ_NEXT(curelm, field) != (elm)) \ + curelm = STAILQ_NEXT(curelm, field); \ + STAILQ_REMOVE_AFTER(head, curelm, field); \ + } \ + TRASHIT(*oldnext); \ + } while (0) + +#define STAILQ_REMOVE_AFTER(head, elm, field) \ + do { \ + if ((STAILQ_NEXT(elm, field) = \ + STAILQ_NEXT(STAILQ_NEXT(elm, field), field)) \ + == NULL) \ + (head)->stqh_last = &STAILQ_NEXT((elm), field); \ + } while (0) + +#define STAILQ_REMOVE_HEAD(head, field) \ + do { \ + if ((STAILQ_FIRST((head)) = \ + STAILQ_NEXT(STAILQ_FIRST((head)), field)) \ + == NULL) \ + (head)->stqh_last = &STAILQ_FIRST((head)); \ + } while (0) + +#define STAILQ_SWAP(head1, head2, type) \ + do { \ + struct type *swap_first = STAILQ_FIRST(head1); \ + struct type **swap_last = (head1)->stqh_last; \ + STAILQ_FIRST(head1) = STAILQ_FIRST(head2); \ + (head1)->stqh_last = (head2)->stqh_last; \ + STAILQ_FIRST(head2) = swap_first; \ + (head2)->stqh_last = swap_last; \ + if (STAILQ_EMPTY(head1)) \ + (head1)->stqh_last = &STAILQ_FIRST(head1); \ + if (STAILQ_EMPTY(head2)) \ + (head2)->stqh_last = &STAILQ_FIRST(head2); \ + } while (0) + + +/* + * List declarations. + */ +#define LIST_HEAD(name, type) \ + struct name { \ + struct type *lh_first; /* first element */ \ + } + +#define LIST_HEAD_INITIALIZER(head) \ + { \ + NULL \ + } + +#define LIST_ENTRY(type) \ + struct { \ + struct type *le_next; /* next element */ \ + struct type **le_prev; /* address of previous next element */ \ + } + +/* + * List functions. + */ + +#if (defined(_KERNEL) && defined(INVARIANTS)) +#define QMD_LIST_CHECK_HEAD(head, field) \ + do { \ + if (LIST_FIRST((head)) != NULL \ + && LIST_FIRST((head))->field.le_prev \ + != &LIST_FIRST((head))) \ + panic("Bad list head %p first->prev != head", (head)); \ + } while (0) + +#define QMD_LIST_CHECK_NEXT(elm, field) \ + do { \ + if (LIST_NEXT((elm), field) != NULL \ + && LIST_NEXT((elm), field)->field.le_prev \ + != &((elm)->field.le_next)) \ + panic("Bad link elm %p next->prev != elm", (elm)); \ + } while (0) + +#define QMD_LIST_CHECK_PREV(elm, field) \ + do { \ + if (*(elm)->field.le_prev != (elm)) \ + panic("Bad link elm %p prev->next != elm", (elm)); \ + } while (0) +#else +#define QMD_LIST_CHECK_HEAD(head, field) +#define QMD_LIST_CHECK_NEXT(elm, field) +#define QMD_LIST_CHECK_PREV(elm, field) +#endif /* (_KERNEL && INVARIANTS) */ + +#define LIST_EMPTY(head) ((head)->lh_first == NULL) + +#define LIST_FIRST(head) ((head)->lh_first) + +#define LIST_FOREACH(var, head, field) \ + for ((var) = LIST_FIRST((head)); (var); (var) = LIST_NEXT((var), field)) + +#define LIST_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = LIST_FIRST((head)); \ + (var) && ((tvar) = LIST_NEXT((var), field), 1); (var) = (tvar)) + +#define LIST_INIT(head) \ + do { \ + LIST_FIRST((head)) = NULL; \ + } while (0) + +#define LIST_INSERT_AFTER(listelm, elm, field) \ + do { \ + QMD_LIST_CHECK_NEXT(listelm, field); \ + if ((LIST_NEXT((elm), field) = LIST_NEXT((listelm), field)) \ + != NULL) \ + LIST_NEXT((listelm), field)->field.le_prev = \ + &LIST_NEXT((elm), field); \ + LIST_NEXT((listelm), field) = (elm); \ + (elm)->field.le_prev = &LIST_NEXT((listelm), field); \ + } while (0) + +#define LIST_INSERT_BEFORE(listelm, elm, field) \ + do { \ + QMD_LIST_CHECK_PREV(listelm, field); \ + (elm)->field.le_prev = (listelm)->field.le_prev; \ + LIST_NEXT((elm), field) = (listelm); \ + *(listelm)->field.le_prev = (elm); \ + (listelm)->field.le_prev = &LIST_NEXT((elm), field); \ + } while (0) + +#define LIST_INSERT_HEAD(head, elm, field) \ + do { \ + QMD_LIST_CHECK_HEAD((head), field); \ + if ((LIST_NEXT((elm), field) = LIST_FIRST((head))) != NULL) \ + LIST_FIRST((head))->field.le_prev = \ + &LIST_NEXT((elm), field); \ + LIST_FIRST((head)) = (elm); \ + (elm)->field.le_prev = &LIST_FIRST((head)); \ + } while (0) + +#define LIST_NEXT(elm, field) ((elm)->field.le_next) + +#define LIST_REMOVE(elm, field) \ + do { \ + QMD_SAVELINK(oldnext, (elm)->field.le_next); \ + QMD_SAVELINK(oldprev, (elm)->field.le_prev); \ + QMD_LIST_CHECK_NEXT(elm, field); \ + QMD_LIST_CHECK_PREV(elm, field); \ + if (LIST_NEXT((elm), field) != NULL) \ + LIST_NEXT((elm), field)->field.le_prev = \ + (elm)->field.le_prev; \ + *(elm)->field.le_prev = LIST_NEXT((elm), field); \ + TRASHIT(*oldnext); \ + TRASHIT(*oldprev); \ + } while (0) + +#define LIST_SWAP(head1, head2, type, field) \ + do { \ + struct type *swap_tmp = LIST_FIRST((head1)); \ + LIST_FIRST((head1)) = LIST_FIRST((head2)); \ + LIST_FIRST((head2)) = swap_tmp; \ + if ((swap_tmp = LIST_FIRST((head1))) != NULL) \ + swap_tmp->field.le_prev = &LIST_FIRST((head1)); \ + if ((swap_tmp = LIST_FIRST((head2))) != NULL) \ + swap_tmp->field.le_prev = &LIST_FIRST((head2)); \ + } while (0) + +/* + * Tail queue declarations. + */ +#define TAILQ_HEAD(name, type) \ + struct name { \ + struct type *tqh_first; /* first element */ \ + struct type **tqh_last; /* addr of last next element */ \ + TRACEBUF \ + } + +#define TAILQ_HEAD_INITIALIZER(head) \ + { \ + NULL, &(head).tqh_first \ + } + +#define TAILQ_ENTRY(type) \ + struct { \ + struct type *tqe_next; /* next element */ \ + struct type **tqe_prev; /* address of previous next element */ \ + TRACEBUF \ + } + +/* + * Tail queue functions. + */ +#if (defined(_KERNEL) && defined(INVARIANTS)) +#define QMD_TAILQ_CHECK_HEAD(head, field) \ + do { \ + if (!TAILQ_EMPTY(head) \ + && TAILQ_FIRST((head))->field.tqe_prev \ + != &TAILQ_FIRST((head))) \ + panic("Bad tailq head %p first->prev != head", \ + (head)); \ + } while (0) + +#define QMD_TAILQ_CHECK_TAIL(head, field) \ + do { \ + if (*(head)->tqh_last != NULL) \ + panic("Bad tailq NEXT(%p->tqh_last) != NULL", (head)); \ + } while (0) + +#define QMD_TAILQ_CHECK_NEXT(elm, field) \ + do { \ + if (TAILQ_NEXT((elm), field) != NULL \ + && TAILQ_NEXT((elm), field)->field.tqe_prev \ + != &((elm)->field.tqe_next)) \ + panic("Bad link elm %p next->prev != elm", (elm)); \ + } while (0) + +#define QMD_TAILQ_CHECK_PREV(elm, field) \ + do { \ + if (*(elm)->field.tqe_prev != (elm)) \ + panic("Bad link elm %p prev->next != elm", (elm)); \ + } while (0) +#else +#define QMD_TAILQ_CHECK_HEAD(head, field) +#define QMD_TAILQ_CHECK_TAIL(head, headname) +#define QMD_TAILQ_CHECK_NEXT(elm, field) +#define QMD_TAILQ_CHECK_PREV(elm, field) +#endif /* (_KERNEL && INVARIANTS) */ + +#define TAILQ_CONCAT(head1, head2, field) \ + do { \ + if (!TAILQ_EMPTY(head2)) { \ + *(head1)->tqh_last = (head2)->tqh_first; \ + (head2)->tqh_first->field.tqe_prev = \ + (head1)->tqh_last; \ + (head1)->tqh_last = (head2)->tqh_last; \ + TAILQ_INIT((head2)); \ + QMD_TRACE_HEAD(head1); \ + QMD_TRACE_HEAD(head2); \ + } \ + } while (0) + +#define TAILQ_EMPTY(head) ((head)->tqh_first == NULL) + +#define TAILQ_FIRST(head) ((head)->tqh_first) + +#define TAILQ_FOREACH(var, head, field) \ + for ((var) = TAILQ_FIRST((head)); (var); \ + (var) = TAILQ_NEXT((var), field)) + +#define TAILQ_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = TAILQ_FIRST((head)); \ + (var) && ((tvar) = TAILQ_NEXT((var), field), 1); (var) = (tvar)) + +#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \ + for ((var) = TAILQ_LAST((head), headname); (var); \ + (var) = TAILQ_PREV((var), headname, field)) + +#define TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar) \ + for ((var) = TAILQ_LAST((head), headname); \ + (var) && ((tvar) = TAILQ_PREV((var), headname, field), 1); \ + (var) = (tvar)) + +#define TAILQ_INIT(head) \ + do { \ + TAILQ_FIRST((head)) = NULL; \ + (head)->tqh_last = &TAILQ_FIRST((head)); \ + QMD_TRACE_HEAD(head); \ + } while (0) + +#define TAILQ_INSERT_AFTER(head, listelm, elm, field) \ + do { \ + QMD_TAILQ_CHECK_NEXT(listelm, field); \ + if ((TAILQ_NEXT((elm), field) = TAILQ_NEXT((listelm), field)) \ + != NULL) \ + TAILQ_NEXT((elm), field)->field.tqe_prev = \ + &TAILQ_NEXT((elm), field); \ + else { \ + (head)->tqh_last = &TAILQ_NEXT((elm), field); \ + QMD_TRACE_HEAD(head); \ + } \ + TAILQ_NEXT((listelm), field) = (elm); \ + (elm)->field.tqe_prev = &TAILQ_NEXT((listelm), field); \ + QMD_TRACE_ELEM(&(elm)->field); \ + QMD_TRACE_ELEM(&listelm->field); \ + } while (0) + +#define TAILQ_INSERT_BEFORE(listelm, elm, field) \ + do { \ + QMD_TAILQ_CHECK_PREV(listelm, field); \ + (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \ + TAILQ_NEXT((elm), field) = (listelm); \ + *(listelm)->field.tqe_prev = (elm); \ + (listelm)->field.tqe_prev = &TAILQ_NEXT((elm), field); \ + QMD_TRACE_ELEM(&(elm)->field); \ + QMD_TRACE_ELEM(&listelm->field); \ + } while (0) + +#define TAILQ_INSERT_HEAD(head, elm, field) \ + do { \ + QMD_TAILQ_CHECK_HEAD(head, field); \ + if ((TAILQ_NEXT((elm), field) = TAILQ_FIRST((head))) != NULL) \ + TAILQ_FIRST((head))->field.tqe_prev = \ + &TAILQ_NEXT((elm), field); \ + else \ + (head)->tqh_last = &TAILQ_NEXT((elm), field); \ + TAILQ_FIRST((head)) = (elm); \ + (elm)->field.tqe_prev = &TAILQ_FIRST((head)); \ + QMD_TRACE_HEAD(head); \ + QMD_TRACE_ELEM(&(elm)->field); \ + } while (0) + +#define TAILQ_INSERT_TAIL(head, elm, field) \ + do { \ + QMD_TAILQ_CHECK_TAIL(head, field); \ + TAILQ_NEXT((elm), field) = NULL; \ + (elm)->field.tqe_prev = (head)->tqh_last; \ + *(head)->tqh_last = (elm); \ + (head)->tqh_last = &TAILQ_NEXT((elm), field); \ + QMD_TRACE_HEAD(head); \ + QMD_TRACE_ELEM(&(elm)->field); \ + } while (0) + +#define TAILQ_LAST(head, headname) \ + (*(((struct headname *)((head)->tqh_last))->tqh_last)) + +#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next) + +#define TAILQ_PREV(elm, headname, field) \ + (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last)) + +#define TAILQ_REMOVE(head, elm, field) \ + do { \ + QMD_SAVELINK(oldnext, (elm)->field.tqe_next); \ + QMD_SAVELINK(oldprev, (elm)->field.tqe_prev); \ + QMD_TAILQ_CHECK_NEXT(elm, field); \ + QMD_TAILQ_CHECK_PREV(elm, field); \ + if ((TAILQ_NEXT((elm), field)) != NULL) \ + TAILQ_NEXT((elm), field)->field.tqe_prev = \ + (elm)->field.tqe_prev; \ + else { \ + (head)->tqh_last = (elm)->field.tqe_prev; \ + QMD_TRACE_HEAD(head); \ + } \ + *(elm)->field.tqe_prev = TAILQ_NEXT((elm), field); \ + TRASHIT(*oldnext); \ + TRASHIT(*oldprev); \ + QMD_TRACE_ELEM(&(elm)->field); \ + } while (0) + +#define TAILQ_SWAP(head1, head2, type, field) \ + do { \ + struct type *swap_first = (head1)->tqh_first; \ + struct type **swap_last = (head1)->tqh_last; \ + (head1)->tqh_first = (head2)->tqh_first; \ + (head1)->tqh_last = (head2)->tqh_last; \ + (head2)->tqh_first = swap_first; \ + (head2)->tqh_last = swap_last; \ + if ((swap_first = (head1)->tqh_first) != NULL) \ + swap_first->field.tqe_prev = &(head1)->tqh_first; \ + else \ + (head1)->tqh_last = &(head1)->tqh_first; \ + if ((swap_first = (head2)->tqh_first) != NULL) \ + swap_first->field.tqe_prev = &(head2)->tqh_first; \ + else \ + (head2)->tqh_last = &(head2)->tqh_first; \ + } while (0) + +#endif /* !_SYS_QUEUE_H_ */ diff --git a/lib/imsg-buffer.c b/lib/imsg-buffer.c index a486fc17c1..ae660504e4 100644 --- a/lib/imsg-buffer.c +++ b/lib/imsg-buffer.c @@ -18,7 +18,7 @@ #include -#include "openbsd-queue.h" +#include "queue.h" #include "imsg.h" int ibuf_realloc(struct ibuf *, size_t); diff --git a/lib/imsg.c b/lib/imsg.c index fc62c13734..999ab679b8 100644 --- a/lib/imsg.c +++ b/lib/imsg.c @@ -18,7 +18,7 @@ #include -#include "openbsd-queue.h" +#include "queue.h" #include "imsg.h" int imsg_fd_overhead = 0; diff --git a/lib/queue.h b/lib/queue.h index 658b602ba3..29b67a26e6 100644 --- a/lib/queue.h +++ b/lib/queue.h @@ -1,679 +1,76 @@ -/*- - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)queue.h 8.5 (Berkeley) 8/20/94 - * $FreeBSD$ - */ - -#ifndef _SYS_QUEUE_H_ -#define _SYS_QUEUE_H_ - /* - * This file defines four types of data structures: singly-linked lists, - * singly-linked tail queues, lists and tail queues. + * lists and queues implementations * - * A singly-linked list is headed by a single forward pointer. The elements - * are singly linked for minimum space and pointer manipulation overhead at - * the expense of O(n) removal for arbitrary elements. New elements can be - * added to the list after an existing element or at the head of the list. - * Elements being removed from the head of the list should use the explicit - * macro for this purpose for optimum efficiency. A singly-linked list may - * only be traversed in the forward direction. Singly-linked lists are ideal - * for applications with large datasets and few or no removals or for - * implementing a LIFO queue. + * 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. * - * A singly-linked tail queue is headed by a pair of pointers, one to the - * head of the list and the other to the tail of the list. The elements are - * singly linked for minimum space and pointer manipulation overhead at the - * expense of O(n) removal for arbitrary elements. New elements can be added - * to the list after an existing element, at the head of the list, or at the - * end of the list. Elements being removed from the head of the tail queue - * should use the explicit macro for this purpose for optimum efficiency. - * A singly-linked tail queue may only be traversed in the forward direction. - * Singly-linked tail queues are ideal for applications with large datasets - * and few or no removals or for implementing a FIFO queue. - * - * A list is headed by a single forward pointer (or an array of forward - * pointers for a hash table header). The elements are doubly linked - * so that an arbitrary element can be removed without a need to - * traverse the list. New elements can be added to the list before - * or after an existing element or at the head of the list. A list - * may only be traversed in the forward direction. - * - * A tail queue is headed by a pair of pointers, one to the head of the - * list and the other to the tail of the list. The elements are doubly - * linked so that an arbitrary element can be removed without a need to - * traverse the list. New elements can be added to the list before or - * after an existing element, at the head of the list, or at the end of - * the list. A tail queue may be traversed in either direction. - * - * For details on the use of these macros, see the queue(3) manual page. - * - * - * SLIST LIST STAILQ TAILQ - * _HEAD + + + + - * _HEAD_INITIALIZER + + + + - * _ENTRY + + + + - * _INIT + + + + - * _EMPTY + + + + - * _FIRST + + + + - * _NEXT + + + + - * _PREV - - - + - * _LAST - - + + - * _FOREACH + + + + - * _FOREACH_SAFE + + + + - * _FOREACH_REVERSE - - - + - * _FOREACH_REVERSE_SAFE - - - + - * _INSERT_HEAD + + + + - * _INSERT_BEFORE - + - + - * _INSERT_AFTER + + + + - * _INSERT_TAIL - - + + - * _CONCAT - - + + - * _REMOVE_AFTER + - + - - * _REMOVE_HEAD + - + - - * _REMOVE + + + + - * _SWAP + + + + + * 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; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifdef QUEUE_MACRO_DEBUG -/* Store the last 2 places the queue element or head was altered */ -struct qm_trace { - char *lastfile; - int lastline; - char *prevfile; - int prevline; -}; -#define TRACEBUF struct qm_trace trace; -#define TRASHIT(x) do {(x) = (void *)-1;} while (0) -#define QMD_SAVELINK(name, link) void **name = (void *)&(link) +#ifndef _FRR_QUEUE_H +#define _FRR_QUEUE_H -#define QMD_TRACE_HEAD(head) \ - do { \ - (head)->trace.prevline = (head)->trace.lastline; \ - (head)->trace.prevfile = (head)->trace.lastfile; \ - (head)->trace.lastline = __LINE__; \ - (head)->trace.lastfile = __FILE__; \ - } while (0) +#if defined(__OpenBSD__) && !defined(STAILQ_HEAD) +#include "openbsd-queue.h" -#define QMD_TRACE_ELEM(elem) \ - do { \ - (elem)->trace.prevline = (elem)->trace.lastline; \ - (elem)->trace.prevfile = (elem)->trace.lastfile; \ - (elem)->trace.lastline = __LINE__; \ - (elem)->trace.lastfile = __FILE__; \ - } while (0) - -#else -#define QMD_TRACE_ELEM(elem) -#define QMD_TRACE_HEAD(head) -#define QMD_SAVELINK(name, link) -#define TRACEBUF -#define TRASHIT(x) -#endif /* QUEUE_MACRO_DEBUG */ - -/* - * Singly-linked List declarations. - */ -#define SLIST_HEAD(name, type) \ - struct name { \ - struct type *slh_first; /* first element */ \ - } - -#define SLIST_HEAD_INITIALIZER(head) \ - { \ - NULL \ - } - -#define SLIST_ENTRY(type) \ - struct { \ - struct type *sle_next; /* next element */ \ - } - -/* - * Singly-linked List functions. - */ -#define SLIST_EMPTY(head) ((head)->slh_first == NULL) - -#define SLIST_FIRST(head) ((head)->slh_first) - -#define SLIST_FOREACH(var, head, field) \ - for ((var) = SLIST_FIRST((head)); (var); \ - (var) = SLIST_NEXT((var), field)) - -#define SLIST_FOREACH_SAFE(var, head, field, tvar) \ - for ((var) = SLIST_FIRST((head)); \ - (var) && ((tvar) = SLIST_NEXT((var), field), 1); (var) = (tvar)) - -#define SLIST_FOREACH_PREVPTR(var, varp, head, field) \ - for ((varp) = &SLIST_FIRST((head)); ((var) = *(varp)) != NULL; \ - (varp) = &SLIST_NEXT((var), field)) - -#define SLIST_INIT(head) \ - do { \ - SLIST_FIRST((head)) = NULL; \ - } while (0) - -#define SLIST_INSERT_AFTER(slistelm, elm, field) \ - do { \ - SLIST_NEXT((elm), field) = SLIST_NEXT((slistelm), field); \ - SLIST_NEXT((slistelm), field) = (elm); \ - } while (0) - -#define SLIST_INSERT_HEAD(head, elm, field) \ - do { \ - SLIST_NEXT((elm), field) = SLIST_FIRST((head)); \ - SLIST_FIRST((head)) = (elm); \ - } while (0) - -#define SLIST_NEXT(elm, field) ((elm)->field.sle_next) - -#define SLIST_REMOVE(head, elm, type, field) \ - do { \ - QMD_SAVELINK(oldnext, (elm)->field.sle_next); \ - if (SLIST_FIRST((head)) == (elm)) { \ - SLIST_REMOVE_HEAD((head), field); \ - } else { \ - struct type *curelm = SLIST_FIRST((head)); \ - while (SLIST_NEXT(curelm, field) != (elm)) \ - curelm = SLIST_NEXT(curelm, field); \ - SLIST_REMOVE_AFTER(curelm, field); \ - } \ - TRASHIT(*oldnext); \ - } while (0) - -#define SLIST_REMOVE_AFTER(elm, field) \ - do { \ - SLIST_NEXT(elm, field) = \ - SLIST_NEXT(SLIST_NEXT(elm, field), field); \ - } while (0) - -#define SLIST_REMOVE_HEAD(head, field) \ - do { \ - SLIST_FIRST((head)) = SLIST_NEXT(SLIST_FIRST((head)), field); \ - } while (0) - -#define SLIST_SWAP(head1, head2, type) \ - do { \ - struct type *swap_first = SLIST_FIRST(head1); \ - SLIST_FIRST(head1) = SLIST_FIRST(head2); \ - SLIST_FIRST(head2) = swap_first; \ - } while (0) - -/* - * Singly-linked Tail queue declarations. - */ -#define STAILQ_HEAD(name, type) \ - struct name { \ - struct type *stqh_first; /* first element */ \ - struct type **stqh_last; /* addr of last next element */ \ - } - -#define STAILQ_HEAD_INITIALIZER(head) \ - { \ - NULL, &(head).stqh_first \ - } - -#define STAILQ_ENTRY(type) \ - struct { \ - struct type *stqe_next; /* next element */ \ - } - -/* - * Singly-linked Tail queue functions. - */ -#define STAILQ_CONCAT(head1, head2) \ - do { \ - if (!STAILQ_EMPTY((head2))) { \ - *(head1)->stqh_last = (head2)->stqh_first; \ - (head1)->stqh_last = (head2)->stqh_last; \ - STAILQ_INIT((head2)); \ - } \ - } while (0) - -#define STAILQ_EMPTY(head) ((head)->stqh_first == NULL) - -#define STAILQ_FIRST(head) ((head)->stqh_first) - -#define STAILQ_FOREACH(var, head, field) \ - for ((var) = STAILQ_FIRST((head)); (var); \ - (var) = STAILQ_NEXT((var), field)) - - -#define STAILQ_FOREACH_SAFE(var, head, field, tvar) \ - for ((var) = STAILQ_FIRST((head)); \ - (var) && ((tvar) = STAILQ_NEXT((var), field), 1); (var) = (tvar)) - -#define STAILQ_INIT(head) \ - do { \ - STAILQ_FIRST((head)) = NULL; \ - (head)->stqh_last = &STAILQ_FIRST((head)); \ - } while (0) - -#define STAILQ_INSERT_AFTER(head, tqelm, elm, field) \ - do { \ - if ((STAILQ_NEXT((elm), field) = STAILQ_NEXT((tqelm), field)) \ - == NULL) \ - (head)->stqh_last = &STAILQ_NEXT((elm), field); \ - STAILQ_NEXT((tqelm), field) = (elm); \ - } while (0) - -#define STAILQ_INSERT_HEAD(head, elm, field) \ - do { \ - if ((STAILQ_NEXT((elm), field) = STAILQ_FIRST((head))) \ - == NULL) \ - (head)->stqh_last = &STAILQ_NEXT((elm), field); \ - STAILQ_FIRST((head)) = (elm); \ - } while (0) - -#define STAILQ_INSERT_TAIL(head, elm, field) \ - do { \ - STAILQ_NEXT((elm), field) = NULL; \ - *(head)->stqh_last = (elm); \ - (head)->stqh_last = &STAILQ_NEXT((elm), field); \ - } while (0) +/* Try to map FreeBSD implementation to OpenBSD one. */ +#define STAILQ_HEAD(name, type) SIMPLEQ_HEAD(name, type) +#define STAILQ_HEAD_INITIALIZER(head) SIMPLEQ_HEAD_INITIALIZER(head) +#define STAILQ_ENTRY(entry) SIMPLEQ_ENTRY(entry) +#define STAILQ_CONCAT(head1, head2) SIMPLEQ_CONCAT(head1, head2) +#define STAILQ_EMPTY(head) SIMPLEQ_EMPTY(head) +#define STAILQ_FIRST(head) SIMPLEQ_FIRST(head) +#define STAILQ_FOREACH(var, head, field) SIMPLEQ_FOREACH(var, head, field) +#define STAILQ_FOREACH_SAFE(var, head, field, tvar) SIMPLEQ_FOREACH_SAFE(var, head, field, tvar) +#define STAILQ_INIT(head) SIMPLEQ_INIT(head) +#define STAILQ_INSERT_AFTER(head, tqelm, elm, field) SIMPLEQ_INSERT_AFTER(head, tqelm, elm, field) +#define STAILQ_INSERT_HEAD(head, elm, field) SIMPLEQ_INSERT_HEAD(head, elm, field) +#define STAILQ_INSERT_TAIL(head, elm, field) SIMPLEQ_INSERT_TAIL(head, elm, field) #define STAILQ_LAST(head, type, field) \ - (STAILQ_EMPTY((head)) \ + (SIMPLEQ_EMPTY((head)) \ ? NULL \ - : ((struct type *)(void *)((char *)((head)->stqh_last) \ - - __offsetof(struct type, \ + : ((struct type *)(void *)((char *)((head)->sqh_last) \ + - offsetof(struct type, \ field)))) - -#define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next) - +#define STAILQ_NEXT(elm, field) SIMPLEQ_NEXT(elm, field) #define STAILQ_REMOVE(head, elm, type, field) \ do { \ - QMD_SAVELINK(oldnext, (elm)->field.stqe_next); \ - if (STAILQ_FIRST((head)) == (elm)) { \ - STAILQ_REMOVE_HEAD((head), field); \ + if (SIMPLEQ_FIRST((head)) == (elm)) { \ + SIMPLEQ_REMOVE_HEAD((head), field); \ } else { \ - struct type *curelm = STAILQ_FIRST((head)); \ - while (STAILQ_NEXT(curelm, field) != (elm)) \ - curelm = STAILQ_NEXT(curelm, field); \ - STAILQ_REMOVE_AFTER(head, curelm, field); \ + struct type *curelm = SIMPLEQ_FIRST((head)); \ + while (SIMPLEQ_NEXT(curelm, field) != (elm)) \ + curelm = SIMPLEQ_NEXT(curelm, field); \ + SIMPLEQ_REMOVE_AFTER(head, curelm, field); \ } \ - TRASHIT(*oldnext); \ } while (0) - -#define STAILQ_REMOVE_AFTER(head, elm, field) \ - do { \ - if ((STAILQ_NEXT(elm, field) = \ - STAILQ_NEXT(STAILQ_NEXT(elm, field), field)) \ - == NULL) \ - (head)->stqh_last = &STAILQ_NEXT((elm), field); \ - } while (0) - -#define STAILQ_REMOVE_HEAD(head, field) \ - do { \ - if ((STAILQ_FIRST((head)) = \ - STAILQ_NEXT(STAILQ_FIRST((head)), field)) \ - == NULL) \ - (head)->stqh_last = &STAILQ_FIRST((head)); \ - } while (0) - +#define STAILQ_REMOVE_AFTER(head, elm, field) SIMPLEQ_REMOVE_AFTER(head, elm, field) +#define STAILQ_REMOVE_HEAD(head, field) SIMPLEQ_REMOVE_HEAD(head, field) #define STAILQ_SWAP(head1, head2, type) \ do { \ struct type *swap_first = STAILQ_FIRST(head1); \ - struct type **swap_last = (head1)->stqh_last; \ + struct type **swap_last = (head1)->sqh_last; \ STAILQ_FIRST(head1) = STAILQ_FIRST(head2); \ - (head1)->stqh_last = (head2)->stqh_last; \ + (head1)->sqh_last = (head2)->sqh_last; \ STAILQ_FIRST(head2) = swap_first; \ - (head2)->stqh_last = swap_last; \ + (head2)->sqh_last = swap_last; \ if (STAILQ_EMPTY(head1)) \ - (head1)->stqh_last = &STAILQ_FIRST(head1); \ + (head1)->sqh_last = &STAILQ_FIRST(head1); \ if (STAILQ_EMPTY(head2)) \ - (head2)->stqh_last = &STAILQ_FIRST(head2); \ - } while (0) - - -/* - * List declarations. - */ -#define LIST_HEAD(name, type) \ - struct name { \ - struct type *lh_first; /* first element */ \ - } - -#define LIST_HEAD_INITIALIZER(head) \ - { \ - NULL \ - } - -#define LIST_ENTRY(type) \ - struct { \ - struct type *le_next; /* next element */ \ - struct type **le_prev; /* address of previous next element */ \ - } - -/* - * List functions. - */ - -#if (defined(_KERNEL) && defined(INVARIANTS)) -#define QMD_LIST_CHECK_HEAD(head, field) \ - do { \ - if (LIST_FIRST((head)) != NULL \ - && LIST_FIRST((head))->field.le_prev \ - != &LIST_FIRST((head))) \ - panic("Bad list head %p first->prev != head", (head)); \ - } while (0) - -#define QMD_LIST_CHECK_NEXT(elm, field) \ - do { \ - if (LIST_NEXT((elm), field) != NULL \ - && LIST_NEXT((elm), field)->field.le_prev \ - != &((elm)->field.le_next)) \ - panic("Bad link elm %p next->prev != elm", (elm)); \ - } while (0) - -#define QMD_LIST_CHECK_PREV(elm, field) \ - do { \ - if (*(elm)->field.le_prev != (elm)) \ - panic("Bad link elm %p prev->next != elm", (elm)); \ + (head2)->sqh_last = &STAILQ_FIRST(head2); \ } while (0) #else -#define QMD_LIST_CHECK_HEAD(head, field) -#define QMD_LIST_CHECK_NEXT(elm, field) -#define QMD_LIST_CHECK_PREV(elm, field) -#endif /* (_KERNEL && INVARIANTS) */ +#include "freebsd-queue.h" +#endif /* defined(__OpenBSD__) && !defined(STAILQ_HEAD) */ -#define LIST_EMPTY(head) ((head)->lh_first == NULL) - -#define LIST_FIRST(head) ((head)->lh_first) - -#define LIST_FOREACH(var, head, field) \ - for ((var) = LIST_FIRST((head)); (var); (var) = LIST_NEXT((var), field)) - -#define LIST_FOREACH_SAFE(var, head, field, tvar) \ - for ((var) = LIST_FIRST((head)); \ - (var) && ((tvar) = LIST_NEXT((var), field), 1); (var) = (tvar)) - -#define LIST_INIT(head) \ - do { \ - LIST_FIRST((head)) = NULL; \ - } while (0) - -#define LIST_INSERT_AFTER(listelm, elm, field) \ - do { \ - QMD_LIST_CHECK_NEXT(listelm, field); \ - if ((LIST_NEXT((elm), field) = LIST_NEXT((listelm), field)) \ - != NULL) \ - LIST_NEXT((listelm), field)->field.le_prev = \ - &LIST_NEXT((elm), field); \ - LIST_NEXT((listelm), field) = (elm); \ - (elm)->field.le_prev = &LIST_NEXT((listelm), field); \ - } while (0) - -#define LIST_INSERT_BEFORE(listelm, elm, field) \ - do { \ - QMD_LIST_CHECK_PREV(listelm, field); \ - (elm)->field.le_prev = (listelm)->field.le_prev; \ - LIST_NEXT((elm), field) = (listelm); \ - *(listelm)->field.le_prev = (elm); \ - (listelm)->field.le_prev = &LIST_NEXT((elm), field); \ - } while (0) - -#define LIST_INSERT_HEAD(head, elm, field) \ - do { \ - QMD_LIST_CHECK_HEAD((head), field); \ - if ((LIST_NEXT((elm), field) = LIST_FIRST((head))) != NULL) \ - LIST_FIRST((head))->field.le_prev = \ - &LIST_NEXT((elm), field); \ - LIST_FIRST((head)) = (elm); \ - (elm)->field.le_prev = &LIST_FIRST((head)); \ - } while (0) - -#define LIST_NEXT(elm, field) ((elm)->field.le_next) - -#define LIST_REMOVE(elm, field) \ - do { \ - QMD_SAVELINK(oldnext, (elm)->field.le_next); \ - QMD_SAVELINK(oldprev, (elm)->field.le_prev); \ - QMD_LIST_CHECK_NEXT(elm, field); \ - QMD_LIST_CHECK_PREV(elm, field); \ - if (LIST_NEXT((elm), field) != NULL) \ - LIST_NEXT((elm), field)->field.le_prev = \ - (elm)->field.le_prev; \ - *(elm)->field.le_prev = LIST_NEXT((elm), field); \ - TRASHIT(*oldnext); \ - TRASHIT(*oldprev); \ - } while (0) - -#define LIST_SWAP(head1, head2, type, field) \ - do { \ - struct type *swap_tmp = LIST_FIRST((head1)); \ - LIST_FIRST((head1)) = LIST_FIRST((head2)); \ - LIST_FIRST((head2)) = swap_tmp; \ - if ((swap_tmp = LIST_FIRST((head1))) != NULL) \ - swap_tmp->field.le_prev = &LIST_FIRST((head1)); \ - if ((swap_tmp = LIST_FIRST((head2))) != NULL) \ - swap_tmp->field.le_prev = &LIST_FIRST((head2)); \ - } while (0) - -/* - * Tail queue declarations. - */ -#define TAILQ_HEAD(name, type) \ - struct name { \ - struct type *tqh_first; /* first element */ \ - struct type **tqh_last; /* addr of last next element */ \ - TRACEBUF \ - } - -#define TAILQ_HEAD_INITIALIZER(head) \ - { \ - NULL, &(head).tqh_first \ - } - -#define TAILQ_ENTRY(type) \ - struct { \ - struct type *tqe_next; /* next element */ \ - struct type **tqe_prev; /* address of previous next element */ \ - TRACEBUF \ - } - -/* - * Tail queue functions. - */ -#if (defined(_KERNEL) && defined(INVARIANTS)) -#define QMD_TAILQ_CHECK_HEAD(head, field) \ - do { \ - if (!TAILQ_EMPTY(head) \ - && TAILQ_FIRST((head))->field.tqe_prev \ - != &TAILQ_FIRST((head))) \ - panic("Bad tailq head %p first->prev != head", \ - (head)); \ - } while (0) - -#define QMD_TAILQ_CHECK_TAIL(head, field) \ - do { \ - if (*(head)->tqh_last != NULL) \ - panic("Bad tailq NEXT(%p->tqh_last) != NULL", (head)); \ - } while (0) - -#define QMD_TAILQ_CHECK_NEXT(elm, field) \ - do { \ - if (TAILQ_NEXT((elm), field) != NULL \ - && TAILQ_NEXT((elm), field)->field.tqe_prev \ - != &((elm)->field.tqe_next)) \ - panic("Bad link elm %p next->prev != elm", (elm)); \ - } while (0) - -#define QMD_TAILQ_CHECK_PREV(elm, field) \ - do { \ - if (*(elm)->field.tqe_prev != (elm)) \ - panic("Bad link elm %p prev->next != elm", (elm)); \ - } while (0) -#else -#define QMD_TAILQ_CHECK_HEAD(head, field) -#define QMD_TAILQ_CHECK_TAIL(head, headname) -#define QMD_TAILQ_CHECK_NEXT(elm, field) -#define QMD_TAILQ_CHECK_PREV(elm, field) -#endif /* (_KERNEL && INVARIANTS) */ - -#define TAILQ_CONCAT(head1, head2, field) \ - do { \ - if (!TAILQ_EMPTY(head2)) { \ - *(head1)->tqh_last = (head2)->tqh_first; \ - (head2)->tqh_first->field.tqe_prev = \ - (head1)->tqh_last; \ - (head1)->tqh_last = (head2)->tqh_last; \ - TAILQ_INIT((head2)); \ - QMD_TRACE_HEAD(head1); \ - QMD_TRACE_HEAD(head2); \ - } \ - } while (0) - -#define TAILQ_EMPTY(head) ((head)->tqh_first == NULL) - -#define TAILQ_FIRST(head) ((head)->tqh_first) - -#define TAILQ_FOREACH(var, head, field) \ - for ((var) = TAILQ_FIRST((head)); (var); \ - (var) = TAILQ_NEXT((var), field)) - -#define TAILQ_FOREACH_SAFE(var, head, field, tvar) \ - for ((var) = TAILQ_FIRST((head)); \ - (var) && ((tvar) = TAILQ_NEXT((var), field), 1); (var) = (tvar)) - -#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \ - for ((var) = TAILQ_LAST((head), headname); (var); \ - (var) = TAILQ_PREV((var), headname, field)) - -#define TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar) \ - for ((var) = TAILQ_LAST((head), headname); \ - (var) && ((tvar) = TAILQ_PREV((var), headname, field), 1); \ - (var) = (tvar)) - -#define TAILQ_INIT(head) \ - do { \ - TAILQ_FIRST((head)) = NULL; \ - (head)->tqh_last = &TAILQ_FIRST((head)); \ - QMD_TRACE_HEAD(head); \ - } while (0) - -#define TAILQ_INSERT_AFTER(head, listelm, elm, field) \ - do { \ - QMD_TAILQ_CHECK_NEXT(listelm, field); \ - if ((TAILQ_NEXT((elm), field) = TAILQ_NEXT((listelm), field)) \ - != NULL) \ - TAILQ_NEXT((elm), field)->field.tqe_prev = \ - &TAILQ_NEXT((elm), field); \ - else { \ - (head)->tqh_last = &TAILQ_NEXT((elm), field); \ - QMD_TRACE_HEAD(head); \ - } \ - TAILQ_NEXT((listelm), field) = (elm); \ - (elm)->field.tqe_prev = &TAILQ_NEXT((listelm), field); \ - QMD_TRACE_ELEM(&(elm)->field); \ - QMD_TRACE_ELEM(&listelm->field); \ - } while (0) - -#define TAILQ_INSERT_BEFORE(listelm, elm, field) \ - do { \ - QMD_TAILQ_CHECK_PREV(listelm, field); \ - (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \ - TAILQ_NEXT((elm), field) = (listelm); \ - *(listelm)->field.tqe_prev = (elm); \ - (listelm)->field.tqe_prev = &TAILQ_NEXT((elm), field); \ - QMD_TRACE_ELEM(&(elm)->field); \ - QMD_TRACE_ELEM(&listelm->field); \ - } while (0) - -#define TAILQ_INSERT_HEAD(head, elm, field) \ - do { \ - QMD_TAILQ_CHECK_HEAD(head, field); \ - if ((TAILQ_NEXT((elm), field) = TAILQ_FIRST((head))) != NULL) \ - TAILQ_FIRST((head))->field.tqe_prev = \ - &TAILQ_NEXT((elm), field); \ - else \ - (head)->tqh_last = &TAILQ_NEXT((elm), field); \ - TAILQ_FIRST((head)) = (elm); \ - (elm)->field.tqe_prev = &TAILQ_FIRST((head)); \ - QMD_TRACE_HEAD(head); \ - QMD_TRACE_ELEM(&(elm)->field); \ - } while (0) - -#define TAILQ_INSERT_TAIL(head, elm, field) \ - do { \ - QMD_TAILQ_CHECK_TAIL(head, field); \ - TAILQ_NEXT((elm), field) = NULL; \ - (elm)->field.tqe_prev = (head)->tqh_last; \ - *(head)->tqh_last = (elm); \ - (head)->tqh_last = &TAILQ_NEXT((elm), field); \ - QMD_TRACE_HEAD(head); \ - QMD_TRACE_ELEM(&(elm)->field); \ - } while (0) - -#define TAILQ_LAST(head, headname) \ - (*(((struct headname *)((head)->tqh_last))->tqh_last)) - -#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next) - -#define TAILQ_PREV(elm, headname, field) \ - (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last)) - -#define TAILQ_REMOVE(head, elm, field) \ - do { \ - QMD_SAVELINK(oldnext, (elm)->field.tqe_next); \ - QMD_SAVELINK(oldprev, (elm)->field.tqe_prev); \ - QMD_TAILQ_CHECK_NEXT(elm, field); \ - QMD_TAILQ_CHECK_PREV(elm, field); \ - if ((TAILQ_NEXT((elm), field)) != NULL) \ - TAILQ_NEXT((elm), field)->field.tqe_prev = \ - (elm)->field.tqe_prev; \ - else { \ - (head)->tqh_last = (elm)->field.tqe_prev; \ - QMD_TRACE_HEAD(head); \ - } \ - *(elm)->field.tqe_prev = TAILQ_NEXT((elm), field); \ - TRASHIT(*oldnext); \ - TRASHIT(*oldprev); \ - QMD_TRACE_ELEM(&(elm)->field); \ - } while (0) - -#define TAILQ_SWAP(head1, head2, type, field) \ - do { \ - struct type *swap_first = (head1)->tqh_first; \ - struct type **swap_last = (head1)->tqh_last; \ - (head1)->tqh_first = (head2)->tqh_first; \ - (head1)->tqh_last = (head2)->tqh_last; \ - (head2)->tqh_first = swap_first; \ - (head2)->tqh_last = swap_last; \ - if ((swap_first = (head1)->tqh_first) != NULL) \ - swap_first->field.tqe_prev = &(head1)->tqh_first; \ - else \ - (head1)->tqh_last = &(head1)->tqh_first; \ - if ((swap_first = (head2)->tqh_first) != NULL) \ - swap_first->field.tqe_prev = &(head2)->tqh_first; \ - else \ - (head2)->tqh_last = &(head2)->tqh_first; \ - } while (0) - -#endif /* !_SYS_QUEUE_H_ */ +#endif /* _FRR_QUEUE_H */ diff --git a/lib/subdir.am b/lib/subdir.am index 6a62cbb678..8545184228 100644 --- a/lib/subdir.am +++ b/lib/subdir.am @@ -90,6 +90,7 @@ pkginclude_HEADERS += \ lib/event_counter.h \ lib/fifo.h \ lib/filter.h \ + lib/freebsd-queue.h \ lib/frr_pthread.h \ lib/frratomic.h \ lib/getopt.h \ @@ -125,6 +126,7 @@ pkginclude_HEADERS += \ lib/ptm_lib.h \ lib/pw.h \ lib/qobj.h \ + lib/queue.h \ lib/routemap.h \ lib/sbuf.h \ lib/sha256.h \ @@ -222,7 +224,6 @@ EXTRA_DIST += \ lib/command_lex.h \ lib/command_parse.h \ lib/gitversion.pl \ - lib/queue.h \ lib/route_types.pl \ lib/route_types.txt \ # end From f104f6c1a62c92a4420e1d99abb336d566c1ff51 Mon Sep 17 00:00:00 2001 From: Jorge Boncompte Date: Tue, 8 Aug 2017 20:32:30 +0200 Subject: [PATCH 018/130] lib: cleanup the work queue implementation Convert the work queue implementation to not use the generic linked list to mantain the item list and use instead a simple queue from queue.h that does not allocate memory for each node. Signed-off-by: Jorge Boncompte --- lib/freebsd-queue.h | 2 +- lib/workqueue.c | 54 +++++++++++++++++++-------------------------- lib/workqueue.h | 36 +++++++++++++++++++++++++++++- zebra/zebra_rib.c | 2 +- 4 files changed, 60 insertions(+), 34 deletions(-) diff --git a/lib/freebsd-queue.h b/lib/freebsd-queue.h index 658b602ba3..d198f5674f 100644 --- a/lib/freebsd-queue.h +++ b/lib/freebsd-queue.h @@ -302,7 +302,7 @@ struct qm_trace { (STAILQ_EMPTY((head)) \ ? NULL \ : ((struct type *)(void *)((char *)((head)->stqh_last) \ - - __offsetof(struct type, \ + - offsetof(struct type, \ field)))) #define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next) diff --git a/lib/workqueue.c b/lib/workqueue.c index 612421c80b..b76b73b367 100644 --- a/lib/workqueue.c +++ b/lib/workqueue.c @@ -72,14 +72,7 @@ struct work_queue *work_queue_new(struct thread_master *m, new->master = m; SET_FLAG(new->flags, WQ_UNPLUGGED); - if ((new->items = list_new()) == NULL) { - XFREE(MTYPE_WORK_QUEUE_NAME, new->name); - XFREE(MTYPE_WORK_QUEUE, new); - - return NULL; - } - - new->items->del = (void (*)(void *))work_queue_item_free; + STAILQ_INIT(&new->items); listnode_add(work_queues, new); @@ -97,8 +90,6 @@ void work_queue_free(struct work_queue *wq) if (wq->thread != NULL) thread_cancel(wq->thread); - /* list_delete frees items via callback */ - list_delete(wq->items); listnode_delete(work_queues, wq); XFREE(MTYPE_WORK_QUEUE_NAME, wq->name); @@ -114,8 +105,8 @@ bool work_queue_is_scheduled(struct work_queue *wq) static int work_queue_schedule(struct work_queue *wq, unsigned int delay) { /* if appropriate, schedule work queue thread */ - if (CHECK_FLAG(wq->flags, WQ_UNPLUGGED) && (wq->thread == NULL) - && (listcount(wq->items) > 0)) { + if (CHECK_FLAG(wq->flags, WQ_UNPLUGGED) && (wq->thread == NULL) && + !work_queue_empty(wq)) { wq->thread = NULL; thread_add_timer_msec(wq->master, work_queue_run, wq, delay, &wq->thread); @@ -139,33 +130,35 @@ void work_queue_add(struct work_queue *wq, void *data) } item->data = data; - listnode_add(wq->items, item); + work_queue_item_enqueue(wq, item); work_queue_schedule(wq, wq->spec.hold); return; } -static void work_queue_item_remove(struct work_queue *wq, struct listnode *ln) +static void work_queue_item_remove(struct work_queue *wq, + struct work_queue_item *item) { - struct work_queue_item *item = listgetdata(ln); - assert(item && item->data); /* call private data deletion callback if needed */ if (wq->spec.del_item_data) wq->spec.del_item_data(wq, item->data); - list_delete_node(wq->items, ln); + work_queue_item_dequeue(wq, item); + work_queue_item_free(item); return; } -static void work_queue_item_requeue(struct work_queue *wq, struct listnode *ln) +static void work_queue_item_requeue(struct work_queue *wq, struct work_queue_item *item) { - LISTNODE_DETACH(wq->items, ln); - LISTNODE_ATTACH(wq->items, ln); /* attach to end of list */ + work_queue_item_dequeue(wq, item); + + /* attach to end of list */ + work_queue_item_enqueue(wq, item); } DEFUN (show_work_queues, @@ -186,7 +179,7 @@ DEFUN (show_work_queues, for (ALL_LIST_ELEMENTS_RO(work_queues, node, wq)) { vty_out(vty, "%c %8d %5d %8ld %8ld %7d %6d %8ld %6u %s\n", (CHECK_FLAG(wq->flags, WQ_UNPLUGGED) ? ' ' : 'P'), - listcount(wq->items), wq->spec.hold, wq->runs, + work_queue_item_count(wq), wq->spec.hold, wq->runs, wq->yields, wq->cycles.best, wq->cycles.granularity, wq->cycles.total, (wq->runs) ? (unsigned int)(wq->cycles.total / wq->runs) @@ -233,16 +226,15 @@ void work_queue_unplug(struct work_queue *wq) int work_queue_run(struct thread *thread) { struct work_queue *wq; - struct work_queue_item *item; + struct work_queue_item *item, *titem; wq_item_status ret; unsigned int cycles = 0; - struct listnode *node, *nnode; char yielded = 0; wq = THREAD_ARG(thread); wq->thread = NULL; - assert(wq && wq->items); + assert(wq); /* calculate cycle granularity: * list iteration == 1 run @@ -266,7 +258,7 @@ int work_queue_run(struct thread *thread) if (wq->cycles.granularity == 0) wq->cycles.granularity = WORK_QUEUE_MIN_GRANULARITY; - for (ALL_LIST_ELEMENTS(wq->items, node, nnode, item)) { + STAILQ_FOREACH_SAFE(item, &wq->items, wq, titem) { assert(item && item->data); /* dont run items which are past their allowed retries */ @@ -274,7 +266,7 @@ int work_queue_run(struct thread *thread) /* run error handler, if any */ if (wq->spec.errorfunc) wq->spec.errorfunc(wq, item->data); - work_queue_item_remove(wq, node); + work_queue_item_remove(wq, item); continue; } @@ -298,7 +290,7 @@ int work_queue_run(struct thread *thread) } case WQ_REQUEUE: { item->ran--; - work_queue_item_requeue(wq, node); + work_queue_item_requeue(wq, item); /* If a single node is being used with a meta-queue * (e.g., zebra), * update the next node as we don't want to exit the @@ -309,8 +301,8 @@ int work_queue_run(struct thread *thread) * will kick in * to terminate the thread when time has exceeded. */ - if (nnode == NULL) - nnode = node; + if (titem == NULL) + titem = item; break; } case WQ_RETRY_NOW: @@ -323,7 +315,7 @@ int work_queue_run(struct thread *thread) /* fallthru */ case WQ_SUCCESS: default: { - work_queue_item_remove(wq, node); + work_queue_item_remove(wq, item); break; } } @@ -376,7 +368,7 @@ stats: #endif /* Is the queue done yet? If it is, call the completion callback. */ - if (listcount(wq->items) > 0) + if (!work_queue_empty(wq)) work_queue_schedule(wq, 0); else if (wq->spec.completion_func) wq->spec.completion_func(wq); diff --git a/lib/workqueue.h b/lib/workqueue.h index ff7f57690d..df35d44fbc 100644 --- a/lib/workqueue.h +++ b/lib/workqueue.h @@ -24,6 +24,7 @@ #define _QUAGGA_WORK_QUEUE_H #include "memory.h" +#include "queue.h" DECLARE_MTYPE(WORK_QUEUE) /* Hold time for the initial schedule of a queue run, in millisec */ @@ -43,6 +44,7 @@ typedef enum { /* A single work queue item, unsurprisingly */ struct work_queue_item { + STAILQ_ENTRY(work_queue_item) wq; void *data; /* opaque data */ unsigned short ran; /* # of times item has been run */ }; @@ -91,7 +93,8 @@ struct work_queue { } spec; /* remaining fields should be opaque to users */ - struct list *items; /* queue item list */ + STAILQ_HEAD(work_queue_items, work_queue_item) items; /* queue item list */ + int item_count; /* queued items */ unsigned long runs; /* runs count */ unsigned long yields; /* yields count */ @@ -107,6 +110,37 @@ struct work_queue { /* User API */ +static inline int work_queue_item_count(struct work_queue *wq) +{ + return wq->item_count; +} + +static inline bool work_queue_empty(struct work_queue *wq) +{ + return (wq->item_count == 0) ? true : false; +} + +static inline struct work_queue_item *work_queue_last_item(struct work_queue *wq) +{ + return STAILQ_LAST(&wq->items, work_queue_item, wq); +} + +static inline void work_queue_item_enqueue(struct work_queue *wq, + struct work_queue_item *item) +{ + STAILQ_INSERT_TAIL(&wq->items, item, wq); + wq->item_count++; +} + +static inline void work_queue_item_dequeue(struct work_queue *wq, + struct work_queue_item *item) +{ + assert(wq->item_count > 0); + + wq->item_count--; + STAILQ_REMOVE(&wq->items, item, work_queue_item, wq); +} + /* create a new work queue, of given name. * user must fill in the spec of the returned work queue before adding * anything to it diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index ed53554265..b27201616d 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -1820,7 +1820,7 @@ void rib_queue_add(struct route_node *rn) * holder, if necessary, then push the work into it in any case. * This semantics was introduced after 0.99.9 release. */ - if (!zebrad.ribq->items->count) + if (work_queue_empty(zebrad.ribq)) work_queue_add(zebrad.ribq, zebrad.mq); rib_meta_queue_add(zebrad.mq, rn); From 92375c917edb63c32d5441f6a264e73af5b2a2a0 Mon Sep 17 00:00:00 2001 From: Jorge Boncompte Date: Mon, 7 Aug 2017 13:40:10 +0200 Subject: [PATCH 019/130] bgpd: inline bgp_lock()/bgp_unlock() Signed-off-by: Jorge Boncompte --- bgpd/bgp_route.c | 3 +-- bgpd/bgpd.c | 19 ++----------------- bgpd/bgpd.h | 23 ++++++++++++++++------- 3 files changed, 19 insertions(+), 26 deletions(-) diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 35f793f861..741fa5ceeb 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -2248,8 +2248,7 @@ void bgp_process(struct bgp *bgp, struct bgp_node *rn, afi_t afi, safi_t safi) /* all unlocked in bgp_processq_del */ bgp_table_lock(bgp_node_table(rn)); pqnode->rn = bgp_lock_node(rn); - pqnode->bgp = bgp; - bgp_lock(bgp); + pqnode->bgp = bgp_lock(bgp); pqnode->afi = afi; pqnode->safi = safi; work_queue_add(bm->process_main_queue, pqnode); diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index d7733fbacd..9d7c38c871 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -1116,9 +1116,8 @@ struct peer *peer_new(struct bgp *bgp) peer->status = Idle; peer->ostatus = Idle; peer->cur_event = peer->last_event = peer->last_major_event = 0; - peer->bgp = bgp; + peer->bgp = bgp_lock(bgp); peer = peer_lock(peer); /* initial reference */ - bgp_lock(bgp); peer->password = NULL; /* Set default flags. */ @@ -3106,21 +3105,7 @@ int bgp_delete(struct bgp *bgp) return 0; } -static void bgp_free(struct bgp *); - -void bgp_lock(struct bgp *bgp) -{ - ++bgp->lock; -} - -void bgp_unlock(struct bgp *bgp) -{ - assert(bgp->lock > 0); - if (--bgp->lock == 0) - bgp_free(bgp); -} - -static void bgp_free(struct bgp *bgp) +void bgp_free(struct bgp *bgp) { afi_t afi; safi_t safi; diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h index bfdddc69b1..f6e7b2277f 100644 --- a/bgpd/bgpd.h +++ b/bgpd/bgpd.h @@ -1252,9 +1252,6 @@ extern int bgp_flag_set(struct bgp *, int); extern int bgp_flag_unset(struct bgp *, int); extern int bgp_flag_check(struct bgp *, int); -extern void bgp_lock(struct bgp *); -extern void bgp_unlock(struct bgp *); - extern void bgp_router_id_zebra_bump(vrf_id_t, const struct prefix *); extern int bgp_router_id_static_set(struct bgp *, struct in_addr); @@ -1395,6 +1392,20 @@ extern struct peer_af *peer_af_find(struct peer *, afi_t, safi_t); extern int peer_af_delete(struct peer *, afi_t, safi_t); extern void bgp_close(void); +extern void bgp_free(struct bgp *); + +static inline struct bgp *bgp_lock(struct bgp *bgp) +{ + bgp->lock++; + return bgp; +} + +static inline void bgp_unlock(struct bgp *bgp) +{ + assert(bgp->lock > 0); + if (--bgp->lock == 0) + bgp_free(bgp); +} static inline int afindex(afi_t afi, safi_t safi) { @@ -1540,10 +1551,8 @@ static inline struct vrf *bgp_vrf_lookup_by_instance_type(struct bgp *bgp) static inline void bgp_vrf_link(struct bgp *bgp, struct vrf *vrf) { bgp->vrf_id = vrf->vrf_id; - if (vrf->info != (void *)bgp) { - bgp_lock(bgp); - vrf->info = (void *)bgp; - } + if (vrf->info != (void *)bgp) + vrf->info = (void *)bgp_lock(bgp); } /* Unlink BGP instance from VRF. */ From aac2483887eddfe782a31f03b5a30643793935f5 Mon Sep 17 00:00:00 2001 From: Jorge Boncompte Date: Sat, 5 Aug 2017 12:59:05 +0200 Subject: [PATCH 020/130] bgpd: bgp process queue optimization There are several code paths that dump nodes to the queue for route processing in a loop. This patch tries to reduce memory allocations/freeing (work item, list node) and thread scheduling overhead by batching the nodes in a simple queue list. In the past when route processing wasn't event driven (bgp_scan()), this used to have a noticeable impact in table loading, convergence time and memory heap fragmentation due to reduced alloc's/free's. Signed-off-by: Jorge Boncompte --- bgpd/bgp_route.c | 118 +++++++++++++++++++++++++++++++---------------- bgpd/bgp_table.h | 3 ++ 2 files changed, 81 insertions(+), 40 deletions(-) diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 741fa5ceeb..bb204b01f1 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -2001,18 +2001,15 @@ int bgp_zebra_has_route_changed(struct bgp_node *rn, struct bgp_info *selected) struct bgp_process_queue { struct bgp *bgp; - struct bgp_node *rn; - afi_t afi; - safi_t safi; + STAILQ_HEAD(, bgp_node)pqueue; +#define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0) + unsigned int flags; + unsigned int queued; }; -static wq_item_status bgp_process_main(struct work_queue *wq, void *data) +static void bgp_process_main_one(struct bgp *bgp, struct bgp_node *rn, + afi_t afi, safi_t safi) { - struct bgp_process_queue *pq = data; - struct bgp *bgp = pq->bgp; - struct bgp_node *rn = pq->rn; - afi_t afi = pq->afi; - safi_t safi = pq->safi; struct prefix *p = &rn->p; struct bgp_info *new_select; struct bgp_info *old_select; @@ -2033,7 +2030,7 @@ static wq_item_status bgp_process_main(struct work_queue *wq, void *data) bgp->main_peers_update_hold = 0; bgp_start_routeadv(bgp); - return WQ_SUCCESS; + return; } /* Best path selection. */ @@ -2114,7 +2111,7 @@ static wq_item_status bgp_process_main(struct work_queue *wq, void *data) } UNSET_FLAG(rn->flags, BGP_NODE_PROCESS_SCHEDULED); - return WQ_SUCCESS; + return; } /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set @@ -2192,21 +2189,42 @@ static wq_item_status bgp_process_main(struct work_queue *wq, void *data) bgp_info_reap(rn, old_select); UNSET_FLAG(rn->flags, BGP_NODE_PROCESS_SCHEDULED); + return; +} + +static wq_item_status bgp_process_wq(struct work_queue *wq, void *data) +{ + struct bgp_process_queue *pqnode = data; + struct bgp *bgp = pqnode->bgp; + struct bgp_table *table; + struct bgp_node *rn, *nrn; + + /* eoiu marker */ + if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)) { + bgp_process_main_one(bgp, NULL, 0, 0); + + return WQ_SUCCESS; + } + + STAILQ_FOREACH_SAFE(rn, &pqnode->pqueue, pq, nrn) { + table = bgp_node_table(rn); + + bgp_process_main_one(bgp, rn, table->afi, table->safi); + + bgp_unlock_node(rn); + bgp_table_unlock(table); + } + return WQ_SUCCESS; } static void bgp_processq_del(struct work_queue *wq, void *data) { - struct bgp_process_queue *pq = data; - struct bgp_table *table; + struct bgp_process_queue *pqnode = data; - bgp_unlock(pq->bgp); - if (pq->rn) { - table = bgp_node_table(pq->rn); - bgp_unlock_node(pq->rn); - bgp_table_unlock(table); - } - XFREE(MTYPE_BGP_PROCESS_QUEUE, pq); + bgp_unlock(pqnode->bgp); + + XFREE(MTYPE_BGP_PROCESS_QUEUE, pqnode); } void bgp_process_queue_init(void) @@ -2221,7 +2239,7 @@ void bgp_process_queue_init(void) } } - bm->process_main_queue->spec.workfunc = &bgp_process_main; + bm->process_main_queue->spec.workfunc = &bgp_process_wq; bm->process_main_queue->spec.del_item_data = &bgp_processq_del; bm->process_main_queue->spec.max_retries = 0; bm->process_main_queue->spec.hold = 50; @@ -2229,30 +2247,56 @@ void bgp_process_queue_init(void) bm->process_main_queue->spec.yield = 50 * 1000L; } +static struct bgp_process_queue *bgp_process_queue_work(struct work_queue *wq, + struct bgp *bgp) +{ + struct bgp_process_queue *pqnode; + + pqnode = XCALLOC(MTYPE_BGP_PROCESS_QUEUE, sizeof(struct bgp_process_queue)); + + /* unlocked in bgp_processq_del */ + pqnode->bgp = bgp_lock(bgp); + STAILQ_INIT(&pqnode->pqueue); + + work_queue_add(wq, pqnode); + + return pqnode; +} + void bgp_process(struct bgp *bgp, struct bgp_node *rn, afi_t afi, safi_t safi) { +#define ARBITRARY_PROCESS_QLEN 10000 + struct work_queue *wq = bm->process_main_queue; struct bgp_process_queue *pqnode; /* already scheduled for processing? */ if (CHECK_FLAG(rn->flags, BGP_NODE_PROCESS_SCHEDULED)) return; - if (bm->process_main_queue == NULL) + if (wq == NULL) return; - pqnode = XCALLOC(MTYPE_BGP_PROCESS_QUEUE, - sizeof(struct bgp_process_queue)); - if (!pqnode) - return; + /* Add route nodes to an existing work queue item until reaching the + limit only if is from the same BGP view and it's not an EOIU marker */ + if (work_queue_item_count(wq)) { + struct work_queue_item *item = work_queue_last_item(wq); + pqnode = item->data; - /* all unlocked in bgp_processq_del */ + if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER) || + pqnode->bgp != bgp || pqnode->queued >= ARBITRARY_PROCESS_QLEN) + pqnode = bgp_process_queue_work(wq, bgp); + } else + pqnode = bgp_process_queue_work(wq, bgp); + + /* all unlocked in bgp_process_wq */ bgp_table_lock(bgp_node_table(rn)); - pqnode->rn = bgp_lock_node(rn); - pqnode->bgp = bgp_lock(bgp); - pqnode->afi = afi; - pqnode->safi = safi; - work_queue_add(bm->process_main_queue, pqnode); + SET_FLAG(rn->flags, BGP_NODE_PROCESS_SCHEDULED); + bgp_lock_node(rn); + + STAILQ_INSERT_TAIL(&pqnode->pqueue, rn, pq); + pqnode->queued++; + return; } @@ -2263,15 +2307,9 @@ void bgp_add_eoiu_mark(struct bgp *bgp) if (bm->process_main_queue == NULL) return; - pqnode = XCALLOC(MTYPE_BGP_PROCESS_QUEUE, - sizeof(struct bgp_process_queue)); - if (!pqnode) - return; + pqnode = bgp_process_queue_work(bm->process_main_queue, bgp); - pqnode->rn = NULL; - pqnode->bgp = bgp; - bgp_lock(bgp); - work_queue_add(bm->process_main_queue, pqnode); + SET_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER); } static int bgp_maximum_prefix_restart_timer(struct thread *thread) diff --git a/bgpd/bgp_table.h b/bgpd/bgp_table.h index 0d5706f7cb..a4f3b604c2 100644 --- a/bgpd/bgp_table.h +++ b/bgpd/bgp_table.h @@ -23,6 +23,7 @@ #include "mpls.h" #include "table.h" +#include "queue.h" struct bgp_table { /* afi/safi of this table */ @@ -52,6 +53,8 @@ struct bgp_node { struct bgp_node *prn; + STAILQ_ENTRY(bgp_node) pq; + mpls_label_t local_label; uint64_t version; From 19aad877b70501d759b9326e9736aa23ca16d578 Mon Sep 17 00:00:00 2001 From: Jorge Boncompte Date: Wed, 9 Aug 2017 13:57:49 +0200 Subject: [PATCH 021/130] lib: optimize IPV4_ADDR_[SAME|COPY]() Change all callers of IPV4_ADDR_SAME() to pass a pointer to a struct in_addr Use assignment and comparison instead of memcpy() and memcmp(). Avoids function calls. Faster. Signed-off-by: Jorge Boncompte --- bgpd/rfapi/rfapi_import.c | 4 ++-- eigrpd/eigrp_packet.c | 2 +- lib/prefix.c | 3 +-- lib/prefix.h | 16 ++++++++++++++-- ospfd/ospf_packet.c | 2 +- zebra/zebra_rib.c | 2 +- zebra/zebra_static.c | 4 ++-- 7 files changed, 22 insertions(+), 11 deletions(-) diff --git a/bgpd/rfapi/rfapi_import.c b/bgpd/rfapi/rfapi_import.c index 7e0ed9150b..d63975a22b 100644 --- a/bgpd/rfapi/rfapi_import.c +++ b/bgpd/rfapi/rfapi_import.c @@ -1224,8 +1224,8 @@ static int rfapiVpnBiSamePtUn(struct bgp_info *bi1, struct bgp_info *bi2) switch (pfx_un1.family) { case AF_INET: - if (!IPV4_ADDR_SAME(&pfx_un1.u.prefix4.s_addr, - &pfx_un2.u.prefix4.s_addr)) + if (!IPV4_ADDR_SAME(&pfx_un1.u.prefix4, + &pfx_un2.u.prefix4)) return 0; break; case AF_INET6: diff --git a/eigrpd/eigrp_packet.c b/eigrpd/eigrp_packet.c index dfc7463025..45c2dd8edc 100644 --- a/eigrpd/eigrp_packet.c +++ b/eigrpd/eigrp_packet.c @@ -530,7 +530,7 @@ int eigrp_read(struct thread *thread) /* Self-originated packet should be discarded silently. */ if (eigrp_if_lookup_by_local_addr(eigrp, NULL, iph->ip_src) - || (IPV4_ADDR_SAME(&iph->ip_src.s_addr, &ei->address->u.prefix4))) { + || (IPV4_ADDR_SAME(&iph->ip_src, &ei->address->u.prefix4))) { if (IS_DEBUG_EIGRP_TRANSMIT(0, RECV)) zlog_debug( "eigrp_read[%s]: Dropping self-originated packet", diff --git a/lib/prefix.c b/lib/prefix.c index de521b2e3e..2f61eb6e8b 100644 --- a/lib/prefix.c +++ b/lib/prefix.c @@ -497,8 +497,7 @@ int prefix_same(const struct prefix *p1, const struct prefix *p2) if (p1->family == p2->family && p1->prefixlen == p2->prefixlen) { if (p1->family == AF_INET) - if (IPV4_ADDR_SAME(&p1->u.prefix4.s_addr, - &p2->u.prefix4.s_addr)) + if (IPV4_ADDR_SAME(&p1->u.prefix4, &p2->u.prefix4)) return 1; if (p1->family == AF_INET6) if (IPV6_ADDR_SAME(&p1->u.prefix6.s6_addr, diff --git a/lib/prefix.h b/lib/prefix.h index f0644ea88e..bc4abb492a 100644 --- a/lib/prefix.h +++ b/lib/prefix.h @@ -241,8 +241,20 @@ union prefixconstptr { #define IPV4_MAX_BITLEN 32 #define IPV4_MAX_PREFIXLEN 32 #define IPV4_ADDR_CMP(D,S) memcmp ((D), (S), IPV4_MAX_BYTELEN) -#define IPV4_ADDR_SAME(D,S) (memcmp ((D), (S), IPV4_MAX_BYTELEN) == 0) -#define IPV4_ADDR_COPY(D,S) memcpy ((D), (S), IPV4_MAX_BYTELEN) + +static inline bool ipv4_addr_same(const struct in_addr *a, + const struct in_addr *b) +{ + return (a->s_addr == b->s_addr); +} +#define IPV4_ADDR_SAME(A,B) ipv4_addr_same((A), (B)) + +static inline void ipv4_addr_copy(struct in_addr *dst, + const struct in_addr *src) +{ + dst->s_addr = src->s_addr; +} +#define IPV4_ADDR_COPY(D,S) ipv4_addr_copy((D), (S)) #define IPV4_NET0(a) ((((u_int32_t) (a)) & 0xff000000) == 0x00000000) #define IPV4_NET127(a) ((((u_int32_t) (a)) & 0xff000000) == 0x7f000000) diff --git a/ospfd/ospf_packet.c b/ospfd/ospf_packet.c index ac2406ec2d..36f9a6757a 100644 --- a/ospfd/ospf_packet.c +++ b/ospfd/ospf_packet.c @@ -3938,7 +3938,7 @@ void ospf_ls_upd_send(struct ospf_neighbor *nbr, struct list *update, int flag) if (flag == OSPF_SEND_PACKET_INDIRECT) zlog_warn( "* LS-Update is directly sent on NBMA network."); - if (IPV4_ADDR_SAME(&oi->address->u.prefix4, &p.prefix.s_addr)) + if (IPV4_ADDR_SAME(&oi->address->u.prefix4, &p.prefix)) zlog_warn("* LS-Update is sent to myself."); } diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index b27201616d..dc61ea5e40 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -2352,7 +2352,7 @@ void rib_delete(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, break; } for (ALL_NEXTHOPS(re->nexthop, nexthop)) - if (IPV4_ADDR_SAME(&nexthop->gate.ipv4, gate) + if (IPV4_ADDR_SAME(&nexthop->gate.ipv4, &gate->ipv4) || IPV6_ADDR_SAME(&nexthop->gate.ipv6, gate)) { same = re; diff --git a/zebra/zebra_static.c b/zebra/zebra_static.c index dba228ea35..6815916faf 100644 --- a/zebra/zebra_static.c +++ b/zebra/zebra_static.c @@ -398,7 +398,7 @@ int static_add_route(afi_t afi, safi_t safi, u_char type, struct prefix *p, for (si = rn->info; si; si = si->next) { if (type == si->type && (!gate || ((afi == AFI_IP - && IPV4_ADDR_SAME(gate, &si->addr.ipv4)) + && IPV4_ADDR_SAME(&gate->ipv4, &si->addr.ipv4)) || (afi == AFI_IP6 && IPV6_ADDR_SAME(gate, &si->addr.ipv6)))) && (!strcmp (ifname ? ifname : "", si->ifname))) { @@ -515,7 +515,7 @@ int static_delete_route(afi_t afi, safi_t safi, u_char type, struct prefix *p, for (si = rn->info; si; si = si->next) if (type == si->type && (!gate || ((afi == AFI_IP - && IPV4_ADDR_SAME(gate, &si->addr.ipv4)) + && IPV4_ADDR_SAME(&gate->ipv4, &si->addr.ipv4)) || (afi == AFI_IP6 && IPV6_ADDR_SAME(gate, &si->addr.ipv6)))) && (!strcmp(ifname ? ifname : "", si->ifname)) From a5d4c69d6a6a6c2bd23e4f1af97a7ef024973210 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 17 Aug 2017 13:05:08 -0400 Subject: [PATCH 022/130] pimd: Fix memory leak on failure case When we fail to create upstream we were not properly cleaning up all memory. Signed-off-by: Donald Sharp --- pimd/pim_upstream.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index 751611479e..1fc952fdf8 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -698,6 +698,8 @@ static struct pim_upstream *pim_upstream_new(struct pim_instance *pim, if (up->sources) list_delete(up->sources); + list_delete(up->ifchannels); + hash_release(pim->upstream_hash, up); XFREE(MTYPE_PIM_UPSTREAM, up); return NULL; From f90f65a242e18ad2ae1229853f904227cc36900a Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 17 Aug 2017 19:03:46 -0400 Subject: [PATCH 023/130] eigrpd: Cleanup FIFO The FIFO really was a LIFO for some reason. Push new packets onto the top, always pull from the bottom. This allows eigrp neighbors to come up. Topotests eigrp-topo1( in a topotest PR ) now form neighbors with itself. With this commit. Signed-off-by: Donald Sharp --- eigrpd/eigrp_hello.c | 4 +-- eigrpd/eigrp_packet.c | 57 +++++++++++------------------------------ eigrpd/eigrp_packet.h | 6 ++--- eigrpd/eigrp_query.c | 2 +- eigrpd/eigrp_reply.c | 2 +- eigrpd/eigrp_siaquery.c | 2 +- eigrpd/eigrp_siareply.c | 2 +- eigrpd/eigrp_update.c | 8 +++--- 8 files changed, 27 insertions(+), 56 deletions(-) diff --git a/eigrpd/eigrp_hello.c b/eigrpd/eigrp_hello.c index 4654ead434..67f75c536b 100644 --- a/eigrpd/eigrp_hello.c +++ b/eigrpd/eigrp_hello.c @@ -707,7 +707,7 @@ void eigrp_hello_send_ack(struct eigrp_neighbor *nbr) inet_ntoa(nbr->src)); /* Add packet to the top of the interface output queue*/ - eigrp_fifo_push_head(nbr->ei->obuf, ep); + eigrp_fifo_push(nbr->ei->obuf, ep); /* Hook thread to write packet. */ if (nbr->ei->on_write_q == 0) { @@ -755,7 +755,7 @@ void eigrp_hello_send(struct eigrp_interface *ei, u_char flags, if (ep) { // Add packet to the top of the interface output queue - eigrp_fifo_push_head(ei->obuf, ep); + eigrp_fifo_push(ei->obuf, ep); /* Hook thread to write packet. */ if (ei->on_write_q == 0) { diff --git a/eigrpd/eigrp_packet.c b/eigrpd/eigrp_packet.c index 9f3de10141..cd677f1ae6 100644 --- a/eigrpd/eigrp_packet.c +++ b/eigrpd/eigrp_packet.c @@ -336,7 +336,7 @@ int eigrp_write(struct thread *thread) #endif /* WANT_EIGRP_WRITE_FRAGMENT */ /* Get one packet from queue. */ - ep = eigrp_fifo_head(ei->obuf); + ep = eigrp_fifo_next(ei->obuf); assert(ep); assert(ep->length >= EIGRP_HEADER_LEN); @@ -437,7 +437,7 @@ int eigrp_write(struct thread *thread) /* Now delete packet from queue. */ eigrp_packet_delete(ei); - if (eigrp_fifo_head(ei->obuf) == NULL) { + if (eigrp_fifo_next(ei->obuf) == NULL) { ei->on_write_q = 0; list_delete_node(eigrp->oi_write_q, node); } @@ -636,7 +636,7 @@ int eigrp_read(struct thread *thread) struct eigrp_packet *ep; - ep = eigrp_fifo_tail(nbr->retrans_queue); + ep = eigrp_fifo_next(nbr->retrans_queue); if (ep) { if (ntohl(eigrph->ack) == ep->sequence_number) { if ((nbr->state == EIGRP_NEIGHBOR_PENDING) @@ -651,17 +651,17 @@ int eigrp_read(struct thread *thread) ntohl(eigrph->sequence); eigrp_update_send_EOT(nbr); } - ep = eigrp_fifo_pop_tail(nbr->retrans_queue); + ep = eigrp_fifo_pop(nbr->retrans_queue); eigrp_packet_free(ep); if (nbr->retrans_queue->count > 0) { eigrp_send_packet_reliably(nbr); } } } - ep = eigrp_fifo_tail(nbr->multicast_queue); + ep = eigrp_fifo_next(nbr->multicast_queue); if (ep) { if (ntohl(eigrph->ack) == ep->sequence_number) { - ep = eigrp_fifo_pop_tail(nbr->multicast_queue); + ep = eigrp_fifo_pop(nbr->multicast_queue); eigrp_packet_free(ep); if (nbr->multicast_queue->count > 0) { eigrp_send_packet_reliably(nbr); @@ -843,13 +843,13 @@ void eigrp_send_packet_reliably(struct eigrp_neighbor *nbr) { struct eigrp_packet *ep; - ep = eigrp_fifo_tail(nbr->retrans_queue); + ep = eigrp_fifo_next(nbr->retrans_queue); if (ep) { struct eigrp_packet *duplicate; duplicate = eigrp_packet_duplicate(ep, nbr); /* Add packet to the top of the interface output queue*/ - eigrp_fifo_push_head(nbr->ei->obuf, duplicate); + eigrp_fifo_push(nbr->ei->obuf, duplicate); /*Start retransmission timer*/ thread_add_timer(master, eigrp_unack_packet_retrans, nbr, @@ -911,7 +911,7 @@ void eigrp_packet_header_init(int type, struct eigrp_interface *ei, } /* Add new packet to head of fifo. */ -void eigrp_fifo_push_head(struct eigrp_fifo *fifo, struct eigrp_packet *ep) +void eigrp_fifo_push(struct eigrp_fifo *fifo, struct eigrp_packet *ep) { ep->next = fifo->head; ep->previous = NULL; @@ -927,14 +927,8 @@ void eigrp_fifo_push_head(struct eigrp_fifo *fifo, struct eigrp_packet *ep) fifo->count++; } -/* Return first fifo entry. */ -struct eigrp_packet *eigrp_fifo_head(struct eigrp_fifo *fifo) -{ - return fifo->head; -} - /* Return last fifo entry. */ -struct eigrp_packet *eigrp_fifo_tail(struct eigrp_fifo *fifo) +struct eigrp_packet *eigrp_fifo_next(struct eigrp_fifo *fifo) { return fifo->tail; } @@ -949,27 +943,6 @@ void eigrp_packet_delete(struct eigrp_interface *ei) eigrp_packet_free(ep); } -/* Delete first packet from fifo. */ -struct eigrp_packet *eigrp_fifo_pop(struct eigrp_fifo *fifo) -{ - struct eigrp_packet *ep; - - ep = fifo->head; - - if (ep) { - fifo->head = ep->next; - - if (fifo->head == NULL) - fifo->tail = NULL; - else - fifo->head->previous = NULL; - - fifo->count--; - } - - return ep; -} - void eigrp_packet_free(struct eigrp_packet *ep) { if (ep->s) @@ -1030,14 +1003,14 @@ int eigrp_unack_packet_retrans(struct thread *thread) nbr = (struct eigrp_neighbor *)THREAD_ARG(thread); struct eigrp_packet *ep; - ep = eigrp_fifo_tail(nbr->retrans_queue); + ep = eigrp_fifo_next(nbr->retrans_queue); if (ep) { struct eigrp_packet *duplicate; duplicate = eigrp_packet_duplicate(ep, nbr); /* Add packet to the top of the interface output queue*/ - eigrp_fifo_push_head(nbr->ei->obuf, duplicate); + eigrp_fifo_push(nbr->ei->obuf, duplicate); ep->retrans_counter++; if (ep->retrans_counter == EIGRP_PACKET_RETRANS_MAX) @@ -1067,13 +1040,13 @@ int eigrp_unack_multicast_packet_retrans(struct thread *thread) nbr = (struct eigrp_neighbor *)THREAD_ARG(thread); struct eigrp_packet *ep; - ep = eigrp_fifo_tail(nbr->multicast_queue); + ep = eigrp_fifo_next(nbr->multicast_queue); if (ep) { struct eigrp_packet *duplicate; duplicate = eigrp_packet_duplicate(ep, nbr); /* Add packet to the top of the interface output queue*/ - eigrp_fifo_push_head(nbr->ei->obuf, duplicate); + eigrp_fifo_push(nbr->ei->obuf, duplicate); ep->retrans_counter++; if (ep->retrans_counter == EIGRP_PACKET_RETRANS_MAX) @@ -1098,7 +1071,7 @@ int eigrp_unack_multicast_packet_retrans(struct thread *thread) } /* Get packet from tail of fifo. */ -struct eigrp_packet *eigrp_fifo_pop_tail(struct eigrp_fifo *fifo) +struct eigrp_packet *eigrp_fifo_pop(struct eigrp_fifo *fifo) { struct eigrp_packet *ep; diff --git a/eigrpd/eigrp_packet.h b/eigrpd/eigrp_packet.h index 890fc33c0f..040204a7fc 100644 --- a/eigrpd/eigrp_packet.h +++ b/eigrpd/eigrp_packet.h @@ -48,11 +48,9 @@ extern void eigrp_packet_checksum(struct eigrp_interface *, struct stream *, u_int16_t); extern struct eigrp_fifo *eigrp_fifo_new(void); -extern struct eigrp_packet *eigrp_fifo_head(struct eigrp_fifo *); -extern struct eigrp_packet *eigrp_fifo_tail(struct eigrp_fifo *); +extern struct eigrp_packet *eigrp_fifo_next(struct eigrp_fifo *); extern struct eigrp_packet *eigrp_fifo_pop(struct eigrp_fifo *); -extern struct eigrp_packet *eigrp_fifo_pop_tail(struct eigrp_fifo *); -extern void eigrp_fifo_push_head(struct eigrp_fifo *, struct eigrp_packet *); +extern void eigrp_fifo_push(struct eigrp_fifo *, struct eigrp_packet *); extern void eigrp_fifo_free(struct eigrp_fifo *); extern void eigrp_fifo_reset(struct eigrp_fifo *); diff --git a/eigrpd/eigrp_query.c b/eigrpd/eigrp_query.c index 92bc792c6a..d6299ad923 100644 --- a/eigrpd/eigrp_query.c +++ b/eigrpd/eigrp_query.c @@ -207,7 +207,7 @@ void eigrp_send_query(struct eigrp_interface *ei) for (ALL_LIST_ELEMENTS(ei->nbrs, node2, nnode2, nbr)) { if (nbr->state == EIGRP_NEIGHBOR_UP) { /*Put packet to retransmission queue*/ - eigrp_fifo_push_head(nbr->retrans_queue, ep); + eigrp_fifo_push(nbr->retrans_queue, ep); ep_saved = true; if (nbr->retrans_queue->count == 1) { diff --git a/eigrpd/eigrp_reply.c b/eigrpd/eigrp_reply.c index c96c3008ca..1a4af15900 100644 --- a/eigrpd/eigrp_reply.c +++ b/eigrpd/eigrp_reply.c @@ -144,7 +144,7 @@ void eigrp_send_reply(struct eigrp_neighbor *nbr, struct eigrp_prefix_entry *pe) ep->sequence_number = nbr->ei->eigrp->sequence_number; /*Put packet to retransmission queue*/ - eigrp_fifo_push_head(nbr->retrans_queue, ep); + eigrp_fifo_push(nbr->retrans_queue, ep); if (nbr->retrans_queue->count == 1) { eigrp_send_packet_reliably(nbr); diff --git a/eigrpd/eigrp_siaquery.c b/eigrpd/eigrp_siaquery.c index a5df2381ca..215df7b8ee 100644 --- a/eigrpd/eigrp_siaquery.c +++ b/eigrpd/eigrp_siaquery.c @@ -153,7 +153,7 @@ void eigrp_send_siaquery(struct eigrp_neighbor *nbr, if (nbr->state == EIGRP_NEIGHBOR_UP) { /*Put packet to retransmission queue*/ - eigrp_fifo_push_head(nbr->retrans_queue, ep); + eigrp_fifo_push(nbr->retrans_queue, ep); if (nbr->retrans_queue->count == 1) { eigrp_send_packet_reliably(nbr); diff --git a/eigrpd/eigrp_siareply.c b/eigrpd/eigrp_siareply.c index 0b684b498b..32f0c8be33 100644 --- a/eigrpd/eigrp_siareply.c +++ b/eigrpd/eigrp_siareply.c @@ -152,7 +152,7 @@ void eigrp_send_siareply(struct eigrp_neighbor *nbr, if (nbr->state == EIGRP_NEIGHBOR_UP) { /*Put packet to retransmission queue*/ - eigrp_fifo_push_head(nbr->retrans_queue, ep); + eigrp_fifo_push(nbr->retrans_queue, ep); if (nbr->retrans_queue->count == 1) { eigrp_send_packet_reliably(nbr); diff --git a/eigrpd/eigrp_update.c b/eigrpd/eigrp_update.c index 3c82fdfde8..3af5524b87 100644 --- a/eigrpd/eigrp_update.c +++ b/eigrpd/eigrp_update.c @@ -497,7 +497,7 @@ void eigrp_update_send_init(struct eigrp_neighbor *nbr) ep->length, ep->sequence_number, inet_ntoa(ep->dst)); /*Put packet to retransmission queue*/ - eigrp_fifo_push_head(nbr->retrans_queue, ep); + eigrp_fifo_push(nbr->retrans_queue, ep); if (nbr->retrans_queue->count == 1) { eigrp_send_packet_reliably(nbr); @@ -528,7 +528,7 @@ static void eigrp_update_place_on_nbr_queue(struct eigrp_neighbor *nbr, ep->length, ep->sequence_number, inet_ntoa(ep->dst)); /*Put packet to retransmission queue*/ - eigrp_fifo_push_head(nbr->retrans_queue, ep); + eigrp_fifo_push(nbr->retrans_queue, ep); } void eigrp_update_send_EOT(struct eigrp_neighbor *nbr) @@ -731,7 +731,7 @@ void eigrp_update_send(struct eigrp_interface *ei) if (nbr->state == EIGRP_NEIGHBOR_UP) { packet_sent = true; /*Put packet to retransmission queue*/ - eigrp_fifo_push_head(nbr->retrans_queue, ep); + eigrp_fifo_push(nbr->retrans_queue, ep); if (nbr->retrans_queue->count == 1) { eigrp_send_packet_reliably(nbr); @@ -980,7 +980,7 @@ static void eigrp_update_send_GR_part(struct eigrp_neighbor *nbr) ep->length, ep->sequence_number, inet_ntoa(ep->dst)); /*Put packet to retransmission queue*/ - eigrp_fifo_push_head(nbr->retrans_queue, ep); + eigrp_fifo_push(nbr->retrans_queue, ep); if (nbr->retrans_queue->count == 1) { eigrp_send_packet_reliably(nbr); From 0f6c16fbe66c84b38263c1c0e29b1db429f614de Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 17 Aug 2017 19:20:45 -0400 Subject: [PATCH 024/130] eigrpd: Cleanup some more debugs Properly place a few more debugs. Signed-off-by: Donald Sharp --- eigrpd/eigrp_packet.c | 2 +- eigrpd/eigrp_update.c | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/eigrpd/eigrp_packet.c b/eigrpd/eigrp_packet.c index cd677f1ae6..adea165f48 100644 --- a/eigrpd/eigrp_packet.c +++ b/eigrpd/eigrp_packet.c @@ -903,7 +903,7 @@ void eigrp_packet_header_init(int type, struct eigrp_interface *ei, // eigrph->sequence = htonl(3); eigrph->flags = htonl(flags); - if (IS_DEBUG_EIGRP_TRANSMIT(0, RECV)) + if (IS_DEBUG_EIGRP_TRANSMIT(0, PACKET_DETAIL)) zlog_debug("Packet Header Init Seq [%u] Ack [%u]", htonl(eigrph->sequence), htonl(eigrph->ack)); diff --git a/eigrpd/eigrp_update.c b/eigrpd/eigrp_update.c index 3af5524b87..846b016c6a 100644 --- a/eigrpd/eigrp_update.c +++ b/eigrpd/eigrp_update.c @@ -762,8 +762,6 @@ void eigrp_update_send_all(struct eigrp *eigrp, pe->req_action &= ~EIGRP_FSM_NEED_UPDATE; listnode_delete(eigrp->topology_changes_internalIPV4, pe); - zlog_debug("UPDATE COUNT: %d", - eigrp->topology_changes_internalIPV4->count); } } } From 29e48d5859ebc091fb42510b76a5aa9df8aee967 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 17 Aug 2017 19:40:44 -0400 Subject: [PATCH 025/130] eigrpd: and More Debugging Cleanup Signed-off-by: Donald Sharp --- eigrpd/eigrp_packet.c | 4 ++-- eigrpd/eigrp_reply.c | 4 ---- eigrpd/eigrp_update.c | 4 ---- 3 files changed, 2 insertions(+), 10 deletions(-) diff --git a/eigrpd/eigrp_packet.c b/eigrpd/eigrp_packet.c index adea165f48..f38b759e9f 100644 --- a/eigrpd/eigrp_packet.c +++ b/eigrpd/eigrp_packet.c @@ -644,8 +644,8 @@ int eigrp_read(struct thread *thread) == nbr->init_sequence_number)) { eigrp_nbr_state_set(nbr, EIGRP_NEIGHBOR_UP); - zlog_info( - "Neighbor adjacency became full"); + zlog_info("Neighbor(%s) adjacency became full", + inet_ntoa(nbr->src)); nbr->init_sequence_number = 0; nbr->recv_sequence_number = ntohl(eigrph->sequence); diff --git a/eigrpd/eigrp_reply.c b/eigrpd/eigrp_reply.c index 1a4af15900..60390ad8a3 100644 --- a/eigrpd/eigrp_reply.c +++ b/eigrpd/eigrp_reply.c @@ -84,9 +84,7 @@ void eigrp_send_reply(struct eigrp_neighbor *nbr, struct eigrp_prefix_entry *pe) plist = e->prefix[EIGRP_FILTER_OUT]; alist_i = nbr->ei->list[EIGRP_FILTER_OUT]; plist_i = nbr->ei->prefix[EIGRP_FILTER_OUT]; - zlog_info("REPLY Send: Filtering"); - zlog_info("REPLY SEND Prefix: %s", inet_ntoa(nbr->src)); /* Check if any list fits */ if ((alist && access_list_apply(alist, (struct prefix *)pe2->destination_ipv4) @@ -106,8 +104,6 @@ void eigrp_send_reply(struct eigrp_neighbor *nbr, struct eigrp_prefix_entry *pe) zlog_info("REPLY SEND: Setting Metric to max"); pe2->reported_metric.delay = EIGRP_MAX_METRIC; - } else { - zlog_info("REPLY SEND: Not setting metric"); } /* diff --git a/eigrpd/eigrp_update.c b/eigrpd/eigrp_update.c index 846b016c6a..68c0b92fd8 100644 --- a/eigrpd/eigrp_update.c +++ b/eigrpd/eigrp_update.c @@ -684,13 +684,9 @@ void eigrp_update_send(struct eigrp_interface *ei) && prefix_list_apply(plist_i, (struct prefix *)dest_addr) == PREFIX_DENY)) { - zlog_info("PROC OUT: Skipping"); // pe->reported_metric.delay = EIGRP_MAX_METRIC; - zlog_info("PROC OUT Prefix: %s", - inet_ntoa(dest_addr->prefix)); continue; } else { - zlog_info("PROC OUT: NENastavujem metriku "); length += eigrp_add_internalTLV_to_stream(ep->s, pe); has_tlv = 1; From 510afcd647cce718dc25bd70179cb6fe6096113b Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 18 Aug 2017 09:45:16 -0400 Subject: [PATCH 026/130] bgpd: Fix bgp clear help string The bgp clear help string was misordered. New output: robot.cumulusnetworks.com# clear bgp (1-4294967295) Clear peers with the AS number * Clear all peers A.B.C.D BGP neighbor address to clear WORD BGP neighbor on interface to clear X:X::X:X BGP IPv6 neighbor to clear external Clear all external peers ipv4 Address Family ipv6 Address Family peer-group Clear all members of peer-group prefix Clear bestpath and re-advertise view BGP view vrf BGP VRF Fixes: #1005 Signed-off-by: Donald Sharp --- bgpd/bgp_vty.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index 01c27920f5..2e18a6d44f 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -6145,6 +6145,8 @@ DEFUN (clear_ip_bgp_all, IP_STR BGP_STR BGP_INSTANCE_HELP_STR + BGP_AFI_HELP_STR + BGP_SAFI_WITH_LABEL_HELP_STR "Clear all peers\n" "BGP neighbor address to clear\n" "BGP IPv6 neighbor to clear\n" @@ -6153,8 +6155,6 @@ DEFUN (clear_ip_bgp_all, "Clear all external peers\n" "Clear all members of peer-group\n" "BGP peer-group name\n" - BGP_AFI_HELP_STR - BGP_SAFI_WITH_LABEL_HELP_STR BGP_SOFT_STR BGP_SOFT_IN_STR BGP_SOFT_OUT_STR From ba117367612c347f4112398488b36cad94dd5e2d Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 18 Aug 2017 10:57:07 -0400 Subject: [PATCH 027/130] tools: Always ensure that the daemon exists at startup When starting up FRR with tools/frr, ensure that the daemon specified that we are about to start actually exists. Signed-off-by: Donald Sharp --- tools/frr | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/tools/frr b/tools/frr index 0bea3ee81d..4eb4a5c28c 100755 --- a/tools/frr +++ b/tools/frr @@ -72,6 +72,11 @@ vtysh_b () # returns: 0=ok, 1=error check_daemon() { + if [ $1 != "watchfrr" -a $1 != "vtysh_enable" ]; then + # check for daemon binary + if [ ! -x "$D_PATH/$1" ]; then return 1; fi + fi + # If the integrated config file is used the others are not checked. if [ -r "$C_PATH/frr.conf" ]; then return 0 @@ -80,9 +85,6 @@ check_daemon() # vtysh_enable has no config file nor binary so skip check. # (Not sure why vtysh_enable is in this list but does not hurt) if [ $1 != "watchfrr" -a $1 != "vtysh_enable" ]; then - # check for daemon binary - if [ ! -x "$D_PATH/$1" ]; then return 1; fi - # check for config file if [ -n "$2" ]; then if [ ! -r "$C_PATH/$1-$2.conf" ]; then From 1a0770e387bccdaadc6b4d48ba505d3d332034b6 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 18 Aug 2017 14:57:37 -0400 Subject: [PATCH 028/130] eigrpd: Only put 1 packet at a time on send queue When we have received an ack for the last reliable packet we must only put 1 packet onto the send queue. Signed-off-by: Donald Sharp --- eigrpd/eigrp_packet.c | 43 +++++++++++++++++++------------------------ 1 file changed, 19 insertions(+), 24 deletions(-) diff --git a/eigrpd/eigrp_packet.c b/eigrpd/eigrp_packet.c index f38b759e9f..dde553d53f 100644 --- a/eigrpd/eigrp_packet.c +++ b/eigrpd/eigrp_packet.c @@ -628,35 +628,30 @@ int eigrp_read(struct thread *thread) /* New testing block of code for handling Acks */ if (ntohl(eigrph->ack) != 0) { + struct eigrp_packet *ep = NULL; + nbr = eigrp_nbr_get(ei, eigrph, iph); - /* neighbor must be valid, eigrp_nbr_get creates if none existed - */ + // neighbor must be valid, eigrp_nbr_get creates if none existed assert(nbr); - struct eigrp_packet *ep; - ep = eigrp_fifo_next(nbr->retrans_queue); - if (ep) { - if (ntohl(eigrph->ack) == ep->sequence_number) { - if ((nbr->state == EIGRP_NEIGHBOR_PENDING) - && (ntohl(eigrph->ack) - == nbr->init_sequence_number)) { - eigrp_nbr_state_set(nbr, - EIGRP_NEIGHBOR_UP); - zlog_info("Neighbor(%s) adjacency became full", - inet_ntoa(nbr->src)); - nbr->init_sequence_number = 0; - nbr->recv_sequence_number = - ntohl(eigrph->sequence); - eigrp_update_send_EOT(nbr); - } - ep = eigrp_fifo_pop(nbr->retrans_queue); - eigrp_packet_free(ep); - if (nbr->retrans_queue->count > 0) { - eigrp_send_packet_reliably(nbr); - } + if ((ep) && (ntohl(eigrph->ack) == ep->sequence_number)) { + ep = eigrp_fifo_pop(nbr->retrans_queue); + eigrp_packet_free(ep); + + if ((nbr->state == EIGRP_NEIGHBOR_PENDING) + && (ntohl(eigrph->ack) == nbr->init_sequence_number)) { + eigrp_nbr_state_set(nbr, EIGRP_NEIGHBOR_UP); + zlog_info("Neighbor(%s) adjacency became full", + inet_ntoa(nbr->src)); + nbr->init_sequence_number = 0; + nbr->recv_sequence_number = + ntohl(eigrph->sequence); + eigrp_update_send_EOT(nbr); } + else + eigrp_send_packet_reliably(nbr); } ep = eigrp_fifo_next(nbr->multicast_queue); if (ep) { @@ -1073,7 +1068,7 @@ int eigrp_unack_multicast_packet_retrans(struct thread *thread) /* Get packet from tail of fifo. */ struct eigrp_packet *eigrp_fifo_pop(struct eigrp_fifo *fifo) { - struct eigrp_packet *ep; + struct eigrp_packet *ep = NULL; ep = fifo->tail; From 17a2f658da67b8317d99294fc56071145e1a65e0 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 18 Aug 2017 14:58:50 -0400 Subject: [PATCH 029/130] eigrpd: When generating packets only put one on send queue at a time When we generate update packets to go to our neighbor, Only put one packet at a time on the send queue. Signed-off-by: Donald Sharp --- eigrpd/eigrp_update.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/eigrpd/eigrp_update.c b/eigrpd/eigrp_update.c index 68c0b92fd8..5599965f6a 100644 --- a/eigrpd/eigrp_update.c +++ b/eigrpd/eigrp_update.c @@ -529,6 +529,9 @@ static void eigrp_update_place_on_nbr_queue(struct eigrp_neighbor *nbr, /*Put packet to retransmission queue*/ eigrp_fifo_push(nbr->retrans_queue, ep); + + if (nbr->retrans_queue->count == 1) + eigrp_send_packet_reliably(nbr); } void eigrp_update_send_EOT(struct eigrp_neighbor *nbr) @@ -567,7 +570,6 @@ void eigrp_update_send_EOT(struct eigrp_neighbor *nbr) if ((length + 0x001D) > (u_int16_t)nbr->ei->ifp->mtu) { eigrp_update_place_on_nbr_queue (nbr, ep, seq_no, length); - eigrp_send_packet_reliably(nbr); seq_no++; length = EIGRP_HEADER_LEN; @@ -615,7 +617,6 @@ void eigrp_update_send_EOT(struct eigrp_neighbor *nbr) } eigrp_update_place_on_nbr_queue (nbr, ep, seq_no, length); - eigrp_send_packet_reliably(nbr); } void eigrp_update_send(struct eigrp_interface *ei) From a75c1cc19127c543648a57f6f5ea9f3e13666a7f Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Sat, 19 Aug 2017 13:42:48 -0400 Subject: [PATCH 030/130] eigrpd: Fix memory leak in eigrp_update When we send packets to a nbr, make a duplicate copy as that each packet sent is assumed to be a complete to itself. Also clean up indentation in loop over figuring out what to send. Signed-off-by: Donald Sharp --- eigrpd/eigrp_update.c | 104 +++++++++++++++++++++--------------------- 1 file changed, 53 insertions(+), 51 deletions(-) diff --git a/eigrpd/eigrp_update.c b/eigrpd/eigrp_update.c index 5599965f6a..e42f84abc6 100644 --- a/eigrpd/eigrp_update.c +++ b/eigrpd/eigrp_update.c @@ -651,53 +651,47 @@ void eigrp_update_send(struct eigrp_interface *ei) has_tlv = 0; for (ALL_LIST_ELEMENTS(ei->eigrp->topology_changes_internalIPV4, node, nnode, pe)) { - if (pe->req_action & EIGRP_FSM_NEED_UPDATE) { - /* Get destination address from prefix */ - dest_addr = pe->destination_ipv4; - /* - * Filtering - */ - // TODO: Work in progress - /* get list from eigrp process */ - e = eigrp_lookup(); - /* Get access-lists and prefix-lists from process and - * interface */ - alist = e->list[EIGRP_FILTER_OUT]; - plist = e->prefix[EIGRP_FILTER_OUT]; - alist_i = ei->list[EIGRP_FILTER_OUT]; - plist_i = ei->prefix[EIGRP_FILTER_OUT]; + if (!(pe->req_action & EIGRP_FSM_NEED_UPDATE)) + continue; - /* Check if any list fits */ - if ((alist - && access_list_apply(alist, - (struct prefix *)dest_addr) - == FILTER_DENY) - || (plist - && prefix_list_apply(plist, - (struct prefix *)dest_addr) - == PREFIX_DENY) - || (alist_i - && access_list_apply(alist_i, - (struct prefix *)dest_addr) - == FILTER_DENY) - || (plist_i - && prefix_list_apply(plist_i, - (struct prefix *)dest_addr) - == PREFIX_DENY)) { - // pe->reported_metric.delay = EIGRP_MAX_METRIC; - continue; - } else { - length += eigrp_add_internalTLV_to_stream(ep->s, - pe); - has_tlv = 1; - } - /* - * End of filtering - */ + /* Get destination address from prefix */ + dest_addr = pe->destination_ipv4; - /* NULL the pointer */ - dest_addr = NULL; + /* + * Filtering + */ + e = eigrp_lookup(); + /* Get access-lists and prefix-lists from process and + * interface */ + alist = e->list[EIGRP_FILTER_OUT]; + plist = e->prefix[EIGRP_FILTER_OUT]; + alist_i = ei->list[EIGRP_FILTER_OUT]; + plist_i = ei->prefix[EIGRP_FILTER_OUT]; + + /* Check if any list fits */ + if ((alist + && access_list_apply(alist, + (struct prefix *)dest_addr) + == FILTER_DENY) + || (plist + && prefix_list_apply(plist, + (struct prefix *)dest_addr) + == PREFIX_DENY) + || (alist_i + && access_list_apply(alist_i, + (struct prefix *)dest_addr) + == FILTER_DENY) + || (plist_i + && prefix_list_apply(plist_i, + (struct prefix *)dest_addr) + == PREFIX_DENY)) { + // pe->reported_metric.delay = EIGRP_MAX_METRIC; + continue; + } else { + length += eigrp_add_internalTLV_to_stream(ep->s, + pe); + has_tlv = 1; } } @@ -725,14 +719,22 @@ void eigrp_update_send(struct eigrp_interface *ei) ep->sequence_number); for (ALL_LIST_ELEMENTS(ei->nbrs, node, nnode, nbr)) { - if (nbr->state == EIGRP_NEIGHBOR_UP) { - packet_sent = true; - /*Put packet to retransmission queue*/ - eigrp_fifo_push(nbr->retrans_queue, ep); + struct eigrp_packet *ep_dup; - if (nbr->retrans_queue->count == 1) { - eigrp_send_packet_reliably(nbr); - } + if (nbr->state != EIGRP_NEIGHBOR_UP) + continue; + + if (packet_sent) + ep_dup = eigrp_packet_duplicate(ep); + else + ep_dup = ep; + + packet_sent = true; + /*Put packet to retransmission queue*/ + eigrp_fifo_push(nbr->retrans_queue, ep_dup); + + if (nbr->retrans_queue->count == 1) { + eigrp_send_packet_reliably(nbr); } } From a6e8810ee341b0c1fc959ca0c9ed044990b4bfc8 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Sat, 19 Aug 2017 14:15:34 -0400 Subject: [PATCH 031/130] eigrpd: Allow eigrp_update_send to recognize a full packet Modify code to allow the eigrp_update_send function to recognize that we have a full packet and to do the right thing from there. Signed-off-by: Donald Sharp --- eigrpd/eigrp_update.c | 90 +++++++++++++++++++++++++++++++------------ 1 file changed, 65 insertions(+), 25 deletions(-) diff --git a/eigrpd/eigrp_update.c b/eigrpd/eigrp_update.c index e42f84abc6..8971635bfd 100644 --- a/eigrpd/eigrp_update.c +++ b/eigrpd/eigrp_update.c @@ -534,6 +534,38 @@ static void eigrp_update_place_on_nbr_queue(struct eigrp_neighbor *nbr, eigrp_send_packet_reliably(nbr); } +static void eigrp_update_send_to_all_nbrs(struct eigrp_interface *ei, + struct eigrp_packet *ep) +{ + struct listnode *node, *nnode; + struct eigrp_neighbor *nbr; + bool packet_sent = false; + + for (ALL_LIST_ELEMENTS(ei->nbrs, node, nnode, nbr)) { + struct eigrp_packet *ep_dup; + + if (nbr->state != EIGRP_NEIGHBOR_UP) + continue; + + if (packet_sent) + ep_dup = eigrp_packet_duplicate(ep, NULL); + else + ep_dup = ep; + + ep_dup->nbr = nbr; + packet_sent = true; + /*Put packet to retransmission queue*/ + eigrp_fifo_push(nbr->retrans_queue, ep_dup); + + if (nbr->retrans_queue->count == 1) { + eigrp_send_packet_reliably(nbr); + } + } + + if (!packet_sent) + eigrp_packet_free(ep); +} + void eigrp_update_send_EOT(struct eigrp_neighbor *nbr) { struct eigrp_packet *ep; @@ -617,13 +649,13 @@ void eigrp_update_send_EOT(struct eigrp_neighbor *nbr) } eigrp_update_place_on_nbr_queue (nbr, ep, seq_no, length); + nbr->ei->eigrp->sequence_number = seq_no++; } void eigrp_update_send(struct eigrp_interface *ei) { struct eigrp_packet *ep; struct listnode *node, *nnode; - struct eigrp_neighbor *nbr; struct eigrp_prefix_entry *pe; u_char has_tlv; struct access_list *alist; @@ -632,7 +664,10 @@ void eigrp_update_send(struct eigrp_interface *ei) struct prefix_list *plist_i; struct eigrp *e; struct prefix_ipv4 *dest_addr; - bool packet_sent = false; + u_int32_t seq_no = ei->eigrp->sequence_number; + + if (ei->nbrs->count == 0) + return; u_int16_t length = EIGRP_HEADER_LEN; @@ -640,7 +675,7 @@ void eigrp_update_send(struct eigrp_interface *ei) /* Prepare EIGRP INIT UPDATE header */ eigrp_packet_header_init(EIGRP_OPC_UPDATE, ei, ep->s, 0, - ei->eigrp->sequence_number, 0); + seq_no, 0); // encode Authentication TLV, if needed if ((IF_DEF_PARAMS(ei->ifp)->auth_type == EIGRP_AUTH_TYPE_MD5) @@ -655,6 +690,31 @@ void eigrp_update_send(struct eigrp_interface *ei) if (!(pe->req_action & EIGRP_FSM_NEED_UPDATE)) continue; + if ((length + 0x001D) > (u_int16_t)ei->ifp->mtu) { + if ((IF_DEF_PARAMS(ei->ifp)->auth_type == EIGRP_AUTH_TYPE_MD5) + && (IF_DEF_PARAMS(ei->ifp)->auth_keychain != NULL)) { + eigrp_make_md5_digest(ei, ep->s, EIGRP_AUTH_UPDATE_FLAG); + } + + eigrp_packet_checksum(ei, ep->s, length); + ep->length = length; + + ep->dst.s_addr = htonl(EIGRP_MULTICAST_ADDRESS); + + ep->sequence_number = seq_no; + seq_no++; + eigrp_update_send_to_all_nbrs(ei, ep); + + length = EIGRP_HEADER_LEN; + ep = eigrp_packet_new(ei->ifp->mtu, NULL); + eigrp_packet_header_init(EIGRP_OPC_UPDATE, ei, ep->s, 0, + seq_no, 0); + if ((IF_DEF_PARAMS(ei->ifp)->auth_type == EIGRP_AUTH_TYPE_MD5) + && (IF_DEF_PARAMS(ei->ifp)->auth_keychain != NULL)) { + length += eigrp_add_authTLV_MD5_to_stream(ep->s, ei); + } + has_tlv = 0; + } /* Get destination address from prefix */ dest_addr = pe->destination_ipv4; @@ -718,28 +778,8 @@ void eigrp_update_send(struct eigrp_interface *ei) zlog_debug("Enqueuing Update length[%u] Seq [%u]", length, ep->sequence_number); - for (ALL_LIST_ELEMENTS(ei->nbrs, node, nnode, nbr)) { - struct eigrp_packet *ep_dup; - - if (nbr->state != EIGRP_NEIGHBOR_UP) - continue; - - if (packet_sent) - ep_dup = eigrp_packet_duplicate(ep); - else - ep_dup = ep; - - packet_sent = true; - /*Put packet to retransmission queue*/ - eigrp_fifo_push(nbr->retrans_queue, ep_dup); - - if (nbr->retrans_queue->count == 1) { - eigrp_send_packet_reliably(nbr); - } - } - - if (!packet_sent) - eigrp_packet_free(ep); + eigrp_update_send_to_all_nbrs(ei, ep); + ei->eigrp->sequence_number = seq_no++; } void eigrp_update_send_all(struct eigrp *eigrp, From cf2f4daee37d1cbb92d29cbb3f0bf3268ee372cd Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Sat, 19 Aug 2017 14:38:17 -0400 Subject: [PATCH 032/130] eigrpd: Pass in actual used parameter to header creation Signed-off-by: Donald Sharp --- eigrpd/eigrp_hello.c | 2 +- eigrpd/eigrp_packet.c | 6 +++--- eigrpd/eigrp_packet.h | 2 +- eigrpd/eigrp_query.c | 2 +- eigrpd/eigrp_reply.c | 2 +- eigrpd/eigrp_siaquery.c | 2 +- eigrpd/eigrp_siareply.c | 2 +- eigrpd/eigrp_update.c | 26 ++++++++++++++------------ 8 files changed, 23 insertions(+), 21 deletions(-) diff --git a/eigrpd/eigrp_hello.c b/eigrpd/eigrp_hello.c index 67f75c536b..d56767fafc 100644 --- a/eigrpd/eigrp_hello.c +++ b/eigrpd/eigrp_hello.c @@ -618,7 +618,7 @@ static struct eigrp_packet *eigrp_hello_encode(struct eigrp_interface *ei, if (ep) { // encode common header feilds - eigrp_packet_header_init(EIGRP_OPC_HELLO, ei, ep->s, 0, 0, ack); + eigrp_packet_header_init(EIGRP_OPC_HELLO, ei->eigrp, ep->s, 0, 0, ack); // encode Authentication TLV if ((IF_DEF_PARAMS(ei->ifp)->auth_type == EIGRP_AUTH_TYPE_MD5) diff --git a/eigrpd/eigrp_packet.c b/eigrpd/eigrp_packet.c index dde553d53f..3b4a57ed54 100644 --- a/eigrpd/eigrp_packet.c +++ b/eigrpd/eigrp_packet.c @@ -877,7 +877,7 @@ void eigrp_packet_checksum(struct eigrp_interface *ei, struct stream *s, } /* Make EIGRP header. */ -void eigrp_packet_header_init(int type, struct eigrp_interface *ei, +void eigrp_packet_header_init(int type, struct eigrp *eigrp, struct stream *s, u_int32_t flags, u_int32_t sequence, u_int32_t ack) { @@ -890,8 +890,8 @@ void eigrp_packet_header_init(int type, struct eigrp_interface *ei, eigrph->opcode = (u_char)type; eigrph->checksum = 0; - eigrph->vrid = htons(ei->eigrp->vrid); - eigrph->ASNumber = htons(ei->eigrp->AS); + eigrph->vrid = htons(eigrp->vrid); + eigrph->ASNumber = htons(eigrp->AS); eigrph->ack = htonl(ack); eigrph->sequence = htonl(sequence); // if(flags == EIGRP_INIT_FLAG) diff --git a/eigrpd/eigrp_packet.h b/eigrpd/eigrp_packet.h index 040204a7fc..03fe412f1f 100644 --- a/eigrpd/eigrp_packet.h +++ b/eigrpd/eigrp_packet.h @@ -41,7 +41,7 @@ extern struct eigrp_packet *eigrp_packet_duplicate(struct eigrp_packet *, struct eigrp_neighbor *); extern void eigrp_packet_free(struct eigrp_packet *); extern void eigrp_packet_delete(struct eigrp_interface *); -extern void eigrp_packet_header_init(int, struct eigrp_interface *, +extern void eigrp_packet_header_init(int, struct eigrp *, struct stream *, u_int32_t, u_int32_t, u_int32_t); extern void eigrp_packet_checksum(struct eigrp_interface *, struct stream *, diff --git a/eigrpd/eigrp_query.c b/eigrpd/eigrp_query.c index d6299ad923..3bca444ab7 100644 --- a/eigrpd/eigrp_query.c +++ b/eigrpd/eigrp_query.c @@ -162,7 +162,7 @@ void eigrp_send_query(struct eigrp_interface *ei) ep = eigrp_packet_new(ei->ifp->mtu, NULL); /* Prepare EIGRP INIT UPDATE header */ - eigrp_packet_header_init(EIGRP_OPC_QUERY, ei, ep->s, 0, + eigrp_packet_header_init(EIGRP_OPC_QUERY, ei->eigrp, ep->s, 0, ei->eigrp->sequence_number, 0); // encode Authentication TLV, if needed diff --git a/eigrpd/eigrp_reply.c b/eigrpd/eigrp_reply.c index 60390ad8a3..e59db80393 100644 --- a/eigrpd/eigrp_reply.c +++ b/eigrpd/eigrp_reply.c @@ -113,7 +113,7 @@ void eigrp_send_reply(struct eigrp_neighbor *nbr, struct eigrp_prefix_entry *pe) ep = eigrp_packet_new(nbr->ei->ifp->mtu, nbr); /* Prepare EIGRP INIT UPDATE header */ - eigrp_packet_header_init(EIGRP_OPC_REPLY, nbr->ei, ep->s, 0, + eigrp_packet_header_init(EIGRP_OPC_REPLY, e, ep->s, 0, nbr->ei->eigrp->sequence_number, 0); // encode Authentication TLV, if needed diff --git a/eigrpd/eigrp_siaquery.c b/eigrpd/eigrp_siaquery.c index 215df7b8ee..30f65ee87d 100644 --- a/eigrpd/eigrp_siaquery.c +++ b/eigrpd/eigrp_siaquery.c @@ -126,7 +126,7 @@ void eigrp_send_siaquery(struct eigrp_neighbor *nbr, ep = eigrp_packet_new(nbr->ei->ifp->mtu, nbr); /* Prepare EIGRP INIT UPDATE header */ - eigrp_packet_header_init(EIGRP_OPC_SIAQUERY, nbr->ei, ep->s, 0, + eigrp_packet_header_init(EIGRP_OPC_SIAQUERY, nbr->ei->eigrp, ep->s, 0, nbr->ei->eigrp->sequence_number, 0); // encode Authentication TLV, if needed diff --git a/eigrpd/eigrp_siareply.c b/eigrpd/eigrp_siareply.c index 32f0c8be33..3050b91032 100644 --- a/eigrpd/eigrp_siareply.c +++ b/eigrpd/eigrp_siareply.c @@ -125,7 +125,7 @@ void eigrp_send_siareply(struct eigrp_neighbor *nbr, ep = eigrp_packet_new(nbr->ei->ifp->mtu, nbr); /* Prepare EIGRP INIT UPDATE header */ - eigrp_packet_header_init(EIGRP_OPC_SIAREPLY, nbr->ei, ep->s, 0, + eigrp_packet_header_init(EIGRP_OPC_SIAREPLY, nbr->ei->eigrp, ep->s, 0, nbr->ei->eigrp->sequence_number, 0); // encode Authentication TLV, if needed diff --git a/eigrpd/eigrp_update.c b/eigrpd/eigrp_update.c index 8971635bfd..7a7b1dd5d6 100644 --- a/eigrpd/eigrp_update.c +++ b/eigrpd/eigrp_update.c @@ -471,9 +471,10 @@ void eigrp_update_send_init(struct eigrp_neighbor *nbr) nbr->ei->eigrp->sequence_number, nbr->recv_sequence_number); - eigrp_packet_header_init( - EIGRP_OPC_UPDATE, nbr->ei, ep->s, EIGRP_INIT_FLAG, - nbr->ei->eigrp->sequence_number, nbr->recv_sequence_number); + eigrp_packet_header_init(EIGRP_OPC_UPDATE, nbr->ei->eigrp, + ep->s, EIGRP_INIT_FLAG, + nbr->ei->eigrp->sequence_number, + nbr->recv_sequence_number); // encode Authentication TLV, if needed if ((IF_DEF_PARAMS(nbr->ei->ifp)->auth_type == EIGRP_AUTH_TYPE_MD5) @@ -584,9 +585,9 @@ void eigrp_update_send_EOT(struct eigrp_neighbor *nbr) ep = eigrp_packet_new(nbr->ei->ifp->mtu, nbr); /* Prepare EIGRP EOT UPDATE header */ - eigrp_packet_header_init(EIGRP_OPC_UPDATE, nbr->ei, ep->s, EIGRP_EOT_FLAG, - seq_no, - nbr->recv_sequence_number); + eigrp_packet_header_init(EIGRP_OPC_UPDATE, nbr->ei->eigrp, + ep->s, EIGRP_EOT_FLAG, + seq_no, nbr->recv_sequence_number); // encode Authentication TLV, if needed if((IF_DEF_PARAMS (nbr->ei->ifp)->auth_type == EIGRP_AUTH_TYPE_MD5) && @@ -606,7 +607,8 @@ void eigrp_update_send_EOT(struct eigrp_neighbor *nbr) length = EIGRP_HEADER_LEN; ep = eigrp_packet_new(nbr->ei->ifp->mtu, nbr); - eigrp_packet_header_init(EIGRP_OPC_UPDATE, nbr->ei, ep->s, EIGRP_EOT_FLAG, + eigrp_packet_header_init(EIGRP_OPC_UPDATE, nbr->ei->eigrp, + ep->s, EIGRP_EOT_FLAG, seq_no, nbr->recv_sequence_number); if((IF_DEF_PARAMS (nbr->ei->ifp)->auth_type == EIGRP_AUTH_TYPE_MD5) && @@ -674,8 +676,8 @@ void eigrp_update_send(struct eigrp_interface *ei) ep = eigrp_packet_new(ei->ifp->mtu, NULL); /* Prepare EIGRP INIT UPDATE header */ - eigrp_packet_header_init(EIGRP_OPC_UPDATE, ei, ep->s, 0, - seq_no, 0); + eigrp_packet_header_init(EIGRP_OPC_UPDATE, ei->eigrp, + ep->s, 0, seq_no, 0); // encode Authentication TLV, if needed if ((IF_DEF_PARAMS(ei->ifp)->auth_type == EIGRP_AUTH_TYPE_MD5) @@ -707,8 +709,8 @@ void eigrp_update_send(struct eigrp_interface *ei) length = EIGRP_HEADER_LEN; ep = eigrp_packet_new(ei->ifp->mtu, NULL); - eigrp_packet_header_init(EIGRP_OPC_UPDATE, ei, ep->s, 0, - seq_no, 0); + eigrp_packet_header_init(EIGRP_OPC_UPDATE, ei->eigrp, + ep->s, 0, seq_no, 0); if ((IF_DEF_PARAMS(ei->ifp)->auth_type == EIGRP_AUTH_TYPE_MD5) && (IF_DEF_PARAMS(ei->ifp)->auth_keychain != NULL)) { length += eigrp_add_authTLV_MD5_to_stream(ep->s, ei); @@ -875,7 +877,7 @@ static void eigrp_update_send_GR_part(struct eigrp_neighbor *nbr) ep = eigrp_packet_new(nbr->ei->ifp->mtu, nbr); /* Prepare EIGRP Graceful restart UPDATE header */ - eigrp_packet_header_init(EIGRP_OPC_UPDATE, nbr->ei, ep->s, flags, + eigrp_packet_header_init(EIGRP_OPC_UPDATE, nbr->ei->eigrp, ep->s, flags, nbr->ei->eigrp->sequence_number, nbr->recv_sequence_number); From 01cbe587b04e0cf766099ee2dda8cae831aa25e2 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Sat, 19 Aug 2017 20:56:50 -0400 Subject: [PATCH 033/130] eigrpd: Setup eigrp to send FRR version Send to our peer the major/minor version of FRR that we are working with. I decided to use FRR instead of the os major/minor because the os itself doesn't tell you what version of EIGRP you are actually using. Signed-off-by: Donald Sharp --- eigrpd/eigrp_hello.c | 18 ++++++++++++++++-- eigrpd/eigrp_main.c | 2 ++ eigrpd/eigrp_packet.h | 1 + 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/eigrpd/eigrp_hello.c b/eigrpd/eigrp_hello.c index d56767fafc..ca05c653ce 100644 --- a/eigrpd/eigrp_hello.c +++ b/eigrpd/eigrp_hello.c @@ -405,6 +405,20 @@ void eigrp_hello_receive(struct eigrp *eigrp, struct ip *iph, inet_ntoa(nbr->src)); } +u_int32_t FRR_MAJOR; +u_int32_t FRR_MINOR; + +void eigrp_sw_version_initialize(void) +{ + char ver_string[] = VERSION; + char *dash = strstr(ver_string, "-"); + + if (dash) + dash[0] = '\0'; + + sscanf(ver_string, "%d.%d", &FRR_MAJOR, &FRR_MINOR); +} + /** * @fn eigrp_sw_version_encode * @@ -427,8 +441,8 @@ static u_int16_t eigrp_sw_version_encode(struct stream *s) // encode the version of quagga we're running // DVS: need to figure out a cleaner way to do this - stream_putc(s, 0); //!< major os version - stream_putc(s, 99); //!< minor os version + stream_putc(s, FRR_MAJOR); //!< major os version + stream_putc(s, FRR_MINOR); //!< minor os version /* and the core eigrp version */ stream_putc(s, EIGRP_MAJOR_VERSION); diff --git a/eigrpd/eigrp_main.c b/eigrpd/eigrp_main.c index 4c99821d3c..705e04b34d 100644 --- a/eigrpd/eigrp_main.c +++ b/eigrpd/eigrp_main.c @@ -159,6 +159,8 @@ int main(int argc, char **argv, char **envp) } } + eigrp_sw_version_initialize(); + /* EIGRP master init. */ eigrp_master_init(); eigrp_om->master = frr_init(); diff --git a/eigrpd/eigrp_packet.h b/eigrpd/eigrp_packet.h index 03fe412f1f..e72048ecc3 100644 --- a/eigrpd/eigrp_packet.h +++ b/eigrpd/eigrp_packet.h @@ -71,6 +71,7 @@ extern int eigrp_unack_multicast_packet_retrans(struct thread *); * untill there is reason to have their own header, these externs are found in * eigrp_hello.c */ +extern void eigrp_sw_version_initialize(void); extern void eigrp_hello_send(struct eigrp_interface *, u_char, struct in_addr *); extern void eigrp_hello_send_ack(struct eigrp_neighbor *); From ca9e3d23f60f2823b701cef9b341e13657af0482 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Sat, 19 Aug 2017 21:07:54 -0400 Subject: [PATCH 034/130] eigrpd: Fix code comments Signed-off-by: Donald Sharp --- eigrpd/eigrp_hello.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/eigrpd/eigrp_hello.c b/eigrpd/eigrp_hello.c index ca05c653ce..ef10ebf54c 100644 --- a/eigrpd/eigrp_hello.c +++ b/eigrpd/eigrp_hello.c @@ -439,8 +439,6 @@ static u_int16_t eigrp_sw_version_encode(struct stream *s) stream_putw(s, EIGRP_TLV_SW_VERSION); stream_putw(s, length); - // encode the version of quagga we're running - // DVS: need to figure out a cleaner way to do this stream_putc(s, FRR_MAJOR); //!< major os version stream_putc(s, FRR_MINOR); //!< minor os version From 3b4e6bd594833a32835f4cd59f471a7174711662 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Sat, 19 Aug 2017 21:21:00 -0400 Subject: [PATCH 035/130] ospf6d: Remove ospf6d version string This version string has not been updated in over 11 years. I cannot see any viable reason that we should use or update or anything with this value, remove. Signed-off-by: Donald Sharp --- ospf6d/ospf6d.c | 19 ------------------- ospf6d/ospf6d.h | 2 -- 2 files changed, 21 deletions(-) diff --git a/ospf6d/ospf6d.c b/ospf6d/ospf6d.c index 6b47fca578..48c34b7975 100644 --- a/ospf6d/ospf6d.c +++ b/ospf6d/ospf6d.c @@ -44,8 +44,6 @@ #include "ospf6d.h" #include "ospf6_bfd.h" -char ospf6_daemon_version[] = OSPF6_DAEMON_VERSION; - struct route_node *route_prev(struct route_node *node) { struct route_node *end; @@ -70,21 +68,6 @@ struct route_node *route_prev(struct route_node *node) return prev; } - -/* show database functions */ -DEFUN (show_version_ospf6, - show_version_ospf6_cmd, - "show version ospf6", - SHOW_STR - "Display version\n" - "Display ospf6d version\n" - ) -{ - vty_out(vty, "Zebra OSPF6d Version: %s\n", ospf6_daemon_version); - - return CMD_SUCCESS; -} - static struct cmd_node debug_node = { DEBUG_NODE, "", 1 /* VTYSH */ }; @@ -1174,8 +1157,6 @@ void ospf6_init(void) install_element_ospf6_clear_interface(); - install_element(VIEW_NODE, &show_version_ospf6_cmd); - install_element(VIEW_NODE, &show_ipv6_ospf6_border_routers_cmd); install_element(VIEW_NODE, &show_ipv6_ospf6_linkstate_cmd); diff --git a/ospf6d/ospf6d.h b/ospf6d/ospf6d.h index 1515c3ad0c..77a40eac63 100644 --- a/ospf6d/ospf6d.h +++ b/ospf6d/ospf6d.h @@ -21,8 +21,6 @@ #ifndef OSPF6D_H #define OSPF6D_H -#define OSPF6_DAEMON_VERSION "0.9.7r" - #include "libospf.h" #include "thread.h" From f7856a4466e535eaca803d9cd75f6a768c2b396e Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Sat, 19 Aug 2017 21:23:14 -0400 Subject: [PATCH 036/130] isisd: Remove unused version Signed-off-by: Donald Sharp --- isisd/isisd.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/isisd/isisd.h b/isisd/isisd.h index da02854f5c..36fe0b5937 100644 --- a/isisd/isisd.h +++ b/isisd/isisd.h @@ -25,8 +25,6 @@ #include "vty.h" -#define ISISD_VERSION "0.0.7" - #include "isisd/isis_constants.h" #include "isisd/isis_common.h" #include "isisd/isis_redist.h" From c283f389d12116559ef1acb2ed09c320842959da Mon Sep 17 00:00:00 2001 From: "Donnie Savage (dsavage)" Date: Sat, 19 Aug 2017 21:32:26 -0400 Subject: [PATCH 037/130] eigrpd: fix crash when external route is received When an external route is received, eigrpd will crash. For now, quietly discard the TLV. Work must be done to handle tlv processing and changes needed to FSM so it understands an external should not be chooses if an internal exist. Signed-off-by: Donnie Savage --- eigrpd/eigrp_query.c | 19 ++++++++++++++++--- eigrpd/eigrp_update.c | 19 ++++++++++++++++--- 2 files changed, 32 insertions(+), 6 deletions(-) diff --git a/eigrpd/eigrp_query.c b/eigrpd/eigrp_query.c index 3bca444ab7..00f9ee1267 100644 --- a/eigrpd/eigrp_query.c +++ b/eigrpd/eigrp_query.c @@ -91,8 +91,10 @@ void eigrp_query_receive(struct eigrp *eigrp, struct ip *iph, { struct eigrp_neighbor *nbr; struct TLV_IPv4_Internal_type *tlv; + struct prefix_ipv4 dest_addr; u_int16_t type; + u_int16_t length; /* increment statistics. */ ei->query_in++; @@ -107,9 +109,8 @@ void eigrp_query_receive(struct eigrp *eigrp, struct ip *iph, while (s->endp > s->getp) { type = stream_getw(s); - if (type == EIGRP_TLV_IPv4_INT) { - struct prefix_ipv4 dest_addr; - + switch (type) { + case EIGRP_TLV_IPv4_INT: stream_set_getp(s, s->getp - sizeof(u_int16_t)); tlv = eigrp_read_ipv4_tlv(s); @@ -142,6 +143,18 @@ void eigrp_query_receive(struct eigrp *eigrp, struct ip *iph, eigrp_fsm_event(msg, event); } eigrp_IPv4_InternalTLV_free(tlv); + break; + + case EIGRP_TLV_IPv4_EXT: + /* DVS: processing of external routes needs packet and fsm work. + * for now, lets just not creash the box + */ + default: + length = stream_getw(s); + // -2 for type, -2 for len + for (length-=4; length ; length--) { + (void)stream_getc(s); + } } } eigrp_hello_send_ack(nbr); diff --git a/eigrpd/eigrp_update.c b/eigrpd/eigrp_update.c index 7a7b1dd5d6..d0c6520c4e 100644 --- a/eigrpd/eigrp_update.c +++ b/eigrpd/eigrp_update.c @@ -169,9 +169,11 @@ void eigrp_update_receive(struct eigrp *eigrp, struct ip *iph, struct eigrp_neighbor_entry *ne; u_int32_t flags; u_int16_t type; + u_int16_t length; u_char same; struct access_list *alist; struct prefix_list *plist; + struct prefix_ipv4 dest_addr; struct eigrp *e; u_char graceful_restart; u_char graceful_restart_final; @@ -287,9 +289,8 @@ void eigrp_update_receive(struct eigrp *eigrp, struct ip *iph, /*If there is topology information*/ while (s->endp > s->getp) { type = stream_getw(s); - if (type == EIGRP_TLV_IPv4_INT) { - struct prefix_ipv4 dest_addr; - + switch (type) { + case EIGRP_TLV_IPv4_INT: stream_set_getp(s, s->getp - sizeof(u_int16_t)); tlv = eigrp_read_ipv4_tlv(s); @@ -436,6 +437,18 @@ void eigrp_update_receive(struct eigrp *eigrp, struct ip *iph, pe); } eigrp_IPv4_InternalTLV_free(tlv); + break; + + case EIGRP_TLV_IPv4_EXT: + /* DVS: processing of external routes needs packet and fsm work. + * for now, lets just not creash the box + */ + default: + length = stream_getw(s); + // -2 for type, -2 for len + for (length-=4; length ; length--) { + (void)stream_getc(s); + } } } From 7292d8510f37ad85a295d8e361631a85e1e87234 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 18 Aug 2017 11:12:31 -0400 Subject: [PATCH 038/130] vtysh: Convert 'show logging' to use helper function. The 'show logging' command was not using the 'show_per_daemon' function for some reason. Signed-off-by: Donald Sharp --- vtysh/vtysh.c | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/vtysh/vtysh.c b/vtysh/vtysh.c index f971c171bc..0c3cb27c18 100644 --- a/vtysh/vtysh.c +++ b/vtysh/vtysh.c @@ -1941,20 +1941,8 @@ DEFUN (vtysh_show_logging, SHOW_STR "Show current logging configuration\n") { - unsigned int i; - int ret = CMD_SUCCESS; - char line[] = "do show logging\n"; - - for (i = 0; i < array_size(vtysh_client); i++) - if (vtysh_client[i].fd >= 0) { - fprintf(stdout, "Logging configuration 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("do show logging\n", + "Logging configuration for %s:\n"); } DEFUNSH(VTYSH_ALL, vtysh_log_stdout, vtysh_log_stdout_cmd, "log stdout", From 87f6dc504d5d227ea66a4da37b350c2fc3df212b Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 18 Aug 2017 12:50:13 -0400 Subject: [PATCH 039/130] *: Add 'show debugging' command from vtysh Allow vtysh to query every daemon about its debugging status in one go. Signed-off-by: Donald Sharp --- babeld/babel_zebra.c | 16 ++++++++++++++++ bgpd/bgp_debug.c | 12 ++++++------ bgpd/rfapi/vnc_debug.c | 14 +++++++------- eigrpd/eigrp_dump.c | 12 ++++++------ isisd/isisd.c | 19 ++++++++++--------- ldpd/ldp_vty_cmds.c | 14 +++++++------- nhrpd/nhrp_vty.c | 10 +++++----- ospf6d/ospf6d.c | 18 +++++++++++++++++- ospfd/ospf_dump.c | 26 +++++++++++++------------- pimd/pim_cmd.c | 15 +++++++++------ ripd/rip_debug.c | 12 ++++++------ ripngd/ripng_debug.c | 12 ++++++------ vtysh/vtysh.c | 14 +++++++++++++- zebra/debug.c | 12 ++++++------ 14 files changed, 127 insertions(+), 79 deletions(-) diff --git a/babeld/babel_zebra.c b/babeld/babel_zebra.c index 11b9c5956c..2ec5c3d7c3 100644 --- a/babeld/babel_zebra.c +++ b/babeld/babel_zebra.c @@ -310,6 +310,20 @@ debug_babel_config_write (struct vty * vty) #endif /* NO_DEBUG */ } +DEFUN_NOSH (show_debugging_babel, + show_debugging_babel_cmd, + "show debugging [babel]", + SHOW_STR + DEBUG_STR + "Babel") +{ + vty_out(vty, "BABEL debugging status\n"); + + debug_babel_config_write(vty); + + return CMD_SUCCESS; +} + static void babel_zebra_connected (struct zclient *zclient) { @@ -339,6 +353,8 @@ void babelz_zebra_init(void) install_element(ENABLE_NODE, &no_debug_babel_cmd); install_element(CONFIG_NODE, &debug_babel_cmd); install_element(CONFIG_NODE, &no_debug_babel_cmd); + + install_element(VIEW_NODE, &show_debugging_babel_cmd); } static int diff --git a/bgpd/bgp_debug.c b/bgpd/bgp_debug.c index bcb3c5fc18..c1c4f2b39c 100644 --- a/bgpd/bgp_debug.c +++ b/bgpd/bgp_debug.c @@ -1615,12 +1615,12 @@ DEFUN (no_debug_bgp, return CMD_SUCCESS; } -DEFUN (show_debugging_bgp, - show_debugging_bgp_cmd, - "show debugging bgp", - SHOW_STR - DEBUG_STR - BGP_STR) +DEFUN_NOSH (show_debugging_bgp, + show_debugging_bgp_cmd, + "show debugging [bgp]", + SHOW_STR + DEBUG_STR + BGP_STR) { vty_out(vty, "BGP debugging status:\n"); diff --git a/bgpd/rfapi/vnc_debug.c b/bgpd/rfapi/vnc_debug.c index d4ff9451c3..3e9b5ed6b9 100644 --- a/bgpd/rfapi/vnc_debug.c +++ b/bgpd/rfapi/vnc_debug.c @@ -142,13 +142,13 @@ DEFUN (no_debug_bgp_vnc_all, * show/save ***********************************************************************/ -DEFUN (show_debugging_bgp_vnc, - show_debugging_bgp_vnc_cmd, - "show debugging bgp vnc", - SHOW_STR - DEBUG_STR - BGP_STR - VNC_STR) +DEFUN_NOSH (show_debugging_bgp_vnc, + show_debugging_bgp_vnc_cmd, + "show debugging bgp vnc", + SHOW_STR + DEBUG_STR + BGP_STR + VNC_STR) { size_t i; diff --git a/eigrpd/eigrp_dump.c b/eigrpd/eigrp_dump.c index aca6e59816..0cb1ee5876 100644 --- a/eigrpd/eigrp_dump.c +++ b/eigrpd/eigrp_dump.c @@ -323,12 +323,12 @@ void show_ip_eigrp_neighbor_entry(struct vty *vty, struct eigrp *eigrp, } -DEFUN (show_debugging_eigrp, - show_debugging_eigrp_cmd, - "show debugging eigrp", - SHOW_STR - DEBUG_STR - EIGRP_STR) +DEFUN_NOSH (show_debugging_eigrp, + show_debugging_eigrp_cmd, + "show debugging [eigrp]", + SHOW_STR + DEBUG_STR + EIGRP_STR) { int i; diff --git a/isisd/isisd.c b/isisd/isisd.c index 60b9367da9..dba34e8e35 100644 --- a/isisd/isisd.c +++ b/isisd/isisd.c @@ -758,17 +758,18 @@ void print_debug(struct vty *vty, int flags, int onoff) vty_out(vty, "IS-IS LSP scheduling debugging is %s\n", onoffs); } -DEFUN (show_debugging, - show_debugging_isis_cmd, - "show debugging isis", - SHOW_STR - "State of each debugging option\n" - ISIS_STR) +DEFUN_NOSH (show_debugging, + show_debugging_isis_cmd, + "show debugging [isis]", + SHOW_STR + "State of each debugging option\n" + ISIS_STR) { - if (isis->debugs) { - vty_out(vty, "IS-IS:\n"); + vty_out (vty, "IS-IS debugging status:\n"); + + if (isis->debugs) print_debug(vty, isis->debugs, 1); - } + return CMD_SUCCESS; } diff --git a/ldpd/ldp_vty_cmds.c b/ldpd/ldp_vty_cmds.c index db92b93628..be473063cd 100644 --- a/ldpd/ldp_vty_cmds.c +++ b/ldpd/ldp_vty_cmds.c @@ -684,13 +684,13 @@ DEFPY (ldp_show_l2vpn_atom_vc, return (ldp_vty_show_atom_vc(vty, json)); } -DEFPY (ldp_show_debugging_mpls_ldp, - ldp_show_debugging_mpls_ldp_cmd, - "show debugging mpls ldp", - "Show running system information\n" - "Debugging functions\n" - "MPLS information\n" - "Label Distribution Protocol\n") +DEFUN_NOSH (ldp_show_debugging_mpls_ldp, + ldp_show_debugging_mpls_ldp_cmd, + "show debugging [mpls ldp]", + "Show running system information\n" + "Debugging functions\n" + "MPLS information\n" + "Label Distribution Protocol\n") { return (ldp_vty_show_debugging(vty)); } diff --git a/nhrpd/nhrp_vty.c b/nhrpd/nhrp_vty.c index 20ef17de00..6d78fc1d2b 100644 --- a/nhrpd/nhrp_vty.c +++ b/nhrpd/nhrp_vty.c @@ -110,11 +110,11 @@ static int toggle_flag( #ifndef NO_DEBUG -DEFUN(show_debugging_nhrp, show_debugging_nhrp_cmd, - "show debugging nhrp", - SHOW_STR - "Debugging information\n" - "NHRP configuration\n") +DEFUN_NOSH(show_debugging_nhrp, show_debugging_nhrp_cmd, + "show debugging [nhrp]", + SHOW_STR + "Debugging information\n" + "NHRP configuration\n") { int i; diff --git a/ospf6d/ospf6d.c b/ospf6d/ospf6d.c index 48c34b7975..f6b9e0ec14 100644 --- a/ospf6d/ospf6d.c +++ b/ospf6d/ospf6d.c @@ -85,10 +85,24 @@ static int config_write_ospf6_debug(struct vty *vty) config_write_ospf6_debug_asbr(vty); config_write_ospf6_debug_abr(vty); config_write_ospf6_debug_flood(vty); - vty_out(vty, "!\n"); + return 0; } +DEFUN_NOSH (show_debugging_ospf6, + show_debugging_ospf6_cmd, + "show debugging [ospf6]", + SHOW_STR + DEBUG_STR + OSPF6_STR) +{ + vty_out(vty, "OSPF6 debugging status:"); + + config_write_ospf6_debug(vty); + + return CMD_SUCCESS; +} + #define AREA_LSDB_TITLE_FORMAT \ "\n Area Scoped Link State Database (Area %s)\n\n" #define IF_LSDB_TITLE_FORMAT \ @@ -1157,6 +1171,8 @@ void ospf6_init(void) install_element_ospf6_clear_interface(); + install_element(VIEW_NODE, &show_debugging_ospf6_cmd); + install_element(VIEW_NODE, &show_ipv6_ospf6_border_routers_cmd); install_element(VIEW_NODE, &show_ipv6_ospf6_linkstate_cmd); diff --git a/ospfd/ospf_dump.c b/ospfd/ospf_dump.c index d3d1ffed5e..619bd4e5f5 100644 --- a/ospfd/ospf_dump.c +++ b/ospfd/ospf_dump.c @@ -1597,12 +1597,12 @@ static int show_debugging_ospf_common(struct vty *vty, struct ospf *ospf) return CMD_SUCCESS; } -DEFUN (show_debugging_ospf, - show_debugging_ospf_cmd, - "show debugging ospf", - SHOW_STR - DEBUG_STR - OSPF_STR) +DEFUN_NOSH (show_debugging_ospf, + show_debugging_ospf_cmd, + "show debugging [ospf]", + SHOW_STR + DEBUG_STR + OSPF_STR) { struct ospf *ospf; @@ -1612,13 +1612,13 @@ DEFUN (show_debugging_ospf, return show_debugging_ospf_common(vty, ospf); } -DEFUN (show_debugging_ospf_instance, - show_debugging_ospf_instance_cmd, - "show debugging ospf (1-65535)", - SHOW_STR - DEBUG_STR - OSPF_STR - "Instance ID\n") +DEFUN_NOSH (show_debugging_ospf_instance, + show_debugging_ospf_instance_cmd, + "show debugging ospf (1-65535)", + SHOW_STR + DEBUG_STR + OSPF_STR + "Instance ID\n") { int idx_number = 3; struct ospf *ospf; diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index 3bffaf855b..9c79fd87e2 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -7254,14 +7254,17 @@ DEFUN (no_debug_msdp_packets, ALIAS(no_debug_msdp_packets, undebug_msdp_packets_cmd, "undebug msdp packets", UNDEBUG_STR DEBUG_MSDP_STR DEBUG_MSDP_PACKETS_STR) -DEFUN (show_debugging_pim, - show_debugging_pim_cmd, - "show debugging pim", - SHOW_STR - DEBUG_STR - PIM_STR) +DEFUN_NOSH (show_debugging_pim, + show_debugging_pim_cmd, + "show debugging [pim]", + SHOW_STR + DEBUG_STR + PIM_STR) { + vty_out(vty, "PIM debugging status\n"); + pim_debug_config_write(vty); + return CMD_SUCCESS; } diff --git a/ripd/rip_debug.c b/ripd/rip_debug.c index 492d036991..56ba8e7f3e 100644 --- a/ripd/rip_debug.c +++ b/ripd/rip_debug.c @@ -27,12 +27,12 @@ unsigned long rip_debug_event = 0; unsigned long rip_debug_packet = 0; unsigned long rip_debug_zebra = 0; -DEFUN (show_debugging_rip, - show_debugging_rip_cmd, - "show debugging rip", - SHOW_STR - DEBUG_STR - RIP_STR) +DEFUN_NOSH (show_debugging_rip, + show_debugging_rip_cmd, + "show debugging [rip]", + SHOW_STR + DEBUG_STR + RIP_STR) { vty_out(vty, "RIP debugging status:\n"); diff --git a/ripngd/ripng_debug.c b/ripngd/ripng_debug.c index d56161d39e..9ebc302b1b 100644 --- a/ripngd/ripng_debug.c +++ b/ripngd/ripng_debug.c @@ -28,12 +28,12 @@ unsigned long ripng_debug_event = 0; unsigned long ripng_debug_packet = 0; unsigned long ripng_debug_zebra = 0; -DEFUN (show_debugging_ripng, - show_debugging_ripng_cmd, - "show debugging ripng", - SHOW_STR - DEBUG_STR - "RIPng configuration\n") +DEFUN_NOSH (show_debugging_ripng, + show_debugging_ripng_cmd, + "show debugging [ripng]", + SHOW_STR + DEBUG_STR + "RIPng configuration\n") { vty_out(vty, "RIPng debugging status:\n"); diff --git a/vtysh/vtysh.c b/vtysh/vtysh.c index 0c3cb27c18..379dbf21be 100644 --- a/vtysh/vtysh.c +++ b/vtysh/vtysh.c @@ -1914,6 +1914,16 @@ static int show_per_daemon(const char *line, const char *headline) return ret; } +DEFUN (vtysh_show_debugging, + vtysh_show_debugging_cmd, + "show debugging", + SHOW_STR + DEBUG_STR) +{ + return show_per_daemon("do show debugging\n", + "Debugging Information for %s:\n"); +} + /* Memory */ DEFUN (vtysh_show_memory, vtysh_show_memory_cmd, @@ -1921,7 +1931,8 @@ DEFUN (vtysh_show_memory, SHOW_STR "Memory statistics\n") { - return show_per_daemon("show memory\n", "Memory statistics for %s:\n"); + return show_per_daemon("show memory\n", + "Memory statistics for %s:\n"); } DEFUN (vtysh_show_modules, @@ -3220,6 +3231,7 @@ void vtysh_init_vty(void) install_element(ENABLE_NODE, &vtysh_start_zsh_cmd); #endif + install_element(VIEW_NODE, &vtysh_show_debugging_cmd); install_element(VIEW_NODE, &vtysh_show_memory_cmd); install_element(VIEW_NODE, &vtysh_show_modules_cmd); diff --git a/zebra/debug.c b/zebra/debug.c index 25f47bc51a..afeba1c6de 100644 --- a/zebra/debug.c +++ b/zebra/debug.c @@ -34,12 +34,12 @@ unsigned long zebra_debug_mpls; unsigned long zebra_debug_vxlan; unsigned long zebra_debug_pw; -DEFUN (show_debugging_zebra, - show_debugging_zebra_cmd, - "show debugging zebra", - SHOW_STR - "Debugging information\n" - "Zebra configuration\n") +DEFUN_NOSH (show_debugging_zebra, + show_debugging_zebra_cmd, + "show debugging [zebra]", + SHOW_STR + "Debugging information\n" + "Zebra configuration\n") { vty_out(vty, "Zebra debugging status:\n"); From d261dd7ea1b9fbbae23b3acafe1aa6afdad94a88 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Fri, 18 Aug 2017 13:10:36 +0200 Subject: [PATCH 040/130] zebra: put pseudowire show cmd under mpls Let's group this where it belongs and not clutter the commands too much. Signed-off-by: David Lamparter --- zebra/zebra_pw.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/zebra/zebra_pw.c b/zebra/zebra_pw.c index 4f1d8b0915..0b6263fac5 100644 --- a/zebra/zebra_pw.c +++ b/zebra/zebra_pw.c @@ -434,8 +434,9 @@ DEFUN (pseudowire_control_word, DEFUN (show_pseudowires, show_pseudowires_cmd, - "show pseudowires", + "show mpls pseudowires", SHOW_STR + MPLS_STR "Pseudowires") { struct zebra_vrf *zvrf; From 40818cec851ee74be69a461db5bb14ace67f784b Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Mon, 21 Aug 2017 14:34:31 +0200 Subject: [PATCH 041/130] lib: move hashstats under debug, show per-daemon Signed-off-by: David Lamparter --- lib/hash.c | 13 +++++++------ vtysh/vtysh.c | 13 +++++++++++++ 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/lib/hash.c b/lib/hash.c index 66341cf2f1..243521bef7 100644 --- a/lib/hash.c +++ b/lib/hash.c @@ -335,12 +335,13 @@ void hash_free(struct hash *hash) /* CLI commands ------------------------------------------------------------ */ -DEFUN(show_hash_stats, - show_hash_stats_cmd, - "show hashtable [statistics]", - SHOW_STR - "Statistics about hash tables\n" - "Statistics about hash tables\n") +DEFUN_NOSH(show_hash_stats, + show_hash_stats_cmd, + "show debugging hashtable [statistics]", + SHOW_STR + DEBUG_STR + "Statistics about hash tables\n" + "Statistics about hash tables\n") { struct hash *h; struct listnode *ln; diff --git a/vtysh/vtysh.c b/vtysh/vtysh.c index 70c6442473..85cbcae4df 100644 --- a/vtysh/vtysh.c +++ b/vtysh/vtysh.c @@ -1925,6 +1925,18 @@ DEFUN (vtysh_show_debugging, "Debugging Information for %s:\n"); } +DEFUN (vtysh_show_debugging_hashtable, + vtysh_show_debugging_hashtable_cmd, + "show debugging hashtable [statistics]", + SHOW_STR + DEBUG_STR + "Statistics about hash tables\n" + "Statistics about hash tables\n") +{ + return show_per_daemon("do show debugging hashtable\n", + "Hashtable statistics for %s:\n"); +} + /* Memory */ DEFUN (vtysh_show_memory, vtysh_show_memory_cmd, @@ -3233,6 +3245,7 @@ void vtysh_init_vty(void) #endif install_element(VIEW_NODE, &vtysh_show_debugging_cmd); + install_element(VIEW_NODE, &vtysh_show_debugging_hashtable_cmd); install_element(VIEW_NODE, &vtysh_show_memory_cmd); install_element(VIEW_NODE, &vtysh_show_modules_cmd); From 53b997359fe5c18b64e587f0324ee0258ef5a719 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Mon, 31 Jul 2017 22:34:26 +0200 Subject: [PATCH 042/130] build: fix --disable-snmp --disable-foo results in "no" as value in $enable_foo Signed-off-by: David Lamparter --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 710a71f636..bf66e00f9f 100755 --- a/configure.ac +++ b/configure.ac @@ -1366,7 +1366,7 @@ fi dnl ------------------ dnl check Net-SNMP library dnl ------------------ -if test "${enable_snmp}" != ""; then +if test "${enable_snmp}" != "" -a "${enable_snmp}" != "no"; then AC_PATH_TOOL([NETSNMP_CONFIG], [net-snmp-config], [no]) if test x"$NETSNMP_CONFIG" = x"no"; then AC_MSG_ERROR([--enable-snmp given but unable to find net-snmp-config]) From 8e9e4bd4bf0493013e071d9edb5c374c78549c73 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Mon, 21 Aug 2017 20:05:51 +0200 Subject: [PATCH 043/130] bgpd: don't zprivs_terminate() twice zprivs_terminate() is called from bgp_exit() Signed-off-by: David Lamparter --- bgpd/bgp_main.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/bgpd/bgp_main.c b/bgpd/bgp_main.c index d1359402df..3bf9ea02d5 100644 --- a/bgpd/bgp_main.c +++ b/bgpd/bgp_main.c @@ -140,11 +140,8 @@ __attribute__((__noreturn__)) void sigint(void) { zlog_notice("Terminating on signal"); - if (!retain_mode) { + if (!retain_mode) bgp_terminate(); - if (bgpd_privs.user) /* NULL if skip_runas flag set */ - zprivs_terminate(&bgpd_privs); - } bgp_exit(0); From 4093d47b9913113e1e30f8cce82bd8104a0efa8e Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Mon, 21 Aug 2017 20:17:53 +0200 Subject: [PATCH 044/130] lib: terminate capabilities only if initialized zprivs_caps_init() is called conditionally, apply the same condition on terminate. Signed-off-by: David Lamparter --- lib/privs.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/privs.c b/lib/privs.c index eda3fb02d4..cfe7d6d6f8 100644 --- a/lib/privs.c +++ b/lib/privs.c @@ -856,7 +856,9 @@ void zprivs_terminate(struct zebra_privs_t *zprivs) } #ifdef HAVE_CAPABILITIES - zprivs_caps_terminate(); + if (zprivs->user || zprivs->group || zprivs->cap_num_p + || zprivs->cap_num_i) + zprivs_caps_terminate(); #else /* !HAVE_CAPABILITIES */ /* only change uid if we don't have the correct one */ if ((zprivs_state.zuid) && (zprivs_state.zsuid != zprivs_state.zuid)) { From acf3a851b97209cbb922c279ae8ae9493a786686 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Tue, 22 Aug 2017 15:27:08 +0200 Subject: [PATCH 045/130] lib: fix const-check in route_node route_node->lock is "const" if --enable-dev-build is used. This is done to deter people from messing with internals of the route_table... unfortunately, the inline'd route_[un]lock_node runs into this. Signed-off-by: David Lamparter --- lib/table.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/table.h b/lib/table.h index ece40d86b3..9637fec149 100644 --- a/lib/table.h +++ b/lib/table.h @@ -227,7 +227,7 @@ extern void route_table_iter_cleanup(route_table_iter_t *iter); /* Lock node. */ static inline struct route_node *route_lock_node(struct route_node *node) { - node->lock++; + (*(unsigned *)&node->lock)++; return node; } @@ -235,7 +235,7 @@ static inline struct route_node *route_lock_node(struct route_node *node) static inline void route_unlock_node(struct route_node *node) { assert(node->lock > 0); - node->lock--; + (*(unsigned *)&node->lock)--; if (node->lock == 0) route_node_delete(node); From b81ef7b30a074ab6f90446e595a7ef4aefc75fad Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Tue, 22 Aug 2017 10:52:07 -0300 Subject: [PATCH 046/130] zebra: fix display of static routes pointing to nonexistent interfaces Bug introduced a couple of weeks ago by myself. Only happens when the route has an IP nexthop + a nexthop interface. Example: debian(config)# ip route 10.0.1.0/24 172.16.1.10 fake1 debian(config)# do sh run Building configuration... [snip] ! ip route 10.0.1.0/24 172.16.1.10 unknown ! end Signed-off-by: Renato Westphal --- zebra/zebra_vty.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c index f01f037ed5..9f887e8401 100644 --- a/zebra/zebra_vty.c +++ b/zebra/zebra_vty.c @@ -1705,16 +1705,14 @@ static int static_config(struct vty *vty, afi_t afi, safi_t safi, inet_ntop(AF_INET, &si->addr.ipv4, buf, sizeof buf), - ifindex2ifname(si->ifindex, - si->vrf_id)); + si->ifname); break; case STATIC_IPV6_GATEWAY_IFNAME: vty_out(vty, " %s %s", inet_ntop(AF_INET6, &si->addr.ipv6, buf, sizeof buf), - ifindex2ifname(si->ifindex, - si->vrf_id)); + si->ifname); break; } From f0c4b8e1c8209229891ed76a1e408bfccd557cee Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Tue, 22 Aug 2017 10:57:55 -0300 Subject: [PATCH 047/130] zebra: redistribute srcdest routes to the client daemons Somehow we missed these bits from the original srcdest patchset. Signed-off-by: Renato Westphal --- zebra/redistribute.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zebra/redistribute.c b/zebra/redistribute.c index ed27dc3e83..410ddcd4a0 100644 --- a/zebra/redistribute.c +++ b/zebra/redistribute.c @@ -114,7 +114,7 @@ static void zebra_redistribute(struct zserv *client, int type, u_short instance, if (!table) return; - for (rn = route_top(table); rn; rn = route_next(rn)) + for (rn = route_top(table); rn; rn = srcdest_route_next(rn)) RNODE_FOREACH_RE(rn, newre) { struct prefix *dst_p, *src_p; From a5fdb4c510dd61f0300f6ed6c1b6a7d33f85933b Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Tue, 22 Aug 2017 11:18:10 -0300 Subject: [PATCH 048/130] isisd: return proper error codes in some commands CMD_ERR_AMBIGUOUS should only be used internally by the CLI. Signed-off-by: Renato Westphal --- isisd/isis_vty.c | 86 ++++++++++++++++++++++++------------------------ isisd/isisd.c | 22 ++++++------- 2 files changed, 54 insertions(+), 54 deletions(-) diff --git a/isisd/isis_vty.c b/isisd/isis_vty.c index 2a19465a01..17d8ad3c0b 100644 --- a/isisd/isis_vty.c +++ b/isisd/isis_vty.c @@ -181,7 +181,7 @@ DEFUN (no_isis_passive, if (if_is_loopback(circuit->interface)) { vty_out(vty, "Can't set no passive for loopback interface\n"); - return CMD_ERR_AMBIGUOUS; + return CMD_WARNING_CONFIG_FAILED; } isis_circuit_passive_set(circuit, 0); @@ -206,7 +206,7 @@ DEFUN (isis_circuit_type, is_type = string2circuit_t(argv[idx_level]->arg); if (!is_type) { vty_out(vty, "Unknown circuit-type \n"); - return CMD_ERR_AMBIGUOUS; + return CMD_WARNING_CONFIG_FAILED; } if (circuit->state == C_STATE_UP @@ -214,7 +214,7 @@ DEFUN (isis_circuit_type, && circuit->area->is_type != is_type) { vty_out(vty, "Invalid circuit level for area %s.\n", circuit->area->area_tag); - return CMD_ERR_AMBIGUOUS; + return CMD_WARNING_CONFIG_FAILED; } isis_circuit_is_type_set(circuit, is_type); @@ -262,7 +262,7 @@ DEFUN (isis_network, if (isis_circuit_circ_type_set(circuit, CIRCUIT_T_P2P)) { vty_out(vty, "isis network point-to-point is valid only on broadcast interfaces\n"); - return CMD_ERR_AMBIGUOUS; + return CMD_WARNING_CONFIG_FAILED; } return CMD_SUCCESS; @@ -283,7 +283,7 @@ DEFUN (no_isis_network, if (isis_circuit_circ_type_set(circuit, CIRCUIT_T_BROADCAST)) { vty_out(vty, "isis network point-to-point is valid only on broadcast interfaces\n"); - return CMD_ERR_AMBIGUOUS; + return CMD_WARNING_CONFIG_FAILED; } return CMD_SUCCESS; @@ -313,7 +313,7 @@ DEFUN (isis_passwd, argv[idx_word]->arg); if (rv) { vty_out(vty, "Too long circuit password (>254)\n"); - return CMD_ERR_AMBIGUOUS; + return CMD_WARNING_CONFIG_FAILED; } return CMD_SUCCESS; @@ -355,7 +355,7 @@ DEFUN (isis_priority, prio = atoi(argv[idx_number]->arg); if (prio < MIN_PRIORITY || prio > MAX_PRIORITY) { vty_out(vty, "Invalid priority %d - should be <0-127>\n", prio); - return CMD_ERR_AMBIGUOUS; + return CMD_WARNING_CONFIG_FAILED; } circuit->priority[0] = prio; @@ -400,7 +400,7 @@ DEFUN (isis_priority_l1, prio = atoi(argv[idx_number]->arg); if (prio < MIN_PRIORITY || prio > MAX_PRIORITY) { vty_out(vty, "Invalid priority %d - should be <0-127>\n", prio); - return CMD_ERR_AMBIGUOUS; + return CMD_WARNING_CONFIG_FAILED; } circuit->priority[0] = prio; @@ -444,7 +444,7 @@ DEFUN (isis_priority_l2, prio = atoi(argv[idx_number]->arg); if (prio < MIN_PRIORITY || prio > MAX_PRIORITY) { vty_out(vty, "Invalid priority %d - should be <0-127>\n", prio); - return CMD_ERR_AMBIGUOUS; + return CMD_WARNING_CONFIG_FAILED; } circuit->priority[1] = prio; @@ -494,7 +494,7 @@ DEFUN (isis_metric, "Invalid metric %d - should be <0-63> " "when narrow metric type enabled\n", met); - return CMD_ERR_AMBIGUOUS; + return CMD_WARNING_CONFIG_FAILED; } /* RFC4444 */ @@ -504,7 +504,7 @@ DEFUN (isis_metric, "Invalid metric %d - should be <0-16777215> " "when wide metric type enabled\n", met); - return CMD_ERR_AMBIGUOUS; + return CMD_WARNING_CONFIG_FAILED; } isis_circuit_metric_set(circuit, IS_LEVEL_1, met); @@ -554,7 +554,7 @@ DEFUN (isis_metric_l1, "Invalid metric %d - should be <0-63> " "when narrow metric type enabled\n", met); - return CMD_ERR_AMBIGUOUS; + return CMD_WARNING_CONFIG_FAILED; } /* RFC4444 */ @@ -564,7 +564,7 @@ DEFUN (isis_metric_l1, "Invalid metric %d - should be <0-16777215> " "when wide metric type enabled\n", met); - return CMD_ERR_AMBIGUOUS; + return CMD_WARNING_CONFIG_FAILED; } isis_circuit_metric_set(circuit, IS_LEVEL_1, met); @@ -613,7 +613,7 @@ DEFUN (isis_metric_l2, "Invalid metric %d - should be <0-63> " "when narrow metric type enabled\n", met); - return CMD_ERR_AMBIGUOUS; + return CMD_WARNING_CONFIG_FAILED; } /* RFC4444 */ @@ -623,7 +623,7 @@ DEFUN (isis_metric_l2, "Invalid metric %d - should be <0-16777215> " "when wide metric type enabled\n", met); - return CMD_ERR_AMBIGUOUS; + return CMD_WARNING_CONFIG_FAILED; } isis_circuit_metric_set(circuit, IS_LEVEL_2, met); @@ -667,7 +667,7 @@ DEFUN (isis_hello_interval, if (interval < MIN_HELLO_INTERVAL || interval > MAX_HELLO_INTERVAL) { vty_out(vty, "Invalid hello-interval %d - should be <1-600>\n", interval); - return CMD_ERR_AMBIGUOUS; + return CMD_WARNING_CONFIG_FAILED; } circuit->hello_interval[0] = (u_int16_t)interval; @@ -714,7 +714,7 @@ DEFUN (isis_hello_interval_l1, if (interval < MIN_HELLO_INTERVAL || interval > MAX_HELLO_INTERVAL) { vty_out(vty, "Invalid hello-interval %ld - should be <1-600>\n", interval); - return CMD_ERR_AMBIGUOUS; + return CMD_WARNING_CONFIG_FAILED; } circuit->hello_interval[0] = (u_int16_t)interval; @@ -760,7 +760,7 @@ DEFUN (isis_hello_interval_l2, if (interval < MIN_HELLO_INTERVAL || interval > MAX_HELLO_INTERVAL) { vty_out(vty, "Invalid hello-interval %ld - should be <1-600>\n", interval); - return CMD_ERR_AMBIGUOUS; + return CMD_WARNING_CONFIG_FAILED; } circuit->hello_interval[1] = (u_int16_t)interval; @@ -806,7 +806,7 @@ DEFUN (isis_hello_multiplier, vty_out(vty, "Invalid hello-multiplier %d - should be <2-100>\n", mult); - return CMD_ERR_AMBIGUOUS; + return CMD_WARNING_CONFIG_FAILED; } circuit->hello_multiplier[0] = (u_int16_t)mult; @@ -854,7 +854,7 @@ DEFUN (isis_hello_multiplier_l1, vty_out(vty, "Invalid hello-multiplier %d - should be <2-100>\n", mult); - return CMD_ERR_AMBIGUOUS; + return CMD_WARNING_CONFIG_FAILED; } circuit->hello_multiplier[0] = (u_int16_t)mult; @@ -901,7 +901,7 @@ DEFUN (isis_hello_multiplier_l2, vty_out(vty, "Invalid hello-multiplier %d - should be <2-100>\n", mult); - return CMD_ERR_AMBIGUOUS; + return CMD_WARNING_CONFIG_FAILED; } circuit->hello_multiplier[1] = (u_int16_t)mult; @@ -979,7 +979,7 @@ DEFUN (csnp_interval, if (interval < MIN_CSNP_INTERVAL || interval > MAX_CSNP_INTERVAL) { vty_out(vty, "Invalid csnp-interval %lu - should be <1-600>\n", interval); - return CMD_ERR_AMBIGUOUS; + return CMD_WARNING_CONFIG_FAILED; } circuit->csnp_interval[0] = (u_int16_t)interval; @@ -1026,7 +1026,7 @@ DEFUN (csnp_interval_l1, if (interval < MIN_CSNP_INTERVAL || interval > MAX_CSNP_INTERVAL) { vty_out(vty, "Invalid csnp-interval %lu - should be <1-600>\n", interval); - return CMD_ERR_AMBIGUOUS; + return CMD_WARNING_CONFIG_FAILED; } circuit->csnp_interval[0] = (u_int16_t)interval; @@ -1072,7 +1072,7 @@ DEFUN (csnp_interval_l2, if (interval < MIN_CSNP_INTERVAL || interval > MAX_CSNP_INTERVAL) { vty_out(vty, "Invalid csnp-interval %lu - should be <1-600>\n", interval); - return CMD_ERR_AMBIGUOUS; + return CMD_WARNING_CONFIG_FAILED; } circuit->csnp_interval[1] = (u_int16_t)interval; @@ -1117,7 +1117,7 @@ DEFUN (psnp_interval, if (interval < MIN_PSNP_INTERVAL || interval > MAX_PSNP_INTERVAL) { vty_out(vty, "Invalid psnp-interval %lu - should be <1-120>\n", interval); - return CMD_ERR_AMBIGUOUS; + return CMD_WARNING_CONFIG_FAILED; } circuit->psnp_interval[0] = (u_int16_t)interval; @@ -1164,7 +1164,7 @@ DEFUN (psnp_interval_l1, if (interval < MIN_PSNP_INTERVAL || interval > MAX_PSNP_INTERVAL) { vty_out(vty, "Invalid psnp-interval %lu - should be <1-120>\n", interval); - return CMD_ERR_AMBIGUOUS; + return CMD_WARNING_CONFIG_FAILED; } circuit->psnp_interval[0] = (u_int16_t)interval; @@ -1210,7 +1210,7 @@ DEFUN (psnp_interval_l2, if (interval < MIN_PSNP_INTERVAL || interval > MAX_PSNP_INTERVAL) { vty_out(vty, "Invalid psnp-interval %lu - should be <1-120>\n", interval); - return CMD_ERR_AMBIGUOUS; + return CMD_WARNING_CONFIG_FAILED; } circuit->psnp_interval[1] = (u_int16_t)interval; @@ -1253,12 +1253,12 @@ DEFUN (circuit_topology, if (circuit->area && circuit->area->oldmetric) { vty_out(vty, "Multi topology IS-IS can only be used with wide metrics\n"); - return CMD_ERR_AMBIGUOUS; + return CMD_WARNING_CONFIG_FAILED; } if (mtid == (uint16_t)-1) { vty_out(vty, "Don't know topology '%s'\n", arg); - return CMD_ERR_AMBIGUOUS; + return CMD_WARNING_CONFIG_FAILED; } return isis_circuit_mt_enabled_set(circuit, mtid, true); @@ -1281,12 +1281,12 @@ DEFUN (no_circuit_topology, if (circuit->area && circuit->area->oldmetric) { vty_out(vty, "Multi topology IS-IS can only be used with wide metrics\n"); - return CMD_ERR_AMBIGUOUS; + return CMD_WARNING_CONFIG_FAILED; } if (mtid == (uint16_t)-1) { vty_out(vty, "Don't know topology '%s'\n", arg); - return CMD_ERR_AMBIGUOUS; + return CMD_WARNING_CONFIG_FAILED; } return isis_circuit_mt_enabled_set(circuit, mtid, false); @@ -1298,11 +1298,11 @@ static int validate_metric_style_narrow(struct vty *vty, struct isis_area *area) struct listnode *node; if (!vty) - return CMD_ERR_AMBIGUOUS; + return CMD_WARNING_CONFIG_FAILED; if (!area) { vty_out(vty, "ISIS area is invalid\n"); - return CMD_ERR_AMBIGUOUS; + return CMD_WARNING_CONFIG_FAILED; } for (ALL_LIST_ELEMENTS_RO(area->circuit_list, node, circuit)) { @@ -1311,14 +1311,14 @@ static int validate_metric_style_narrow(struct vty *vty, struct isis_area *area) && (circuit->te_metric[0] > MAX_NARROW_LINK_METRIC)) { vty_out(vty, "ISIS circuit %s metric is invalid\n", circuit->interface->name); - return CMD_ERR_AMBIGUOUS; + return CMD_WARNING_CONFIG_FAILED; } if ((area->is_type & IS_LEVEL_2) && (circuit->is_type & IS_LEVEL_2) && (circuit->te_metric[1] > MAX_NARROW_LINK_METRIC)) { vty_out(vty, "ISIS circuit %s metric is invalid\n", circuit->interface->name); - return CMD_ERR_AMBIGUOUS; + return CMD_WARNING_CONFIG_FAILED; } } @@ -1345,7 +1345,7 @@ DEFUN (metric_style, if (area_is_mt(area)) { vty_out(vty, "Narrow metrics cannot be used while multi topology IS-IS is active\n"); - return CMD_ERR_AMBIGUOUS; + return CMD_WARNING_CONFIG_FAILED; } ret = validate_metric_style_narrow(vty, area); @@ -1373,7 +1373,7 @@ DEFUN (no_metric_style, if (area_is_mt(area)) { vty_out(vty, "Narrow metrics cannot be used while multi topology IS-IS is active\n"); - return CMD_ERR_AMBIGUOUS; + return CMD_WARNING_CONFIG_FAILED; } ret = validate_metric_style_narrow(vty, area); @@ -1470,7 +1470,7 @@ static int area_lsp_mtu_set(struct vty *vty, unsigned int lsp_mtu) "ISIS area contains circuit %s, which has a maximum PDU size of %zu.\n", circuit->interface->name, isis_circuit_pdu_size(circuit)); - return CMD_ERR_AMBIGUOUS; + return CMD_WARNING_CONFIG_FAILED; } } @@ -1568,7 +1568,7 @@ static int set_lsp_gen_interval(struct vty *vty, struct isis_area *area, "LSP gen interval %us must be less than " "the LSP refresh interval %us\n", interval, area->lsp_refresh[lvl - 1]); - return CMD_ERR_AMBIGUOUS; + return CMD_WARNING_CONFIG_FAILED; } } @@ -1817,7 +1817,7 @@ static int area_max_lsp_lifetime_set(struct vty *vty, int level, "the configured LSP gen interval %us\n", refresh_interval, area->lsp_gen_interval[lvl - 1]); - return CMD_ERR_AMBIGUOUS; + return CMD_WARNING_CONFIG_FAILED; } } } @@ -1890,14 +1890,14 @@ static int area_lsp_refresh_interval_set(struct vty *vty, int level, "LSP refresh interval %us must be greater than " "the configured LSP gen interval %us\n", interval, area->lsp_gen_interval[lvl - 1]); - return CMD_ERR_AMBIGUOUS; + return CMD_WARNING_CONFIG_FAILED; } if (interval > (area->max_lsp_lifetime[lvl - 1] - 300)) { vty_out(vty, "LSP refresh interval %us must be less than " "the configured LSP lifetime %us less 300\n", interval, area->max_lsp_lifetime[lvl - 1]); - return CMD_ERR_AMBIGUOUS; + return CMD_WARNING_CONFIG_FAILED; } } @@ -1961,7 +1961,7 @@ static int area_passwd_set(struct vty *vty, int level, if (passwd && strlen(passwd) > 254) { vty_out(vty, "Too long area password (>254)\n"); - return CMD_ERR_AMBIGUOUS; + return CMD_WARNING_CONFIG_FAILED; } type_set(area, level, passwd, snp_auth); diff --git a/isisd/isisd.c b/isisd/isisd.c index dba34e8e35..f8a9df45c7 100644 --- a/isisd/isisd.c +++ b/isisd/isisd.c @@ -347,14 +347,14 @@ int area_net_title(struct vty *vty, const char *net_title) "area address must be at least 8..20 octets long (%d)\n", addr->addr_len); XFREE(MTYPE_ISIS_AREA_ADDR, addr); - return CMD_ERR_AMBIGUOUS; + return CMD_WARNING_CONFIG_FAILED; } if (addr->area_addr[addr->addr_len - 1] != 0) { vty_out(vty, "nsel byte (last byte) in area address must be 0\n"); XFREE(MTYPE_ISIS_AREA_ADDR, addr); - return CMD_ERR_AMBIGUOUS; + return CMD_WARNING_CONFIG_FAILED; } if (isis->sysid_set == 0) { @@ -374,7 +374,7 @@ int area_net_title(struct vty *vty, const char *net_title) vty_out(vty, "System ID must not change when defining additional area addresses\n"); XFREE(MTYPE_ISIS_AREA_ADDR, addr); - return CMD_ERR_AMBIGUOUS; + return CMD_WARNING_CONFIG_FAILED; } /* now we see that we don't already have this address */ @@ -419,7 +419,7 @@ int area_clear_net_title(struct vty *vty, const char *net_title) vty_out(vty, "Unsupported area address length %d, should be 8...20 \n", addr.addr_len); - return CMD_ERR_AMBIGUOUS; + return CMD_WARNING_CONFIG_FAILED; } memcpy(addr.area_addr, buff, (int)addr.addr_len); @@ -1405,7 +1405,7 @@ static int show_isis_database(struct vty *vty, const char *argv, int ui_level) (u_char)strtol((char *)number, NULL, 16); pos -= 4; if (strncmp(pos, ".", 1) != 0) - return CMD_ERR_AMBIGUOUS; + return CMD_WARNING; } if (strncmp(pos, ".", 1) == 0) { memcpy(number, ++pos, 2); @@ -1570,16 +1570,16 @@ DEFUN (isis_topology, if (area->oldmetric) { vty_out(vty, "Multi topology IS-IS can only be used with wide metrics\n"); - return CMD_ERR_AMBIGUOUS; + return CMD_WARNING_CONFIG_FAILED; } if (mtid == (uint16_t)-1) { vty_out(vty, "Don't know topology '%s'\n", arg); - return CMD_ERR_AMBIGUOUS; + return CMD_WARNING_CONFIG_FAILED; } if (mtid == ISIS_MT_IPV4_UNICAST) { vty_out(vty, "Cannot configure IPv4 unicast topology\n"); - return CMD_ERR_AMBIGUOUS; + return CMD_WARNING_CONFIG_FAILED; } area_set_mt_enabled(area, mtid, true); @@ -1603,16 +1603,16 @@ DEFUN (no_isis_topology, if (area->oldmetric) { vty_out(vty, "Multi topology IS-IS can only be used with wide metrics\n"); - return CMD_ERR_AMBIGUOUS; + return CMD_WARNING_CONFIG_FAILED; } if (mtid == (uint16_t)-1) { vty_out(vty, "Don't know topology '%s'\n", arg); - return CMD_ERR_AMBIGUOUS; + return CMD_WARNING_CONFIG_FAILED; } if (mtid == ISIS_MT_IPV4_UNICAST) { vty_out(vty, "Cannot configure IPv4 unicast topology\n"); - return CMD_ERR_AMBIGUOUS; + return CMD_WARNING_CONFIG_FAILED; } area_set_mt_enabled(area, mtid, false); From 325730733775c94ba54d769f49ca213df552ce6b Mon Sep 17 00:00:00 2001 From: Quentin Young Date: Tue, 22 Aug 2017 10:55:12 -0400 Subject: [PATCH 049/130] ospfd, ospf6d: cleanup some `no` commands Signed-off-by: Quentin Young --- ospf6d/ospf6_interface.c | 13 +++++++------ ospfd/ospf_vty.c | 11 +++++++---- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/ospf6d/ospf6_interface.c b/ospf6d/ospf6_interface.c index 1d17a1c233..c970e990c8 100644 --- a/ospf6d/ospf6_interface.c +++ b/ospf6d/ospf6_interface.c @@ -1171,8 +1171,7 @@ DEFUN (ipv6_ospf6_cost, IP6_STR OSPF6_STR "Interface cost\n" - "Outgoing metric of this interface\n" - ) + "Outgoing metric of this interface\n") { VTY_DECLVAR_CONTEXT(interface, ifp); int idx_number = 3; @@ -1206,12 +1205,12 @@ DEFUN (ipv6_ospf6_cost, DEFUN (no_ipv6_ospf6_cost, no_ipv6_ospf6_cost_cmd, - "no ipv6 ospf6 cost", + "no ipv6 ospf6 cost [(1-65535)]", NO_STR IP6_STR OSPF6_STR "Calculate interface cost from bandwidth\n" - ) + "Outgoing metric of this interface\n") { VTY_DECLVAR_CONTEXT(interface, ifp); struct ospf6_interface *oi; @@ -1654,11 +1653,13 @@ DEFUN (ipv6_ospf6_network, DEFUN (no_ipv6_ospf6_network, no_ipv6_ospf6_network_cmd, - "no ipv6 ospf6 network", + "no ipv6 ospf6 network []", NO_STR IP6_STR OSPF6_STR - "Set default network type\n") + "Set default network type\n" + "Specify OSPF6 broadcast network\n" + "Specify OSPF6 point-to-point network\n") { VTY_DECLVAR_CONTEXT(interface, ifp); struct ospf6_interface *oi; diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c index 47c4d0078c..87aef1ea97 100644 --- a/ospfd/ospf_vty.c +++ b/ospfd/ospf_vty.c @@ -1897,7 +1897,8 @@ DEFUN (no_ospf_area_filter_list, DEFUN (ospf_area_authentication_message_digest, ospf_area_authentication_message_digest_cmd, - "area authentication message-digest", + "[no] area authentication message-digest", + NO_STR "OSPF area parameters\n" "OSPF area ID in IP address format\n" "OSPF area ID as a decimal value\n" @@ -1914,7 +1915,7 @@ DEFUN (ospf_area_authentication_message_digest, area = ospf_area_get(ospf, area_id); ospf_area_display_format_set(ospf, area, format); - area->auth_type = OSPF_AUTH_CRYPTOGRAPHIC; + area->auth_type = strmatch(argv[0]->text, "no") ? OSPF_AUTH_NULL : OSPF_AUTH_CRYPTOGRAPHIC; return CMD_SUCCESS; } @@ -6887,10 +6888,12 @@ DEFUN (no_ip_ospf_transmit_delay, DEFUN_HIDDEN (no_ospf_transmit_delay, no_ospf_transmit_delay_cmd, - "no ospf transmit-delay", + "no ospf transmit-delay [(1-65535) [A.B.C.D]]", NO_STR "OSPF interface commands\n" - "Link state transmit delay\n") + "Link state transmit delay\n" + "Seconds\n" + "Address of interface") { return no_ip_ospf_transmit_delay(self, vty, argc, argv); } From feda3ca36c9d28af67b26336b41b1d839fb2d79f Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Tue, 22 Aug 2017 18:49:23 +0200 Subject: [PATCH 050/130] *: update git-reindent-branch.py - autodetect whether it's on master or stable/3.0 - grab .clang-format from master Signed-off-by: David Lamparter --- git-reindent-branch.py | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) 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') From 318cac96ef7e16a17fd1ab97b67ede5c07651c52 Mon Sep 17 00:00:00 2001 From: Daniel Walton Date: Tue, 22 Aug 2017 18:14:50 +0000 Subject: [PATCH 051/130] bgpd: Memory wasting in zebra by non used MPLS FECs Signed-off-by: Daniel Walton --- bgpd/bgp_route.c | 7 +++- bgpd/bgp_vty.c | 23 +----------- bgpd/bgpd.c | 95 ++++++++++++++++++++++++++++++++++++++---------- bgpd/bgpd.h | 4 ++ 4 files changed, 85 insertions(+), 44 deletions(-) diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index bb204b01f1..0c60231ded 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -2045,7 +2045,7 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_node *rn, * to do this upon changes to best path except of the label index * changes. */ - if (safi == SAFI_UNICAST) { + if (bgp->allocate_mpls_labels[afi][safi]) { if (new_select) { if (!old_select || bgp_label_index_differs(new_select, old_select) @@ -2066,8 +2066,11 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_node *rn, } else bgp_register_for_label(rn, new_select); } - } else if (CHECK_FLAG(rn->flags, BGP_NODE_REGISTERED_FOR_LABEL)) + } else if (CHECK_FLAG(rn->flags, BGP_NODE_REGISTERED_FOR_LABEL)) { bgp_unregister_for_label(rn); + } + } else if (CHECK_FLAG(rn->flags, BGP_NODE_REGISTERED_FOR_LABEL)) { + bgp_unregister_for_label(rn); } /* If best route remains the same and this is not due to user-initiated diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index 2e18a6d44f..f040ed9a08 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -7018,26 +7018,6 @@ static int bgp_show_summary(struct vty *vty, struct bgp *bgp, int afi, int safi, return CMD_SUCCESS; } -/* - * Return if we have a peer configured to use this afi/safi - */ -static int bgp_show_summary_afi_safi_peer_exists(struct bgp *bgp, int afi, - int safi) -{ - struct listnode *node; - struct peer *peer; - - for (ALL_LIST_ELEMENTS_RO(bgp->peer, node, peer)) { - if (!CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE)) - continue; - - if (peer->afc[afi][safi]) - return 1; - } - - return 0; -} - static void bgp_show_summary_afi_safi(struct vty *vty, struct bgp *bgp, int afi, int safi, u_char use_json, json_object *json) @@ -7056,8 +7036,7 @@ static void bgp_show_summary_afi_safi(struct vty *vty, struct bgp *bgp, int afi, if (safi_wildcard) safi = 1; /* SAFI_UNICAST */ while (safi < SAFI_MAX) { - if (bgp_show_summary_afi_safi_peer_exists(bgp, afi, - safi)) { + if (bgp_afi_safi_peer_exists(bgp, afi, safi)) { json_output = true; if (is_wildcard) { /* diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index 9d7c38c871..ba2e82a42e 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -1391,6 +1391,32 @@ void bgp_peer_conf_if_to_su_update(struct peer *peer) hash_get(peer->bgp->peerhash, peer, hash_alloc_intern); } +static void bgp_recalculate_afi_safi_bestpaths(struct bgp *bgp, afi_t afi, + safi_t safi) +{ + struct bgp_node *rn, *nrn; + + for (rn = bgp_table_top(bgp->rib[afi][safi]); rn; + rn = bgp_route_next(rn)) { + if (rn->info != NULL) { + /* Special handling for 2-level routing + * tables. */ + if (safi == SAFI_MPLS_VPN + || safi == SAFI_ENCAP + || safi == SAFI_EVPN) { + for (nrn = bgp_table_top(( + struct bgp_table + *)(rn->info)); + nrn; + nrn = bgp_route_next(nrn)) + bgp_process(bgp, nrn, + afi, safi); + } else + bgp_process(bgp, rn, afi, safi); + } + } +} + /* Force a bestpath recalculation for all prefixes. This is used * when 'bgp bestpath' commands are entered. */ @@ -1398,29 +1424,10 @@ void bgp_recalculate_all_bestpaths(struct bgp *bgp) { afi_t afi; safi_t safi; - struct bgp_node *rn, *nrn; for (afi = AFI_IP; afi < AFI_MAX; afi++) { for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) { - for (rn = bgp_table_top(bgp->rib[afi][safi]); rn; - rn = bgp_route_next(rn)) { - if (rn->info != NULL) { - /* Special handling for 2-level routing - * tables. */ - if (safi == SAFI_MPLS_VPN - || safi == SAFI_ENCAP - || safi == SAFI_EVPN) { - for (nrn = bgp_table_top(( - struct bgp_table - *)(rn->info)); - nrn; - nrn = bgp_route_next(nrn)) - bgp_process(bgp, nrn, - afi, safi); - } else - bgp_process(bgp, rn, afi, safi); - } - } + bgp_recalculate_afi_safi_bestpaths(bgp, afi, safi); } } } @@ -1500,6 +1507,25 @@ struct peer *peer_create_accept(struct bgp *bgp) return peer; } +/* + * Return true if we have a peer configured to use this afi/safi + */ +int bgp_afi_safi_peer_exists(struct bgp *bgp, afi_t afi, safi_t safi) +{ + struct listnode *node; + struct peer *peer; + + for (ALL_LIST_ELEMENTS_RO(bgp->peer, node, peer)) { + if (!CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE)) + continue; + + if (peer->afc[afi][safi]) + return 1; + } + + return 0; +} + /* Change peer's AS number. */ void peer_as_change(struct peer *peer, as_t as, int as_specified) { @@ -1714,11 +1740,14 @@ int peer_activate(struct peer *peer, afi_t afi, safi_t safi) struct peer_group *group; struct listnode *node, *nnode; struct peer *tmp_peer; + struct bgp *bgp; /* Nothing to do if we've already activated this peer */ if (peer->afc[afi][safi]) return ret; + bgp = peer->bgp; + /* This is a peer-group so activate all of the members of the * peer-group as well */ if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { @@ -1741,6 +1770,17 @@ int peer_activate(struct peer *peer, afi_t afi, safi_t safi) ret |= non_peergroup_activate_af(peer, afi, safi); } + /* If this is the first peer to be activated for this afi/labeled-unicast + * recalc bestpaths to trigger label allocation */ + if (safi == SAFI_LABELED_UNICAST && !bgp->allocate_mpls_labels[afi][SAFI_UNICAST]) { + + if (BGP_DEBUG(zebra, ZEBRA)) + zlog_info("peer(s) are now active for labeled-unicast, allocate MPLS labels"); + + bgp->allocate_mpls_labels[afi][SAFI_UNICAST] = 1; + bgp_recalculate_afi_safi_bestpaths(bgp, afi, SAFI_UNICAST); + } + return ret; } @@ -1798,6 +1838,7 @@ int peer_deactivate(struct peer *peer, afi_t afi, safi_t safi) struct peer_group *group; struct peer *tmp_peer; struct listnode *node, *nnode; + struct bgp *bgp; /* Nothing to do if we've already de-activated this peer */ if (!peer->afc[afi][safi]) @@ -1821,6 +1862,20 @@ int peer_deactivate(struct peer *peer, afi_t afi, safi_t safi) ret |= non_peergroup_deactivate_af(peer, afi, safi); } + bgp = peer->bgp; + + /* If this is the last peer to be deactivated for this afi/labeled-unicast + * recalc bestpaths to trigger label deallocation */ + if (safi == SAFI_LABELED_UNICAST && + bgp->allocate_mpls_labels[afi][SAFI_UNICAST] && + !bgp_afi_safi_peer_exists(bgp, afi, safi)) { + + if (BGP_DEBUG(zebra, ZEBRA)) + zlog_info("peer(s) are no longer active for labeled-unicast, deallocate MPLS labels"); + + bgp->allocate_mpls_labels[afi][SAFI_UNICAST] = 0; + bgp_recalculate_afi_safi_bestpaths(bgp, afi, SAFI_UNICAST); + } return ret; } diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h index f6e7b2277f..5ede9ba13d 100644 --- a/bgpd/bgpd.h +++ b/bgpd/bgpd.h @@ -333,6 +333,9 @@ struct bgp { /* BGP redistribute configuration. */ struct list *redist[AFI_MAX][ZEBRA_ROUTE_MAX]; + /* Allocate MPLS labels */ + u_char allocate_mpls_labels[AFI_MAX][SAFI_MAX]; + /* timer to re-evaluate neighbor default-originate route-maps */ struct thread *t_rmap_def_originate_eval; #define RMAP_DEFAULT_ORIGINATE_EVAL_TIMER 5 @@ -1280,6 +1283,7 @@ extern int bgp_listen_limit_unset(struct bgp *); extern int bgp_update_delay_active(struct bgp *); extern int bgp_update_delay_configured(struct bgp *); +extern int bgp_afi_safi_peer_exists(struct bgp *bgp, afi_t afi, safi_t safi); extern void peer_as_change(struct peer *, as_t, int); extern int peer_remote_as(struct bgp *, union sockunion *, const char *, as_t *, int, afi_t, safi_t); From 7b2ff250318a27a03937b1edae68ffbf06714eab Mon Sep 17 00:00:00 2001 From: Daniel Walton Date: Tue, 22 Aug 2017 19:11:31 +0000 Subject: [PATCH 052/130] bgpd: remove json option from 'sh ip bgp' commands that do not support it Signed-off-by: Daniel Walton --- bgpd/bgp_route.c | 114 +++++++++++++++++++++++++++++++---------------- 1 file changed, 75 insertions(+), 39 deletions(-) diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 0c60231ded..d54dec269c 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -8838,32 +8838,28 @@ DEFUN (show_ip_bgp_large_community, static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi); -/* BGP route print out function. */ + +/* BGP route print out function without JSON */ DEFUN (show_ip_bgp, show_ip_bgp_cmd, "show [ip] bgp [ VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]]\ - [<\ - cidr-only\ - |dampening \ - |route-map WORD\ - |prefix-list WORD\ - |filter-list WORD\ - |statistics\ - |community [ [exact-match]]\ - |community-list <(1-500)|WORD> [exact-match]\ - |A.B.C.D/M longer-prefixes\ - |X:X::X:X/M longer-prefixes>\ - ] [json]", + \ + |route-map WORD\ + |prefix-list WORD\ + |filter-list WORD\ + |statistics\ + |community [exact-match]\ + |community-list <(1-500)|WORD> [exact-match]\ + |A.B.C.D/M longer-prefixes\ + |X:X::X:X/M longer-prefixes\ + >", SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR BGP_SAFI_WITH_LABEL_HELP_STR - "Display only routes with non-natural netmasks\n" "Display detailed information about dampening\n" - "Display flap statistics of routes\n" - "Display paths suppressed due to dampening\n" "Display detail of configured dampening parameters\n" "Display routes matching the route-map\n" "A route-map to match on\n" @@ -8885,13 +8881,11 @@ DEFUN (show_ip_bgp, "IPv4 prefix\n" "Display route and more specific routes\n" "IPv6 prefix\n" - "Display route and more specific routes\n" - JSON_STR) + "Display route and more specific routes\n") { afi_t afi = AFI_IP6; safi_t safi = SAFI_UNICAST; int exact_match = 0; - enum bgp_show_type sh_type = bgp_show_type_normal; struct bgp *bgp = NULL; int idx = 0; @@ -8900,23 +8894,8 @@ DEFUN (show_ip_bgp, if (!idx) return CMD_WARNING; - int uj = use_json(argc, argv); - if (uj) - argc--; - - if (argv_find(argv, argc, "cidr-only", &idx)) - return bgp_show(vty, bgp, afi, safi, bgp_show_type_cidr_only, - NULL, uj); - if (argv_find(argv, argc, "dampening", &idx)) { - if (argv_find(argv, argc, "dampened-paths", &idx)) - return bgp_show(vty, bgp, afi, safi, - bgp_show_type_dampend_paths, NULL, uj); - else if (argv_find(argv, argc, "flap-statistics", &idx)) - return bgp_show(vty, bgp, afi, safi, - bgp_show_type_flap_statistics, NULL, - uj); - else if (argv_find(argv, argc, "parameters", &idx)) + if (argv_find(argv, argc, "parameters", &idx)) return bgp_show_dampening_parameters(vty, afi, safi); } @@ -8945,10 +8924,6 @@ DEFUN (show_ip_bgp, return bgp_show_community(vty, bgp, argc, argv, exact_match, afi, safi); } - /* show all communities */ - else - return bgp_show(vty, bgp, afi, safi, - bgp_show_type_community_all, NULL, uj); } if (argv_find(argv, argc, "community-list", &idx)) { @@ -8965,6 +8940,66 @@ DEFUN (show_ip_bgp, safi, bgp_show_type_prefix_longer); + return CMD_WARNING; +} + +/* BGP route print out function with JSON */ +DEFUN (show_ip_bgp_json, + show_ip_bgp_json_cmd, + "show [ip] bgp [ VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]]\ + [<\ + cidr-only\ + |dampening \ + |community \ + >] [json]", + SHOW_STR + IP_STR + BGP_STR + BGP_INSTANCE_HELP_STR + BGP_AFI_HELP_STR + BGP_SAFI_WITH_LABEL_HELP_STR + "Display only routes with non-natural netmasks\n" + "Display detailed information about dampening\n" + "Display flap statistics of routes\n" + "Display paths suppressed due to dampening\n" + "Display routes matching the communities\n" + JSON_STR) +{ + afi_t afi = AFI_IP6; + safi_t safi = SAFI_UNICAST; + enum bgp_show_type sh_type = bgp_show_type_normal; + struct bgp *bgp = NULL; + int idx = 0; + + bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi, + &bgp); + if (!idx) + return CMD_WARNING; + + int uj = use_json(argc, argv); + if (uj) + argc--; + + if (argv_find(argv, argc, "cidr-only", &idx)) + return bgp_show(vty, bgp, afi, safi, bgp_show_type_cidr_only, + NULL, uj); + + if (argv_find(argv, argc, "dampening", &idx)) { + if (argv_find(argv, argc, "dampened-paths", &idx)) + return bgp_show(vty, bgp, afi, safi, + bgp_show_type_dampend_paths, NULL, uj); + else if (argv_find(argv, argc, "flap-statistics", &idx)) + return bgp_show(vty, bgp, afi, safi, + bgp_show_type_flap_statistics, NULL, + uj); + } + + if (argv_find(argv, argc, "community", &idx)) { + /* show all communities */ + return bgp_show(vty, bgp, afi, safi, + bgp_show_type_community_all, NULL, uj); + } + if (safi == SAFI_MPLS_VPN) return bgp_show_mpls_vpn(vty, afi, NULL, bgp_show_type_normal, NULL, 0, uj); @@ -11283,6 +11318,7 @@ void bgp_route_init(void) /* IPv4 labeled-unicast configuration. */ install_element(VIEW_NODE, &show_ip_bgp_instance_all_cmd); install_element(VIEW_NODE, &show_ip_bgp_cmd); + install_element(VIEW_NODE, &show_ip_bgp_json_cmd); install_element(VIEW_NODE, &show_ip_bgp_route_cmd); install_element(VIEW_NODE, &show_ip_bgp_regexp_cmd); From e889891d8b543a93521e4d15a51770daf482b979 Mon Sep 17 00:00:00 2001 From: Daniel Walton Date: Tue, 22 Aug 2017 19:33:22 +0000 Subject: [PATCH 053/130] bgpd: 'show ip bgp regex' needs to be VRF aware Signed-off-by: Daniel Walton --- bgpd/bgp_route.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index d54dec269c..cc9e902eb1 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -8020,7 +8020,8 @@ static int bgp_show_community_list(struct vty *vty, struct bgp *bgp, static int bgp_show_prefix_longer(struct vty *vty, struct bgp *bgp, const char *prefix, afi_t afi, safi_t safi, enum bgp_show_type type); -static int bgp_show_regexp(struct vty *vty, const char *regstr, afi_t afi, +static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, + const char *regstr, afi_t afi, safi_t safi, enum bgp_show_type type); static int bgp_show_community(struct vty *vty, struct bgp *bgp, int argc, struct cmd_token **argv, int exact, afi_t afi, @@ -9109,7 +9110,7 @@ DEFUN (show_ip_bgp_regexp, idx++; char *regstr = argv_concat(argv, argc, idx); - int rc = bgp_show_regexp(vty, (const char *)regstr, afi, safi, + int rc = bgp_show_regexp(vty, bgp, (const char *)regstr, afi, safi, bgp_show_type_regexp); XFREE(MTYPE_TMP, regstr); return rc; @@ -9144,7 +9145,8 @@ DEFUN (show_ip_bgp_instance_all, return CMD_SUCCESS; } -static int bgp_show_regexp(struct vty *vty, const char *regstr, afi_t afi, +static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, + const char *regstr, afi_t afi, safi_t safi, enum bgp_show_type type) { regex_t *regex; @@ -9156,7 +9158,7 @@ static int bgp_show_regexp(struct vty *vty, const char *regstr, afi_t afi, return CMD_WARNING; } - rc = bgp_show(vty, NULL, afi, safi, type, regex, 0); + rc = bgp_show(vty, bgp, afi, safi, type, regex, 0); bgp_regex_free(regex); return rc; } From d23d6de866561418be6aab0298301a4aa558b538 Mon Sep 17 00:00:00 2001 From: Quentin Young Date: Tue, 22 Aug 2017 12:29:53 -0400 Subject: [PATCH 054/130] ospf6d: add `no` forms for interface commands Signed-off-by: Quentin Young --- ospf6d/ospf6_interface.c | 108 +++++++++++++++++++++++++++++++-------- 1 file changed, 87 insertions(+), 21 deletions(-) diff --git a/ospf6d/ospf6_interface.c b/ospf6d/ospf6_interface.c index c970e990c8..bb63fb966e 100644 --- a/ospf6d/ospf6_interface.c +++ b/ospf6d/ospf6_interface.c @@ -1291,8 +1291,7 @@ DEFUN (ipv6_ospf6_hellointerval, IP6_STR OSPF6_STR "Time between HELLO packets\n" - SECONDS_STR - ) + SECONDS_STR) { VTY_DECLVAR_CONTEXT(interface, ifp); int idx_number = 3; @@ -1304,10 +1303,21 @@ DEFUN (ipv6_ospf6_hellointerval, oi = ospf6_interface_create(ifp); assert(oi); - oi->hello_interval = strtol(argv[idx_number]->arg, NULL, 10); + oi->hello_interval = strmatch(argv[0]->text, "no") + ? OSPF_HELLO_INTERVAL_DEFAULT + : strtoul(argv[idx_number]->arg, NULL, 10); return CMD_SUCCESS; } +ALIAS (ipv6_ospf6_hellointerval, + no_ipv6_ospf6_hellointerval_cmd, + "no ipv6 ospf6 hello-interval [(1-65535)]", + NO_STR + IP6_STR + OSPF6_STR + "Time between HELLO packets\n" + SECONDS_STR) + /* interface variable set command */ DEFUN (ipv6_ospf6_deadinterval, ipv6_ospf6_deadinterval_cmd, @@ -1315,8 +1325,7 @@ DEFUN (ipv6_ospf6_deadinterval, IP6_STR OSPF6_STR "Interval time after which a neighbor is declared down\n" - SECONDS_STR - ) + SECONDS_STR) { VTY_DECLVAR_CONTEXT(interface, ifp); int idx_number = 3; @@ -1328,10 +1337,21 @@ DEFUN (ipv6_ospf6_deadinterval, oi = ospf6_interface_create(ifp); assert(oi); - oi->dead_interval = strtol(argv[idx_number]->arg, NULL, 10); + oi->dead_interval = strmatch(argv[0]->arg, "no") + ? OSPF_ROUTER_DEAD_INTERVAL_DEFAULT + : strtoul(argv[idx_number]->arg, NULL, 10); return CMD_SUCCESS; } +ALIAS (ipv6_ospf6_deadinterval, + no_ipv6_ospf6_deadinterval_cmd, + "no ipv6 ospf6 dead-interval [(1-65535)]", + NO_STR + IP6_STR + OSPF6_STR + "Interval time after which a neighbor is declared down\n" + SECONDS_STR) + /* interface variable set command */ DEFUN (ipv6_ospf6_transmitdelay, ipv6_ospf6_transmitdelay_cmd, @@ -1351,10 +1371,21 @@ DEFUN (ipv6_ospf6_transmitdelay, oi = ospf6_interface_create(ifp); assert(oi); - oi->transdelay = strtol(argv[idx_number]->arg, NULL, 10); + oi->transdelay = strmatch(argv[0]->text, "no") + ? OSPF6_INTERFACE_TRANSDELAY + : strtoul(argv[idx_number]->arg, NULL, 10); return CMD_SUCCESS; } +ALIAS (ipv6_ospf6_transmitdelay, + no_ipv6_ospf6_transmitdelay_cmd, + "no ipv6 ospf6 transmit-delay [(1-3600)]", + NO_STR + IP6_STR + OSPF6_STR + "Link state transmit delay\n" + SECONDS_STR) + /* interface variable set command */ DEFUN (ipv6_ospf6_retransmitinterval, ipv6_ospf6_retransmitinterval_cmd, @@ -1362,8 +1393,7 @@ DEFUN (ipv6_ospf6_retransmitinterval, IP6_STR OSPF6_STR "Time between retransmitting lost link state advertisements\n" - SECONDS_STR - ) + SECONDS_STR) { VTY_DECLVAR_CONTEXT(interface, ifp); int idx_number = 3; @@ -1375,10 +1405,21 @@ DEFUN (ipv6_ospf6_retransmitinterval, oi = ospf6_interface_create(ifp); assert(oi); - oi->rxmt_interval = strtol(argv[idx_number]->arg, NULL, 10); + oi->rxmt_interval = strmatch(argv[0]->text, "no") + ? OSPF_RETRANSMIT_INTERVAL_DEFAULT + : strtoul(argv[idx_number]->arg, NULL, 10); return CMD_SUCCESS; } +ALIAS (ipv6_ospf6_retransmitinterval, + no_ipv6_ospf6_retransmitinterval_cmd, + "no ipv6 ospf6 retransmit-interval [(1-65535)]", + NO_STR + IP6_STR + OSPF6_STR + "Time between retransmitting lost link state advertisements\n" + SECONDS_STR) + /* interface variable set command */ DEFUN (ipv6_ospf6_priority, ipv6_ospf6_priority_cmd, @@ -1386,8 +1427,7 @@ DEFUN (ipv6_ospf6_priority, IP6_STR OSPF6_STR "Router priority\n" - "Priority value\n" - ) + "Priority value\n") { VTY_DECLVAR_CONTEXT(interface, ifp); int idx_number = 3; @@ -1399,7 +1439,9 @@ DEFUN (ipv6_ospf6_priority, oi = ospf6_interface_create(ifp); assert(oi); - oi->priority = strtol(argv[idx_number]->arg, NULL, 10); + oi->priority = strmatch(argv[0]->text, "no") + ? OSPF6_INTERFACE_PRIORITY + : strtoul(argv[idx_number]->arg, NULL, 10); if (oi->area && (oi->state == OSPF6_INTERFACE_DROTHER || oi->state == OSPF6_INTERFACE_BDR @@ -1409,14 +1451,22 @@ DEFUN (ipv6_ospf6_priority, return CMD_SUCCESS; } +ALIAS (ipv6_ospf6_priority, + no_ipv6_ospf6_priority_cmd, + "no ipv6 ospf6 priority [(0-255)]", + NO_STR + IP6_STR + OSPF6_STR + "Router priority\n" + "Priority value\n") + DEFUN (ipv6_ospf6_instance, ipv6_ospf6_instance_cmd, "ipv6 ospf6 instance-id (0-255)", IP6_STR OSPF6_STR "Instance ID for this interface\n" - "Instance ID value\n" - ) + "Instance ID value\n") { VTY_DECLVAR_CONTEXT(interface, ifp); int idx_number = 3; @@ -1428,10 +1478,21 @@ DEFUN (ipv6_ospf6_instance, oi = ospf6_interface_create(ifp); assert(oi); - oi->instance_id = strtol(argv[idx_number]->arg, NULL, 10); + oi->instance_id = strmatch(argv[0]->text, "no") + ? OSPF6_INTERFACE_INSTANCE_ID + : strtoul(argv[idx_number]->arg, NULL, 10); return CMD_SUCCESS; } +ALIAS (ipv6_ospf6_instance, + no_ipv6_ospf6_instance_cmd, + "no ipv6 ospf6 instance-id [(0-255)]", + NO_STR + IP6_STR + OSPF6_STR + "Instance ID for this interface\n" + "Instance ID value\n") + DEFUN (ipv6_ospf6_passive, ipv6_ospf6_passive_cmd, "ipv6 ospf6 passive", @@ -1575,13 +1636,13 @@ DEFUN (ipv6_ospf6_advertise_prefix_list, DEFUN (no_ipv6_ospf6_advertise_prefix_list, no_ipv6_ospf6_advertise_prefix_list_cmd, - "no ipv6 ospf6 advertise prefix-list", + "no ipv6 ospf6 advertise prefix-list [WORD]", NO_STR IP6_STR OSPF6_STR "Advertising options\n" "Filter prefix using prefix-list\n" - ) + "Prefix list name\n") { VTY_DECLVAR_CONTEXT(interface, ifp); struct ospf6_interface *oi; @@ -1592,10 +1653,8 @@ DEFUN (no_ipv6_ospf6_advertise_prefix_list, oi = ospf6_interface_create(ifp); assert(oi); - if (oi->plist_name) { + if (oi->plist_name) XFREE(MTYPE_CFG_PLIST_NAME, oi->plist_name); - oi->plist_name = NULL; - } ospf6_interface_connected_route_update(oi->interface); @@ -1773,12 +1832,19 @@ void ospf6_interface_init(void) install_element(INTERFACE_NODE, &no_ipv6_ospf6_cost_cmd); install_element(INTERFACE_NODE, &ipv6_ospf6_ifmtu_cmd); install_element(INTERFACE_NODE, &no_ipv6_ospf6_ifmtu_cmd); + install_element(INTERFACE_NODE, &ipv6_ospf6_deadinterval_cmd); install_element(INTERFACE_NODE, &ipv6_ospf6_hellointerval_cmd); install_element(INTERFACE_NODE, &ipv6_ospf6_priority_cmd); install_element(INTERFACE_NODE, &ipv6_ospf6_retransmitinterval_cmd); install_element(INTERFACE_NODE, &ipv6_ospf6_transmitdelay_cmd); install_element(INTERFACE_NODE, &ipv6_ospf6_instance_cmd); + install_element(INTERFACE_NODE, &no_ipv6_ospf6_deadinterval_cmd); + install_element(INTERFACE_NODE, &no_ipv6_ospf6_hellointerval_cmd); + install_element(INTERFACE_NODE, &no_ipv6_ospf6_priority_cmd); + install_element(INTERFACE_NODE, &no_ipv6_ospf6_retransmitinterval_cmd); + install_element(INTERFACE_NODE, &no_ipv6_ospf6_transmitdelay_cmd); + install_element(INTERFACE_NODE, &no_ipv6_ospf6_instance_cmd); install_element(INTERFACE_NODE, &ipv6_ospf6_passive_cmd); install_element(INTERFACE_NODE, &no_ipv6_ospf6_passive_cmd); From 5e8c8947e3fb53d2fdbdf804c6014d6ecdb0b904 Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Tue, 22 Aug 2017 17:01:54 -0300 Subject: [PATCH 055/130] zebra: increase maximum label stack depth * Bump MPLS_MAX_LABELS from 2 to 16; * Adjust the static_nh_label structure and the mpls_label2str() function; * On OpenBSD, print an error message when trying to push more than one label at once (kernel limitation). While here, add support for MPLSv6 FTNs in OpenBSD. This is not the full package. We still can't pop multiple labels at once, or do things like swap a label and push other ones. We'll address that in the future. Signed-off-by: Renato Westphal --- zebra/rt_socket.c | 48 ++++++++++++++++++++++++++++++-------- zebra/zebra_mpls.c | 31 ++++++++++-------------- zebra/zebra_mpls.h | 2 +- zebra/zebra_mpls_openbsd.c | 9 +++++++ zebra/zebra_static.h | 4 +++- 5 files changed, 63 insertions(+), 31 deletions(-) diff --git a/zebra/rt_socket.c b/zebra/rt_socket.c index 4e4d726b46..32ae41b917 100644 --- a/zebra/rt_socket.c +++ b/zebra/rt_socket.c @@ -71,6 +71,27 @@ static int sin_masklen(struct in_addr mask) } #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */ +#ifdef __OpenBSD__ +static int kernel_rtm_add_labels(struct nexthop_label *nh_label, + struct sockaddr_mpls *smpls) +{ + if (nh_label->num_labels > 1) { + zlog_warn( + "%s: can't push %u labels at " + "once (maximum is 1)", + __func__, nh_label->num_labels); + return -1; + } + + memset(smpls, 0, sizeof(*smpls)); + smpls->smpls_len = sizeof(*smpls); + smpls->smpls_family = AF_MPLS; + smpls->smpls_label = htonl(nh_label->label[0] << MPLS_LABEL_OFFSET); + + return 0; +} +#endif + /* Interface between zebra message and rtm message. */ static int kernel_rtm_ipv4(int cmd, struct prefix *p, struct route_entry *re) @@ -150,15 +171,11 @@ static int kernel_rtm_ipv4(int cmd, struct prefix *p, struct route_entry *re) } #ifdef __OpenBSD__ - if (nexthop->nh_label) { - memset(&smpls, 0, sizeof(smpls)); - smpls.smpls_len = sizeof(smpls); - smpls.smpls_family = AF_MPLS; - smpls.smpls_label = - htonl(nexthop->nh_label->label[0] - << MPLS_LABEL_OFFSET); - smplsp = (union sockunion *)&smpls; - } + if (nexthop->nh_label + && !kernel_rtm_add_labels(nexthop->nh_label, + &smpls)) + continue; + smplsp = (union sockunion *)&smpls; #endif error = rtm_write( @@ -266,6 +283,10 @@ static int kernel_rtm_ipv6(int cmd, struct prefix *p, struct route_entry *re) { struct sockaddr_in6 *mask; struct sockaddr_in6 sin_dest, sin_mask, sin_gate; +#ifdef __OpenBSD__ + struct sockaddr_mpls smpls; +#endif + union sockunion *smplsp = NULL; struct nexthop *nexthop; int nexthop_num = 0; ifindex_t ifindex = 0; @@ -338,10 +359,17 @@ static int kernel_rtm_ipv6(int cmd, struct prefix *p, struct route_entry *re) mask = &sin_mask; } +#ifdef __OpenBSD__ + if (nexthop->nh_label + && !kernel_rtm_add_labels(nexthop->nh_label, &smpls)) + continue; + smplsp = (union sockunion *)&smpls; +#endif + error = rtm_write(cmd, (union sockunion *)&sin_dest, (union sockunion *)mask, gate ? (union sockunion *)&sin_gate : NULL, - NULL, ifindex, re->flags, re->metric); + smplsp, ifindex, re->flags, re->metric); #if 0 if (error) diff --git a/zebra/zebra_mpls.c b/zebra/zebra_mpls.c index 47cf7a3cbf..cee3a03858 100644 --- a/zebra/zebra_mpls.c +++ b/zebra/zebra_mpls.c @@ -1671,27 +1671,20 @@ int mpls_str2label(const char *label_str, u_int8_t *num_labels, char *mpls_label2str(u_int8_t num_labels, mpls_label_t *labels, char *buf, int len, int pretty) { - char *buf_ptr = buf; + char label_buf[BUFSIZ]; + int i; + buf[0] = '\0'; - - if (pretty) { - if (num_labels == 1) { - label2str(labels[0], buf, len); - } else if (num_labels == 2) { - label2str(labels[0], buf, len); - buf_ptr += strlen(buf); - - snprintf(buf_ptr, len, "/"); - buf_ptr++; - - label2str(labels[1], buf_ptr, len); - } - } else { - if (num_labels == 1) - snprintf(buf, len, "%u", labels[0]); - else if (num_labels == 2) - snprintf(buf, len, "%u/%u", labels[0], labels[1]); + for (i = 0; i < num_labels; i++) { + if (i != 0) + strlcat(buf, "/", len); + if (pretty) + label2str(labels[i], label_buf, sizeof(label_buf)); + else + snprintf(label_buf, sizeof(label_buf), "%u", labels[i]); + strlcat(buf, label_buf, len); } + return buf; } diff --git a/zebra/zebra_mpls.h b/zebra/zebra_mpls.h index c8dab39210..6bddc4d00f 100644 --- a/zebra/zebra_mpls.h +++ b/zebra/zebra_mpls.h @@ -37,7 +37,7 @@ /* Definitions and macros. */ -#define MPLS_MAX_LABELS 2 /* Maximum # labels that can be pushed. */ +#define MPLS_MAX_LABELS 16 /* Maximum # labels that can be pushed. */ #define NHLFE_FAMILY(nhlfe) \ (((nhlfe)->nexthop->type == NEXTHOP_TYPE_IPV6 \ diff --git a/zebra/zebra_mpls_openbsd.c b/zebra/zebra_mpls_openbsd.c index 119cd5b700..33f0d49d4d 100644 --- a/zebra/zebra_mpls_openbsd.c +++ b/zebra/zebra_mpls_openbsd.c @@ -256,6 +256,15 @@ static int kernel_lsp_cmd(int action, zebra_lsp_t *lsp) || (action == RTM_DELETE && (CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_INSTALLED) && CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB)))) { + if (nhlfe->nexthop->nh_label->num_labels > 1) { + zlog_warn( + "%s: can't push %u labels at once " + "(maximum is 1)", + __func__, + nhlfe->nexthop->nh_label->num_labels); + continue; + } + nexthop_num++; switch (NHLFE_FAMILY(nhlfe)) { diff --git a/zebra/zebra_static.h b/zebra/zebra_static.h index 6ab47094a1..ff9f0f59e7 100644 --- a/zebra/zebra_static.h +++ b/zebra/zebra_static.h @@ -22,11 +22,13 @@ #ifndef __ZEBRA_STATIC_H__ #define __ZEBRA_STATIC_H__ +#include "zebra/zebra_mpls.h" + /* Static route label information */ struct static_nh_label { u_int8_t num_labels; u_int8_t reserved[3]; - mpls_label_t label[2]; + mpls_label_t label[MPLS_MAX_LABELS]; }; typedef enum { From 5ecf5540097c30ab0b02b3ac18133b17e660c9db Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Tue, 22 Aug 2017 20:09:26 -0300 Subject: [PATCH 056/130] bgpd: fix file descriptor leak Bug introduced by commit 37d361e7. Removing the call to bgp_close() from bgp_delete() was a mistake. Reported-by: Don Slice Signed-off-by: Renato Westphal --- bgpd/bgpd.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index 9d7c38c871..e3650417fa 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -3087,6 +3087,8 @@ int bgp_delete(struct bgp *bgp) * routes to be processed still referencing the struct bgp. */ listnode_delete(bm->bgp, bgp); + if (list_isempty(bm->bgp)) + bgp_close(); /* Deregister from Zebra, if needed */ if (IS_BGP_INST_KNOWN_TO_ZEBRA(bgp)) From 9d1c2659293a757a672bf0aa0d2f5ca20a2b28e5 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Wed, 23 Aug 2017 15:48:36 +0200 Subject: [PATCH 057/130] zebra: don't print 0.0.0.0:0 for FPM config Fixes: #319 Signed-off-by: David Lamparter --- zebra/zebra_fpm.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) 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); From d00061ea32901096fa4c3af6b9e65914dd895031 Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Sat, 12 Aug 2017 13:03:29 -0300 Subject: [PATCH 058/130] *: reduce excessive indentation in a few places Signed-off-by: Renato Westphal --- eigrpd/eigrp_zebra.c | 122 ++++++------- isisd/isis_zebra.c | 130 +++++++------- ospf6d/ospf6_zebra.c | 124 ++++++------- ospfd/ospf_zebra.c | 401 +++++++++++++++++++++---------------------- ripd/rip_zebra.c | 189 ++++++++++---------- ripngd/ripng_zebra.c | 177 ++++++++++--------- 6 files changed, 569 insertions(+), 574 deletions(-) diff --git a/eigrpd/eigrp_zebra.c b/eigrpd/eigrp_zebra.c index 1ee1237f75..00b269b489 100644 --- a/eigrpd/eigrp_zebra.c +++ b/eigrpd/eigrp_zebra.c @@ -398,81 +398,83 @@ void eigrp_zebra_route_add(struct prefix_ipv4 *p, struct list *successors) int psize; struct stream *s; - if (zclient->redist[AFI_IP][ZEBRA_ROUTE_EIGRP]) { - message = 0; - flags = 0; + if (!zclient->redist[AFI_IP][ZEBRA_ROUTE_EIGRP]) + return; - /* EIGRP pass nexthop and metric */ - SET_FLAG(message, ZAPI_MESSAGE_NEXTHOP); + message = 0; + flags = 0; - /* Make packet. */ - s = zclient->obuf; - stream_reset(s); + /* EIGRP pass nexthop and metric */ + SET_FLAG(message, ZAPI_MESSAGE_NEXTHOP); - /* Put command, type, flags, message. */ - zclient_create_header(s, ZEBRA_IPV4_ROUTE_ADD, VRF_DEFAULT); - stream_putc(s, ZEBRA_ROUTE_EIGRP); - stream_putw(s, 0); - stream_putl(s, flags); - stream_putc(s, message); - stream_putw(s, SAFI_UNICAST); + /* Make packet. */ + s = zclient->obuf; + stream_reset(s); - /* Put prefix information. */ - psize = PSIZE(p->prefixlen); - stream_putc(s, p->prefixlen); - stream_write(s, (u_char *)&p->prefix, psize); + /* Put command, type, flags, message. */ + zclient_create_header(s, ZEBRA_IPV4_ROUTE_ADD, VRF_DEFAULT); + stream_putc(s, ZEBRA_ROUTE_EIGRP); + stream_putw(s, 0); + stream_putl(s, flags); + stream_putc(s, message); + stream_putw(s, SAFI_UNICAST); - /* Nexthop count. */ - stream_putc(s, successors->count); + /* Put prefix information. */ + psize = PSIZE(p->prefixlen); + stream_putc(s, p->prefixlen); + stream_write(s, (u_char *)&p->prefix, psize); - /* Nexthop, ifindex, distance and metric information. */ - for (ALL_LIST_ELEMENTS_RO(successors, node, te)) { - if (te->adv_router->src.s_addr) { - stream_putc(s, NEXTHOP_TYPE_IPV4_IFINDEX); - stream_put_in_addr(s, &te->adv_router->src); - } else - stream_putc(s, NEXTHOP_TYPE_IFINDEX); - stream_putl(s, te->ei->ifp->ifindex); - } + /* Nexthop count. */ + stream_putc(s, successors->count); - if (IS_DEBUG_EIGRP(zebra, ZEBRA_REDISTRIBUTE)) { - char buf[2][INET_ADDRSTRLEN]; - zlog_debug("Zebra: Route add %s/%d nexthop %s", - inet_ntop(AF_INET, &p->prefix, buf[0], - sizeof(buf[0])), - p->prefixlen, - inet_ntop(AF_INET, 0 /*&p->nexthop*/, buf[1], - sizeof(buf[1]))); - } - - stream_putw_at(s, 0, stream_get_endp(s)); - - zclient_send_message(zclient); + /* Nexthop, ifindex, distance and metric information. */ + for (ALL_LIST_ELEMENTS_RO(successors, node, te)) { + if (te->adv_router->src.s_addr) { + stream_putc(s, NEXTHOP_TYPE_IPV4_IFINDEX); + stream_put_in_addr(s, &te->adv_router->src); + } else + stream_putc(s, NEXTHOP_TYPE_IFINDEX); + stream_putl(s, te->ei->ifp->ifindex); } + + if (IS_DEBUG_EIGRP(zebra, ZEBRA_REDISTRIBUTE)) { + char buf[2][INET_ADDRSTRLEN]; + zlog_debug("Zebra: Route add %s/%d nexthop %s", + inet_ntop(AF_INET, &p->prefix, buf[0], + sizeof(buf[0])), + p->prefixlen, + inet_ntop(AF_INET, 0 /*&p->nexthop*/, buf[1], + sizeof(buf[1]))); + } + + stream_putw_at(s, 0, stream_get_endp(s)); + + zclient_send_message(zclient); } void eigrp_zebra_route_delete(struct prefix_ipv4 *p) { struct zapi_ipv4 api; - if (zclient->redist[AFI_IP][ZEBRA_ROUTE_EIGRP]) { - api.vrf_id = VRF_DEFAULT; - api.type = ZEBRA_ROUTE_EIGRP; - api.instance = 0; - api.flags = 0; - api.message = 0; - api.safi = SAFI_UNICAST; - zapi_ipv4_route(ZEBRA_IPV4_ROUTE_DELETE, zclient, p, &api); + if (!zclient->redist[AFI_IP][ZEBRA_ROUTE_EIGRP]) + return; - if (IS_DEBUG_EIGRP(zebra, ZEBRA_REDISTRIBUTE)) { - char buf[2][INET_ADDRSTRLEN]; - zlog_debug("Zebra: Route del %s/%d nexthop %s", - inet_ntop(AF_INET, &p->prefix, buf[0], - sizeof(buf[0])), - p->prefixlen, - inet_ntop(AF_INET, 0 /*&p->nexthop*/, buf[1], - sizeof(buf[1]))); - } + api.vrf_id = VRF_DEFAULT; + api.type = ZEBRA_ROUTE_EIGRP; + api.instance = 0; + api.flags = 0; + api.message = 0; + api.safi = SAFI_UNICAST; + zapi_ipv4_route(ZEBRA_IPV4_ROUTE_DELETE, zclient, p, &api); + + if (IS_DEBUG_EIGRP(zebra, ZEBRA_REDISTRIBUTE)) { + char buf[2][INET_ADDRSTRLEN]; + zlog_debug("Zebra: Route del %s/%d nexthop %s", + inet_ntop(AF_INET, &p->prefix, buf[0], + sizeof(buf[0])), + p->prefixlen, + inet_ntop(AF_INET, 0 /*&p->nexthop*/, buf[1], + sizeof(buf[1]))); } return; diff --git a/isisd/isis_zebra.c b/isisd/isis_zebra.c index 8c6968f8ec..c1d558fc22 100644 --- a/isisd/isis_zebra.c +++ b/isisd/isis_zebra.c @@ -258,63 +258,62 @@ static void isis_zebra_route_add_ipv4(struct prefix *prefix, if (CHECK_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED)) return; - if (vrf_bitmap_check(zclient->redist[AFI_IP][ZEBRA_ROUTE_ISIS], - VRF_DEFAULT)) { - message = 0; - flags = 0; + if (!vrf_bitmap_check(zclient->redist[AFI_IP][ZEBRA_ROUTE_ISIS], + VRF_DEFAULT)) + return; - SET_FLAG(message, ZAPI_MESSAGE_NEXTHOP); - SET_FLAG(message, ZAPI_MESSAGE_METRIC); + message = 0; + flags = 0; + + SET_FLAG(message, ZAPI_MESSAGE_NEXTHOP); + SET_FLAG(message, ZAPI_MESSAGE_METRIC); #if 0 - SET_FLAG (message, ZAPI_MESSAGE_DISTANCE); + SET_FLAG (message, ZAPI_MESSAGE_DISTANCE); #endif - stream = zclient->obuf; - stream_reset(stream); - zclient_create_header(stream, ZEBRA_IPV4_ROUTE_ADD, - VRF_DEFAULT); - /* type */ - stream_putc(stream, ZEBRA_ROUTE_ISIS); - /* instance */ - stream_putw(stream, 0); - /* flags */ - stream_putl(stream, flags); - /* message */ - stream_putc(stream, message); - /* SAFI */ - stream_putw(stream, SAFI_UNICAST); - /* prefix information */ - psize = PSIZE(prefix->prefixlen); - stream_putc(stream, prefix->prefixlen); - stream_write(stream, (u_char *)&prefix->u.prefix4, psize); + stream = zclient->obuf; + stream_reset(stream); + zclient_create_header(stream, ZEBRA_IPV4_ROUTE_ADD, VRF_DEFAULT); + /* type */ + stream_putc(stream, ZEBRA_ROUTE_ISIS); + /* instance */ + stream_putw(stream, 0); + /* flags */ + stream_putl(stream, flags); + /* message */ + stream_putc(stream, message); + /* SAFI */ + stream_putw(stream, SAFI_UNICAST); + /* prefix information */ + psize = PSIZE(prefix->prefixlen); + stream_putc(stream, prefix->prefixlen); + stream_write(stream, (u_char *)&prefix->u.prefix4, psize); - stream_putc(stream, listcount(route_info->nexthops)); + stream_putc(stream, listcount(route_info->nexthops)); - /* Nexthop, ifindex, distance and metric information */ - for (ALL_LIST_ELEMENTS_RO(route_info->nexthops, node, - nexthop)) { - /* FIXME: can it be ? */ - if (nexthop->ip.s_addr != INADDR_ANY) { - stream_putc(stream, NEXTHOP_TYPE_IPV4_IFINDEX); - stream_put_in_addr(stream, &nexthop->ip); - stream_putl(stream, nexthop->ifindex); - } else { - stream_putc(stream, NEXTHOP_TYPE_IFINDEX); - stream_putl(stream, nexthop->ifindex); - } + /* Nexthop, ifindex, distance and metric information */ + for (ALL_LIST_ELEMENTS_RO(route_info->nexthops, node, nexthop)) { + /* FIXME: can it be ? */ + if (nexthop->ip.s_addr != INADDR_ANY) { + stream_putc(stream, NEXTHOP_TYPE_IPV4_IFINDEX); + stream_put_in_addr(stream, &nexthop->ip); + stream_putl(stream, nexthop->ifindex); + } else { + stream_putc(stream, NEXTHOP_TYPE_IFINDEX); + stream_putl(stream, nexthop->ifindex); } -#if 0 - if (CHECK_FLAG (message, ZAPI_MESSAGE_DISTANCE)) - stream_putc (stream, route_info->depth); -#endif - if (CHECK_FLAG(message, ZAPI_MESSAGE_METRIC)) - stream_putl(stream, route_info->cost); - - stream_putw_at(stream, 0, stream_get_endp(stream)); - zclient_send_message(zclient); - SET_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED); - UNSET_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_RESYNC); } +#if 0 + if (CHECK_FLAG (message, ZAPI_MESSAGE_DISTANCE)) + stream_putc (stream, route_info->depth); +#endif + if (CHECK_FLAG(message, ZAPI_MESSAGE_METRIC)) + stream_putl(stream, route_info->cost); + + stream_putw_at(stream, 0, stream_get_endp(stream)); + zclient_send_message(zclient); + SET_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED); + UNSET_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_RESYNC); } static void isis_zebra_route_del_ipv4(struct prefix *prefix, @@ -323,23 +322,22 @@ static void isis_zebra_route_del_ipv4(struct prefix *prefix, struct zapi_ipv4 api; struct prefix_ipv4 prefix4; - if (vrf_bitmap_check(zclient->redist[AFI_IP][ZEBRA_ROUTE_ISIS], - VRF_DEFAULT)) { - api.vrf_id = VRF_DEFAULT; - api.type = ZEBRA_ROUTE_ISIS; - api.instance = 0; - api.flags = 0; - api.message = 0; - api.safi = SAFI_UNICAST; - prefix4.family = AF_INET; - prefix4.prefixlen = prefix->prefixlen; - prefix4.prefix = prefix->u.prefix4; - zapi_ipv4_route(ZEBRA_IPV4_ROUTE_DELETE, zclient, &prefix4, - &api); - } UNSET_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED); - return; + if (!vrf_bitmap_check(zclient->redist[AFI_IP][ZEBRA_ROUTE_ISIS], + VRF_DEFAULT)) + return; + + api.vrf_id = VRF_DEFAULT; + api.type = ZEBRA_ROUTE_ISIS; + api.instance = 0; + api.flags = 0; + api.message = 0; + api.safi = SAFI_UNICAST; + prefix4.family = AF_INET; + prefix4.prefixlen = prefix->prefixlen; + prefix4.prefix = prefix->u.prefix4; + zapi_ipv4_route(ZEBRA_IPV4_ROUTE_DELETE, zclient, &prefix4, &api); } static void isis_zebra_route_add_ipv6(struct prefix *prefix, @@ -367,8 +365,8 @@ static void isis_zebra_route_add_ipv6(struct prefix *prefix, SET_FLAG(api.message, ZAPI_MESSAGE_METRIC); api.metric = route_info->cost; #if 0 - SET_FLAG (api.message, ZAPI_MESSAGE_DISTANCE); - api.distance = route_info->depth; + SET_FLAG (api.message, ZAPI_MESSAGE_DISTANCE); + api.distance = route_info->depth; #endif api.nexthop_num = listcount(route_info->nexthops6); api.ifindex_num = listcount(route_info->nexthops6); diff --git a/ospf6d/ospf6_zebra.c b/ospf6d/ospf6_zebra.c index d33f41730e..dc97f1ff4b 100644 --- a/ospf6d/ospf6_zebra.c +++ b/ospf6d/ospf6_zebra.c @@ -497,40 +497,42 @@ void ospf6_zebra_add_discard(struct ospf6_route *request) char buf[INET6_ADDRSTRLEN]; struct prefix_ipv6 *dest; - if (vrf_bitmap_check(zclient->redist[AFI_IP6][ZEBRA_ROUTE_OSPF6], - VRF_DEFAULT)) { - if (!CHECK_FLAG(request->flag, OSPF6_ROUTE_BLACKHOLE_ADDED)) { - api.vrf_id = VRF_DEFAULT; - api.type = ZEBRA_ROUTE_OSPF6; - api.flags = ZEBRA_FLAG_BLACKHOLE; - api.instance = 0; - api.message = 0; - api.safi = SAFI_UNICAST; - SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); - api.nexthop_num = 0; - api.ifindex_num = 0; + if (!vrf_bitmap_check(zclient->redist[AFI_IP6][ZEBRA_ROUTE_OSPF6], + VRF_DEFAULT)) + return; - dest = (struct prefix_ipv6 *)&request->prefix; + if (!CHECK_FLAG(request->flag, OSPF6_ROUTE_BLACKHOLE_ADDED)) { + api.vrf_id = VRF_DEFAULT; + api.type = ZEBRA_ROUTE_OSPF6; + api.flags = ZEBRA_FLAG_BLACKHOLE; + api.instance = 0; + api.message = 0; + api.safi = SAFI_UNICAST; + SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); + api.nexthop_num = 0; + api.ifindex_num = 0; - zapi_ipv6_route(ZEBRA_IPV6_ROUTE_ADD, zclient, dest, - NULL, &api); + dest = (struct prefix_ipv6 *)&request->prefix; - if (IS_OSPF6_DEBUG_ZEBRA(SEND)) - zlog_debug("Zebra: Route add discard %s/%d", - inet_ntop(AF_INET6, &dest->prefix, - buf, INET6_ADDRSTRLEN), - dest->prefixlen); - SET_FLAG(request->flag, OSPF6_ROUTE_BLACKHOLE_ADDED); - } else { - dest = (struct prefix_ipv6 *)&request->prefix; + zapi_ipv6_route(ZEBRA_IPV6_ROUTE_ADD, zclient, dest, NULL, + &api); - if (IS_OSPF6_DEBUG_ZEBRA(SEND)) - zlog_debug( - "Zebra: Blackhole route present already %s/%d", - inet_ntop(AF_INET6, &dest->prefix, buf, - INET6_ADDRSTRLEN), - dest->prefixlen); - } + if (IS_OSPF6_DEBUG_ZEBRA(SEND)) + zlog_debug("Zebra: Route add discard %s/%d", + inet_ntop(AF_INET6, &dest->prefix, buf, + INET6_ADDRSTRLEN), + dest->prefixlen); + + SET_FLAG(request->flag, OSPF6_ROUTE_BLACKHOLE_ADDED); + } else { + dest = (struct prefix_ipv6 *)&request->prefix; + + if (IS_OSPF6_DEBUG_ZEBRA(SEND)) + zlog_debug( + "Zebra: Blackhole route present already %s/%d", + inet_ntop(AF_INET6, &dest->prefix, buf, + INET6_ADDRSTRLEN), + dest->prefixlen); } } @@ -540,39 +542,41 @@ void ospf6_zebra_delete_discard(struct ospf6_route *request) char buf[INET6_ADDRSTRLEN]; struct prefix_ipv6 *dest; - if (vrf_bitmap_check(zclient->redist[AFI_IP6][ZEBRA_ROUTE_OSPF6], - VRF_DEFAULT)) { - if (CHECK_FLAG(request->flag, OSPF6_ROUTE_BLACKHOLE_ADDED)) { - api.vrf_id = VRF_DEFAULT; - api.type = ZEBRA_ROUTE_OSPF6; - api.flags = ZEBRA_FLAG_BLACKHOLE; - api.instance = 0; - api.message = 0; - api.safi = SAFI_UNICAST; - SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); - api.nexthop_num = 0; - api.ifindex_num = 0; + if (!vrf_bitmap_check(zclient->redist[AFI_IP6][ZEBRA_ROUTE_OSPF6], + VRF_DEFAULT)) + return; - dest = (struct prefix_ipv6 *)&request->prefix; + if (CHECK_FLAG(request->flag, OSPF6_ROUTE_BLACKHOLE_ADDED)) { + api.vrf_id = VRF_DEFAULT; + api.type = ZEBRA_ROUTE_OSPF6; + api.flags = ZEBRA_FLAG_BLACKHOLE; + api.instance = 0; + api.message = 0; + api.safi = SAFI_UNICAST; + SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); + api.nexthop_num = 0; + api.ifindex_num = 0; - zapi_ipv6_route(ZEBRA_IPV6_ROUTE_DELETE, zclient, dest, - NULL, &api); + dest = (struct prefix_ipv6 *)&request->prefix; - if (IS_OSPF6_DEBUG_ZEBRA(SEND)) - zlog_debug("Zebra: Route delete discard %s/%d", - inet_ntop(AF_INET6, &dest->prefix, - buf, INET6_ADDRSTRLEN), - dest->prefixlen); - UNSET_FLAG(request->flag, OSPF6_ROUTE_BLACKHOLE_ADDED); - } else { - dest = (struct prefix_ipv6 *)&request->prefix; - if (IS_OSPF6_DEBUG_ZEBRA(SEND)) - zlog_debug( - "Zebra: Blackhole route already deleted %s/%d", - inet_ntop(AF_INET6, &dest->prefix, buf, - INET6_ADDRSTRLEN), - dest->prefixlen); - } + zapi_ipv6_route(ZEBRA_IPV6_ROUTE_DELETE, zclient, dest, NULL, + &api); + + if (IS_OSPF6_DEBUG_ZEBRA(SEND)) + zlog_debug("Zebra: Route delete discard %s/%d", + inet_ntop(AF_INET6, &dest->prefix, buf, + INET6_ADDRSTRLEN), + dest->prefixlen); + + UNSET_FLAG(request->flag, OSPF6_ROUTE_BLACKHOLE_ADDED); + } else { + dest = (struct prefix_ipv6 *)&request->prefix; + if (IS_OSPF6_DEBUG_ZEBRA(SEND)) + zlog_debug( + "Zebra: Blackhole route already deleted %s/%d", + inet_ntop(AF_INET6, &dest->prefix, buf, + INET6_ADDRSTRLEN), + dest->prefixlen); } } diff --git a/ospfd/ospf_zebra.c b/ospfd/ospf_zebra.c index d615afc072..f9668f2495 100644 --- a/ospfd/ospf_zebra.c +++ b/ospfd/ospf_zebra.c @@ -342,118 +342,116 @@ void ospf_zebra_add(struct prefix_ipv4 *p, struct ospf_route * or) struct listnode *node; struct ospf *ospf = ospf_lookup(); - if ((ospf->instance - && redist_check_instance( - &zclient->mi_redist[AFI_IP][ZEBRA_ROUTE_OSPF], - ospf->instance)) - || vrf_bitmap_check(zclient->redist[AFI_IP][ZEBRA_ROUTE_OSPF], - VRF_DEFAULT)) { - message = 0; - flags = 0; + if (!(ospf->instance + && redist_check_instance( + &zclient->mi_redist[AFI_IP][ZEBRA_ROUTE_OSPF], + ospf->instance)) + && !vrf_bitmap_check(zclient->redist[AFI_IP][ZEBRA_ROUTE_OSPF], + VRF_DEFAULT)) + return; - /* OSPF pass nexthop and metric */ - SET_FLAG(message, ZAPI_MESSAGE_NEXTHOP); - SET_FLAG(message, ZAPI_MESSAGE_METRIC); + message = 0; + flags = 0; - /* Distance value. */ - distance = ospf_distance_apply(p, or); - if (distance) - SET_FLAG(message, ZAPI_MESSAGE_DISTANCE); + /* OSPF pass nexthop and metric */ + SET_FLAG(message, ZAPI_MESSAGE_NEXTHOP); + SET_FLAG(message, ZAPI_MESSAGE_METRIC); - /* Check if path type is ASE */ - if (((or->path_type == OSPF_PATH_TYPE1_EXTERNAL) - || (or->path_type == OSPF_PATH_TYPE2_EXTERNAL)) - && (or->u.ext.tag > 0) && (or->u.ext.tag <= ROUTE_TAG_MAX)) - SET_FLAG(message, ZAPI_MESSAGE_TAG); + /* Distance value. */ + distance = ospf_distance_apply(p, or); + if (distance) + SET_FLAG(message, ZAPI_MESSAGE_DISTANCE); - /* Make packet. */ - s = zclient->obuf; - stream_reset(s); + /* Check if path type is ASE */ + if (((or->path_type == OSPF_PATH_TYPE1_EXTERNAL) + || (or->path_type == OSPF_PATH_TYPE2_EXTERNAL)) + && (or->u.ext.tag > 0) && (or->u.ext.tag <= ROUTE_TAG_MAX)) + SET_FLAG(message, ZAPI_MESSAGE_TAG); - /* Put command, type, flags, message. */ - zclient_create_header(s, ZEBRA_IPV4_ROUTE_ADD, VRF_DEFAULT); - stream_putc(s, ZEBRA_ROUTE_OSPF); - stream_putw(s, ospf->instance); - stream_putl(s, flags); - stream_putc(s, message); - stream_putw(s, SAFI_UNICAST); + /* Make packet. */ + s = zclient->obuf; + stream_reset(s); - /* Put prefix information. */ - psize = PSIZE(p->prefixlen); - stream_putc(s, p->prefixlen); - stream_write(s, (u_char *)&p->prefix, psize); + /* Put command, type, flags, message. */ + zclient_create_header(s, ZEBRA_IPV4_ROUTE_ADD, VRF_DEFAULT); + stream_putc(s, ZEBRA_ROUTE_OSPF); + stream_putw(s, ospf->instance); + stream_putl(s, flags); + stream_putc(s, message); + stream_putw(s, SAFI_UNICAST); - /* Nexthop count. */ - stream_putc(s, or->paths->count); + /* Put prefix information. */ + psize = PSIZE(p->prefixlen); + stream_putc(s, p->prefixlen); + stream_write(s, (u_char *)&p->prefix, psize); - /* Nexthop, ifindex, distance and metric information. */ - for (ALL_LIST_ELEMENTS_RO(or->paths, node, path)) { + /* Nexthop count. */ + stream_putc(s, or->paths->count); + + /* Nexthop, ifindex, distance and metric information. */ + for (ALL_LIST_ELEMENTS_RO(or->paths, node, path)) { #ifdef HAVE_NETLINK - if (path->unnumbered - || (path->nexthop.s_addr != INADDR_ANY - && path->ifindex != 0)) { - stream_putc(s, NEXTHOP_TYPE_IPV4_IFINDEX); - stream_put_in_addr(s, &path->nexthop); + if (path->unnumbered || (path->nexthop.s_addr != INADDR_ANY + && path->ifindex != 0)) { + stream_putc(s, NEXTHOP_TYPE_IPV4_IFINDEX); + stream_put_in_addr(s, &path->nexthop); + stream_putl(s, path->ifindex); + } else if (path->nexthop.s_addr != INADDR_ANY) { + stream_putc(s, NEXTHOP_TYPE_IPV4); + stream_put_in_addr(s, &path->nexthop); + } else { + stream_putc(s, NEXTHOP_TYPE_IFINDEX); + if (path->ifindex) stream_putl(s, path->ifindex); - } else if (path->nexthop.s_addr != INADDR_ANY) { - stream_putc(s, NEXTHOP_TYPE_IPV4); - stream_put_in_addr(s, &path->nexthop); - } else { - stream_putc(s, NEXTHOP_TYPE_IFINDEX); - if (path->ifindex) - stream_putl(s, path->ifindex); - else - stream_putl(s, 0); - } + else + stream_putl(s, 0); + } #else /* HAVE_NETLINK */ - if (path->nexthop.s_addr != INADDR_ANY - && path->ifindex != 0) { - stream_putc(s, NEXTHOP_TYPE_IPV4_IFINDEX); - stream_put_in_addr(s, &path->nexthop); + if (path->nexthop.s_addr != INADDR_ANY && path->ifindex != 0) { + stream_putc(s, NEXTHOP_TYPE_IPV4_IFINDEX); + stream_put_in_addr(s, &path->nexthop); + stream_putl(s, path->ifindex); + } else if (path->nexthop.s_addr != INADDR_ANY) { + stream_putc(s, NEXTHOP_TYPE_IPV4); + stream_put_in_addr(s, &path->nexthop); + } else { + stream_putc(s, NEXTHOP_TYPE_IFINDEX); + if (path->ifindex) stream_putl(s, path->ifindex); - } else if (path->nexthop.s_addr != INADDR_ANY) { - stream_putc(s, NEXTHOP_TYPE_IPV4); - stream_put_in_addr(s, &path->nexthop); - } else { - stream_putc(s, NEXTHOP_TYPE_IFINDEX); - if (path->ifindex) - stream_putl(s, path->ifindex); - else - stream_putl(s, 0); - } + else + stream_putl(s, 0); + } #endif /* HAVE_NETLINK */ - if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE)) { - char buf[2][INET_ADDRSTRLEN]; - zlog_debug( - "Zebra: Route add %s/%d nexthop %s, ifindex=%d", - inet_ntop(AF_INET, &p->prefix, buf[0], - sizeof(buf[0])), - p->prefixlen, - inet_ntop(AF_INET, &path->nexthop, - buf[1], sizeof(buf[1])), - path->ifindex); - } + if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE)) { + char buf[2][INET_ADDRSTRLEN]; + zlog_debug( + "Zebra: Route add %s/%d nexthop %s, ifindex=%d", + inet_ntop(AF_INET, &p->prefix, buf[0], + sizeof(buf[0])), + p->prefixlen, inet_ntop(AF_INET, &path->nexthop, + buf[1], sizeof(buf[1])), + path->ifindex); } - - if (CHECK_FLAG(message, ZAPI_MESSAGE_DISTANCE)) - stream_putc(s, distance); - if (CHECK_FLAG(message, ZAPI_MESSAGE_METRIC)) { - if (or->path_type == OSPF_PATH_TYPE1_EXTERNAL) - stream_putl(s, or->cost + or->u.ext.type2_cost); - else if (or->path_type == OSPF_PATH_TYPE2_EXTERNAL) - stream_putl(s, or->u.ext.type2_cost); - else - stream_putl(s, or->cost); - } - - if (CHECK_FLAG(message, ZAPI_MESSAGE_TAG)) - stream_putl(s, or->u.ext.tag); - - stream_putw_at(s, 0, stream_get_endp(s)); - - zclient_send_message(zclient); } + + if (CHECK_FLAG(message, ZAPI_MESSAGE_DISTANCE)) + stream_putc(s, distance); + if (CHECK_FLAG(message, ZAPI_MESSAGE_METRIC)) { + if (or->path_type == OSPF_PATH_TYPE1_EXTERNAL) + stream_putl(s, or->cost + or->u.ext.type2_cost); + else if (or->path_type == OSPF_PATH_TYPE2_EXTERNAL) + stream_putl(s, or->u.ext.type2_cost); + else + stream_putl(s, or->cost); + } + + if (CHECK_FLAG(message, ZAPI_MESSAGE_TAG)) + stream_putl(s, or->u.ext.tag); + + stream_putw_at(s, 0, stream_get_endp(s)); + + zclient_send_message(zclient); } void ospf_zebra_delete(struct prefix_ipv4 *p, struct ospf_route * or) @@ -467,78 +465,77 @@ void ospf_zebra_delete(struct prefix_ipv4 *p, struct ospf_route * or) struct listnode *node; struct ospf *ospf = ospf_lookup(); - if ((ospf->instance - && redist_check_instance( - &zclient->mi_redist[AFI_IP][ZEBRA_ROUTE_OSPF], - ospf->instance)) - || vrf_bitmap_check(zclient->redist[AFI_IP][ZEBRA_ROUTE_OSPF], - VRF_DEFAULT)) { - message = 0; - flags = 0; - /* Distance value. */ - distance = ospf_distance_apply(p, or); - /* Make packet. */ - s = zclient->obuf; - stream_reset(s); + if (!(ospf->instance + && redist_check_instance( + &zclient->mi_redist[AFI_IP][ZEBRA_ROUTE_OSPF], + ospf->instance)) + && !vrf_bitmap_check(zclient->redist[AFI_IP][ZEBRA_ROUTE_OSPF], + VRF_DEFAULT)) + return; - /* Put command, type, flags, message. */ - zclient_create_header(s, ZEBRA_IPV4_ROUTE_DELETE, VRF_DEFAULT); - stream_putc(s, ZEBRA_ROUTE_OSPF); - stream_putw(s, ospf->instance); - stream_putl(s, flags); - stream_putc(s, message); - stream_putw(s, SAFI_UNICAST); + message = 0; + flags = 0; + /* Distance value. */ + distance = ospf_distance_apply(p, or); + /* Make packet. */ + s = zclient->obuf; + stream_reset(s); - /* Put prefix information. */ - psize = PSIZE(p->prefixlen); - stream_putc(s, p->prefixlen); - stream_write(s, (u_char *)&p->prefix, psize); + /* Put command, type, flags, message. */ + zclient_create_header(s, ZEBRA_IPV4_ROUTE_DELETE, VRF_DEFAULT); + stream_putc(s, ZEBRA_ROUTE_OSPF); + stream_putw(s, ospf->instance); + stream_putl(s, flags); + stream_putc(s, message); + stream_putw(s, SAFI_UNICAST); - /* Nexthop count. */ - stream_putc(s, or->paths->count); + /* Put prefix information. */ + psize = PSIZE(p->prefixlen); + stream_putc(s, p->prefixlen); + stream_write(s, (u_char *)&p->prefix, psize); - /* Nexthop, ifindex, distance and metric information. */ - for (ALL_LIST_ELEMENTS_RO(or->paths, node, path)) { - if (path->nexthop.s_addr != INADDR_ANY - && path->ifindex != 0) { - stream_putc(s, NEXTHOP_TYPE_IPV4_IFINDEX); - stream_put_in_addr(s, &path->nexthop); - stream_putl(s, path->ifindex); - } else if (path->nexthop.s_addr != INADDR_ANY) { - stream_putc(s, NEXTHOP_TYPE_IPV4); - stream_put_in_addr(s, &path->nexthop); - } else { - stream_putc(s, NEXTHOP_TYPE_IFINDEX); - stream_putl(s, path->ifindex); - } + /* Nexthop count. */ + stream_putc(s, or->paths->count); - if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE)) { - char buf[2][INET_ADDRSTRLEN]; - zlog_debug( - "Zebra: Route delete %s/%d nexthop %s", - inet_ntop(AF_INET, &p->prefix, buf[0], - sizeof(buf[0])), - p->prefixlen, - inet_ntop(AF_INET, &path->nexthop, - buf[1], sizeof(buf[1]))); - } + /* Nexthop, ifindex, distance and metric information. */ + for (ALL_LIST_ELEMENTS_RO(or->paths, node, path)) { + if (path->nexthop.s_addr != INADDR_ANY && path->ifindex != 0) { + stream_putc(s, NEXTHOP_TYPE_IPV4_IFINDEX); + stream_put_in_addr(s, &path->nexthop); + stream_putl(s, path->ifindex); + } else if (path->nexthop.s_addr != INADDR_ANY) { + stream_putc(s, NEXTHOP_TYPE_IPV4); + stream_put_in_addr(s, &path->nexthop); + } else { + stream_putc(s, NEXTHOP_TYPE_IFINDEX); + stream_putl(s, path->ifindex); } - if (CHECK_FLAG(message, ZAPI_MESSAGE_DISTANCE)) - stream_putc(s, distance); - if (CHECK_FLAG(message, ZAPI_MESSAGE_METRIC)) { - if (or->path_type == OSPF_PATH_TYPE1_EXTERNAL) - stream_putl(s, or->cost + or->u.ext.type2_cost); - else if (or->path_type == OSPF_PATH_TYPE2_EXTERNAL) - stream_putl(s, or->u.ext.type2_cost); - else - stream_putl(s, or->cost); + if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE)) { + char buf[2][INET_ADDRSTRLEN]; + zlog_debug("Zebra: Route delete %s/%d nexthop %s", + inet_ntop(AF_INET, &p->prefix, buf[0], + sizeof(buf[0])), + p->prefixlen, + inet_ntop(AF_INET, &path->nexthop, buf[1], + sizeof(buf[1]))); } - - stream_putw_at(s, 0, stream_get_endp(s)); - - zclient_send_message(zclient); } + + if (CHECK_FLAG(message, ZAPI_MESSAGE_DISTANCE)) + stream_putc(s, distance); + if (CHECK_FLAG(message, ZAPI_MESSAGE_METRIC)) { + if (or->path_type == OSPF_PATH_TYPE1_EXTERNAL) + stream_putl(s, or->cost + or->u.ext.type2_cost); + else if (or->path_type == OSPF_PATH_TYPE2_EXTERNAL) + stream_putl(s, or->u.ext.type2_cost); + else + stream_putl(s, or->cost); + } + + stream_putw_at(s, 0, stream_get_endp(s)); + + zclient_send_message(zclient); } void ospf_zebra_add_discard(struct prefix_ipv4 *p) @@ -546,29 +543,30 @@ void ospf_zebra_add_discard(struct prefix_ipv4 *p) struct zapi_ipv4 api; struct ospf *ospf = ospf_lookup(); - if ((ospf->instance - && redist_check_instance( - &zclient->mi_redist[AFI_IP][ZEBRA_ROUTE_OSPF], - ospf->instance)) - || vrf_bitmap_check(zclient->redist[AFI_IP][ZEBRA_ROUTE_OSPF], - VRF_DEFAULT)) { - api.vrf_id = VRF_DEFAULT; - api.type = ZEBRA_ROUTE_OSPF; - api.instance = ospf->instance; - api.flags = ZEBRA_FLAG_BLACKHOLE; - api.message = 0; - api.safi = SAFI_UNICAST; - SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); - api.nexthop_num = 0; - api.ifindex_num = 0; - api.tag = 0; + if (!(ospf->instance + && redist_check_instance( + &zclient->mi_redist[AFI_IP][ZEBRA_ROUTE_OSPF], + ospf->instance)) + && !vrf_bitmap_check(zclient->redist[AFI_IP][ZEBRA_ROUTE_OSPF], + VRF_DEFAULT)) + return; - zapi_ipv4_route(ZEBRA_IPV4_ROUTE_ADD, zclient, p, &api); + api.vrf_id = VRF_DEFAULT; + api.type = ZEBRA_ROUTE_OSPF; + api.instance = ospf->instance; + api.flags = ZEBRA_FLAG_BLACKHOLE; + api.message = 0; + api.safi = SAFI_UNICAST; + SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); + api.nexthop_num = 0; + api.ifindex_num = 0; + api.tag = 0; - if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE)) - zlog_debug("Zebra: Route add discard %s/%d", - inet_ntoa(p->prefix), p->prefixlen); - } + zapi_ipv4_route(ZEBRA_IPV4_ROUTE_ADD, zclient, p, &api); + + if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE)) + zlog_debug("Zebra: Route add discard %s/%d", + inet_ntoa(p->prefix), p->prefixlen); } void ospf_zebra_delete_discard(struct prefix_ipv4 *p) @@ -576,29 +574,30 @@ void ospf_zebra_delete_discard(struct prefix_ipv4 *p) struct zapi_ipv4 api; struct ospf *ospf = ospf_lookup(); - if ((ospf->instance - && redist_check_instance( - &zclient->mi_redist[AFI_IP][ZEBRA_ROUTE_OSPF], - ospf->instance)) - || vrf_bitmap_check(zclient->redist[AFI_IP][ZEBRA_ROUTE_OSPF], - VRF_DEFAULT)) { - api.vrf_id = VRF_DEFAULT; - api.type = ZEBRA_ROUTE_OSPF; - api.instance = ospf->instance; - api.flags = ZEBRA_FLAG_BLACKHOLE; - api.message = 0; - api.safi = SAFI_UNICAST; - SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); - api.nexthop_num = 0; - api.ifindex_num = 0; - api.tag = 0; + if (!(ospf->instance + && redist_check_instance( + &zclient->mi_redist[AFI_IP][ZEBRA_ROUTE_OSPF], + ospf->instance)) + && !vrf_bitmap_check(zclient->redist[AFI_IP][ZEBRA_ROUTE_OSPF], + VRF_DEFAULT)) + return; - zapi_ipv4_route(ZEBRA_IPV4_ROUTE_DELETE, zclient, p, &api); + api.vrf_id = VRF_DEFAULT; + api.type = ZEBRA_ROUTE_OSPF; + api.instance = ospf->instance; + api.flags = ZEBRA_FLAG_BLACKHOLE; + api.message = 0; + api.safi = SAFI_UNICAST; + SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); + api.nexthop_num = 0; + api.ifindex_num = 0; + api.tag = 0; - if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE)) - zlog_debug("Zebra: Route delete discard %s/%d", - inet_ntoa(p->prefix), p->prefixlen); - } + zapi_ipv4_route(ZEBRA_IPV4_ROUTE_DELETE, zclient, p, &api); + + if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE)) + zlog_debug("Zebra: Route delete discard %s/%d", + inet_ntoa(p->prefix), p->prefixlen); } struct ospf_external *ospf_external_lookup(u_char type, u_short instance) diff --git a/ripd/rip_zebra.c b/ripd/rip_zebra.c index 961a846db2..8a166745ec 100644 --- a/ripd/rip_zebra.c +++ b/ripd/rip_zebra.c @@ -48,73 +48,70 @@ static void rip_zebra_ipv4_send(struct route_node *rp, u_char cmd) struct rip_info *rinfo = NULL; int count = 0; - if (vrf_bitmap_check(zclient->redist[AFI_IP][ZEBRA_ROUTE_RIP], - VRF_DEFAULT)) { - api.vrf_id = VRF_DEFAULT; - api.type = ZEBRA_ROUTE_RIP; - api.instance = 0; - api.flags = 0; - api.message = 0; - api.safi = SAFI_UNICAST; + if (!vrf_bitmap_check(zclient->redist[AFI_IP][ZEBRA_ROUTE_RIP], + VRF_DEFAULT)) + return; - if (nexthops_len < listcount(list)) { - nexthops_len = listcount(list); - nexthops = XREALLOC(MTYPE_TMP, nexthops, - nexthops_len - * sizeof(struct in_addr *)); - } + api.vrf_id = VRF_DEFAULT; + api.type = ZEBRA_ROUTE_RIP; + api.instance = 0; + api.flags = 0; + api.message = 0; + api.safi = SAFI_UNICAST; - SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); - for (ALL_LIST_ELEMENTS_RO(list, listnode, rinfo)) { - nexthops[count++] = &rinfo->nexthop; - if (cmd == ZEBRA_IPV4_ROUTE_ADD) - SET_FLAG(rinfo->flags, RIP_RTF_FIB); - else - UNSET_FLAG(rinfo->flags, RIP_RTF_FIB); - } - - api.nexthop = nexthops; - api.nexthop_num = count; - api.ifindex_num = 0; - - rinfo = listgetdata(listhead(list)); - - SET_FLAG(api.message, ZAPI_MESSAGE_METRIC); - api.metric = rinfo->metric; - - if (rinfo->distance - && rinfo->distance != ZEBRA_RIP_DISTANCE_DEFAULT) { - SET_FLAG(api.message, ZAPI_MESSAGE_DISTANCE); - api.distance = rinfo->distance; - } - - if (rinfo->tag) { - SET_FLAG(api.message, ZAPI_MESSAGE_TAG); - api.tag = rinfo->tag; - } - - zapi_ipv4_route(cmd, zclient, (struct prefix_ipv4 *)&rp->p, - &api); - - if (IS_RIP_DEBUG_ZEBRA) { - if (rip->ecmp) - zlog_debug("%s: %s/%d nexthops %d", - (cmd == ZEBRA_IPV4_ROUTE_ADD) - ? "Install into zebra" - : "Delete from zebra", - inet_ntoa(rp->p.u.prefix4), - rp->p.prefixlen, count); - else - zlog_debug("%s: %s/%d", - (cmd == ZEBRA_IPV4_ROUTE_ADD) - ? "Install into zebra" - : "Delete from zebra", - inet_ntoa(rp->p.u.prefix4), - rp->p.prefixlen); - } - - rip_global_route_changes++; + if (nexthops_len < listcount(list)) { + nexthops_len = listcount(list); + nexthops = XREALLOC(MTYPE_TMP, nexthops, + nexthops_len * sizeof(struct in_addr *)); } + + SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); + for (ALL_LIST_ELEMENTS_RO(list, listnode, rinfo)) { + nexthops[count++] = &rinfo->nexthop; + if (cmd == ZEBRA_IPV4_ROUTE_ADD) + SET_FLAG(rinfo->flags, RIP_RTF_FIB); + else + UNSET_FLAG(rinfo->flags, RIP_RTF_FIB); + } + + api.nexthop = nexthops; + api.nexthop_num = count; + api.ifindex_num = 0; + + rinfo = listgetdata(listhead(list)); + + SET_FLAG(api.message, ZAPI_MESSAGE_METRIC); + api.metric = rinfo->metric; + + if (rinfo->distance && rinfo->distance != ZEBRA_RIP_DISTANCE_DEFAULT) { + SET_FLAG(api.message, ZAPI_MESSAGE_DISTANCE); + api.distance = rinfo->distance; + } + + if (rinfo->tag) { + SET_FLAG(api.message, ZAPI_MESSAGE_TAG); + api.tag = rinfo->tag; + } + + zapi_ipv4_route(cmd, zclient, (struct prefix_ipv4 *)&rp->p, &api); + + if (IS_RIP_DEBUG_ZEBRA) { + if (rip->ecmp) + zlog_debug("%s: %s/%d nexthops %d", + (cmd == ZEBRA_IPV4_ROUTE_ADD) + ? "Install into zebra" + : "Delete from zebra", + inet_ntoa(rp->p.u.prefix4), rp->p.prefixlen, + count); + else + zlog_debug("%s: %s/%d", + (cmd == ZEBRA_IPV4_ROUTE_ADD) + ? "Install into zebra" + : "Delete from zebra", + inet_ntoa(rp->p.u.prefix4), rp->p.prefixlen); + } + + rip_global_route_changes++; } /* Add/update ECMP routes to zebra. */ @@ -623,39 +620,39 @@ int config_write_rip_redistribute(struct vty *vty, int config_mode) { int i; - for (i = 0; i < ZEBRA_ROUTE_MAX; i++) - if (i != zclient->redist_default - && vrf_bitmap_check(zclient->redist[AFI_IP][i], - VRF_DEFAULT)) { - if (config_mode) { - if (rip->route_map[i].metric_config) { - if (rip->route_map[i].name) - vty_out(vty, - " redistribute %s metric %d route-map %s\n", - zebra_route_string(i), - rip->route_map[i] - .metric, - rip->route_map[i].name); - else - vty_out(vty, - " redistribute %s metric %d\n", - zebra_route_string(i), - rip->route_map[i] - .metric); - } else { - if (rip->route_map[i].name) - vty_out(vty, - " redistribute %s route-map %s\n", - zebra_route_string(i), - rip->route_map[i].name); - else - vty_out(vty, - " redistribute %s\n", - zebra_route_string(i)); - } - } else - vty_out(vty, " %s", zebra_route_string(i)); + for (i = 0; i < ZEBRA_ROUTE_MAX; i++) { + if (i == zclient->redist_default + || !vrf_bitmap_check(zclient->redist[AFI_IP][i], + VRF_DEFAULT)) + continue; + + if (!config_mode) { + vty_out(vty, " %s", zebra_route_string(i)); + continue; } + + if (rip->route_map[i].metric_config) { + if (rip->route_map[i].name) + vty_out(vty, + " redistribute %s metric %d route-map %s\n", + zebra_route_string(i), + rip->route_map[i].metric, + rip->route_map[i].name); + else + vty_out(vty, " redistribute %s metric %d\n", + zebra_route_string(i), + rip->route_map[i].metric); + } else { + if (rip->route_map[i].name) + vty_out(vty, " redistribute %s route-map %s\n", + zebra_route_string(i), + rip->route_map[i].name); + else + vty_out(vty, " redistribute %s\n", + zebra_route_string(i)); + } + } + return 0; } diff --git a/ripngd/ripng_zebra.c b/ripngd/ripng_zebra.c index 386bee43b8..875ec4f225 100644 --- a/ripngd/ripng_zebra.c +++ b/ripngd/ripng_zebra.c @@ -49,71 +49,69 @@ static void ripng_zebra_ipv6_send(struct route_node *rp, u_char cmd) struct ripng_info *rinfo = NULL; int count = 0; - if (vrf_bitmap_check(zclient->redist[AFI_IP6][ZEBRA_ROUTE_RIPNG], - VRF_DEFAULT)) { - api.vrf_id = VRF_DEFAULT; - api.type = ZEBRA_ROUTE_RIPNG; - api.instance = 0; - api.flags = 0; - api.message = 0; - api.safi = SAFI_UNICAST; + if (!vrf_bitmap_check(zclient->redist[AFI_IP6][ZEBRA_ROUTE_RIPNG], + VRF_DEFAULT)) + return; - if (nexthops_len < listcount(list)) { - nexthops_len = listcount(list); - nexthops = XREALLOC( - MTYPE_TMP, nexthops, - nexthops_len * sizeof(struct in6_addr *)); - ifindexes = - XREALLOC(MTYPE_TMP, ifindexes, - nexthops_len * sizeof(unsigned int)); - } + api.vrf_id = VRF_DEFAULT; + api.type = ZEBRA_ROUTE_RIPNG; + api.instance = 0; + api.flags = 0; + api.message = 0; + api.safi = SAFI_UNICAST; - SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); - SET_FLAG(api.message, ZAPI_MESSAGE_IFINDEX); - for (ALL_LIST_ELEMENTS_RO(list, listnode, rinfo)) { - nexthops[count] = &rinfo->nexthop; - ifindexes[count] = rinfo->ifindex; - count++; - if (cmd == ZEBRA_IPV6_ROUTE_ADD) - SET_FLAG(rinfo->flags, RIPNG_RTF_FIB); - else - UNSET_FLAG(rinfo->flags, RIPNG_RTF_FIB); - } + if (nexthops_len < listcount(list)) { + nexthops_len = listcount(list); + nexthops = XREALLOC(MTYPE_TMP, nexthops, + nexthops_len * sizeof(struct in6_addr *)); + ifindexes = XREALLOC(MTYPE_TMP, ifindexes, + nexthops_len * sizeof(unsigned int)); + } - api.nexthop = nexthops; - api.nexthop_num = count; - api.ifindex = ifindexes; - api.ifindex_num = count; + SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); + SET_FLAG(api.message, ZAPI_MESSAGE_IFINDEX); + for (ALL_LIST_ELEMENTS_RO(list, listnode, rinfo)) { + nexthops[count] = &rinfo->nexthop; + ifindexes[count] = rinfo->ifindex; + count++; + if (cmd == ZEBRA_IPV6_ROUTE_ADD) + SET_FLAG(rinfo->flags, RIPNG_RTF_FIB); + else + UNSET_FLAG(rinfo->flags, RIPNG_RTF_FIB); + } - rinfo = listgetdata(listhead(list)); + api.nexthop = nexthops; + api.nexthop_num = count; + api.ifindex = ifindexes; + api.ifindex_num = count; - SET_FLAG(api.message, ZAPI_MESSAGE_METRIC); - api.metric = rinfo->metric; + rinfo = listgetdata(listhead(list)); - if (rinfo->tag) { - SET_FLAG(api.message, ZAPI_MESSAGE_TAG); - api.tag = rinfo->tag; - } + SET_FLAG(api.message, ZAPI_MESSAGE_METRIC); + api.metric = rinfo->metric; - zapi_ipv6_route(cmd, zclient, (struct prefix_ipv6 *)&rp->p, - NULL, &api); + if (rinfo->tag) { + SET_FLAG(api.message, ZAPI_MESSAGE_TAG); + api.tag = rinfo->tag; + } - if (IS_RIPNG_DEBUG_ZEBRA) { - if (ripng->ecmp) - zlog_debug("%s: %s/%d nexthops %d", - (cmd == ZEBRA_IPV6_ROUTE_ADD) - ? "Install into zebra" - : "Delete from zebra", - inet6_ntoa(rp->p.u.prefix6), - rp->p.prefixlen, count); - else - zlog_debug("%s: %s/%d", - (cmd == ZEBRA_IPV6_ROUTE_ADD) - ? "Install into zebra" - : "Delete from zebra", - inet6_ntoa(rp->p.u.prefix6), - rp->p.prefixlen); - } + zapi_ipv6_route(cmd, zclient, (struct prefix_ipv6 *)&rp->p, NULL, &api); + + if (IS_RIPNG_DEBUG_ZEBRA) { + if (ripng->ecmp) + zlog_debug("%s: %s/%d nexthops %d", + (cmd == ZEBRA_IPV6_ROUTE_ADD) + ? "Install into zebra" + : "Delete from zebra", + inet6_ntoa(rp->p.u.prefix6), rp->p.prefixlen, + count); + else + zlog_debug("%s: %s/%d", + (cmd == ZEBRA_IPV6_ROUTE_ADD) + ? "Install into zebra" + : "Delete from zebra", + inet6_ntoa(rp->p.u.prefix6), + rp->p.prefixlen); } } @@ -452,41 +450,38 @@ void ripng_redistribute_write(struct vty *vty, int config_mode) { int i; - for (i = 0; i < ZEBRA_ROUTE_MAX; i++) - if (i != zclient->redist_default - && vrf_bitmap_check(zclient->redist[AFI_IP6][i], - VRF_DEFAULT)) { - if (config_mode) { - if (ripng->route_map[i].metric_config) { - if (ripng->route_map[i].name) - vty_out(vty, - " redistribute %s metric %d route-map %s\n", - zebra_route_string(i), - ripng->route_map[i] - .metric, - ripng->route_map[i] - .name); - else - vty_out(vty, - " redistribute %s metric %d\n", - zebra_route_string(i), - ripng->route_map[i] - .metric); - } else { - if (ripng->route_map[i].name) - vty_out(vty, - " redistribute %s route-map %s\n", - zebra_route_string(i), - ripng->route_map[i] - .name); - else - vty_out(vty, - " redistribute %s\n", - zebra_route_string(i)); - } - } else - vty_out(vty, " %s", zebra_route_string(i)); + for (i = 0; i < ZEBRA_ROUTE_MAX; i++) { + if (i == zclient->redist_default + || !vrf_bitmap_check(zclient->redist[AFI_IP6][i], + VRF_DEFAULT)) + continue; + + if (!config_mode) { + vty_out(vty, " %s", zebra_route_string(i)); + continue; } + + if (ripng->route_map[i].metric_config) { + if (ripng->route_map[i].name) + vty_out(vty, + " redistribute %s metric %d route-map %s\n", + zebra_route_string(i), + ripng->route_map[i].metric, + ripng->route_map[i].name); + else + vty_out(vty, " redistribute %s metric %d\n", + zebra_route_string(i), + ripng->route_map[i].metric); + } else { + if (ripng->route_map[i].name) + vty_out(vty, " redistribute %s route-map %s\n", + zebra_route_string(i), + ripng->route_map[i].name); + else + vty_out(vty, " redistribute %s\n", + zebra_route_string(i)); + } + } } /* RIPng configuration write function. */ From 153856bbe96ea6b78aa0cc184ba6f4def7aace04 Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Sat, 19 Aug 2017 11:20:42 -0300 Subject: [PATCH 059/130] lib: remove redundant zebra messages This also fixes a bug of ipv6 routes advertised by the VNC code being ignored by zebra. Signed-off-by: Renato Westphal --- bgpd/rfapi/vnc_zebra.c | 8 ++++---- lib/log.c | 4 ---- lib/zclient.h | 4 ---- zebra/zserv.c | 8 -------- 4 files changed, 4 insertions(+), 20 deletions(-) diff --git a/bgpd/rfapi/vnc_zebra.c b/bgpd/rfapi/vnc_zebra.c index 3075d4109f..8f4a550bde 100644 --- a/bgpd/rfapi/vnc_zebra.c +++ b/bgpd/rfapi/vnc_zebra.c @@ -527,8 +527,8 @@ static void vnc_zebra_route_msg(struct prefix *p, int nhp_count, void *nhp_ary, p->prefixlen, nhp_count); } - zapi_ipv4_route((add ? ZEBRA_IPV4_NEXTHOP_ADD - : ZEBRA_IPV4_NEXTHOP_DELETE), + zapi_ipv4_route((add ? ZEBRA_IPV4_ROUTE_ADD + : ZEBRA_IPV4_ROUTE_DELETE), zclient_vnc, (struct prefix_ipv4 *)p, &api); } else if (p->family == AF_INET6) { @@ -561,8 +561,8 @@ static void vnc_zebra_route_msg(struct prefix *p, int nhp_count, void *nhp_ary, p->prefixlen, nhp_count); } - zapi_ipv6_route((add ? ZEBRA_IPV6_NEXTHOP_ADD - : ZEBRA_IPV6_NEXTHOP_DELETE), + zapi_ipv6_route((add ? ZEBRA_IPV6_ROUTE_ADD + : ZEBRA_IPV6_ROUTE_DELETE), zclient_vnc, (struct prefix_ipv6 *)p, NULL, &api); } else { diff --git a/lib/log.c b/lib/log.c index 5c89e7080e..b9ce9e69bc 100644 --- a/lib/log.c +++ b/lib/log.c @@ -908,10 +908,6 @@ static const struct zebra_desc_table command_types[] = { DESC_ENTRY(ZEBRA_INTERFACE_LINK_PARAMS), DESC_ENTRY(ZEBRA_MPLS_LABELS_ADD), DESC_ENTRY(ZEBRA_MPLS_LABELS_DELETE), - DESC_ENTRY(ZEBRA_IPV4_NEXTHOP_ADD), - DESC_ENTRY(ZEBRA_IPV4_NEXTHOP_DELETE), - DESC_ENTRY(ZEBRA_IPV6_NEXTHOP_ADD), - DESC_ENTRY(ZEBRA_IPV6_NEXTHOP_DELETE), DESC_ENTRY(ZEBRA_IPMR_ROUTE_STATS), DESC_ENTRY(ZEBRA_LABEL_MANAGER_CONNECT), DESC_ENTRY(ZEBRA_GET_LABEL_CHUNK), diff --git a/lib/zclient.h b/lib/zclient.h index 15d1858d84..0218c1b732 100644 --- a/lib/zclient.h +++ b/lib/zclient.h @@ -100,10 +100,6 @@ typedef enum { ZEBRA_INTERFACE_LINK_PARAMS, ZEBRA_MPLS_LABELS_ADD, ZEBRA_MPLS_LABELS_DELETE, - ZEBRA_IPV4_NEXTHOP_ADD, - ZEBRA_IPV4_NEXTHOP_DELETE, - ZEBRA_IPV6_NEXTHOP_ADD, - ZEBRA_IPV6_NEXTHOP_DELETE, ZEBRA_IPMR_ROUTE_STATS, ZEBRA_LABEL_MANAGER_CONNECT, ZEBRA_GET_LABEL_CHUNK, diff --git a/zebra/zserv.c b/zebra/zserv.c index cd893b5670..aa7189fe89 100644 --- a/zebra/zserv.c +++ b/zebra/zserv.c @@ -2444,14 +2444,6 @@ static int zebra_client_read(struct thread *thread) case ZEBRA_IPV4_ROUTE_IPV6_NEXTHOP_ADD: zread_ipv4_route_ipv6_nexthop_add(client, length, zvrf); break; - case ZEBRA_IPV4_NEXTHOP_ADD: - zread_ipv4_add(client, length, - zvrf); /* LB: r1.0 merge - id was 1 */ - break; - case ZEBRA_IPV4_NEXTHOP_DELETE: - zread_ipv4_delete(client, length, - zvrf); /* LB: r1.0 merge - id was 1 */ - break; case ZEBRA_IPV6_ROUTE_ADD: zread_ipv6_add(client, length, zvrf); break; From 89a8b5cada731a52f71167b7e4faa8a7028374c6 Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Sat, 19 Aug 2017 11:28:21 -0300 Subject: [PATCH 060/130] vnc/eigrpd/isisd: check for the correct message types Signed-off-by: Renato Westphal --- bgpd/rfapi/vnc_zebra.c | 4 ++-- eigrpd/eigrp_zebra.c | 4 ++-- isisd/isis_zebra.c | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/bgpd/rfapi/vnc_zebra.c b/bgpd/rfapi/vnc_zebra.c index 8f4a550bde..29652e59db 100644 --- a/bgpd/rfapi/vnc_zebra.c +++ b/bgpd/rfapi/vnc_zebra.c @@ -367,7 +367,7 @@ static int vnc_zebra_read_ipv4(int command, struct zclient *zclient, else api.metric = 0; - if (command == ZEBRA_IPV4_ROUTE_ADD) { + if (command == ZEBRA_REDISTRIBUTE_IPV4_ADD) { if (BGP_DEBUG(zebra, ZEBRA)) { char buf[2][INET_ADDRSTRLEN]; vnc_zlog_debug_verbose( @@ -456,7 +456,7 @@ static int vnc_zebra_read_ipv6(int command, struct zclient *zclient, if (IN6_IS_ADDR_LINKLOCAL(&p.prefix)) return 0; - if (command == ZEBRA_IPV6_ROUTE_ADD) { + if (command == ZEBRA_REDISTRIBUTE_IPV6_ADD) { if (BGP_DEBUG(zebra, ZEBRA)) { char buf[INET6_ADDRSTRLEN]; vnc_zlog_debug_verbose( diff --git a/eigrpd/eigrp_zebra.c b/eigrpd/eigrp_zebra.c index 00b269b489..0ee89eb675 100644 --- a/eigrpd/eigrp_zebra.c +++ b/eigrpd/eigrp_zebra.c @@ -162,9 +162,9 @@ static int eigrp_zebra_read_ipv4(int command, struct zclient *zclient, if (eigrp == NULL) return 0; - if (command == ZEBRA_IPV4_ROUTE_ADD) { + if (command == ZEBRA_REDISTRIBUTE_IPV4_ADD) { - } else /* if (command == ZEBRA_IPV4_ROUTE_DELETE) */ + } else /* if (command == ZEBRA_REDISTRIBUTE_IPV4_DEL) */ { } diff --git a/isisd/isis_zebra.c b/isisd/isis_zebra.c index c1d558fc22..5fc3a24c30 100644 --- a/isisd/isis_zebra.c +++ b/isisd/isis_zebra.c @@ -568,7 +568,7 @@ static int isis_zebra_read_ipv4(int command, struct zclient *zclient, * without this check) */ if (p.prefixlen == 0 && api.type == ZEBRA_ROUTE_ISIS) - command = ZEBRA_IPV4_ROUTE_DELETE; + command = ZEBRA_REDISTRIBUTE_IPV4_DEL; if (command == ZEBRA_REDISTRIBUTE_IPV4_ADD) isis_redist_add(api.type, p_generic, api.distance, api.metric); @@ -637,7 +637,7 @@ static int isis_zebra_read_ipv6(int command, struct zclient *zclient, * without this check) */ if (p.prefixlen == 0 && api.type == ZEBRA_ROUTE_ISIS) - command = ZEBRA_IPV6_ROUTE_DELETE; + command = ZEBRA_REDISTRIBUTE_IPV6_DEL; if (command == ZEBRA_REDISTRIBUTE_IPV6_ADD) isis_redist_add(api.type, p_generic, api.distance, api.metric); From 34b054ba6d8ff278f52d77328475f542138ce958 Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Sat, 19 Aug 2017 11:38:47 -0300 Subject: [PATCH 061/130] *: remove leftovers from "router zebra" Signed-off-by: Renato Westphal --- babeld/babel_zebra.c | 28 ----------- bgpd/bgp_zebra.c | 16 ------ isisd/isis_zebra.c | 16 ------ lib/zclient.c | 19 -------- lib/zclient.h | 4 -- ospf6d/ospf6_zebra.c | 113 +------------------------------------------ ospfd/ospf_zebra.c | 32 ------------ ripd/rip_zebra.c | 53 -------------------- ripngd/ripng_zebra.c | 56 --------------------- 9 files changed, 1 insertion(+), 336 deletions(-) diff --git a/babeld/babel_zebra.c b/babeld/babel_zebra.c index 2ec5c3d7c3..37f441c30f 100644 --- a/babeld/babel_zebra.c +++ b/babeld/babel_zebra.c @@ -37,7 +37,6 @@ void babelz_zebra_init(void); /* we must use a pointer because of zclient.c's functions (new, free). */ struct zclient *zclient; -static int zebra_config_write (struct vty *vty); /* Debug types */ static struct { @@ -55,15 +54,6 @@ static struct { {0, 0, NULL} }; -/* Zebra node structure. */ -struct cmd_node zebra_node = -{ - ZEBRA_NODE, - "%s(config-router)# ", - 1 /* vtysh? yes */ -}; - - /* Zebra route add and delete treatment (ipv6). */ static int babel_zebra_read_ipv6 (int command, struct zclient *zclient, @@ -347,7 +337,6 @@ void babelz_zebra_init(void) zclient->redistribute_route_ipv6_add = babel_zebra_read_ipv6; zclient->redistribute_route_ipv6_del = babel_zebra_read_ipv6; - install_node (&zebra_node, zebra_config_write); install_element(BABEL_NODE, &babel_redistribute_type_cmd); install_element(ENABLE_NODE, &debug_babel_cmd); install_element(ENABLE_NODE, &no_debug_babel_cmd); @@ -357,23 +346,6 @@ void babelz_zebra_init(void) install_element(VIEW_NODE, &show_debugging_babel_cmd); } -static int -zebra_config_write (struct vty *vty) -{ - if (! zclient->enable) - { - vty_out (vty, "no router zebra\n"); - return 1; - } - else if (! vrf_bitmap_check (zclient->redist[AFI_IP][ZEBRA_ROUTE_BABEL], VRF_DEFAULT)) - { - vty_out (vty, "router zebra\n"); - vty_out (vty, " no redistribute babel\n"); - return 1; - } - return 0; -} - void babel_zebra_close_connexion(void) { diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c index 2fc75ea5a2..193775165c 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -1169,14 +1169,6 @@ void bgp_zebra_announce(struct bgp_node *rn, struct prefix *p, if (!bgp_install_info_to_zebra(bgp)) return; - if ((p->family == AF_INET - && !vrf_bitmap_check(zclient->redist[AFI_IP][ZEBRA_ROUTE_BGP], - bgp->vrf_id)) - || (p->family == AF_INET6 - && !vrf_bitmap_check(zclient->redist[AFI_IP6][ZEBRA_ROUTE_BGP], - bgp->vrf_id))) - return; - if (bgp->main_zebra_update_hold) return; @@ -1590,14 +1582,6 @@ void bgp_zebra_withdraw(struct prefix *p, struct bgp_info *info, safi_t safi) if (!bgp_install_info_to_zebra(peer->bgp)) return; - if ((p->family == AF_INET - && !vrf_bitmap_check(zclient->redist[AFI_IP][ZEBRA_ROUTE_BGP], - peer->bgp->vrf_id)) - || (p->family == AF_INET6 - && !vrf_bitmap_check(zclient->redist[AFI_IP6][ZEBRA_ROUTE_BGP], - peer->bgp->vrf_id))) - return; - flags = 0; if (peer->sort == BGP_PEER_IBGP) { diff --git a/isisd/isis_zebra.c b/isisd/isis_zebra.c index 5fc3a24c30..2eecda91bf 100644 --- a/isisd/isis_zebra.c +++ b/isisd/isis_zebra.c @@ -258,10 +258,6 @@ static void isis_zebra_route_add_ipv4(struct prefix *prefix, if (CHECK_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED)) return; - if (!vrf_bitmap_check(zclient->redist[AFI_IP][ZEBRA_ROUTE_ISIS], - VRF_DEFAULT)) - return; - message = 0; flags = 0; @@ -324,10 +320,6 @@ static void isis_zebra_route_del_ipv4(struct prefix *prefix, UNSET_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED); - if (!vrf_bitmap_check(zclient->redist[AFI_IP][ZEBRA_ROUTE_ISIS], - VRF_DEFAULT)) - return; - api.vrf_id = VRF_DEFAULT; api.type = ZEBRA_ROUTE_ISIS; api.instance = 0; @@ -505,14 +497,6 @@ void isis_zebra_route_update(struct prefix *prefix, if (zclient->sock < 0) return; - if ((prefix->family == AF_INET - && !vrf_bitmap_check(zclient->redist[AFI_IP][ZEBRA_ROUTE_ISIS], - VRF_DEFAULT)) - || (prefix->family == AF_INET6 - && !vrf_bitmap_check(zclient->redist[AFI_IP6][ZEBRA_ROUTE_ISIS], - VRF_DEFAULT))) - return; - if (CHECK_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ACTIVE)) { if (prefix->family == AF_INET) isis_zebra_route_add_ipv4(prefix, route_info); diff --git a/lib/zclient.c b/lib/zclient.c index 24cb699196..f8bbdd85c9 100644 --- a/lib/zclient.c +++ b/lib/zclient.c @@ -352,10 +352,6 @@ void zclient_send_reg_requests(struct zclient *zclient, vrf_id_t vrf_id) int i; afi_t afi; - /* zclient is disabled. */ - if (!zclient->enable) - return; - /* If not connected to the zebra yet. */ if (zclient->sock < 0) return; @@ -418,10 +414,6 @@ void zclient_send_dereg_requests(struct zclient *zclient, vrf_id_t vrf_id) int i; afi_t afi; - /* zclient is disabled. */ - if (!zclient->enable) - return; - /* If not connected to the zebra yet. */ if (zclient->sock < 0) return; @@ -485,10 +477,6 @@ void zclient_send_interface_radv_req(struct zclient *zclient, vrf_id_t vrf_id, { struct stream *s; - /* zclient is disabled. */ - if (!zclient->enable) - return; - /* If not connected to the zebra yet. */ if (zclient->sock < 0) return; @@ -516,10 +504,6 @@ int zclient_start(struct zclient *zclient) if (zclient_debug) zlog_info("zclient_start is called"); - /* zclient is disabled. */ - if (!zclient->enable) - return 0; - /* If already connected to the zebra. */ if (zclient->sock >= 0) return 0; @@ -564,9 +548,6 @@ void zclient_init(struct zclient *zclient, int redist_default, u_short instance) { int afi, i; - /* Enable zebra client connection by default. */ - zclient->enable = 1; - /* Set -1 to the default socket value. */ zclient->sock = -1; diff --git a/lib/zclient.h b/lib/zclient.h index 0218c1b732..ddd9655443 100644 --- a/lib/zclient.h +++ b/lib/zclient.h @@ -137,10 +137,6 @@ struct zclient { /* Socket to zebra daemon. */ int sock; - /* Flag of communication to zebra is enabled or not. Default is on. - This flag is disabled by `no router zebra' statement. */ - int enable; - /* Connection failure count. */ int fail; diff --git a/ospf6d/ospf6_zebra.c b/ospf6d/ospf6_zebra.c index dc97f1ff4b..1c266da888 100644 --- a/ospf6d/ospf6_zebra.c +++ b/ospf6d/ospf6_zebra.c @@ -317,7 +317,7 @@ DEFUN (show_zebra, } vty_out(vty, "Zebra Infomation\n"); - vty_out(vty, " enable: %d fail: %d\n", zclient->enable, zclient->fail); + vty_out(vty, " fail: %d\n", zclient->fail); vty_out(vty, " redistribute default: %d\n", vrf_bitmap_check(zclient->default_information, VRF_DEFAULT)); vty_out(vty, " redistribute:"); @@ -329,27 +329,6 @@ DEFUN (show_zebra, return CMD_SUCCESS; } -/* Zebra configuration write function. */ -static int config_write_ospf6_zebra(struct vty *vty) -{ - if (!zclient->enable) { - vty_out(vty, "no router zebra\n"); - vty_out(vty, "!\n"); - } else if (!vrf_bitmap_check( - zclient->redist[AFI_IP6][ZEBRA_ROUTE_OSPF6], - VRF_DEFAULT)) { - vty_out(vty, "router zebra\n"); - vty_out(vty, " no redistribute ospf6\n"); - vty_out(vty, "!\n"); - } - return 0; -} - -/* Zebra node structure. */ -static struct cmd_node zebra_node = { - ZEBRA_NODE, "%s(config-zebra)# ", -}; - #define ADD 0 #define REM 1 static void ospf6_zebra_route_update(int type, struct ospf6_route *request) @@ -471,23 +450,11 @@ static void ospf6_zebra_route_update(int type, struct ospf6_route *request) void ospf6_zebra_route_update_add(struct ospf6_route *request) { - if (!vrf_bitmap_check(zclient->redist[AFI_IP6][ZEBRA_ROUTE_OSPF6], - VRF_DEFAULT)) { - ospf6->route_table->hook_add = NULL; - ospf6->route_table->hook_remove = NULL; - return; - } ospf6_zebra_route_update(ADD, request); } void ospf6_zebra_route_update_remove(struct ospf6_route *request) { - if (!vrf_bitmap_check(zclient->redist[AFI_IP6][ZEBRA_ROUTE_OSPF6], - VRF_DEFAULT)) { - ospf6->route_table->hook_add = NULL; - ospf6->route_table->hook_remove = NULL; - return; - } ospf6_zebra_route_update(REM, request); } @@ -497,10 +464,6 @@ void ospf6_zebra_add_discard(struct ospf6_route *request) char buf[INET6_ADDRSTRLEN]; struct prefix_ipv6 *dest; - if (!vrf_bitmap_check(zclient->redist[AFI_IP6][ZEBRA_ROUTE_OSPF6], - VRF_DEFAULT)) - return; - if (!CHECK_FLAG(request->flag, OSPF6_ROUTE_BLACKHOLE_ADDED)) { api.vrf_id = VRF_DEFAULT; api.type = ZEBRA_ROUTE_OSPF6; @@ -542,10 +505,6 @@ void ospf6_zebra_delete_discard(struct ospf6_route *request) char buf[INET6_ADDRSTRLEN]; struct prefix_ipv6 *dest; - if (!vrf_bitmap_check(zclient->redist[AFI_IP6][ZEBRA_ROUTE_OSPF6], - VRF_DEFAULT)) - return; - if (CHECK_FLAG(request->flag, OSPF6_ROUTE_BLACKHOLE_ADDED)) { api.vrf_id = VRF_DEFAULT; api.type = ZEBRA_ROUTE_OSPF6; @@ -580,65 +539,6 @@ void ospf6_zebra_delete_discard(struct ospf6_route *request) } } -DEFUN (redistribute_ospf6, - redistribute_ospf6_cmd, - "redistribute ospf6", - "Redistribute control\n" - "OSPF6 route\n") -{ - struct ospf6_route *route; - - if (vrf_bitmap_check(zclient->redist[AFI_IP6][ZEBRA_ROUTE_OSPF6], - VRF_DEFAULT)) - return CMD_SUCCESS; - - vrf_bitmap_set(zclient->redist[AFI_IP6][ZEBRA_ROUTE_OSPF6], - VRF_DEFAULT); - - if (ospf6 == NULL) - return CMD_SUCCESS; - - /* send ospf6 route to zebra route table */ - for (route = ospf6_route_head(ospf6->route_table); route; - route = ospf6_route_next(route)) - ospf6_zebra_route_update_add(route); - - ospf6->route_table->hook_add = ospf6_zebra_route_update_add; - ospf6->route_table->hook_remove = ospf6_zebra_route_update_remove; - - return CMD_SUCCESS; -} - -DEFUN (no_redistribute_ospf6, - no_redistribute_ospf6_cmd, - "no redistribute ospf6", - NO_STR - "Redistribute control\n" - "OSPF6 route\n") -{ - struct ospf6_route *route; - - if (!vrf_bitmap_check(zclient->redist[AFI_IP6][ZEBRA_ROUTE_OSPF6], - VRF_DEFAULT)) - return CMD_SUCCESS; - - vrf_bitmap_unset(zclient->redist[AFI_IP6][ZEBRA_ROUTE_OSPF6], - VRF_DEFAULT); - - if (ospf6 == NULL) - return CMD_SUCCESS; - - ospf6->route_table->hook_add = NULL; - ospf6->route_table->hook_remove = NULL; - - /* withdraw ospf6 route from zebra route table */ - for (route = ospf6_route_head(ospf6->route_table); route; - route = ospf6_route_next(route)) - ospf6_zebra_route_update_remove(route); - - return CMD_SUCCESS; -} - static struct ospf6_distance *ospf6_distance_new(void) { return XCALLOC(MTYPE_OSPF6_DISTANCE, sizeof(struct ospf6_distance)); @@ -794,19 +694,8 @@ void ospf6_zebra_init(struct thread_master *master) zclient->redistribute_route_ipv6_add = ospf6_zebra_read_ipv6; zclient->redistribute_route_ipv6_del = ospf6_zebra_read_ipv6; - /* redistribute connected route by default */ - /* ospf6_zebra_redistribute (ZEBRA_ROUTE_CONNECT); */ - - /* Install zebra node. */ - install_node(&zebra_node, config_write_ospf6_zebra); - /* Install command element for zebra node. */ install_element(VIEW_NODE, &show_ospf6_zebra_cmd); - install_default(ZEBRA_NODE); - install_element(ZEBRA_NODE, &redistribute_ospf6_cmd); - install_element(ZEBRA_NODE, &no_redistribute_ospf6_cmd); - - return; } /* Debug */ diff --git a/ospfd/ospf_zebra.c b/ospfd/ospf_zebra.c index f9668f2495..6d9d56d92d 100644 --- a/ospfd/ospf_zebra.c +++ b/ospfd/ospf_zebra.c @@ -342,14 +342,6 @@ void ospf_zebra_add(struct prefix_ipv4 *p, struct ospf_route * or) struct listnode *node; struct ospf *ospf = ospf_lookup(); - if (!(ospf->instance - && redist_check_instance( - &zclient->mi_redist[AFI_IP][ZEBRA_ROUTE_OSPF], - ospf->instance)) - && !vrf_bitmap_check(zclient->redist[AFI_IP][ZEBRA_ROUTE_OSPF], - VRF_DEFAULT)) - return; - message = 0; flags = 0; @@ -465,14 +457,6 @@ void ospf_zebra_delete(struct prefix_ipv4 *p, struct ospf_route * or) struct listnode *node; struct ospf *ospf = ospf_lookup(); - if (!(ospf->instance - && redist_check_instance( - &zclient->mi_redist[AFI_IP][ZEBRA_ROUTE_OSPF], - ospf->instance)) - && !vrf_bitmap_check(zclient->redist[AFI_IP][ZEBRA_ROUTE_OSPF], - VRF_DEFAULT)) - return; - message = 0; flags = 0; /* Distance value. */ @@ -543,14 +527,6 @@ void ospf_zebra_add_discard(struct prefix_ipv4 *p) struct zapi_ipv4 api; struct ospf *ospf = ospf_lookup(); - if (!(ospf->instance - && redist_check_instance( - &zclient->mi_redist[AFI_IP][ZEBRA_ROUTE_OSPF], - ospf->instance)) - && !vrf_bitmap_check(zclient->redist[AFI_IP][ZEBRA_ROUTE_OSPF], - VRF_DEFAULT)) - return; - api.vrf_id = VRF_DEFAULT; api.type = ZEBRA_ROUTE_OSPF; api.instance = ospf->instance; @@ -574,14 +550,6 @@ void ospf_zebra_delete_discard(struct prefix_ipv4 *p) struct zapi_ipv4 api; struct ospf *ospf = ospf_lookup(); - if (!(ospf->instance - && redist_check_instance( - &zclient->mi_redist[AFI_IP][ZEBRA_ROUTE_OSPF], - ospf->instance)) - && !vrf_bitmap_check(zclient->redist[AFI_IP][ZEBRA_ROUTE_OSPF], - VRF_DEFAULT)) - return; - api.vrf_id = VRF_DEFAULT; api.type = ZEBRA_ROUTE_OSPF; api.instance = ospf->instance; diff --git a/ripd/rip_zebra.c b/ripd/rip_zebra.c index 8a166745ec..f9d2d33f19 100644 --- a/ripd/rip_zebra.c +++ b/ripd/rip_zebra.c @@ -48,10 +48,6 @@ static void rip_zebra_ipv4_send(struct route_node *rp, u_char cmd) struct rip_info *rinfo = NULL; int count = 0; - if (!vrf_bitmap_check(zclient->redist[AFI_IP][ZEBRA_ROUTE_RIP], - VRF_DEFAULT)) - return; - api.vrf_id = VRF_DEFAULT; api.type = ZEBRA_ROUTE_RIP; api.instance = 0; @@ -295,27 +291,6 @@ void rip_redistribute_clean(void) } } -DEFUN (rip_redistribute_rip, - rip_redistribute_rip_cmd, - "redistribute rip", - "Redistribute information from another routing protocol\n" - "Routing Information Protocol (RIP)\n") -{ - vrf_bitmap_set(zclient->redist[AFI_IP][ZEBRA_ROUTE_RIP], VRF_DEFAULT); - return CMD_SUCCESS; -} - -DEFUN (no_rip_redistribute_rip, - no_rip_redistribute_rip_cmd, - "no redistribute rip", - NO_STR - "Redistribute information from another routing protocol\n" - "Routing Information Protocol (RIP)\n") -{ - vrf_bitmap_unset(zclient->redist[AFI_IP][ZEBRA_ROUTE_RIP], VRF_DEFAULT); - return CMD_SUCCESS; -} - DEFUN (rip_redistribute_type, rip_redistribute_type_cmd, "redistribute " FRR_REDIST_STR_RIPD, @@ -601,21 +576,6 @@ DEFUN (no_rip_default_information_originate, return CMD_SUCCESS; } -/* RIP configuration write function. */ -static int config_write_zebra(struct vty *vty) -{ - if (!zclient->enable) { - vty_out(vty, "no router zebra\n"); - return 1; - } else if (!vrf_bitmap_check(zclient->redist[AFI_IP][ZEBRA_ROUTE_RIP], - VRF_DEFAULT)) { - vty_out(vty, "router zebra\n"); - vty_out(vty, " no redistribute rip\n"); - return 1; - } - return 0; -} - int config_write_rip_redistribute(struct vty *vty, int config_mode) { int i; @@ -656,11 +616,6 @@ int config_write_rip_redistribute(struct vty *vty, int config_mode) return 0; } -/* Zebra node structure. */ -static struct cmd_node zebra_node = { - ZEBRA_NODE, "%s(config-router)# ", -}; - static void rip_zebra_connected(struct zclient *zclient) { zclient_send_reg_requests(zclient, VRF_DEFAULT); @@ -681,14 +636,6 @@ void rip_zclient_init(struct thread_master *master) zclient->redistribute_route_ipv4_add = rip_zebra_read_ipv4; zclient->redistribute_route_ipv4_del = rip_zebra_read_ipv4; - /* Install zebra node. */ - install_node(&zebra_node, config_write_zebra); - - /* Install command elements to zebra node. */ - install_default(ZEBRA_NODE); - install_element(ZEBRA_NODE, &rip_redistribute_rip_cmd); - install_element(ZEBRA_NODE, &no_rip_redistribute_rip_cmd); - /* Install command elements to rip node. */ install_element(RIP_NODE, &rip_redistribute_type_cmd); install_element(RIP_NODE, &rip_redistribute_type_routemap_cmd); diff --git a/ripngd/ripng_zebra.c b/ripngd/ripng_zebra.c index 875ec4f225..3845028264 100644 --- a/ripngd/ripng_zebra.c +++ b/ripngd/ripng_zebra.c @@ -49,10 +49,6 @@ static void ripng_zebra_ipv6_send(struct route_node *rp, u_char cmd) struct ripng_info *rinfo = NULL; int count = 0; - if (!vrf_bitmap_check(zclient->redist[AFI_IP6][ZEBRA_ROUTE_RIPNG], - VRF_DEFAULT)) - return; - api.vrf_id = VRF_DEFAULT; api.type = ZEBRA_ROUTE_RIPNG; api.instance = 0; @@ -292,29 +288,6 @@ void ripng_redistribute_clean() } } -DEFUN (ripng_redistribute_ripng, - ripng_redistribute_ripng_cmd, - "redistribute ripng", - "Redistribute information from another routing protocol\n" - "RIPng route\n") -{ - vrf_bitmap_set(zclient->redist[AFI_IP6][ZEBRA_ROUTE_RIPNG], - VRF_DEFAULT); - return CMD_SUCCESS; -} - -DEFUN (no_ripng_redistribute_ripng, - no_ripng_redistribute_ripng_cmd, - "no redistribute ripng", - NO_STR - "Redistribute information from another routing protocol\n" - "RIPng route\n") -{ - vrf_bitmap_unset(zclient->redist[AFI_IP6][ZEBRA_ROUTE_RIPNG], - VRF_DEFAULT); - return CMD_SUCCESS; -} - DEFUN (ripng_redistribute_type, ripng_redistribute_type_cmd, "redistribute " FRR_REDIST_STR_RIPNGD, @@ -484,27 +457,6 @@ void ripng_redistribute_write(struct vty *vty, int config_mode) } } -/* RIPng configuration write function. */ -static int zebra_config_write(struct vty *vty) -{ - if (!zclient->enable) { - vty_out(vty, "no router zebra\n"); - return 1; - } else if (!vrf_bitmap_check( - zclient->redist[AFI_IP6][ZEBRA_ROUTE_RIPNG], - VRF_DEFAULT)) { - vty_out(vty, "router zebra\n"); - vty_out(vty, " no redistribute ripng\n"); - return 1; - } - return 0; -} - -/* Zebra node structure. */ -static struct cmd_node zebra_node = { - ZEBRA_NODE, "%s(config-router)# ", -}; - static void ripng_zebra_connected(struct zclient *zclient) { zclient_send_reg_requests(zclient, VRF_DEFAULT); @@ -527,14 +479,6 @@ void zebra_init(struct thread_master *master) zclient->redistribute_route_ipv6_add = ripng_zebra_read_ipv6; zclient->redistribute_route_ipv6_del = ripng_zebra_read_ipv6; - /* Install zebra node. */ - install_node(&zebra_node, zebra_config_write); - - /* Install command element for zebra node. */ - install_default(ZEBRA_NODE); - install_element(ZEBRA_NODE, &ripng_redistribute_ripng_cmd); - install_element(ZEBRA_NODE, &no_ripng_redistribute_ripng_cmd); - /* Install command elements to ripng node */ install_element(RIPNG_NODE, &ripng_redistribute_type_cmd); install_element(RIPNG_NODE, &ripng_redistribute_type_routemap_cmd); From c125d1d41ef05cf8bd440a3eab94483c18b9874c Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Sat, 19 Aug 2017 12:09:38 -0300 Subject: [PATCH 062/130] babeld/nhrpd: ignore ipv6 srcdest routes Signed-off-by: Renato Westphal --- babeld/babel_zebra.c | 12 +++++++++++- nhrpd/nhrp_route.c | 12 ++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/babeld/babel_zebra.c b/babeld/babel_zebra.c index 37f441c30f..a1d3a9e8cc 100644 --- a/babeld/babel_zebra.c +++ b/babeld/babel_zebra.c @@ -63,7 +63,7 @@ babel_zebra_read_ipv6 (int command, struct zclient *zclient, struct zapi_ipv6 api; unsigned long ifindex = -1; struct in6_addr nexthop; - struct prefix_ipv6 prefix; + struct prefix_ipv6 prefix, src_p; s = zclient->ibuf; ifindex = 0; @@ -82,6 +82,16 @@ babel_zebra_read_ipv6 (int command, struct zclient *zclient, prefix.prefixlen = stream_getc (s); stream_get (&prefix.prefix, s, PSIZE (prefix.prefixlen)); + memset(&src_p, 0, sizeof(src_p)); + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX)) { + src_p.family = AF_INET6; + src_p.prefixlen = stream_getc(s); + stream_get(&src_p.prefix, s, PSIZE(src_p.prefixlen)); + } + if (src_p.prefixlen) + /* we completely ignore srcdest routes for now. */ + return 0; + /* Nexthop, ifindex, distance, metric. */ if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP)) { api.nexthop_num = stream_getc (s); diff --git a/nhrpd/nhrp_route.c b/nhrpd/nhrp_route.c index c8a608c657..e9651adc54 100644 --- a/nhrpd/nhrp_route.c +++ b/nhrpd/nhrp_route.c @@ -193,6 +193,7 @@ int nhrp_route_read(int cmd, struct zclient *zclient, zebra_size_t length, vrf_i struct stream *s; struct interface *ifp = NULL; struct prefix prefix; + struct prefix_ipv6 src_p; union sockunion nexthop_addr; unsigned char message, nexthop_num, ifindex_num; unsigned ifindex; @@ -226,6 +227,17 @@ int nhrp_route_read(int cmd, struct zclient *zclient, zebra_size_t length, vrf_i prefix.prefixlen = stream_getc(s); stream_get(&prefix.u.val, s, PSIZE(prefix.prefixlen)); + memset(&src_p, 0, sizeof(src_p)); + if (prefix.family == AF_INET6 && + CHECK_FLAG(message, ZAPI_MESSAGE_SRCPFX)) { + src_p.family = AF_INET6; + src_p.prefixlen = stream_getc(s); + stream_get(&src_p.prefix, s, PSIZE(src_p.prefixlen)); + } + if (src_p.prefixlen) + /* we completely ignore srcdest routes for now. */ + return 0; + /* Nexthop, ifindex, distance, metric. */ if (CHECK_FLAG(message, ZAPI_MESSAGE_NEXTHOP|ZAPI_MESSAGE_IFINDEX)) { nexthop_num = stream_getc(s); From f38efb809d91605b3b29cf9eb226825d28f680af Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Sat, 19 Aug 2017 13:01:00 -0300 Subject: [PATCH 063/130] zebra: add support for NEXTHOP_TYPE_IPV6_IFINDEX in zserv This is the v6 counterpart of commit c963c20. Fixes a bug where ipv6 routes received from babeld were being ignored. Signed-off-by: Renato Westphal --- zebra/zserv.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/zebra/zserv.c b/zebra/zserv.c index aa7189fe89..b2ee9c0b47 100644 --- a/zebra/zserv.c +++ b/zebra/zserv.c @@ -1534,6 +1534,7 @@ static int zread_ipv6_add(struct zserv *client, u_short length, unsigned int i; struct stream *s; struct in6_addr nhop_addr; + ifindex_t ifindex; struct route_entry *re; u_char message; u_char nexthop_num; @@ -1609,6 +1610,12 @@ static int zread_ipv6_add(struct zserv *client, u_short length, nexthops[nh_count++] = nhop_addr; } break; + case NEXTHOP_TYPE_IPV6_IFINDEX: + stream_get(&nhop_addr, s, 16); + ifindex = stream_getl(s); + route_entry_nexthop_ipv6_ifindex_add( + re, &nhop_addr, ifindex); + break; case NEXTHOP_TYPE_IFINDEX: if (if_count < multipath_num) { ifindices[if_count++] = stream_getl(s); From e959008b1ef36acc572d41555f7df2d3e7f9a0cf Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Sat, 19 Aug 2017 14:12:20 -0300 Subject: [PATCH 064/130] babeld/eigrpd/ldpd/nhrpd: add prefix length sanity checks Pulled from d917882. Signed-off-by: Renato Westphal --- babeld/babel_zebra.c | 6 +++--- eigrpd/eigrp_zebra.c | 2 +- ldpd/ldp_zebra.c | 3 ++- nhrpd/nhrp_route.c | 3 ++- 4 files changed, 8 insertions(+), 6 deletions(-) diff --git a/babeld/babel_zebra.c b/babeld/babel_zebra.c index a1d3a9e8cc..2b998940d7 100644 --- a/babeld/babel_zebra.c +++ b/babeld/babel_zebra.c @@ -79,7 +79,7 @@ babel_zebra_read_ipv6 (int command, struct zclient *zclient, /* IPv6 prefix. */ prefix.family = AF_INET6; - prefix.prefixlen = stream_getc (s); + prefix.prefixlen = MIN (IPV6_MAX_PREFIXLEN, stream_getc (s)); stream_get (&prefix.prefix, s, PSIZE (prefix.prefixlen)); memset(&src_p, 0, sizeof(src_p)); @@ -140,9 +140,9 @@ babel_zebra_read_ipv4 (int command, struct zclient *zclient, api.flags = stream_getl (s); api.message = stream_getc (s); - /* IPv6 prefix. */ + /* IPv4 prefix. */ prefix.family = AF_INET; - prefix.prefixlen = stream_getc (s); + prefix.prefixlen = MIN (IPV4_MAX_PREFIXLEN, stream_getc (s)); stream_get (&prefix.prefix, s, PSIZE (prefix.prefixlen)); /* Nexthop, ifindex, distance, metric. */ diff --git a/eigrpd/eigrp_zebra.c b/eigrpd/eigrp_zebra.c index 0ee89eb675..6fc3f29353 100644 --- a/eigrpd/eigrp_zebra.c +++ b/eigrpd/eigrp_zebra.c @@ -137,7 +137,7 @@ static int eigrp_zebra_read_ipv4(int command, struct zclient *zclient, /* IPv4 prefix. */ memset(&p, 0, sizeof(struct prefix_ipv4)); p.family = AF_INET; - p.prefixlen = stream_getc(s); + p.prefixlen = MIN(IPV4_MAX_PREFIXLEN, stream_getc(s)); stream_get(&p.prefix, s, PSIZE(p.prefixlen)); if (IPV4_NET127(ntohl(p.prefix.s_addr))) diff --git a/ldpd/ldp_zebra.c b/ldpd/ldp_zebra.c index ecc7db8f2e..54c5af62a4 100644 --- a/ldpd/ldp_zebra.c +++ b/ldpd/ldp_zebra.c @@ -427,17 +427,18 @@ ldp_zebra_read_route(int command, struct zclient *zclient, zebra_size_t length, case ZEBRA_REDISTRIBUTE_IPV4_ADD: case ZEBRA_REDISTRIBUTE_IPV4_DEL: kr.af = AF_INET; + kr.prefixlen = MIN(IPV4_MAX_PREFIXLEN, stream_getc(s)); nhlen = sizeof(struct in_addr); break; case ZEBRA_REDISTRIBUTE_IPV6_ADD: case ZEBRA_REDISTRIBUTE_IPV6_DEL: kr.af = AF_INET6; + kr.prefixlen = MIN(IPV6_MAX_PREFIXLEN, stream_getc(s)); nhlen = sizeof(struct in6_addr); break; default: fatalx("ldp_zebra_read_route: unknown command"); } - kr.prefixlen = stream_getc(s); stream_get(&kr.prefix, s, PSIZE(kr.prefixlen)); if (bad_addr(kr.af, &kr.prefix) || diff --git a/nhrpd/nhrp_route.c b/nhrpd/nhrp_route.c index e9651adc54..5116ad068c 100644 --- a/nhrpd/nhrp_route.c +++ b/nhrpd/nhrp_route.c @@ -215,16 +215,17 @@ int nhrp_route_read(int cmd, struct zclient *zclient, zebra_size_t length, vrf_i case ZEBRA_REDISTRIBUTE_IPV4_ADD: case ZEBRA_REDISTRIBUTE_IPV4_DEL: prefix.family = AF_INET; + prefix.prefixlen = MIN(IPV4_MAX_PREFIXLEN, stream_getc(s)); break; case ZEBRA_REDISTRIBUTE_IPV6_ADD: case ZEBRA_REDISTRIBUTE_IPV6_DEL: prefix.family = AF_INET6; + prefix.prefixlen = MIN(IPV6_MAX_PREFIXLEN, stream_getc(s)); break; default: return -1; } afaddrlen = family2addrsize(prefix.family); - prefix.prefixlen = stream_getc(s); stream_get(&prefix.u.val, s, PSIZE(prefix.prefixlen)); memset(&src_p, 0, sizeof(src_p)); From d51b9e4509f69cf3f871a787e69534a60842bab5 Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Sat, 19 Aug 2017 14:26:00 -0300 Subject: [PATCH 065/130] zserv: simplify handling of route delete requests Route attributes like tag, distance and metric are irrelevant when we want to delete a route from a client daemon. The same can be said about the nexthops of the route. Only the IP prefix and client protocol are enough to identify the route we want to remove, considering that zebra maintains at most one route from each client daemon for each prefix. Once rib_delete() is called, it deletes the selected route with all of its nexthops. Signed-off-by: Renato Westphal --- zebra/zserv.c | 125 ++------------------------------------------------ 1 file changed, 3 insertions(+), 122 deletions(-) diff --git a/zebra/zserv.c b/zebra/zserv.c index b2ee9c0b47..a196eb5945 100644 --- a/zebra/zserv.c +++ b/zebra/zserv.c @@ -1281,21 +1281,12 @@ static int zread_ipv4_add(struct zserv *client, u_short length, static int zread_ipv4_delete(struct zserv *client, u_short length, struct zebra_vrf *zvrf) { - int i; struct stream *s; struct zapi_ipv4 api; - struct in_addr nexthop; - union g_addr *nexthop_p; - unsigned long ifindex; struct prefix p; - u_char nexthop_num; - u_char nexthop_type; u_int32_t table_id; s = client->ibuf; - ifindex = 0; - nexthop.s_addr = 0; - nexthop_p = NULL; /* Type, flags, message. */ api.type = stream_getc(s); @@ -1310,63 +1301,10 @@ static int zread_ipv4_delete(struct zserv *client, u_short length, p.prefixlen = stream_getc(s); stream_get(&p.u.prefix4, s, PSIZE(p.prefixlen)); - /* Nexthop, ifindex, distance, metric. */ - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP)) { - nexthop_num = stream_getc(s); - - for (i = 0; i < nexthop_num; i++) { - nexthop_type = stream_getc(s); - - switch (nexthop_type) { - case NEXTHOP_TYPE_IFINDEX: - ifindex = stream_getl(s); - break; - case NEXTHOP_TYPE_IPV4: - nexthop.s_addr = stream_get_ipv4(s); - /* For labeled-unicast, each nexthop is followed - * by label, but - * we don't care for delete. - */ - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_LABEL)) - stream_forward_getp(s, - sizeof(u_int32_t)); - nexthop_p = (union g_addr *)&nexthop; - break; - case NEXTHOP_TYPE_IPV4_IFINDEX: - nexthop.s_addr = stream_get_ipv4(s); - nexthop_p = (union g_addr *)&nexthop; - ifindex = stream_getl(s); - break; - case NEXTHOP_TYPE_IPV6: - stream_forward_getp(s, IPV6_MAX_BYTELEN); - break; - } - } - } - - /* Distance. */ - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_DISTANCE)) - api.distance = stream_getc(s); - else - api.distance = 0; - - /* Metric. */ - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_METRIC)) - api.metric = stream_getl(s); - else - api.metric = 0; - - /* tag */ - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_TAG)) - api.tag = stream_getl(s); - else - api.tag = 0; - table_id = zvrf->table_id; rib_delete(AFI_IP, api.safi, zvrf_id(zvrf), api.type, api.instance, - api.flags, &p, NULL, nexthop_p, ifindex, table_id, - api.metric); + api.flags, &p, NULL, NULL, 0, table_id, 0); client->v4_route_del_cnt++; return 0; } @@ -1688,18 +1626,12 @@ static int zread_ipv6_add(struct zserv *client, u_short length, static int zread_ipv6_delete(struct zserv *client, u_short length, struct zebra_vrf *zvrf) { - int i; struct stream *s; struct zapi_ipv6 api; - struct in6_addr nexthop; - union g_addr *pnexthop = NULL; - unsigned long ifindex; struct prefix p; struct prefix_ipv6 src_p, *src_pp; s = client->ibuf; - ifindex = 0; - memset(&nexthop, 0, sizeof(struct in6_addr)); /* Type, flags, message. */ api.type = stream_getc(s); @@ -1723,59 +1655,8 @@ static int zread_ipv6_delete(struct zserv *client, u_short length, } else src_pp = NULL; - /* Nexthop, ifindex, distance, metric. */ - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP)) { - u_char nexthop_type; - - api.nexthop_num = stream_getc(s); - for (i = 0; i < api.nexthop_num; i++) { - nexthop_type = stream_getc(s); - - switch (nexthop_type) { - case NEXTHOP_TYPE_IPV6: - stream_get(&nexthop, s, 16); - /* For labeled-unicast, each nexthop is followed - * by label, but - * we don't care for delete. - */ - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_LABEL)) - stream_forward_getp(s, - sizeof(u_int32_t)); - pnexthop = (union g_addr *)&nexthop; - break; - case NEXTHOP_TYPE_IFINDEX: - ifindex = stream_getl(s); - break; - } - } - } - - /* Distance. */ - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_DISTANCE)) - api.distance = stream_getc(s); - else - api.distance = 0; - - /* Metric. */ - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_METRIC)) - api.metric = stream_getl(s); - else - api.metric = 0; - - /* tag */ - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_TAG)) - api.tag = stream_getl(s); - else - api.tag = 0; - - if (IN6_IS_ADDR_UNSPECIFIED(&nexthop)) - rib_delete(AFI_IP6, api.safi, zvrf_id(zvrf), api.type, - api.instance, api.flags, &p, src_pp, NULL, ifindex, - client->rtm_table, api.metric); - else - rib_delete(AFI_IP6, api.safi, zvrf_id(zvrf), api.type, - api.instance, api.flags, &p, src_pp, pnexthop, - ifindex, client->rtm_table, api.metric); + rib_delete(AFI_IP6, api.safi, zvrf_id(zvrf), api.type, api.instance, + api.flags, &p, src_pp, NULL, 0, client->rtm_table, 0); client->v6_route_del_cnt++; return 0; From 81c11e3feafcd20e32cb2d437f39603d645e6880 Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Sat, 19 Aug 2017 20:00:25 -0300 Subject: [PATCH 066/130] zserv: identify label type based on the client protocol This fixes a problem where the type of the BGP-LU labels was not being set. Signed-off-by: Renato Westphal --- zebra/zserv.c | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/zebra/zserv.c b/zebra/zserv.c index a196eb5945..e00e1d7c20 100644 --- a/zebra/zserv.c +++ b/zebra/zserv.c @@ -1176,6 +1176,7 @@ static int zread_ipv4_add(struct zserv *client, u_short length, ifindex_t ifindex; safi_t safi; int ret; + enum lsp_types_t label_type; mpls_label_t label; struct nexthop *nexthop; @@ -1208,6 +1209,9 @@ static int zread_ipv4_add(struct zserv *client, u_short length, zserv_nexthop_num_warn(__func__, (const struct prefix *)&p, nexthop_num); + if (CHECK_FLAG(message, ZAPI_MESSAGE_LABEL)) + label_type = lsp_type_from_re_type(client->proto); + for (i = 0; i < nexthop_num; i++) { nexthop_type = stream_getc(s); @@ -1224,9 +1228,8 @@ static int zread_ipv4_add(struct zserv *client, u_short length, * by label. */ if (CHECK_FLAG(message, ZAPI_MESSAGE_LABEL)) { label = (mpls_label_t)stream_getl(s); - nexthop_add_labels( - nexthop, nexthop->nh_label_type, - 1, &label); + nexthop_add_labels(nexthop, label_type, + 1, &label); } break; case NEXTHOP_TYPE_IPV4_IFINDEX: @@ -1339,6 +1342,7 @@ static int zread_ipv4_route_ipv6_nexthop_add(struct zserv *client, static unsigned int ifindices[MULTIPATH_NUM]; int ret; static mpls_label_t labels[MULTIPATH_NUM]; + enum lsp_types_t label_type; mpls_label_t label; struct nexthop *nexthop; @@ -1379,6 +1383,10 @@ static int zread_ipv4_route_ipv6_nexthop_add(struct zserv *client, nexthop_num = stream_getc(s); zserv_nexthop_num_warn(__func__, (const struct prefix *)&p, nexthop_num); + + if (CHECK_FLAG(message, ZAPI_MESSAGE_LABEL)) + label_type = lsp_type_from_re_type(client->proto); + for (i = 0; i < nexthop_num; i++) { nexthop_type = stream_getc(s); @@ -1423,9 +1431,8 @@ static int zread_ipv4_route_ipv6_nexthop_add(struct zserv *client, re, &nexthops[i]); if (CHECK_FLAG(message, ZAPI_MESSAGE_LABEL)) - nexthop_add_labels( - nexthop, nexthop->nh_label_type, - 1, &labels[i]); + nexthop_add_labels(nexthop, label_type, + 1, &labels[i]); } else { if ((i < if_count) && ifindices[i]) route_entry_nexthop_ifindex_add( @@ -1484,6 +1491,7 @@ static int zread_ipv6_add(struct zserv *client, u_short length, static unsigned int ifindices[MULTIPATH_NUM]; int ret; static mpls_label_t labels[MULTIPATH_NUM]; + enum lsp_types_t label_type; mpls_label_t label; struct nexthop *nexthop; @@ -1530,6 +1538,10 @@ static int zread_ipv6_add(struct zserv *client, u_short length, nexthop_num = stream_getc(s); zserv_nexthop_num_warn(__func__, (const struct prefix *)&p, nexthop_num); + + if (CHECK_FLAG(message, ZAPI_MESSAGE_LABEL)) + label_type = lsp_type_from_re_type(client->proto); + for (i = 0; i < nexthop_num; i++) { nexthop_type = stream_getc(s); @@ -1578,9 +1590,8 @@ static int zread_ipv6_add(struct zserv *client, u_short length, nexthop = route_entry_nexthop_ipv6_add( re, &nexthops[i]); if (CHECK_FLAG(message, ZAPI_MESSAGE_LABEL)) - nexthop_add_labels( - nexthop, nexthop->nh_label_type, - 1, &labels[i]); + nexthop_add_labels(nexthop, label_type, + 1, &labels[i]); } else { if ((i < if_count) && ifindices[i]) route_entry_nexthop_ifindex_add( From bb1b9c47ca090ce4484e1f8061f17b5c33f578ee Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Sat, 19 Aug 2017 21:25:12 -0300 Subject: [PATCH 067/130] lib: updates to zapi_route This patch introduces the following changes to the zapi_route structure and associated code: * Use a fixed-size array to store the nexthops instead of a pointer. This makes the zapi_route() function much easier to use when we have multiple nexthops to send. It's also much more efficient to put everything on the stack rather than allocating an array in the heap every time we need to send a route to zebra; * Use the new 'zapi_nexthop' structure. This will allow the client daemons to send labeled routes without having to allocate memory for the labels (the 'nexthop' structure was designed to be memory efficient and doesn't have room for MPLS labels, only a pointer). Also, 'zapi_nexthop' is more compact and more clean from an API perspective; * Embed the route prefix inside the zapi_route structure. Since the route's prefix is sent along with its nexthops and attributes, it makes sense to pack everything inside the same structure. Signed-off-by: Renato Westphal --- babeld/kernel.c | 34 ++++++++++---------- lib/zclient.c | 84 ++++++++++++++++++++++--------------------------- lib/zclient.h | 16 ++++++++-- 3 files changed, 68 insertions(+), 66 deletions(-) diff --git a/babeld/kernel.c b/babeld/kernel.c index 26860f3bae..105a7d0518 100644 --- a/babeld/kernel.c +++ b/babeld/kernel.c @@ -144,15 +144,15 @@ kernel_route_v4(int add, const unsigned char *gate, int ifindex, unsigned int metric) { struct zapi_route api; /* quagga's communication system */ + struct zapi_nexthop *api_nh; /* next router to go - no ECMP */ struct prefix quagga_prefix; /* quagga's prefix */ struct in_addr babel_prefix_addr; /* babeld's prefix addr */ - struct nexthop nexthop; /* next router to go */ - struct nexthop *nexthop_pointer = &nexthop; /* it's an array! */ + + api_nh = &api.nexthops[0]; /* convert to be understandable by quagga */ /* convert given addresses */ uchar_to_inaddr(&babel_prefix_addr, pref); - uchar_to_inaddr(&nexthop.gate.ipv4, gate); /* make prefix structure */ memset (&quagga_prefix, 0, sizeof(quagga_prefix)); @@ -168,6 +168,7 @@ kernel_route_v4(int add, api.instance = 0; api.safi = SAFI_UNICAST; api.vrf_id = VRF_DEFAULT; + api.prefix = quagga_prefix; SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); if(metric >= KERNEL_INFINITY) { @@ -175,13 +176,13 @@ kernel_route_v4(int add, api.nexthop_num = 0; } else { api.nexthop_num = 1; - api.nexthop = &nexthop_pointer; - nexthop.ifindex = ifindex; - if (IPV4_ADDR_SAME (&nexthop.gate.ipv4, &quagga_prefix.u.prefix4) && + api_nh->ifindex = ifindex; + uchar_to_inaddr(&api_nh->gate.ipv4, gate); + if (IPV4_ADDR_SAME (&api_nh->gate.ipv4, &quagga_prefix.u.prefix4) && quagga_prefix.prefixlen == 32) { - nexthop.type = NEXTHOP_TYPE_IFINDEX; + api_nh->type = NEXTHOP_TYPE_IFINDEX; } else { - nexthop.type = NEXTHOP_TYPE_IPV4_IFINDEX; + api_nh->type = NEXTHOP_TYPE_IPV4_IFINDEX; } SET_FLAG(api.message, ZAPI_MESSAGE_METRIC); api.metric = metric; @@ -191,7 +192,7 @@ kernel_route_v4(int add, add ? "adding" : "removing" ); return zapi_route (add ? ZEBRA_IPV4_ROUTE_ADD : ZEBRA_IPV4_ROUTE_DELETE, - zclient, &quagga_prefix, NULL, &api); + zclient, &api); } static int @@ -199,15 +200,15 @@ kernel_route_v6(int add, const unsigned char *pref, unsigned short plen, const unsigned char *gate, int ifindex, unsigned int metric) { struct zapi_route api; /* quagga's communication system */ + struct zapi_nexthop *api_nh; /* next router to go - no ECMP */ struct prefix quagga_prefix; /* quagga's prefix */ struct in6_addr babel_prefix_addr; /* babeld's prefix addr */ - struct nexthop nexthop; /* next router to go */ - struct nexthop *nexthop_pointer = &nexthop; + + api_nh = &api.nexthops[0]; /* convert to be understandable by quagga */ /* convert given addresses */ uchar_to_in6addr(&babel_prefix_addr, pref); - uchar_to_in6addr(&nexthop.gate.ipv6, gate); /* make prefix structure */ memset (&quagga_prefix, 0, sizeof(quagga_prefix)); @@ -223,6 +224,7 @@ kernel_route_v6(int add, const unsigned char *pref, unsigned short plen, api.instance = 0; api.safi = SAFI_UNICAST; api.vrf_id = VRF_DEFAULT; + api.prefix = quagga_prefix; if(metric >= KERNEL_INFINITY) { api.flags = ZEBRA_FLAG_REJECT; @@ -230,10 +232,10 @@ kernel_route_v6(int add, const unsigned char *pref, unsigned short plen, } else { SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); api.nexthop_num = 1; - api.nexthop = &nexthop_pointer; - nexthop.ifindex = ifindex; + api_nh->ifindex = ifindex; + uchar_to_in6addr(&api_nh->gate.ipv6, gate); /* difference to IPv4: always leave the linklocal as nexthop */ - nexthop.type = NEXTHOP_TYPE_IPV6_IFINDEX; + api_nh->type = NEXTHOP_TYPE_IPV6_IFINDEX; SET_FLAG(api.message, ZAPI_MESSAGE_METRIC); api.metric = metric; } @@ -242,7 +244,7 @@ kernel_route_v6(int add, const unsigned char *pref, unsigned short plen, add ? "adding" : "removing" ); return zapi_route (add ? ZEBRA_IPV6_ROUTE_ADD : ZEBRA_IPV6_ROUTE_DELETE, - zclient, &quagga_prefix, NULL, &api); + zclient, &api); } int diff --git a/lib/zclient.c b/lib/zclient.c index f8bbdd85c9..53e8569b77 100644 --- a/lib/zclient.c +++ b/lib/zclient.c @@ -892,16 +892,12 @@ int zapi_ipv6_route(u_char cmd, struct zclient *zclient, struct prefix_ipv6 *p, return zclient_send_message(zclient); } -int zapi_route(u_char cmd, struct zclient *zclient, struct prefix *p, - struct prefix_ipv6 *src_p, struct zapi_route *api) +int zapi_route(u_char cmd, struct zclient *zclient, struct zapi_route *api) { int i; int psize; struct stream *s; - - /* either we have !SRCPFX && src_p == NULL, or SRCPFX && src_p != NULL - */ - assert(!(api->message & ZAPI_MESSAGE_SRCPFX) == !src_p); + struct zapi_nexthop *api_nh; /* Reset stream. */ s = zclient->obuf; @@ -917,69 +913,63 @@ int zapi_route(u_char cmd, struct zclient *zclient, struct prefix *p, stream_putw(s, api->safi); /* Put prefix information. */ - psize = PSIZE(p->prefixlen); - stream_putc(s, p->prefixlen); - stream_write(s, (u_char *)&p->u.prefix, psize); + psize = PSIZE(api->prefix.prefixlen); + stream_putc(s, api->prefix.prefixlen); + stream_write(s, (u_char *)&api->prefix.u.prefix, psize); if (CHECK_FLAG(api->message, ZAPI_MESSAGE_SRCPFX)) { - psize = PSIZE(src_p->prefixlen); - stream_putc(s, src_p->prefixlen); - stream_write(s, (u_char *)&src_p->prefix, psize); + psize = PSIZE(api->src_prefix.prefixlen); + stream_putc(s, api->src_prefix.prefixlen); + stream_write(s, (u_char *)&api->src_prefix.prefix, psize); } /* Nexthop, ifindex, distance and metric information. */ if (CHECK_FLAG(api->message, ZAPI_MESSAGE_NEXTHOP)) { + /* limit the number of nexthops if necessary */ + if (api->nexthop_num > MULTIPATH_NUM) { + char buf[PREFIX2STR_BUFFER]; + + prefix2str(&api->prefix, buf, sizeof(buf)); + zlog_warn( + "%s: prefix %s: encoding %u nexthops out of %u", + __func__, buf, MULTIPATH_NUM, api->nexthop_num); + api->nexthop_num = MULTIPATH_NUM; + } + stream_putc(s, api->nexthop_num); for (i = 0; i < api->nexthop_num; i++) { - stream_putc(s, api->nexthop[i]->type); - switch (api->nexthop[i]->type) { + api_nh = &api->nexthops[i]; + + stream_putc(s, api_nh->type); + switch (api_nh->type) { case NEXTHOP_TYPE_BLACKHOLE: break; case NEXTHOP_TYPE_IPV4: - stream_put_in_addr(s, - &api->nexthop[i]->gate.ipv4); - - /* For labeled-unicast, each nexthop is followed - * by label. */ - if (CHECK_FLAG(api->message, - ZAPI_MESSAGE_LABEL)) - stream_putl( - s, - api->nexthop[i] - ->nh_label->label[0]); + stream_put_in_addr(s, &api_nh->gate.ipv4); break; case NEXTHOP_TYPE_IPV4_IFINDEX: - stream_put_in_addr(s, - &api->nexthop[i]->gate.ipv4); - stream_putl(s, api->nexthop[i]->ifindex); + stream_put_in_addr(s, &api_nh->gate.ipv4); + stream_putl(s, api_nh->ifindex); break; case NEXTHOP_TYPE_IFINDEX: - stream_putl(s, api->nexthop[i]->ifindex); + stream_putl(s, api_nh->ifindex); break; case NEXTHOP_TYPE_IPV6: - stream_write( - s, - (u_char *)&api->nexthop[i]->gate.ipv6, - 16); - - /* For labeled-unicast, each nexthop is followed - * by label. */ - if (CHECK_FLAG(api->message, - ZAPI_MESSAGE_LABEL)) - stream_putl( - s, - api->nexthop[i] - ->nh_label->label[0]); + stream_write(s, (u_char *)&api_nh->gate.ipv6, + 16); break; case NEXTHOP_TYPE_IPV6_IFINDEX: - stream_write( - s, - (u_char *)&api->nexthop[i]->gate.ipv6, - 16); - stream_putl(s, api->nexthop[i]->ifindex); + stream_write(s, (u_char *)&api_nh->gate.ipv6, + 16); + stream_putl(s, api_nh->ifindex); break; } + + /* For labeled-unicast, each nexthop is followed + * by label. */ + if (CHECK_FLAG(api->message, ZAPI_MESSAGE_LABEL)) + stream_putl(s, api_nh->label); } } diff --git a/lib/zclient.h b/lib/zclient.h index ddd9655443..92aeabb07f 100644 --- a/lib/zclient.h +++ b/lib/zclient.h @@ -224,6 +224,13 @@ struct zserv_header { uint16_t command; }; +struct zapi_nexthop { + enum nexthop_types_t type; + ifindex_t ifindex; + union g_addr gate; + mpls_label_t label; +}; + struct zapi_route { u_char type; u_short instance; @@ -234,8 +241,11 @@ struct zapi_route { safi_t safi; + struct prefix prefix; + struct prefix_ipv6 src_prefix; + u_char nexthop_num; - struct nexthop **nexthop; + struct zapi_nexthop nexthops[MULTIPATH_NUM]; u_char distance; @@ -416,7 +426,7 @@ extern int zapi_ipv6_route(u_char cmd, struct zclient *zclient, extern int zapi_ipv4_route_ipv6_nexthop(u_char, struct zclient *, struct prefix_ipv4 *, struct zapi_ipv6 *); -extern int zapi_route(u_char cmd, struct zclient *zclient, struct prefix *p, - struct prefix_ipv6 *src_p, struct zapi_route *api); +extern int zapi_route(u_char cmd, struct zclient *zclient, + struct zapi_route *api); #endif /* _ZEBRA_ZCLIENT_H */ From 0e51b4a368257d54b1e07ff74492ea4705de97f7 Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Sat, 19 Aug 2017 21:59:41 -0300 Subject: [PATCH 068/130] lib/zserv: introduce address-family independent ZAPI message types As noticed in 657cde1, the zapi_ipv[4|6]_route functions are broken in many ways and that's the reason that many client daemons (e.g. ospfd, isisd) need to send handcrafted messages to zebra. The zapi_route() function introduced by Donald solves the problem by providing a consistent way to send ipv4/ipv6 routes to zebra with nexthops of any type, in all possible combinations including IPv4 routes with IPv6 nexthops (for BGP unnumbered routes). This patch goes a bit further and creates two new address-family independent ZAPI message types that the client daemons can use to advertise route information to zebra: ZEBRA_ROUTE_ADD and ZEBRA_ROUTE_DELETE. The big advantage of having address-family independent messages is that it allows us to remove a lot of duplicate code in zebra and in the client daemons. This patch also introduces the zapi_route_decode() function. It will be used by zebra to decode route messages sent by the client daemons using zclient_route_send(), which calls zapi_route_encode(). Later on we'll use this same pair of encode/decode functions to send/receive redistributed routes from zebra to the client daemons, taking the idea of removing code duplication to the next level. Signed-off-by: Renato Westphal --- babeld/kernel.c | 10 ++-- lib/log.c | 2 + lib/zclient.c | 116 +++++++++++++++++++++++++++++++++++--- lib/zclient.h | 7 ++- zebra/zserv.c | 144 ++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 262 insertions(+), 17 deletions(-) diff --git a/babeld/kernel.c b/babeld/kernel.c index 105a7d0518..6cdd66e48d 100644 --- a/babeld/kernel.c +++ b/babeld/kernel.c @@ -190,9 +190,8 @@ kernel_route_v4(int add, debugf(BABEL_DEBUG_ROUTE, "%s route (ipv4) to zebra", add ? "adding" : "removing" ); - return zapi_route (add ? ZEBRA_IPV4_ROUTE_ADD : - ZEBRA_IPV4_ROUTE_DELETE, - zclient, &api); + return zclient_route_send (add ? ZEBRA_ROUTE_ADD : ZEBRA_ROUTE_DELETE, + zclient, &api); } static int @@ -242,9 +241,8 @@ kernel_route_v6(int add, const unsigned char *pref, unsigned short plen, debugf(BABEL_DEBUG_ROUTE, "%s route (ipv6) to zebra", add ? "adding" : "removing" ); - return zapi_route (add ? ZEBRA_IPV6_ROUTE_ADD : - ZEBRA_IPV6_ROUTE_DELETE, - zclient, &api); + return zclient_route_send (add ? ZEBRA_ROUTE_ADD : ZEBRA_ROUTE_DELETE, + zclient, &api); } int diff --git a/lib/log.c b/lib/log.c index b9ce9e69bc..92b2d3b66b 100644 --- a/lib/log.c +++ b/lib/log.c @@ -867,6 +867,8 @@ static const struct zebra_desc_table command_types[] = { DESC_ENTRY(ZEBRA_INTERFACE_UP), DESC_ENTRY(ZEBRA_INTERFACE_DOWN), DESC_ENTRY(ZEBRA_INTERFACE_SET_MASTER), + DESC_ENTRY(ZEBRA_ROUTE_ADD), + DESC_ENTRY(ZEBRA_ROUTE_DELETE), DESC_ENTRY(ZEBRA_IPV4_ROUTE_ADD), DESC_ENTRY(ZEBRA_IPV4_ROUTE_DELETE), DESC_ENTRY(ZEBRA_IPV6_ROUTE_ADD), diff --git a/lib/zclient.c b/lib/zclient.c index 53e8569b77..3f5c7a0f6f 100644 --- a/lib/zclient.c +++ b/lib/zclient.c @@ -892,20 +892,23 @@ int zapi_ipv6_route(u_char cmd, struct zclient *zclient, struct prefix_ipv6 *p, return zclient_send_message(zclient); } -int zapi_route(u_char cmd, struct zclient *zclient, struct zapi_route *api) +int zclient_route_send(u_char cmd, struct zclient *zclient, + struct zapi_route *api) { + if (zapi_route_encode(cmd, zclient->obuf, api) < 0) + return -1; + return zclient_send_message(zclient); +} + +int zapi_route_encode(u_char cmd, struct stream *s, struct zapi_route *api) +{ + struct zapi_nexthop *api_nh; int i; int psize; - struct stream *s; - struct zapi_nexthop *api_nh; - /* Reset stream. */ - s = zclient->obuf; stream_reset(s); - zclient_create_header(s, cmd, api->vrf_id); - /* Put type and nexthop. */ stream_putc(s, api->type); stream_putw(s, api->instance); stream_putl(s, api->flags); @@ -913,6 +916,7 @@ int zapi_route(u_char cmd, struct zclient *zclient, struct zapi_route *api) stream_putw(s, api->safi); /* Put prefix information. */ + stream_putc(s, api->prefix.family); psize = PSIZE(api->prefix.prefixlen); stream_putc(s, api->prefix.prefixlen); stream_write(s, (u_char *)&api->prefix.u.prefix, psize); @@ -923,7 +927,7 @@ int zapi_route(u_char cmd, struct zclient *zclient, struct zapi_route *api) stream_write(s, (u_char *)&api->src_prefix.prefix, psize); } - /* Nexthop, ifindex, distance and metric information. */ + /* Nexthops. */ if (CHECK_FLAG(api->message, ZAPI_MESSAGE_NEXTHOP)) { /* limit the number of nexthops if necessary */ if (api->nexthop_num > MULTIPATH_NUM) { @@ -973,6 +977,7 @@ int zapi_route(u_char cmd, struct zclient *zclient, struct zapi_route *api) } } + /* Attributes. */ if (CHECK_FLAG(api->message, ZAPI_MESSAGE_DISTANCE)) stream_putc(s, api->distance); if (CHECK_FLAG(api->message, ZAPI_MESSAGE_METRIC)) @@ -985,7 +990,100 @@ int zapi_route(u_char cmd, struct zclient *zclient, struct zapi_route *api) /* Put length at the first point of the stream. */ stream_putw_at(s, 0, stream_get_endp(s)); - return zclient_send_message(zclient); + return 0; +} + +int zapi_route_decode(struct stream *s, struct zapi_route *api) +{ + struct zapi_nexthop *api_nh; + int i; + + memset(api, 0, sizeof(*api)); + + /* Type, flags, message. */ + api->type = stream_getc(s); + api->instance = stream_getw(s); + api->flags = stream_getl(s); + api->message = stream_getc(s); + api->safi = stream_getw(s); + + /* Prefix. */ + api->prefix.family = stream_getc(s); + switch (api->prefix.family) { + case AF_INET: + api->prefix.prefixlen = MIN(IPV4_MAX_PREFIXLEN, stream_getc(s)); + break; + case AF_INET6: + api->prefix.prefixlen = MIN(IPV6_MAX_PREFIXLEN, stream_getc(s)); + break; + } + stream_get(&api->prefix.u.prefix, s, PSIZE(api->prefix.prefixlen)); + if (CHECK_FLAG(api->message, ZAPI_MESSAGE_SRCPFX)) { + api->src_prefix.family = AF_INET6; + api->src_prefix.prefixlen = stream_getc(s); + stream_get(&api->src_prefix.prefix, s, + PSIZE(api->src_prefix.prefixlen)); + + if (api->prefix.family != AF_INET6 + || api->src_prefix.prefixlen == 0) + UNSET_FLAG(api->message, ZAPI_MESSAGE_SRCPFX); + } + + /* Nexthops. */ + if (CHECK_FLAG(api->message, ZAPI_MESSAGE_NEXTHOP)) { + api->nexthop_num = stream_getc(s); + if (api->nexthop_num > MULTIPATH_NUM) { + zlog_warn("%s: invalid number of nexthops (%u)", + __func__, api->nexthop_num); + return -1; + } + + for (i = 0; i < api->nexthop_num; i++) { + api_nh = &api->nexthops[i]; + + api_nh->type = stream_getc(s); + switch (api_nh->type) { + case NEXTHOP_TYPE_BLACKHOLE: + break; + case NEXTHOP_TYPE_IPV4: + api_nh->gate.ipv4.s_addr = stream_get_ipv4(s); + break; + case NEXTHOP_TYPE_IPV4_IFINDEX: + api_nh->gate.ipv4.s_addr = stream_get_ipv4(s); + api_nh->ifindex = stream_getl(s); + break; + case NEXTHOP_TYPE_IFINDEX: + api_nh->ifindex = stream_getl(s); + break; + case NEXTHOP_TYPE_IPV6: + stream_get(&api_nh->gate.ipv6, s, 16); + break; + case NEXTHOP_TYPE_IPV6_IFINDEX: + stream_get(&api_nh->gate.ipv6, s, 16); + api_nh->ifindex = stream_getl(s); + break; + } + + /* For labeled-unicast, each nexthop is followed + * by label. */ + if (CHECK_FLAG(api->message, ZAPI_MESSAGE_LABEL)) { + stream_get(&api_nh->label, s, + sizeof(api_nh->label)); + } + } + } + + /* Attributes. */ + if (CHECK_FLAG(api->message, ZAPI_MESSAGE_DISTANCE)) + api->distance = stream_getc(s); + if (CHECK_FLAG(api->message, ZAPI_MESSAGE_METRIC)) + api->metric = stream_getl(s); + if (CHECK_FLAG(api->message, ZAPI_MESSAGE_TAG)) + api->tag = stream_getl(s); + if (CHECK_FLAG(api->message, ZAPI_MESSAGE_MTU)) + api->mtu = stream_getl(s); + + return 0; } /* diff --git a/lib/zclient.h b/lib/zclient.h index 92aeabb07f..2e450ed398 100644 --- a/lib/zclient.h +++ b/lib/zclient.h @@ -59,6 +59,8 @@ typedef enum { ZEBRA_INTERFACE_UP, ZEBRA_INTERFACE_DOWN, ZEBRA_INTERFACE_SET_MASTER, + ZEBRA_ROUTE_ADD, + ZEBRA_ROUTE_DELETE, ZEBRA_IPV4_ROUTE_ADD, ZEBRA_IPV4_ROUTE_DELETE, ZEBRA_IPV6_ROUTE_ADD, @@ -426,7 +428,8 @@ extern int zapi_ipv6_route(u_char cmd, struct zclient *zclient, extern int zapi_ipv4_route_ipv6_nexthop(u_char, struct zclient *, struct prefix_ipv4 *, struct zapi_ipv6 *); -extern int zapi_route(u_char cmd, struct zclient *zclient, - struct zapi_route *api); +extern int zclient_route_send(u_char, struct zclient *, struct zapi_route *); +extern int zapi_route_encode(u_char, struct stream *, struct zapi_route *); +extern int zapi_route_decode(struct stream *, struct zapi_route *); #endif /* _ZEBRA_ZCLIENT_H */ diff --git a/zebra/zserv.c b/zebra/zserv.c index e00e1d7c20..94e34865b5 100644 --- a/zebra/zserv.c +++ b/zebra/zserv.c @@ -1157,6 +1157,144 @@ void zserv_nexthop_num_warn(const char *caller, const struct prefix *p, } } +static int zread_route_add(struct zserv *client, u_short length, + struct zebra_vrf *zvrf) +{ + struct stream *s; + struct zapi_route api; + struct zapi_nexthop *api_nh; + afi_t afi; + struct prefix_ipv6 *src_p = NULL; + struct route_entry *re; + struct nexthop *nexthop; + int i, ret; + + s = client->ibuf; + if (zapi_route_decode(s, &api) < 0) + return -1; + + /* Allocate new route. */ + re = XCALLOC(MTYPE_RE, sizeof(struct route_entry)); + re->type = api.type; + re->instance = api.instance; + re->flags = api.flags; + re->uptime = time(NULL); + re->vrf_id = zvrf_id(zvrf); + re->table = zvrf->table_id; + + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP)) { + for (i = 0; i < api.nexthop_num; i++) { + api_nh = &api.nexthops[i]; + + switch (api_nh->type) { + case NEXTHOP_TYPE_IFINDEX: + route_entry_nexthop_ifindex_add( + re, api_nh->ifindex); + break; + case NEXTHOP_TYPE_IPV4: + nexthop = route_entry_nexthop_ipv4_add( + re, &api_nh->gate.ipv4, NULL); + break; + case NEXTHOP_TYPE_IPV4_IFINDEX: + nexthop = route_entry_nexthop_ipv4_ifindex_add( + re, &api_nh->gate.ipv4, NULL, + api_nh->ifindex); + break; + case NEXTHOP_TYPE_IPV6: + nexthop = route_entry_nexthop_ipv6_add( + re, &api_nh->gate.ipv6); + break; + case NEXTHOP_TYPE_IPV6_IFINDEX: + nexthop = route_entry_nexthop_ipv6_ifindex_add( + re, &api_nh->gate.ipv6, + api_nh->ifindex); + break; + case NEXTHOP_TYPE_BLACKHOLE: + route_entry_nexthop_blackhole_add(re); + break; + } + + /* MPLS labels for BGP-LU or Segment Routing */ + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_LABEL) + && api_nh->type != NEXTHOP_TYPE_IFINDEX + && api_nh->type != NEXTHOP_TYPE_BLACKHOLE) { + enum lsp_types_t label_type; + + label_type = + lsp_type_from_re_type(client->proto); + nexthop_add_labels(nexthop, label_type, 1, + &api_nh->label); + } + } + } + + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_DISTANCE)) + re->distance = api.distance; + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_METRIC)) + re->metric = api.metric; + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_TAG)) + re->tag = api.tag; + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_MTU)) + re->mtu = api.mtu; + + afi = family2afi(api.prefix.family); + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX)) + src_p = &api.src_prefix; + + ret = rib_add_multipath(afi, api.safi, &api.prefix, src_p, re); + + /* Stats */ + switch (api.prefix.family) { + case AF_INET: + if (ret > 0) + client->v4_route_add_cnt++; + else if (ret < 0) + client->v4_route_upd8_cnt++; + break; + case AF_INET6: + if (ret > 0) + client->v6_route_add_cnt++; + else if (ret < 0) + client->v6_route_upd8_cnt++; + break; + } + + return 0; +} + +static int zread_route_del(struct zserv *client, u_short length, + struct zebra_vrf *zvrf) +{ + struct stream *s; + struct zapi_route api; + afi_t afi; + struct prefix_ipv6 *src_p = NULL; + + s = client->ibuf; + if (zapi_route_decode(s, &api) < 0) + return -1; + + afi = family2afi(api.prefix.family); + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX)) + src_p = &api.src_prefix; + + rib_delete(afi, api.safi, zvrf_id(zvrf), api.type, api.instance, + api.flags, &api.prefix, src_p, NULL, 0, zvrf->table_id, + api.metric); + + /* Stats */ + switch (api.prefix.family) { + case AF_INET: + client->v4_route_del_cnt++; + break; + case AF_INET6: + client->v6_route_del_cnt++; + break; + } + + return 0; +} + /* This function support multiple nexthop. */ /* * Parse the ZEBRA_IPV4_ROUTE_ADD sent from client. Update re and @@ -2334,6 +2472,12 @@ static int zebra_client_read(struct thread *thread) case ZEBRA_INTERFACE_DELETE: zread_interface_delete(client, length, zvrf); break; + case ZEBRA_ROUTE_ADD: + zread_route_add(client, length, zvrf); + break; + case ZEBRA_ROUTE_DELETE: + zread_route_del(client, length, zvrf); + break; case ZEBRA_IPV4_ROUTE_ADD: zread_ipv4_add(client, length, zvrf); break; From c8f9e916df033897ee8878d970887a7d9bb07a2b Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Sat, 19 Aug 2017 22:31:32 -0300 Subject: [PATCH 069/130] babeld: unify kernel_route_v4() and kernel_route_v6() Signed-off-by: Renato Westphal --- babeld/kernel.c | 153 +++++++++++++++++------------------------------- 1 file changed, 55 insertions(+), 98 deletions(-) diff --git a/babeld/kernel.c b/babeld/kernel.c index 6cdd66e48d..394d7b1e81 100644 --- a/babeld/kernel.c +++ b/babeld/kernel.c @@ -51,13 +51,8 @@ THE SOFTWARE. static int -kernel_route_v4(int add, const unsigned char *pref, unsigned short plen, - const unsigned char *gate, int ifindex, - unsigned int metric); -static int -kernel_route_v6(int add, const unsigned char *pref, unsigned short plen, - const unsigned char *gate, int ifindex, - unsigned int metric); +zebra_route(int add, int familt, const unsigned char *pref, unsigned short plen, + const unsigned char *gate, int ifindex, unsigned int metric); int kernel_interface_operational(struct interface *interface) @@ -84,7 +79,7 @@ kernel_route(int operation, const unsigned char *pref, unsigned short plen, unsigned int newmetric) { int rc; - int ipv4; + int family; /* Check that the protocol family is consistent. */ if(plen >= 96 && v4mapped(pref)) { @@ -92,46 +87,37 @@ kernel_route(int operation, const unsigned char *pref, unsigned short plen, errno = EINVAL; return -1; } - ipv4 = 1; + family = AF_INET; } else { if(v4mapped(gate)) { errno = EINVAL; return -1; } - ipv4 = 0; + family = AF_INET6; } switch (operation) { case ROUTE_ADD: - return ipv4 ? - kernel_route_v4(1, pref, plen, gate, ifindex, metric): - kernel_route_v6(1, pref, plen, gate, ifindex, metric); + return zebra_route(1, family, pref, plen, gate, ifindex, metric); break; case ROUTE_FLUSH: - return ipv4 ? - kernel_route_v4(0, pref, plen, gate, ifindex, metric): - kernel_route_v6(0, pref, plen, gate, ifindex, metric); + return zebra_route(0, family, pref, plen, gate, ifindex, metric); break; case ROUTE_MODIFY: if(newmetric == metric && memcmp(newgate, gate, 16) == 0 && newifindex == ifindex) return 0; debugf(BABEL_DEBUG_ROUTE, "Modify route: delete old; add new."); - rc = ipv4 ? - kernel_route_v4(0, pref, plen, gate, ifindex, metric): - kernel_route_v6(0, pref, plen, gate, ifindex, metric); - + rc = zebra_route(0, family, pref, plen, gate, ifindex, metric); if (rc < 0) return -1; - rc = ipv4 ? - kernel_route_v4(1, pref, plen, newgate, newifindex, newmetric): - kernel_route_v6(1, pref, plen, newgate, newifindex, newmetric); - + rc = zebra_route(1, family, pref, plen, newgate, newifindex, + newmetric); return rc; break; default: - zlog_err("this should never appens (false value - kernel_route)"); + zlog_err("this should never happen (false value - kernel_route)"); assert(0); exit(1); break; @@ -139,108 +125,79 @@ kernel_route(int operation, const unsigned char *pref, unsigned short plen, } static int -kernel_route_v4(int add, - const unsigned char *pref, unsigned short plen, - const unsigned char *gate, int ifindex, unsigned int metric) +zebra_route(int add, int family, const unsigned char *pref, unsigned short plen, + const unsigned char *gate, int ifindex, unsigned int metric) { struct zapi_route api; /* quagga's communication system */ - struct zapi_nexthop *api_nh; /* next router to go - no ECMP */ struct prefix quagga_prefix; /* quagga's prefix */ - struct in_addr babel_prefix_addr; /* babeld's prefix addr */ + union g_addr babel_prefix_addr; /* babeld's prefix addr */ + struct zapi_nexthop *api_nh; /* next router to go - no ECMP */ api_nh = &api.nexthops[0]; /* convert to be understandable by quagga */ /* convert given addresses */ - uchar_to_inaddr(&babel_prefix_addr, pref); + switch (family) { + case AF_INET: + uchar_to_inaddr(&babel_prefix_addr.ipv4, pref); + break; + case AF_INET6: + uchar_to_in6addr(&babel_prefix_addr.ipv6, pref); + break; + } /* make prefix structure */ memset (&quagga_prefix, 0, sizeof(quagga_prefix)); - quagga_prefix.family = AF_INET; - IPV4_ADDR_COPY (&quagga_prefix.u.prefix4, &babel_prefix_addr); - quagga_prefix.prefixlen = plen - 96; /* our plen is for v4mapped's addr */ + quagga_prefix.family = family; + switch (family) { + case AF_INET: + IPV4_ADDR_COPY (&quagga_prefix.u.prefix4, &babel_prefix_addr.ipv4); + /* our plen is for v4mapped's addr */ + quagga_prefix.prefixlen = plen - 96; + break; + case AF_INET6: + IPV6_ADDR_COPY (&quagga_prefix.u.prefix6, &babel_prefix_addr.ipv6); + quagga_prefix.prefixlen = plen; + break; + } apply_mask(&quagga_prefix); memset(&api, 0, sizeof(api)); api.type = ZEBRA_ROUTE_BABEL; - api.flags = 0; - api.message = 0; - api.instance = 0; api.safi = SAFI_UNICAST; api.vrf_id = VRF_DEFAULT; api.prefix = quagga_prefix; - SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); if(metric >= KERNEL_INFINITY) { api.flags = ZEBRA_FLAG_REJECT; - api.nexthop_num = 0; } else { + SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); api.nexthop_num = 1; api_nh->ifindex = ifindex; - uchar_to_inaddr(&api_nh->gate.ipv4, gate); - if (IPV4_ADDR_SAME (&api_nh->gate.ipv4, &quagga_prefix.u.prefix4) && - quagga_prefix.prefixlen == 32) { - api_nh->type = NEXTHOP_TYPE_IFINDEX; - } else { - api_nh->type = NEXTHOP_TYPE_IPV4_IFINDEX; + + switch (family) { + case AF_INET: + uchar_to_inaddr(&api_nh->gate.ipv4, gate); + if (IPV4_ADDR_SAME (&api_nh->gate.ipv4, &quagga_prefix.u.prefix4) && + quagga_prefix.prefixlen == 32) { + api_nh->type = NEXTHOP_TYPE_IFINDEX; + } else { + api_nh->type = NEXTHOP_TYPE_IPV4_IFINDEX; + } + break; + case AF_INET6: + uchar_to_in6addr(&api_nh->gate.ipv6, gate); + /* difference to IPv4: always leave the linklocal as nexthop */ + api_nh->type = NEXTHOP_TYPE_IPV6_IFINDEX; + break; } SET_FLAG(api.message, ZAPI_MESSAGE_METRIC); api.metric = metric; } - debugf(BABEL_DEBUG_ROUTE, "%s route (ipv4) to zebra", - add ? "adding" : "removing" ); - return zclient_route_send (add ? ZEBRA_ROUTE_ADD : ZEBRA_ROUTE_DELETE, - zclient, &api); -} - -static int -kernel_route_v6(int add, const unsigned char *pref, unsigned short plen, - const unsigned char *gate, int ifindex, unsigned int metric) -{ - struct zapi_route api; /* quagga's communication system */ - struct zapi_nexthop *api_nh; /* next router to go - no ECMP */ - struct prefix quagga_prefix; /* quagga's prefix */ - struct in6_addr babel_prefix_addr; /* babeld's prefix addr */ - - api_nh = &api.nexthops[0]; - - /* convert to be understandable by quagga */ - /* convert given addresses */ - uchar_to_in6addr(&babel_prefix_addr, pref); - - /* make prefix structure */ - memset (&quagga_prefix, 0, sizeof(quagga_prefix)); - quagga_prefix.family = AF_INET6; - IPV6_ADDR_COPY (&quagga_prefix.u.prefix6, &babel_prefix_addr); - quagga_prefix.prefixlen = plen; - apply_mask(&quagga_prefix); - - memset(&api, 0, sizeof(api)); - api.type = ZEBRA_ROUTE_BABEL; - api.flags = 0; - api.message = 0; - api.instance = 0; - api.safi = SAFI_UNICAST; - api.vrf_id = VRF_DEFAULT; - api.prefix = quagga_prefix; - - if(metric >= KERNEL_INFINITY) { - api.flags = ZEBRA_FLAG_REJECT; - api.nexthop_num = 0; - } else { - SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); - api.nexthop_num = 1; - api_nh->ifindex = ifindex; - uchar_to_in6addr(&api_nh->gate.ipv6, gate); - /* difference to IPv4: always leave the linklocal as nexthop */ - api_nh->type = NEXTHOP_TYPE_IPV6_IFINDEX; - SET_FLAG(api.message, ZAPI_MESSAGE_METRIC); - api.metric = metric; - } - - debugf(BABEL_DEBUG_ROUTE, "%s route (ipv6) to zebra", - add ? "adding" : "removing" ); + debugf(BABEL_DEBUG_ROUTE, "%s route (%s) to zebra", + add ? "adding" : "removing", + (family == AF_INET) ? "ipv4" : "ipv6"); return zclient_route_send (add ? ZEBRA_ROUTE_ADD : ZEBRA_ROUTE_DELETE, zclient, &api); } From 52dd3aa483441880ac46eb4bb50069d26dbecf13 Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Sun, 20 Aug 2017 19:57:36 -0300 Subject: [PATCH 070/130] zapi: add support for routes with multiple labels This will be necessary for the Segment Routing feature. Signed-off-by: Renato Westphal --- lib/mpls.h | 3 +++ lib/zclient.c | 42 ++++++++++++++++++++++++++++++++++-------- lib/zclient.h | 5 ++++- zebra/zebra_mpls.h | 2 -- zebra/zserv.c | 5 +++-- 5 files changed, 44 insertions(+), 13 deletions(-) diff --git a/lib/mpls.h b/lib/mpls.h index 025770d479..bf98eecd81 100644 --- a/lib/mpls.h +++ b/lib/mpls.h @@ -44,6 +44,9 @@ #define MPLS_DEFAULT_MIN_SRGB_LABEL 16000 #define MPLS_DEFAULT_MAX_SRGB_LABEL 23999 +/* Maximum # labels that can be pushed. */ +#define MPLS_MAX_LABELS 16 + #define IS_MPLS_RESERVED_LABEL(label) \ (label >= MPLS_MIN_RESERVED_LABEL && label <= MPLS_MAX_RESERVED_LABEL) diff --git a/lib/zclient.c b/lib/zclient.c index 3f5c7a0f6f..e063c7151f 100644 --- a/lib/zclient.c +++ b/lib/zclient.c @@ -970,10 +970,26 @@ int zapi_route_encode(u_char cmd, struct stream *s, struct zapi_route *api) break; } - /* For labeled-unicast, each nexthop is followed - * by label. */ - if (CHECK_FLAG(api->message, ZAPI_MESSAGE_LABEL)) - stream_putl(s, api_nh->label); + /* MPLS labels for BGP-LU or Segment Routing */ + if (CHECK_FLAG(api->message, ZAPI_MESSAGE_LABEL)) { + if (api_nh->label_num > MPLS_MAX_LABELS) { + char buf[PREFIX2STR_BUFFER]; + prefix2str(&api->prefix, buf, + sizeof(buf)); + zlog_err( + "%s: prefix %s: can't encode " + "%u labels (maximum is %u)", + __func__, buf, + api_nh->label_num, + MPLS_MAX_LABELS); + return -1; + } + + stream_putc(s, api_nh->label_num); + stream_put(s, &api_nh->labels[0], + api_nh->label_num + * sizeof(mpls_label_t)); + } } } @@ -1064,11 +1080,21 @@ int zapi_route_decode(struct stream *s, struct zapi_route *api) break; } - /* For labeled-unicast, each nexthop is followed - * by label. */ + /* MPLS labels for BGP-LU or Segment Routing */ if (CHECK_FLAG(api->message, ZAPI_MESSAGE_LABEL)) { - stream_get(&api_nh->label, s, - sizeof(api_nh->label)); + api_nh->label_num = stream_getc(s); + + if (api_nh->label_num > MPLS_MAX_LABELS) { + zlog_warn( + "%s: invalid number of MPLS " + "labels (%u)", + __func__, api_nh->label_num); + return -1; + } + + stream_get(&api_nh->labels[0], s, + api_nh->label_num + * sizeof(mpls_label_t)); } } } diff --git a/lib/zclient.h b/lib/zclient.h index 2e450ed398..40ddbf62df 100644 --- a/lib/zclient.h +++ b/lib/zclient.h @@ -230,7 +230,10 @@ struct zapi_nexthop { enum nexthop_types_t type; ifindex_t ifindex; union g_addr gate; - mpls_label_t label; + + /* MPLS labels for BGP-LU or Segment Routing */ + uint8_t label_num; + mpls_label_t labels[MPLS_MAX_LABELS]; }; struct zapi_route { diff --git a/zebra/zebra_mpls.h b/zebra/zebra_mpls.h index 6bddc4d00f..c8df8670f4 100644 --- a/zebra/zebra_mpls.h +++ b/zebra/zebra_mpls.h @@ -37,8 +37,6 @@ /* Definitions and macros. */ -#define MPLS_MAX_LABELS 16 /* Maximum # labels that can be pushed. */ - #define NHLFE_FAMILY(nhlfe) \ (((nhlfe)->nexthop->type == NEXTHOP_TYPE_IPV6 \ || (nhlfe)->nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX) \ diff --git a/zebra/zserv.c b/zebra/zserv.c index 94e34865b5..de475dccfd 100644 --- a/zebra/zserv.c +++ b/zebra/zserv.c @@ -1222,8 +1222,9 @@ static int zread_route_add(struct zserv *client, u_short length, label_type = lsp_type_from_re_type(client->proto); - nexthop_add_labels(nexthop, label_type, 1, - &api_nh->label); + nexthop_add_labels(nexthop, label_type, + api_nh->label_num, + &api_nh->labels[0]); } } } From c9fb3e233e4c3199d3379952eb56e93f856a4544 Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Sun, 20 Aug 2017 21:17:09 -0300 Subject: [PATCH 071/130] ripd/ripngd: use the new API to send routes to zebra Signed-off-by: Renato Westphal --- ripd/rip_zebra.c | 36 ++++++++++++------------------- ripngd/ripng_zebra.c | 51 ++++++++++++++++---------------------------- 2 files changed, 32 insertions(+), 55 deletions(-) diff --git a/ripd/rip_zebra.c b/ripd/rip_zebra.c index f9d2d33f19..9a9bac51e0 100644 --- a/ripd/rip_zebra.c +++ b/ripd/rip_zebra.c @@ -39,40 +39,32 @@ struct zclient *zclient = NULL; /* Send ECMP routes to zebra. */ static void rip_zebra_ipv4_send(struct route_node *rp, u_char cmd) { - static struct in_addr **nexthops = NULL; - static unsigned int nexthops_len = 0; - struct list *list = (struct list *)rp->info; - struct zapi_ipv4 api; + struct zapi_route api; + struct zapi_nexthop *api_nh; struct listnode *listnode = NULL; struct rip_info *rinfo = NULL; int count = 0; + memset(&api, 0, sizeof(api)); api.vrf_id = VRF_DEFAULT; api.type = ZEBRA_ROUTE_RIP; - api.instance = 0; - api.flags = 0; - api.message = 0; api.safi = SAFI_UNICAST; - if (nexthops_len < listcount(list)) { - nexthops_len = listcount(list); - nexthops = XREALLOC(MTYPE_TMP, nexthops, - nexthops_len * sizeof(struct in_addr *)); - } - SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); for (ALL_LIST_ELEMENTS_RO(list, listnode, rinfo)) { - nexthops[count++] = &rinfo->nexthop; - if (cmd == ZEBRA_IPV4_ROUTE_ADD) + api_nh = &api.nexthops[count]; + api_nh->gate.ipv4 = rinfo->nexthop; + api_nh->type = NEXTHOP_TYPE_IPV4; + if (cmd == ZEBRA_ROUTE_ADD) SET_FLAG(rinfo->flags, RIP_RTF_FIB); else UNSET_FLAG(rinfo->flags, RIP_RTF_FIB); + count++; } - api.nexthop = nexthops; + api.prefix = rp->p; api.nexthop_num = count; - api.ifindex_num = 0; rinfo = listgetdata(listhead(list)); @@ -89,19 +81,19 @@ static void rip_zebra_ipv4_send(struct route_node *rp, u_char cmd) api.tag = rinfo->tag; } - zapi_ipv4_route(cmd, zclient, (struct prefix_ipv4 *)&rp->p, &api); + zclient_route_send(cmd, zclient, &api); if (IS_RIP_DEBUG_ZEBRA) { if (rip->ecmp) zlog_debug("%s: %s/%d nexthops %d", - (cmd == ZEBRA_IPV4_ROUTE_ADD) + (cmd == ZEBRA_ROUTE_ADD) ? "Install into zebra" : "Delete from zebra", inet_ntoa(rp->p.u.prefix4), rp->p.prefixlen, count); else zlog_debug("%s: %s/%d", - (cmd == ZEBRA_IPV4_ROUTE_ADD) + (cmd == ZEBRA_ROUTE_ADD) ? "Install into zebra" : "Delete from zebra", inet_ntoa(rp->p.u.prefix4), rp->p.prefixlen); @@ -113,13 +105,13 @@ static void rip_zebra_ipv4_send(struct route_node *rp, u_char cmd) /* Add/update ECMP routes to zebra. */ void rip_zebra_ipv4_add(struct route_node *rp) { - rip_zebra_ipv4_send(rp, ZEBRA_IPV4_ROUTE_ADD); + rip_zebra_ipv4_send(rp, ZEBRA_ROUTE_ADD); } /* Delete ECMP routes from zebra. */ void rip_zebra_ipv4_delete(struct route_node *rp) { - rip_zebra_ipv4_send(rp, ZEBRA_IPV4_ROUTE_DELETE); + rip_zebra_ipv4_send(rp, ZEBRA_ROUTE_DELETE); } /* Zebra route add and delete treatment. */ diff --git a/ripngd/ripng_zebra.c b/ripngd/ripng_zebra.c index 3845028264..a5ed5c7b2c 100644 --- a/ripngd/ripng_zebra.c +++ b/ripngd/ripng_zebra.c @@ -39,47 +39,33 @@ struct zclient *zclient = NULL; /* Send ECMP routes to zebra. */ static void ripng_zebra_ipv6_send(struct route_node *rp, u_char cmd) { - static struct in6_addr **nexthops = NULL; - static ifindex_t *ifindexes = NULL; - static unsigned int nexthops_len = 0; - struct list *list = (struct list *)rp->info; - struct zapi_ipv6 api; + struct zapi_route api; + struct zapi_nexthop *api_nh; struct listnode *listnode = NULL; struct ripng_info *rinfo = NULL; int count = 0; + memset(&api, 0, sizeof(api)); api.vrf_id = VRF_DEFAULT; api.type = ZEBRA_ROUTE_RIPNG; - api.instance = 0; - api.flags = 0; - api.message = 0; api.safi = SAFI_UNICAST; - - if (nexthops_len < listcount(list)) { - nexthops_len = listcount(list); - nexthops = XREALLOC(MTYPE_TMP, nexthops, - nexthops_len * sizeof(struct in6_addr *)); - ifindexes = XREALLOC(MTYPE_TMP, ifindexes, - nexthops_len * sizeof(unsigned int)); - } + api.prefix = rp->p; SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); - SET_FLAG(api.message, ZAPI_MESSAGE_IFINDEX); for (ALL_LIST_ELEMENTS_RO(list, listnode, rinfo)) { - nexthops[count] = &rinfo->nexthop; - ifindexes[count] = rinfo->ifindex; + api_nh = &api.nexthops[count]; + api_nh->gate.ipv6 = rinfo->nexthop; + api_nh->ifindex = rinfo->ifindex; + api_nh->type = NEXTHOP_TYPE_IPV6_IFINDEX; count++; - if (cmd == ZEBRA_IPV6_ROUTE_ADD) + if (cmd == ZEBRA_ROUTE_ADD) SET_FLAG(rinfo->flags, RIPNG_RTF_FIB); else UNSET_FLAG(rinfo->flags, RIPNG_RTF_FIB); } - api.nexthop = nexthops; api.nexthop_num = count; - api.ifindex = ifindexes; - api.ifindex_num = count; rinfo = listgetdata(listhead(list)); @@ -91,36 +77,35 @@ static void ripng_zebra_ipv6_send(struct route_node *rp, u_char cmd) api.tag = rinfo->tag; } - zapi_ipv6_route(cmd, zclient, (struct prefix_ipv6 *)&rp->p, NULL, &api); + zclient_route_send(cmd, zclient, &api); if (IS_RIPNG_DEBUG_ZEBRA) { if (ripng->ecmp) zlog_debug("%s: %s/%d nexthops %d", - (cmd == ZEBRA_IPV6_ROUTE_ADD) + (cmd == ZEBRA_ROUTE_ADD) ? "Install into zebra" : "Delete from zebra", inet6_ntoa(rp->p.u.prefix6), rp->p.prefixlen, count); else - zlog_debug("%s: %s/%d", - (cmd == ZEBRA_IPV6_ROUTE_ADD) - ? "Install into zebra" - : "Delete from zebra", - inet6_ntoa(rp->p.u.prefix6), - rp->p.prefixlen); + zlog_debug( + "%s: %s/%d", + (cmd == ZEBRA_ROUTE_ADD) ? "Install into zebra" + : "Delete from zebra", + inet6_ntoa(rp->p.u.prefix6), rp->p.prefixlen); } } /* Add/update ECMP routes to zebra. */ void ripng_zebra_ipv6_add(struct route_node *rp) { - ripng_zebra_ipv6_send(rp, ZEBRA_IPV6_ROUTE_ADD); + ripng_zebra_ipv6_send(rp, ZEBRA_ROUTE_ADD); } /* Delete ECMP routes from zebra. */ void ripng_zebra_ipv6_delete(struct route_node *rp) { - ripng_zebra_ipv6_send(rp, ZEBRA_IPV6_ROUTE_DELETE); + ripng_zebra_ipv6_send(rp, ZEBRA_ROUTE_DELETE); } /* Zebra route add and delete treatment. */ From 8fb753e3609249c3937a5613e73e2826c7fb3b76 Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Sun, 20 Aug 2017 21:17:59 -0300 Subject: [PATCH 072/130] eigrpd: use the new API to send routes to zebra Signed-off-by: Renato Westphal --- eigrpd/eigrp_zebra.c | 84 ++++++++++++++++---------------------------- 1 file changed, 31 insertions(+), 53 deletions(-) diff --git a/eigrpd/eigrp_zebra.c b/eigrpd/eigrp_zebra.c index 6fc3f29353..2e386fbf2e 100644 --- a/eigrpd/eigrp_zebra.c +++ b/eigrpd/eigrp_zebra.c @@ -391,90 +391,68 @@ static struct interface *zebra_interface_if_lookup(struct stream *s) void eigrp_zebra_route_add(struct prefix_ipv4 *p, struct list *successors) { + struct zapi_route api; + struct zapi_nexthop *api_nh; struct eigrp_neighbor_entry *te; struct listnode *node; - u_char message; - u_char flags; - int psize; - struct stream *s; + int count = 0; if (!zclient->redist[AFI_IP][ZEBRA_ROUTE_EIGRP]) return; - message = 0; - flags = 0; + memset(&api, 0, sizeof(api)); + api.vrf_id = VRF_DEFAULT; + api.type = ZEBRA_ROUTE_EIGRP; + api.safi = SAFI_UNICAST; + memcpy(&api.prefix, p, sizeof(*p)); - /* EIGRP pass nexthop and metric */ - SET_FLAG(message, ZAPI_MESSAGE_NEXTHOP); - - /* Make packet. */ - s = zclient->obuf; - stream_reset(s); - - /* Put command, type, flags, message. */ - zclient_create_header(s, ZEBRA_IPV4_ROUTE_ADD, VRF_DEFAULT); - stream_putc(s, ZEBRA_ROUTE_EIGRP); - stream_putw(s, 0); - stream_putl(s, flags); - stream_putc(s, message); - stream_putw(s, SAFI_UNICAST); - - /* Put prefix information. */ - psize = PSIZE(p->prefixlen); - stream_putc(s, p->prefixlen); - stream_write(s, (u_char *)&p->prefix, psize); - - /* Nexthop count. */ - stream_putc(s, successors->count); + SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); + api.nexthop_num = successors->count; /* Nexthop, ifindex, distance and metric information. */ for (ALL_LIST_ELEMENTS_RO(successors, node, te)) { + api_nh = &api.nexthops[count]; if (te->adv_router->src.s_addr) { - stream_putc(s, NEXTHOP_TYPE_IPV4_IFINDEX); - stream_put_in_addr(s, &te->adv_router->src); + api_nh->gate.ipv4 = te->adv_router->src; + api_nh->type = NEXTHOP_TYPE_IPV4_IFINDEX; } else - stream_putc(s, NEXTHOP_TYPE_IFINDEX); - stream_putl(s, te->ei->ifp->ifindex); + api_nh->type = NEXTHOP_TYPE_IFINDEX; + api_nh->ifindex = te->ei->ifp->ifindex; + + count++; } if (IS_DEBUG_EIGRP(zebra, ZEBRA_REDISTRIBUTE)) { char buf[2][INET_ADDRSTRLEN]; - zlog_debug("Zebra: Route add %s/%d nexthop %s", - inet_ntop(AF_INET, &p->prefix, buf[0], - sizeof(buf[0])), - p->prefixlen, - inet_ntop(AF_INET, 0 /*&p->nexthop*/, buf[1], - sizeof(buf[1]))); + zlog_debug( + "Zebra: Route add %s/%d nexthop %s", + inet_ntop(AF_INET, &p->prefix, buf[0], sizeof(buf[0])), + p->prefixlen, inet_ntop(AF_INET, 0 /*&p->nexthop*/, + buf[1], sizeof(buf[1]))); } - stream_putw_at(s, 0, stream_get_endp(s)); - - zclient_send_message(zclient); + zclient_route_send(ZEBRA_ROUTE_ADD, zclient, &api); } void eigrp_zebra_route_delete(struct prefix_ipv4 *p) { - struct zapi_ipv4 api; + struct zapi_route api; if (!zclient->redist[AFI_IP][ZEBRA_ROUTE_EIGRP]) return; + memset(&api, 0, sizeof(api)); api.vrf_id = VRF_DEFAULT; api.type = ZEBRA_ROUTE_EIGRP; - api.instance = 0; - api.flags = 0; - api.message = 0; api.safi = SAFI_UNICAST; - zapi_ipv4_route(ZEBRA_IPV4_ROUTE_DELETE, zclient, p, &api); + memcpy(&api.prefix, p, sizeof(*p)); + zclient_route_send(ZEBRA_ROUTE_DELETE, zclient, &api); if (IS_DEBUG_EIGRP(zebra, ZEBRA_REDISTRIBUTE)) { - char buf[2][INET_ADDRSTRLEN]; - zlog_debug("Zebra: Route del %s/%d nexthop %s", - inet_ntop(AF_INET, &p->prefix, buf[0], - sizeof(buf[0])), - p->prefixlen, - inet_ntop(AF_INET, 0 /*&p->nexthop*/, buf[1], - sizeof(buf[1]))); + char buf[INET_ADDRSTRLEN]; + zlog_debug("Zebra: Route del %s/%d", + inet_ntop(AF_INET, &p->prefix, buf, sizeof(buf)), + p->prefixlen); } return; From c0721de4d4cfad92893271cb5b036dab1fe011b6 Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Sun, 20 Aug 2017 21:18:36 -0300 Subject: [PATCH 073/130] isisd: use the new API to send routes to zebra Signed-off-by: Renato Westphal --- isisd/isis_zebra.c | 218 +++++++++++---------------------------------- 1 file changed, 51 insertions(+), 167 deletions(-) diff --git a/isisd/isis_zebra.c b/isisd/isis_zebra.c index 2eecda91bf..35b2091e98 100644 --- a/isisd/isis_zebra.c +++ b/isisd/isis_zebra.c @@ -248,66 +248,47 @@ static int isis_zebra_link_params(int command, struct zclient *zclient, static void isis_zebra_route_add_ipv4(struct prefix *prefix, struct isis_route_info *route_info) { - u_char message; - u_int32_t flags; - int psize; - struct stream *stream; + struct zapi_route api; + struct zapi_nexthop *api_nh; struct isis_nexthop *nexthop; struct listnode *node; + int count = 0; if (CHECK_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED)) return; - message = 0; - flags = 0; - - SET_FLAG(message, ZAPI_MESSAGE_NEXTHOP); - SET_FLAG(message, ZAPI_MESSAGE_METRIC); + memset(&api, 0, sizeof(api)); + api.vrf_id = VRF_DEFAULT; + api.type = ZEBRA_ROUTE_ISIS; + api.safi = SAFI_UNICAST; + api.prefix = *prefix; + SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); + SET_FLAG(api.message, ZAPI_MESSAGE_METRIC); + api.metric = route_info->cost; #if 0 - SET_FLAG (message, ZAPI_MESSAGE_DISTANCE); + SET_FLAG(api.message, ZAPI_MESSAGE_DISTANCE); + api.distance = route_info->depth; #endif - stream = zclient->obuf; - stream_reset(stream); - zclient_create_header(stream, ZEBRA_IPV4_ROUTE_ADD, VRF_DEFAULT); - /* type */ - stream_putc(stream, ZEBRA_ROUTE_ISIS); - /* instance */ - stream_putw(stream, 0); - /* flags */ - stream_putl(stream, flags); - /* message */ - stream_putc(stream, message); - /* SAFI */ - stream_putw(stream, SAFI_UNICAST); - /* prefix information */ - psize = PSIZE(prefix->prefixlen); - stream_putc(stream, prefix->prefixlen); - stream_write(stream, (u_char *)&prefix->u.prefix4, psize); - - stream_putc(stream, listcount(route_info->nexthops)); - /* Nexthop, ifindex, distance and metric information */ for (ALL_LIST_ELEMENTS_RO(route_info->nexthops, node, nexthop)) { + api_nh = &api.nexthops[count]; /* FIXME: can it be ? */ if (nexthop->ip.s_addr != INADDR_ANY) { - stream_putc(stream, NEXTHOP_TYPE_IPV4_IFINDEX); - stream_put_in_addr(stream, &nexthop->ip); - stream_putl(stream, nexthop->ifindex); + api_nh->type = NEXTHOP_TYPE_IPV4_IFINDEX; + api_nh->gate.ipv4 = nexthop->ip; } else { - stream_putc(stream, NEXTHOP_TYPE_IFINDEX); - stream_putl(stream, nexthop->ifindex); + api_nh->type = NEXTHOP_TYPE_IFINDEX; } + api_nh->ifindex = nexthop->ifindex; + count++; } -#if 0 - if (CHECK_FLAG (message, ZAPI_MESSAGE_DISTANCE)) - stream_putc (stream, route_info->depth); -#endif - if (CHECK_FLAG(message, ZAPI_MESSAGE_METRIC)) - stream_putl(stream, route_info->cost); + if (!count) + return; - stream_putw_at(stream, 0, stream_get_endp(stream)); - zclient_send_message(zclient); + api.nexthop_num = count; + + zclient_route_send(ZEBRA_ROUTE_ADD, zclient, &api); SET_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED); UNSET_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_RESYNC); } @@ -315,180 +296,83 @@ static void isis_zebra_route_add_ipv4(struct prefix *prefix, static void isis_zebra_route_del_ipv4(struct prefix *prefix, struct isis_route_info *route_info) { - struct zapi_ipv4 api; - struct prefix_ipv4 prefix4; + struct zapi_route api; UNSET_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED); + memset(&api, 0, sizeof(api)); api.vrf_id = VRF_DEFAULT; api.type = ZEBRA_ROUTE_ISIS; - api.instance = 0; - api.flags = 0; - api.message = 0; api.safi = SAFI_UNICAST; - prefix4.family = AF_INET; - prefix4.prefixlen = prefix->prefixlen; - prefix4.prefix = prefix->u.prefix4; - zapi_ipv4_route(ZEBRA_IPV4_ROUTE_DELETE, zclient, &prefix4, &api); + api.prefix = *prefix; + + zclient_route_send(ZEBRA_ROUTE_DELETE, zclient, &api); } static void isis_zebra_route_add_ipv6(struct prefix *prefix, struct isis_route_info *route_info) { - struct zapi_ipv6 api; - struct in6_addr **nexthop_list; - ifindex_t *ifindex_list; + struct zapi_route api; + struct zapi_nexthop *api_nh; struct isis_nexthop6 *nexthop6; - int i, size; struct listnode *node; - struct prefix_ipv6 prefix6; + int count = 0; if (CHECK_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED)) return; + memset(&api, 0, sizeof(api)); api.vrf_id = VRF_DEFAULT; api.type = ZEBRA_ROUTE_ISIS; - api.instance = 0; - api.flags = 0; - api.message = 0; api.safi = SAFI_UNICAST; SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); - SET_FLAG(api.message, ZAPI_MESSAGE_IFINDEX); SET_FLAG(api.message, ZAPI_MESSAGE_METRIC); api.metric = route_info->cost; #if 0 - SET_FLAG (api.message, ZAPI_MESSAGE_DISTANCE); + SET_FLAG(api.message, ZAPI_MESSAGE_DISTANCE); api.distance = route_info->depth; #endif - api.nexthop_num = listcount(route_info->nexthops6); - api.ifindex_num = listcount(route_info->nexthops6); - - /* allocate memory for nexthop_list */ - size = sizeof(struct isis_nexthop6 *) - * listcount(route_info->nexthops6); - nexthop_list = (struct in6_addr **)XMALLOC(MTYPE_ISIS_TMP, size); - if (!nexthop_list) { - zlog_err("isis_zebra_add_route_ipv6: out of memory!"); - return; - } - - /* allocate memory for ifindex_list */ - size = sizeof(unsigned int) * listcount(route_info->nexthops6); - ifindex_list = (ifindex_t *)XMALLOC(MTYPE_ISIS_TMP, size); - if (!ifindex_list) { - zlog_err("isis_zebra_add_route_ipv6: out of memory!"); - XFREE(MTYPE_ISIS_TMP, nexthop_list); - return; - } + api.prefix = *prefix; /* for each nexthop */ - i = 0; for (ALL_LIST_ELEMENTS_RO(route_info->nexthops6, node, nexthop6)) { if (!IN6_IS_ADDR_LINKLOCAL(&nexthop6->ip6) && !IN6_IS_ADDR_UNSPECIFIED(&nexthop6->ip6)) { - api.nexthop_num--; - api.ifindex_num--; continue; } - nexthop_list[i] = &nexthop6->ip6; - ifindex_list[i] = nexthop6->ifindex; - i++; + api_nh = &api.nexthops[count]; + api_nh->gate.ipv6 = nexthop6->ip6; + api_nh->ifindex = nexthop6->ifindex; + api_nh->type = NEXTHOP_TYPE_IPV6_IFINDEX; + count++; } + if (!count) + return; - api.nexthop = nexthop_list; - api.ifindex = ifindex_list; + api.nexthop_num = count; - if (api.nexthop_num && api.ifindex_num) { - prefix6.family = AF_INET6; - prefix6.prefixlen = prefix->prefixlen; - memcpy(&prefix6.prefix, &prefix->u.prefix6, - sizeof(struct in6_addr)); - zapi_ipv6_route(ZEBRA_IPV6_ROUTE_ADD, zclient, &prefix6, NULL, - &api); - SET_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED); - UNSET_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_RESYNC); - } - - XFREE(MTYPE_ISIS_TMP, nexthop_list); - XFREE(MTYPE_ISIS_TMP, ifindex_list); - - return; + zclient_route_send(ZEBRA_ROUTE_ADD, zclient, &api); + SET_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED); + UNSET_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_RESYNC); } static void isis_zebra_route_del_ipv6(struct prefix *prefix, struct isis_route_info *route_info) { - struct zapi_ipv6 api; - struct in6_addr **nexthop_list; - ifindex_t *ifindex_list; - struct isis_nexthop6 *nexthop6; - int i, size; - struct listnode *node; - struct prefix_ipv6 prefix6; + struct zapi_route api; if (!CHECK_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED)) return; + memset(&api, 0, sizeof(api)); api.vrf_id = VRF_DEFAULT; api.type = ZEBRA_ROUTE_ISIS; - api.instance = 0; - api.flags = 0; - api.message = 0; api.safi = SAFI_UNICAST; - SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); - SET_FLAG(api.message, ZAPI_MESSAGE_IFINDEX); - api.nexthop_num = listcount(route_info->nexthops6); - api.ifindex_num = listcount(route_info->nexthops6); + api.prefix = *prefix; - /* allocate memory for nexthop_list */ - size = sizeof(struct isis_nexthop6 *) - * listcount(route_info->nexthops6); - nexthop_list = (struct in6_addr **)XMALLOC(MTYPE_ISIS_TMP, size); - if (!nexthop_list) { - zlog_err("isis_zebra_route_del_ipv6: out of memory!"); - return; - } - - /* allocate memory for ifindex_list */ - size = sizeof(unsigned int) * listcount(route_info->nexthops6); - ifindex_list = (ifindex_t *)XMALLOC(MTYPE_ISIS_TMP, size); - if (!ifindex_list) { - zlog_err("isis_zebra_route_del_ipv6: out of memory!"); - XFREE(MTYPE_ISIS_TMP, nexthop_list); - return; - } - - /* for each nexthop */ - i = 0; - for (ALL_LIST_ELEMENTS_RO(route_info->nexthops6, node, nexthop6)) { - if (!IN6_IS_ADDR_LINKLOCAL(&nexthop6->ip6) - && !IN6_IS_ADDR_UNSPECIFIED(&nexthop6->ip6)) { - api.nexthop_num--; - api.ifindex_num--; - continue; - } - - nexthop_list[i] = &nexthop6->ip6; - ifindex_list[i] = nexthop6->ifindex; - i++; - } - - api.nexthop = nexthop_list; - api.ifindex = ifindex_list; - - if (api.nexthop_num && api.ifindex_num) { - prefix6.family = AF_INET6; - prefix6.prefixlen = prefix->prefixlen; - memcpy(&prefix6.prefix, &prefix->u.prefix6, - sizeof(struct in6_addr)); - zapi_ipv6_route(ZEBRA_IPV6_ROUTE_DELETE, zclient, &prefix6, - NULL, &api); - UNSET_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED); - } - - XFREE(MTYPE_ISIS_TMP, nexthop_list); - XFREE(MTYPE_ISIS_TMP, ifindex_list); + zclient_route_send(ZEBRA_ROUTE_DELETE, zclient, &api); + UNSET_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED); } void isis_zebra_route_update(struct prefix *prefix, From 6f27a9f6a52aefc26f4c6ee633975cfc9942f5ac Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Sun, 20 Aug 2017 21:18:50 -0300 Subject: [PATCH 074/130] nhrpd: use the new API to send routes to zebra Signed-off-by: Renato Westphal --- nhrpd/nhrp_route.c | 52 +++++++++++++++++++++++++--------------------- 1 file changed, 28 insertions(+), 24 deletions(-) diff --git a/nhrpd/nhrp_route.c b/nhrpd/nhrp_route.c index 5116ad068c..3062b23a6d 100644 --- a/nhrpd/nhrp_route.c +++ b/nhrpd/nhrp_route.c @@ -108,24 +108,27 @@ void nhrp_route_announce(int add, enum nhrp_cache_type type, const struct prefix SET_FLAG(flags, ZEBRA_FLAG_INTERNAL); if (p->family == AF_INET) { - struct in_addr *nexthop_ipv4; - struct zapi_ipv4 api; + struct zapi_route api; + struct zapi_nexthop *api_nh = &api.nexthops[0];; memset(&api, 0, sizeof(api)); api.flags = flags; api.type = ZEBRA_ROUTE_NHRP; api.safi = SAFI_UNICAST; + api.prefix = *p; SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); + api.nexthop_num = 1; if (nexthop) { - nexthop_ipv4 = (struct in_addr *) sockunion_get_addr(nexthop); - api.nexthop_num = 1; - api.nexthop = &nexthop_ipv4; + api_nh->gate.ipv4 = nexthop->sin.sin_addr; + api_nh->type = NEXTHOP_TYPE_IPV4; } if (ifp) { - SET_FLAG(api.message, ZAPI_MESSAGE_IFINDEX); - api.ifindex_num = 1; - api.ifindex = &ifp->ifindex; + api_nh->ifindex = ifp->ifindex; + if (api_nh->type == NEXTHOP_TYPE_IPV4) + api_nh->type = NEXTHOP_TYPE_IPV4_IFINDEX; + else + api_nh->type = NEXTHOP_TYPE_IFINDEX; } if (mtu) { SET_FLAG(api.message, ZAPI_MESSAGE_MTU); @@ -139,32 +142,34 @@ void nhrp_route_announce(int add, enum nhrp_cache_type type, const struct prefix add ? "add" : "del", inet_ntop(AF_INET, &p->u.prefix4, buf[0], sizeof(buf[0])), p->prefixlen, - nexthop ? inet_ntop(AF_INET, api.nexthop[0], buf[1], sizeof(buf[1])) : "", + nexthop ? inet_ntop(AF_INET, &api_nh->gate.ipv4, buf[1], sizeof(buf[1])) : "", api.metric, api.nexthop_num, ifp->name); } - zapi_ipv4_route( - add ? ZEBRA_IPV4_ROUTE_ADD : ZEBRA_IPV4_ROUTE_DELETE, - zclient, (struct prefix_ipv4 *) p, &api); + zclient_route_send(add ? ZEBRA_ROUTE_ADD : ZEBRA_ROUTE_DELETE, + zclient, &api); } else if (p->family == AF_INET6) { - struct in6_addr *nexthop_ipv6; - struct zapi_ipv6 api; + struct zapi_route api; + struct zapi_nexthop *api_nh = &api.nexthops[0];; memset(&api, 0, sizeof(api)); api.flags = flags; api.type = ZEBRA_ROUTE_NHRP; api.safi = SAFI_UNICAST; + api.prefix = *p; SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); + api.nexthop_num = 1; if (nexthop) { - nexthop_ipv6 = (struct in6_addr *) sockunion_get_addr(nexthop); - api.nexthop_num = 1; - api.nexthop = &nexthop_ipv6; + api_nh->gate.ipv6 = nexthop->sin6.sin6_addr; + api_nh->type = NEXTHOP_TYPE_IPV6; } if (ifp) { - SET_FLAG(api.message, ZAPI_MESSAGE_IFINDEX); - api.ifindex_num = 1; - api.ifindex = &ifp->ifindex; + api_nh->ifindex = ifp->ifindex; + if (api_nh->type == NEXTHOP_TYPE_IPV6) + api_nh->type = NEXTHOP_TYPE_IPV6_IFINDEX; + else + api_nh->type = NEXTHOP_TYPE_IFINDEX; } if (mtu) { SET_FLAG(api.message, ZAPI_MESSAGE_MTU); @@ -178,13 +183,12 @@ void nhrp_route_announce(int add, enum nhrp_cache_type type, const struct prefix add ? "add" : "del", inet_ntop(AF_INET6, &p->u.prefix6, buf[0], sizeof(buf[0])), p->prefixlen, - nexthop ? inet_ntop(AF_INET6, api.nexthop[0], buf[1], sizeof(buf[1])) : "", + nexthop ? inet_ntop(AF_INET6, &api_nh->gate.ipv6, buf[1], sizeof(buf[1])) : "", api.metric, api.nexthop_num, ifp->name); } - zapi_ipv6_route( - add ? ZEBRA_IPV6_ROUTE_ADD : ZEBRA_IPV6_ROUTE_DELETE, - zclient, (struct prefix_ipv6 *) p, NULL, &api); + zclient_route_send(add ? ZEBRA_ROUTE_ADD : ZEBRA_ROUTE_DELETE, + zclient, &api); } } From 5fef910e7121b655ef50f12398c2766bde12b6ac Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Sun, 20 Aug 2017 21:18:58 -0300 Subject: [PATCH 075/130] ospfd: use the new API to send routes to zebra Signed-off-by: Renato Westphal --- ospfd/ospf_zebra.c | 221 +++++++++++++-------------------------------- 1 file changed, 63 insertions(+), 158 deletions(-) diff --git a/ospfd/ospf_zebra.c b/ospfd/ospf_zebra.c index 6d9d56d92d..53b68a022b 100644 --- a/ospfd/ospf_zebra.c +++ b/ospfd/ospf_zebra.c @@ -333,87 +333,68 @@ static int ospf_interface_link_params(int command, struct zclient *zclient, void ospf_zebra_add(struct prefix_ipv4 *p, struct ospf_route * or) { - u_char message; + struct zapi_route api; + struct zapi_nexthop *api_nh; u_char distance; - u_int32_t flags; - int psize; - struct stream *s; struct ospf_path *path; struct listnode *node; struct ospf *ospf = ospf_lookup(); + int count = 0; - message = 0; - flags = 0; + memset(&api, 0, sizeof(api)); + api.vrf_id = VRF_DEFAULT; + api.type = ZEBRA_ROUTE_OSPF; + api.instance = ospf->instance; + api.safi = SAFI_UNICAST; - /* OSPF pass nexthop and metric */ - SET_FLAG(message, ZAPI_MESSAGE_NEXTHOP); - SET_FLAG(message, ZAPI_MESSAGE_METRIC); + memcpy(&api.prefix, p, sizeof(*p)); + SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); + api.nexthop_num = or->paths->count; - /* Distance value. */ - distance = ospf_distance_apply(p, or); - if (distance) - SET_FLAG(message, ZAPI_MESSAGE_DISTANCE); + /* Metric value. */ + SET_FLAG(api.message, ZAPI_MESSAGE_METRIC); + if (or->path_type == OSPF_PATH_TYPE1_EXTERNAL) + api.metric = or->cost + or->u.ext.type2_cost; + else if (or->path_type == OSPF_PATH_TYPE2_EXTERNAL) + api.metric = or->u.ext.type2_cost; + else + api.metric = or->cost; /* Check if path type is ASE */ if (((or->path_type == OSPF_PATH_TYPE1_EXTERNAL) || (or->path_type == OSPF_PATH_TYPE2_EXTERNAL)) - && (or->u.ext.tag > 0) && (or->u.ext.tag <= ROUTE_TAG_MAX)) - SET_FLAG(message, ZAPI_MESSAGE_TAG); + && (or->u.ext.tag > 0) && (or->u.ext.tag <= ROUTE_TAG_MAX)) { + SET_FLAG(api.message, ZAPI_MESSAGE_TAG); + api.tag = or->u.ext.tag; + } - /* Make packet. */ - s = zclient->obuf; - stream_reset(s); - - /* Put command, type, flags, message. */ - zclient_create_header(s, ZEBRA_IPV4_ROUTE_ADD, VRF_DEFAULT); - stream_putc(s, ZEBRA_ROUTE_OSPF); - stream_putw(s, ospf->instance); - stream_putl(s, flags); - stream_putc(s, message); - stream_putw(s, SAFI_UNICAST); - - /* Put prefix information. */ - psize = PSIZE(p->prefixlen); - stream_putc(s, p->prefixlen); - stream_write(s, (u_char *)&p->prefix, psize); - - /* Nexthop count. */ - stream_putc(s, or->paths->count); + /* Distance value. */ + distance = ospf_distance_apply(p, or); + if (distance) { + SET_FLAG(api.message, ZAPI_MESSAGE_DISTANCE); + api.distance = distance; + } /* Nexthop, ifindex, distance and metric information. */ for (ALL_LIST_ELEMENTS_RO(or->paths, node, path)) { + api_nh = &api.nexthops[count]; #ifdef HAVE_NETLINK if (path->unnumbered || (path->nexthop.s_addr != INADDR_ANY && path->ifindex != 0)) { - stream_putc(s, NEXTHOP_TYPE_IPV4_IFINDEX); - stream_put_in_addr(s, &path->nexthop); - stream_putl(s, path->ifindex); - } else if (path->nexthop.s_addr != INADDR_ANY) { - stream_putc(s, NEXTHOP_TYPE_IPV4); - stream_put_in_addr(s, &path->nexthop); - } else { - stream_putc(s, NEXTHOP_TYPE_IFINDEX); - if (path->ifindex) - stream_putl(s, path->ifindex); - else - stream_putl(s, 0); - } #else /* HAVE_NETLINK */ if (path->nexthop.s_addr != INADDR_ANY && path->ifindex != 0) { - stream_putc(s, NEXTHOP_TYPE_IPV4_IFINDEX); - stream_put_in_addr(s, &path->nexthop); - stream_putl(s, path->ifindex); - } else if (path->nexthop.s_addr != INADDR_ANY) { - stream_putc(s, NEXTHOP_TYPE_IPV4); - stream_put_in_addr(s, &path->nexthop); - } else { - stream_putc(s, NEXTHOP_TYPE_IFINDEX); - if (path->ifindex) - stream_putl(s, path->ifindex); - else - stream_putl(s, 0); - } #endif /* HAVE_NETLINK */ + api_nh->gate.ipv4 = path->nexthop; + api_nh->ifindex = path->ifindex; + api_nh->type = NEXTHOP_TYPE_IPV4_IFINDEX; + } else if (path->nexthop.s_addr != INADDR_ANY) { + api_nh->gate.ipv4 = path->nexthop; + api_nh->type = NEXTHOP_TYPE_IPV4; + } else { + api_nh->ifindex = path->ifindex; + api_nh->type = NEXTHOP_TYPE_IFINDEX; + } + count++; if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE)) { char buf[2][INET_ADDRSTRLEN]; @@ -427,118 +408,45 @@ void ospf_zebra_add(struct prefix_ipv4 *p, struct ospf_route * or) } } - if (CHECK_FLAG(message, ZAPI_MESSAGE_DISTANCE)) - stream_putc(s, distance); - if (CHECK_FLAG(message, ZAPI_MESSAGE_METRIC)) { - if (or->path_type == OSPF_PATH_TYPE1_EXTERNAL) - stream_putl(s, or->cost + or->u.ext.type2_cost); - else if (or->path_type == OSPF_PATH_TYPE2_EXTERNAL) - stream_putl(s, or->u.ext.type2_cost); - else - stream_putl(s, or->cost); - } - - if (CHECK_FLAG(message, ZAPI_MESSAGE_TAG)) - stream_putl(s, or->u.ext.tag); - - stream_putw_at(s, 0, stream_get_endp(s)); - - zclient_send_message(zclient); + zclient_route_send(ZEBRA_ROUTE_ADD, zclient, &api); } void ospf_zebra_delete(struct prefix_ipv4 *p, struct ospf_route * or) { - u_char message; - u_char distance; - u_int32_t flags; - int psize; - struct stream *s; - struct ospf_path *path; - struct listnode *node; + struct zapi_route api; struct ospf *ospf = ospf_lookup(); - message = 0; - flags = 0; - /* Distance value. */ - distance = ospf_distance_apply(p, or); - /* Make packet. */ - s = zclient->obuf; - stream_reset(s); + memset(&api, 0, sizeof(api)); + api.vrf_id = VRF_DEFAULT; + api.type = ZEBRA_ROUTE_OSPF; + api.instance = ospf->instance; + api.safi = SAFI_UNICAST; + memcpy(&api.prefix, p, sizeof(*p)); - /* Put command, type, flags, message. */ - zclient_create_header(s, ZEBRA_IPV4_ROUTE_DELETE, VRF_DEFAULT); - stream_putc(s, ZEBRA_ROUTE_OSPF); - stream_putw(s, ospf->instance); - stream_putl(s, flags); - stream_putc(s, message); - stream_putw(s, SAFI_UNICAST); - - /* Put prefix information. */ - psize = PSIZE(p->prefixlen); - stream_putc(s, p->prefixlen); - stream_write(s, (u_char *)&p->prefix, psize); - - /* Nexthop count. */ - stream_putc(s, or->paths->count); - - /* Nexthop, ifindex, distance and metric information. */ - for (ALL_LIST_ELEMENTS_RO(or->paths, node, path)) { - if (path->nexthop.s_addr != INADDR_ANY && path->ifindex != 0) { - stream_putc(s, NEXTHOP_TYPE_IPV4_IFINDEX); - stream_put_in_addr(s, &path->nexthop); - stream_putl(s, path->ifindex); - } else if (path->nexthop.s_addr != INADDR_ANY) { - stream_putc(s, NEXTHOP_TYPE_IPV4); - stream_put_in_addr(s, &path->nexthop); - } else { - stream_putc(s, NEXTHOP_TYPE_IFINDEX); - stream_putl(s, path->ifindex); - } - - if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE)) { - char buf[2][INET_ADDRSTRLEN]; - zlog_debug("Zebra: Route delete %s/%d nexthop %s", - inet_ntop(AF_INET, &p->prefix, buf[0], - sizeof(buf[0])), - p->prefixlen, - inet_ntop(AF_INET, &path->nexthop, buf[1], - sizeof(buf[1]))); - } + if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE)) { + char buf[INET_ADDRSTRLEN]; + zlog_debug("Zebra: Route delete %s/%d", + inet_ntop(AF_INET, &p->prefix, buf, sizeof(buf[0])), + p->prefixlen); } - if (CHECK_FLAG(message, ZAPI_MESSAGE_DISTANCE)) - stream_putc(s, distance); - if (CHECK_FLAG(message, ZAPI_MESSAGE_METRIC)) { - if (or->path_type == OSPF_PATH_TYPE1_EXTERNAL) - stream_putl(s, or->cost + or->u.ext.type2_cost); - else if (or->path_type == OSPF_PATH_TYPE2_EXTERNAL) - stream_putl(s, or->u.ext.type2_cost); - else - stream_putl(s, or->cost); - } - - stream_putw_at(s, 0, stream_get_endp(s)); - - zclient_send_message(zclient); + zclient_route_send(ZEBRA_ROUTE_DELETE, zclient, &api); } void ospf_zebra_add_discard(struct prefix_ipv4 *p) { - struct zapi_ipv4 api; + struct zapi_route api; struct ospf *ospf = ospf_lookup(); + memset(&api, 0, sizeof(api)); api.vrf_id = VRF_DEFAULT; api.type = ZEBRA_ROUTE_OSPF; api.instance = ospf->instance; api.flags = ZEBRA_FLAG_BLACKHOLE; - api.message = 0; api.safi = SAFI_UNICAST; - SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); - api.nexthop_num = 0; - api.ifindex_num = 0; - api.tag = 0; + memcpy(&api.prefix, p, sizeof(*p)); - zapi_ipv4_route(ZEBRA_IPV4_ROUTE_ADD, zclient, p, &api); + zclient_route_send(ZEBRA_ROUTE_ADD, zclient, &api); if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE)) zlog_debug("Zebra: Route add discard %s/%d", @@ -547,21 +455,18 @@ void ospf_zebra_add_discard(struct prefix_ipv4 *p) void ospf_zebra_delete_discard(struct prefix_ipv4 *p) { - struct zapi_ipv4 api; + struct zapi_route api; struct ospf *ospf = ospf_lookup(); + memset(&api, 0, sizeof(api)); api.vrf_id = VRF_DEFAULT; api.type = ZEBRA_ROUTE_OSPF; api.instance = ospf->instance; api.flags = ZEBRA_FLAG_BLACKHOLE; - api.message = 0; api.safi = SAFI_UNICAST; - SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); - api.nexthop_num = 0; - api.ifindex_num = 0; - api.tag = 0; + memcpy(&api.prefix, p, sizeof(*p)); - zapi_ipv4_route(ZEBRA_IPV4_ROUTE_DELETE, zclient, p, &api); + zclient_route_send(ZEBRA_ROUTE_DELETE, zclient, &api); if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE)) zlog_debug("Zebra: Route delete discard %s/%d", From 5afa1c6be2b538c2beea713420c0e41e4b49c536 Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Sun, 20 Aug 2017 21:19:07 -0300 Subject: [PATCH 076/130] ospf6d: use the new API to send routes to zebra Signed-off-by: Renato Westphal --- ospf6d/ospf6_route.c | 8 ++-- ospf6d/ospf6_route.h | 4 +- ospf6d/ospf6_zebra.c | 93 ++++++++++++-------------------------------- 3 files changed, 31 insertions(+), 74 deletions(-) diff --git a/ospf6d/ospf6_route.c b/ospf6d/ospf6_route.c index bfe583a911..03791ad7a0 100644 --- a/ospf6d/ospf6_route.c +++ b/ospf6d/ospf6_route.c @@ -285,8 +285,7 @@ void ospf6_add_nexthop(struct list *nh_list, int ifindex, struct in6_addr *addr) } void ospf6_route_zebra_copy_nexthops(struct ospf6_route *route, - ifindex_t *ifindexes, - struct in6_addr **nexthop_addr, + struct zapi_nexthop nexthops[], int entries) { struct ospf6_nexthop *nh; @@ -307,8 +306,9 @@ void ospf6_route_zebra_copy_nexthops(struct ospf6_route *route, IFNAMSIZ, ifname, nh->ifindex); } if (i < entries) { - nexthop_addr[i] = &nh->address; - ifindexes[i] = nh->ifindex; + nexthops[i].gate.ipv6 = nh->address; + nexthops[i].ifindex = nh->ifindex; + nexthops[i].type = NEXTHOP_TYPE_IPV6_IFINDEX; i++; } else { return; diff --git a/ospf6d/ospf6_route.h b/ospf6d/ospf6_route.h index 166074fb70..9eacadbdb7 100644 --- a/ospf6d/ospf6_route.h +++ b/ospf6d/ospf6_route.h @@ -22,6 +22,7 @@ #define OSPF6_ROUTE_H #include "command.h" +#include "zclient.h" #define OSPF6_MULTI_PATH_LIMIT 4 @@ -266,8 +267,7 @@ extern int ospf6_num_nexthops(struct list *nh_list); extern int ospf6_route_cmp_nexthops(struct ospf6_route *a, struct ospf6_route *b); extern void ospf6_route_zebra_copy_nexthops(struct ospf6_route *route, - ifindex_t *ifindices, - struct in6_addr **addr, + struct zapi_nexthop nexthops[], int entries); extern int ospf6_route_get_first_nh_index(struct ospf6_route *route); diff --git a/ospf6d/ospf6_zebra.c b/ospf6d/ospf6_zebra.c index 1c266da888..5655502879 100644 --- a/ospf6d/ospf6_zebra.c +++ b/ospf6d/ospf6_zebra.c @@ -333,13 +333,11 @@ DEFUN (show_zebra, #define REM 1 static void ospf6_zebra_route_update(int type, struct ospf6_route *request) { - struct zapi_ipv6 api; + struct zapi_route api; char buf[PREFIX2STR_BUFFER]; int nhcount; - struct in6_addr **nexthops; - ifindex_t *ifindexes; int ret = 0; - struct prefix_ipv6 *dest; + struct prefix *dest; if (IS_OSPF6_DEBUG_ZEBRA(SEND)) { prefix2str(&request->prefix, buf, sizeof(buf)); @@ -387,36 +385,16 @@ static void ospf6_zebra_route_update(int type, struct ospf6_route *request) return; } - /* allocate memory for nexthop_list */ - nexthops = - XCALLOC(MTYPE_OSPF6_OTHER, nhcount * sizeof(struct in6_addr *)); - if (nexthops == NULL) { - zlog_warn("Can't send route to zebra: malloc failed"); - return; - } - - /* allocate memory for ifindex_list */ - ifindexes = XCALLOC(MTYPE_OSPF6_OTHER, nhcount * sizeof(ifindex_t)); - if (ifindexes == NULL) { - zlog_warn("Can't send route to zebra: malloc failed"); - XFREE(MTYPE_OSPF6_OTHER, nexthops); - return; - } - - ospf6_route_zebra_copy_nexthops(request, ifindexes, nexthops, nhcount); + dest = &request->prefix; + memset(&api, 0, sizeof(api)); api.vrf_id = VRF_DEFAULT; api.type = ZEBRA_ROUTE_OSPF6; - api.instance = 0; - api.flags = 0; - api.message = 0; api.safi = SAFI_UNICAST; + api.prefix = *dest; SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); api.nexthop_num = nhcount; - api.nexthop = nexthops; - SET_FLAG(api.message, ZAPI_MESSAGE_IFINDEX); - api.ifindex_num = nhcount; - api.ifindex = ifindexes; + ospf6_route_zebra_copy_nexthops(request, api.nexthops, nhcount); SET_FLAG(api.message, ZAPI_MESSAGE_METRIC); api.metric = (request->path.metric_type == 2 ? request->path.u.cost_e2 : request->path.cost); @@ -425,26 +403,20 @@ static void ospf6_zebra_route_update(int type, struct ospf6_route *request) api.tag = request->path.tag; } - dest = (struct prefix_ipv6 *)&request->prefix; - SET_FLAG(api.message, ZAPI_MESSAGE_DISTANCE); - api.distance = ospf6_distance_apply(dest, request); + api.distance = + ospf6_distance_apply((struct prefix_ipv6 *)dest, request); if (type == REM) - ret = zapi_ipv6_route(ZEBRA_IPV6_ROUTE_DELETE, zclient, dest, - NULL, &api); + ret = zclient_route_send(ZEBRA_ROUTE_DELETE, zclient, &api); else - ret = zapi_ipv6_route(ZEBRA_IPV6_ROUTE_ADD, zclient, dest, NULL, - &api); + ret = zclient_route_send(ZEBRA_ROUTE_ADD, zclient, &api); if (ret < 0) - zlog_err("zapi_ipv6_route() %s failed: %s", + zlog_err("zclient_route_send() %s failed: %s", (type == REM ? "delete" : "add"), safe_strerror(errno)); - XFREE(MTYPE_OSPF6_OTHER, nexthops); - XFREE(MTYPE_OSPF6_OTHER, ifindexes); - return; } @@ -460,40 +432,32 @@ void ospf6_zebra_route_update_remove(struct ospf6_route *request) void ospf6_zebra_add_discard(struct ospf6_route *request) { - struct zapi_ipv6 api; + struct zapi_route api; char buf[INET6_ADDRSTRLEN]; - struct prefix_ipv6 *dest; + struct prefix *dest = &request->prefix; if (!CHECK_FLAG(request->flag, OSPF6_ROUTE_BLACKHOLE_ADDED)) { + memset(&api, 0, sizeof(api)); api.vrf_id = VRF_DEFAULT; api.type = ZEBRA_ROUTE_OSPF6; api.flags = ZEBRA_FLAG_BLACKHOLE; - api.instance = 0; - api.message = 0; api.safi = SAFI_UNICAST; - SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); - api.nexthop_num = 0; - api.ifindex_num = 0; + api.prefix = *dest; - dest = (struct prefix_ipv6 *)&request->prefix; - - zapi_ipv6_route(ZEBRA_IPV6_ROUTE_ADD, zclient, dest, NULL, - &api); + zclient_route_send(ZEBRA_ROUTE_ADD, zclient, &api); if (IS_OSPF6_DEBUG_ZEBRA(SEND)) zlog_debug("Zebra: Route add discard %s/%d", - inet_ntop(AF_INET6, &dest->prefix, buf, + inet_ntop(AF_INET6, &dest->u.prefix6, buf, INET6_ADDRSTRLEN), dest->prefixlen); SET_FLAG(request->flag, OSPF6_ROUTE_BLACKHOLE_ADDED); } else { - dest = (struct prefix_ipv6 *)&request->prefix; - if (IS_OSPF6_DEBUG_ZEBRA(SEND)) zlog_debug( "Zebra: Blackhole route present already %s/%d", - inet_ntop(AF_INET6, &dest->prefix, buf, + inet_ntop(AF_INET6, &dest->u.prefix6, buf, INET6_ADDRSTRLEN), dest->prefixlen); } @@ -501,39 +465,32 @@ void ospf6_zebra_add_discard(struct ospf6_route *request) void ospf6_zebra_delete_discard(struct ospf6_route *request) { - struct zapi_ipv6 api; + struct zapi_route api; char buf[INET6_ADDRSTRLEN]; - struct prefix_ipv6 *dest; + struct prefix *dest = &request->prefix; if (CHECK_FLAG(request->flag, OSPF6_ROUTE_BLACKHOLE_ADDED)) { + memset(&api, 0, sizeof(api)); api.vrf_id = VRF_DEFAULT; api.type = ZEBRA_ROUTE_OSPF6; api.flags = ZEBRA_FLAG_BLACKHOLE; - api.instance = 0; - api.message = 0; api.safi = SAFI_UNICAST; - SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); - api.nexthop_num = 0; - api.ifindex_num = 0; + api.prefix = *dest; - dest = (struct prefix_ipv6 *)&request->prefix; - - zapi_ipv6_route(ZEBRA_IPV6_ROUTE_DELETE, zclient, dest, NULL, - &api); + zclient_route_send(ZEBRA_ROUTE_DELETE, zclient, &api); if (IS_OSPF6_DEBUG_ZEBRA(SEND)) zlog_debug("Zebra: Route delete discard %s/%d", - inet_ntop(AF_INET6, &dest->prefix, buf, + inet_ntop(AF_INET6, &dest->u.prefix6, buf, INET6_ADDRSTRLEN), dest->prefixlen); UNSET_FLAG(request->flag, OSPF6_ROUTE_BLACKHOLE_ADDED); } else { - dest = (struct prefix_ipv6 *)&request->prefix; if (IS_OSPF6_DEBUG_ZEBRA(SEND)) zlog_debug( "Zebra: Blackhole route already deleted %s/%d", - inet_ntop(AF_INET6, &dest->prefix, buf, + inet_ntop(AF_INET6, &dest->u.prefix6, buf, INET6_ADDRSTRLEN), dest->prefixlen); } From 9eed278b163d2175ee714869085a54f2c3726cca Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Wed, 23 Aug 2017 16:18:49 +0200 Subject: [PATCH 077/130] lib: centralized memstats-at-exit adds a new all-daemon "debug memstats-at-exit" command. Also saves memstats to a file in /tmp, useful if a long-running daemon is having weird issues (e.g. in a user install). Fixes: #437 Signed-off-by: David Lamparter --- bgpd/bgp_main.c | 3 --- lib/command.c | 17 +++++++++++++++++ lib/libfrr.c | 30 ++++++++++++++++++++++++++++++ lib/libfrr.h | 2 ++ lib/log.c | 2 +- lib/memory.c | 10 ++++++---- lib/memory.h | 4 +++- lib/sigevent.c | 2 +- tests/isisd/test_fuzz_isis_tlv.c | 2 +- tests/lib/cli/common_cli.c | 2 +- 10 files changed, 62 insertions(+), 12 deletions(-) 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/lib/command.c b/lib/command.c index 45b5593a3e..f47bf81452 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") @@ -555,6 +556,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 +2370,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 +2542,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 +2576,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/libfrr.c b/lib/libfrr.c index 255f91ec71..c3ef04c673 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]; @@ -841,6 +843,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 +857,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 5c89e7080e..5b2429b31a 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..132d4abd30 100644 --- a/lib/memory.h +++ b/lib/memory.h @@ -18,6 +18,7 @@ #define _QUAGGA_MEMORY_H #include +#include #include #define array_size(ar) (sizeof(ar) / sizeof(ar[0])) @@ -194,7 +195,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/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/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); } From 6bd2b3608d6dc1eca171c30916f029f6f867db6b Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Wed, 23 Aug 2017 16:23:17 +0200 Subject: [PATCH 078/130] lib: fix cosmetic issue with exit race if we're using --terminal, the daemon may in some cases exit fast enough for the parent to see this; this resulted in a confusing/bogus "failed to start, exited 0" message. Signed-off-by: David Lamparter --- lib/libfrr.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/libfrr.c b/lib/libfrr.c index c3ef04c673..9944fdd1e1 100644 --- a/lib/libfrr.c +++ b/lib/libfrr.c @@ -641,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)) From 427f8e61bb711b51891dbaee845215ca228951f1 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Wed, 23 Aug 2017 16:54:15 +0200 Subject: [PATCH 079/130] ospf6d: properly update prefix list references Register add/delete hooks with the prefix list code to properly change ospf6_area's prefix list in/out pointers. There are 2 other uncached uses of prefix lists in the ASBR route-map code and the interface code; these should probably be cached too. (To be fixed another day...) Fixes: #453 Signed-off-by: David Lamparter --- lib/plist.c | 8 ++++++ lib/plist.h | 1 + ospf6d/ospf6_abr.c | 59 ++++++++++++++++++--------------------------- ospf6d/ospf6_area.c | 41 ++++++++++++++++++------------- ospf6d/ospf6_area.h | 1 + ospf6d/ospf6d.c | 18 ++++++++++++++ 6 files changed, 75 insertions(+), 53 deletions(-) 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/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); From 3cbb67f2294305ab8046db0405b0d486650d30dd Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Wed, 23 Aug 2017 17:06:24 +0200 Subject: [PATCH 080/130] lib: better warnings for install_element Also fixes misuse of vector_slot() - that one doesn't check for access beyond end of vector... And print node names in grammar sandbox "printall". Fixes: #543 Signed-off-by: David Lamparter --- lib/command.c | 32 ++++++++++++++++++-------------- lib/grammar_sandbox.c | 3 ++- 2 files changed, 20 insertions(+), 15 deletions(-) diff --git a/lib/command.c b/lib/command.c index f47bf81452..c86025a3bd 100644 --- a/lib/command.c +++ b/lib/command.c @@ -360,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; } @@ -407,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; } 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); From 67eb7a6c9910c121e7975e26eaae199cb03ff2b1 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Wed, 23 Aug 2017 17:33:17 +0200 Subject: [PATCH 081/130] python/clippy: make output file writing less weird This should stomp out any parallel build issues in this regard. Fixes: #971 Signed-off-by: David Lamparter --- common.am | 3 +-- python/clidef.py | 2 +- python/clippy/__init__.py | 15 ++++++++++++--- 3 files changed, 14 insertions(+), 6 deletions(-) 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/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) From 8d0ab76de11bdaf38d9c89291347497bfed2d18b Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Wed, 23 Aug 2017 18:21:30 +0200 Subject: [PATCH 082/130] bgpd: fix stats counting for IPv6 Fixes: #991 Signed-off-by: David Lamparter --- bgpd/bgp_route.c | 51 +++++++++++++++++++++++------------------------- 1 file changed, 24 insertions(+), 27 deletions(-) diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index bb204b01f1..ee6f867cb9 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -20,6 +20,7 @@ */ #include +#include #include "prefix.h" #include "linklist.h" @@ -9347,6 +9348,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 @@ -9415,8 +9417,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]++; @@ -9526,31 +9528,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]); From c0e29be115fcf67e9b7ea77581fbcd94b3402672 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Wed, 23 Aug 2017 18:51:18 +0200 Subject: [PATCH 083/130] lib: prefix: try harder to not hash garbage With prefix_ptr or prefix_ls, there can still be stuff in a struct prefix that we shouldn't hash. Signed-off-by: David Lamparter --- lib/prefix.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) 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); } From 6a35bfba5e4e4135a29e87dc554b4e7f19f06831 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Wed, 23 Aug 2017 15:45:05 +0200 Subject: [PATCH 084/130] build: fix libtool stupidity wrt. parallel install there's no dependency between libraries and other things to be installed, but libtool in its 90ies design wants to relink libraries when installing them. Add manual dependencies to work around this. Signed-off-by: David Lamparter --- Makefile.am | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Makefile.am b/Makefile.am index 494fcd4d56..48f4e50daa 100644 --- a/Makefile.am +++ b/Makefile.am @@ -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 From de1a880c4e1f24e5cb4a2c1e4793fed73107ecbe Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Wed, 23 Aug 2017 20:22:31 +0200 Subject: [PATCH 085/130] lib: split off compiler magic into its own file Also make timed notices available via CONFDATE. Signed-off-by: David Lamparter --- Makefile.am | 2 +- lib/compiler.h | 81 ++++++++++++++++++++++++++++++++++++++++++++++++++ lib/memory.h | 36 +--------------------- lib/prefix.h | 17 +---------- lib/subdir.am | 1 + lib/vty.h | 19 +++--------- 6 files changed, 89 insertions(+), 67 deletions(-) create mode 100644 lib/compiler.h diff --git a/Makefile.am b/Makefile.am index 48f4e50daa..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 = 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/memory.h b/lib/memory.h index 132d4abd30..6de370514a 100644 --- a/lib/memory.h +++ b/lib/memory.h @@ -20,6 +20,7 @@ #include #include #include +#include "compiler.h" #define array_size(ar) (sizeof(ar) / sizeof(ar[0])) @@ -37,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 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/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.") From 9913029c5c2a4e2d3d78d470aa9b91fdeb0fb007 Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Sun, 20 Aug 2017 21:19:25 -0300 Subject: [PATCH 086/130] bgpd: use the new API to send routes to zebra Signed-off-by: Renato Westphal --- bgpd/bgp_zebra.c | 238 ++++++++++++++--------------------------- bgpd/rfapi/vnc_zebra.c | 66 ++++++------ 2 files changed, 114 insertions(+), 190 deletions(-) diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c index 193775165c..2e8188b537 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -58,11 +58,6 @@ /* All information about zebra. */ struct zclient *zclient = NULL; -/* Growable buffer for nexthops sent to zebra */ -struct stream *bgp_nexthop_buf = NULL; -struct stream *bgp_ifindices_buf = NULL; -struct stream *bgp_label_buf = NULL; - /* These array buffers are used in making a copy of the attributes for route-map apply. Arrays are being used here to minimize mallocs and frees for the temporary copy of the attributes. @@ -1153,7 +1148,10 @@ void bgp_zebra_announce(struct bgp_node *rn, struct prefix *p, struct bgp_info *info, struct bgp *bgp, afi_t afi, safi_t safi) { - u_int32_t flags; + struct zapi_route api; + struct zapi_nexthop *api_nh; + int valid_nh_count = 0; + u_char distance; struct peer *peer; struct bgp_info *mpinfo; @@ -1172,7 +1170,14 @@ void bgp_zebra_announce(struct bgp_node *rn, struct prefix *p, if (bgp->main_zebra_update_hold) return; - flags = 0; + /* Make Zebra API structure. */ + memset(&api, 0, sizeof(api)); + api.vrf_id = bgp->vrf_id; + api.type = ZEBRA_ROUTE_BGP; + api.safi = safi; + api.prefix = *p; + SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); + peer = info->peer; tag = info->attr->tag; @@ -1181,33 +1186,27 @@ void bgp_zebra_announce(struct bgp_node *rn, struct prefix *p, * in * the RIB */ if (info->sub_type == BGP_ROUTE_AGGREGATE) - SET_FLAG(flags, ZEBRA_FLAG_BLACKHOLE); + SET_FLAG(api.flags, ZEBRA_FLAG_BLACKHOLE); if (peer->sort == BGP_PEER_IBGP || peer->sort == BGP_PEER_CONFED || info->sub_type == BGP_ROUTE_AGGREGATE) { - SET_FLAG(flags, ZEBRA_FLAG_IBGP); - SET_FLAG(flags, ZEBRA_FLAG_INTERNAL); + SET_FLAG(api.flags, ZEBRA_FLAG_IBGP); + SET_FLAG(api.flags, ZEBRA_FLAG_INTERNAL); } if ((peer->sort == BGP_PEER_EBGP && peer->ttl != 1) || CHECK_FLAG(peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK) || bgp_flag_check(bgp, BGP_FLAG_DISABLE_NH_CONNECTED_CHK)) - SET_FLAG(flags, ZEBRA_FLAG_INTERNAL); + SET_FLAG(api.flags, ZEBRA_FLAG_INTERNAL); if (p->family == AF_INET && !BGP_ATTR_NEXTHOP_AFI_IP6(info->attr)) { - struct zapi_ipv4 api; struct in_addr *nexthop; char buf[2][INET_ADDRSTRLEN]; - int valid_nh_count = 0; int has_valid_label = 0; - /* resize nexthop buffer size if necessary */ - stream_reset(bgp_nexthop_buf); nexthop = NULL; - stream_reset(bgp_label_buf); - if (bgp->table_map[afi][safi].name) BGP_INFO_ATTR_BUF_INIT(); @@ -1240,26 +1239,21 @@ void bgp_zebra_announce(struct bgp_node *rn, struct prefix *p, if (nexthop == NULL) continue; - stream_put(bgp_nexthop_buf, &nexthop, - sizeof(struct in_addr *)); + api_nh = &api.nexthops[valid_nh_count]; + api_nh->gate.ipv4 = *nexthop; + api_nh->type = NEXTHOP_TYPE_IPV4; + if (mpinfo->extra && bgp_is_valid_label(&mpinfo->extra->label)) { has_valid_label = 1; label = label_pton(&mpinfo->extra->label); - stream_put(bgp_label_buf, &label, - sizeof(mpls_label_t)); + + api_nh->label_num = 1; + api_nh->labels[0] = label; } valid_nh_count++; } - api.vrf_id = bgp->vrf_id; - api.flags = flags; - api.type = ZEBRA_ROUTE_BGP; - api.instance = 0; - api.message = 0; - api.safi = safi; - SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); - if (has_valid_label) SET_FLAG(api.message, ZAPI_MESSAGE_LABEL); @@ -1272,24 +1266,15 @@ void bgp_zebra_announce(struct bgp_node *rn, struct prefix *p, * do not want to also encode the 0.0.0.0 nexthop for the * aggregate route. */ - if (CHECK_FLAG(flags, ZEBRA_FLAG_BLACKHOLE)) + if (CHECK_FLAG(api.flags, ZEBRA_FLAG_BLACKHOLE)) api.nexthop_num = 0; else api.nexthop_num = valid_nh_count; - api.nexthop = (struct in_addr **)STREAM_DATA(bgp_nexthop_buf); - if (has_valid_label) { - api.label_num = valid_nh_count; - api.label = (unsigned int *)STREAM_DATA(bgp_label_buf); - } else { - api.label_num = 0; - api.label = NULL; - } - api.ifindex_num = 0; SET_FLAG(api.message, ZAPI_MESSAGE_METRIC); api.metric = metric; - api.tag = 0; + api.tag = 0; if (tag) { SET_FLAG(api.message, ZAPI_MESSAGE_TAG); api.tag = tag; @@ -1313,20 +1298,23 @@ void bgp_zebra_announce(struct bgp_node *rn, struct prefix *p, p->prefixlen, api.metric, api.tag, api.nexthop_num); for (i = 0; i < api.nexthop_num; i++) { + api_nh = &api.nexthops[i]; + label_buf[0] = '\0'; if (has_valid_label) sprintf(label_buf, "label %u", - api.label[i]); + api_nh->labels[0]); zlog_debug(" nhop [%d]: %s %s", i + 1, - inet_ntop(AF_INET, api.nexthop[i], - buf[1], sizeof(buf[1])), + inet_ntop(AF_INET, + &api_nh->gate.ipv4, buf[1], + sizeof(buf[1])), label_buf); } } - zapi_ipv4_route(valid_nh_count ? ZEBRA_IPV4_ROUTE_ADD - : ZEBRA_IPV4_ROUTE_DELETE, - zclient, (struct prefix_ipv4 *)p, &api); + zclient_route_send(valid_nh_count ? ZEBRA_ROUTE_ADD + : ZEBRA_ROUTE_DELETE, + zclient, &api); } /* We have to think about a IPv6 link-local address curse. */ @@ -1334,15 +1322,9 @@ void bgp_zebra_announce(struct bgp_node *rn, struct prefix *p, || (p->family == AF_INET && BGP_ATTR_NEXTHOP_AFI_IP6(info->attr))) { ifindex_t ifindex; struct in6_addr *nexthop; - struct zapi_ipv6 api; - int valid_nh_count = 0; char buf[2][INET6_ADDRSTRLEN]; int has_valid_label = 0; - stream_reset(bgp_nexthop_buf); - stream_reset(bgp_ifindices_buf); - stream_reset(bgp_label_buf); - ifindex = 0; nexthop = NULL; @@ -1399,30 +1381,22 @@ void bgp_zebra_announce(struct bgp_node *rn, struct prefix *p, if (ifindex == 0) continue; - stream_put(bgp_nexthop_buf, &nexthop, - sizeof(struct in6_addr *)); - stream_put(bgp_ifindices_buf, &ifindex, - sizeof(unsigned int)); + api_nh = &api.nexthops[valid_nh_count]; + api_nh->gate.ipv6 = *nexthop; + api_nh->ifindex = ifindex; + api_nh->type = NEXTHOP_TYPE_IPV6_IFINDEX; if (mpinfo->extra && bgp_is_valid_label(&mpinfo->extra->label)) { has_valid_label = 1; label = label_pton(&mpinfo->extra->label); - stream_put(bgp_label_buf, &label, - sizeof(mpls_label_t)); + + api_nh->label_num = 1; + api_nh->labels[0] = label; } valid_nh_count++; } - /* Make Zebra API structure. */ - api.vrf_id = bgp->vrf_id; - api.flags = flags; - api.type = ZEBRA_ROUTE_BGP; - api.instance = 0; - api.message = 0; - api.safi = safi; - SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); - if (has_valid_label) SET_FLAG(api.message, ZAPI_MESSAGE_LABEL); @@ -1435,26 +1409,15 @@ void bgp_zebra_announce(struct bgp_node *rn, struct prefix *p, * do not want to also encode the :: nexthop for the aggregate * route. */ - if (CHECK_FLAG(flags, ZEBRA_FLAG_BLACKHOLE)) + if (CHECK_FLAG(api.flags, ZEBRA_FLAG_BLACKHOLE)) api.nexthop_num = 0; else api.nexthop_num = valid_nh_count; - api.nexthop = (struct in6_addr **)STREAM_DATA(bgp_nexthop_buf); - SET_FLAG(api.message, ZAPI_MESSAGE_IFINDEX); - api.ifindex_num = valid_nh_count; - api.ifindex = (ifindex_t *)STREAM_DATA(bgp_ifindices_buf); - if (has_valid_label) { - api.label_num = valid_nh_count; - api.label = (unsigned int *)STREAM_DATA(bgp_label_buf); - } else { - api.label_num = 0; - api.label = NULL; - } SET_FLAG(api.message, ZAPI_MESSAGE_METRIC); api.metric = metric; - api.tag = 0; + api.tag = 0; if (tag) { SET_FLAG(api.message, ZAPI_MESSAGE_TAG); api.tag = tag; @@ -1478,33 +1441,31 @@ void bgp_zebra_announce(struct bgp_node *rn, struct prefix *p, buf[0], sizeof(buf[0])), p->prefixlen, api.metric, api.tag); for (i = 0; i < api.nexthop_num; i++) { + api_nh = &api.nexthops[i]; + label_buf[0] = '\0'; if (has_valid_label) sprintf(label_buf, "label %u", - api.label[i]); + api_nh->labels[0]); zlog_debug( " nhop [%d]: %s if %s %s", i + 1, inet_ntop(AF_INET6, - api.nexthop[i], + &api_nh->gate.ipv6, buf[1], sizeof(buf[1])), - ifindex2ifname(api.ifindex[i], + ifindex2ifname(api_nh->ifindex, bgp->vrf_id), label_buf); } } if (valid_nh_count) - zapi_ipv4_route_ipv6_nexthop( - ZEBRA_IPV4_ROUTE_IPV6_NEXTHOP_ADD, - zclient, (struct prefix_ipv4 *)p, - (struct zapi_ipv6 *)&api); + zclient_route_send(ZEBRA_ROUTE_ADD, zclient, + &api); else - zapi_ipv4_route(ZEBRA_IPV4_ROUTE_DELETE, - zclient, - (struct prefix_ipv4 *)p, - (struct zapi_ipv4 *)&api); + zclient_route_send(ZEBRA_ROUTE_DELETE, zclient, + &api); } else { if (bgp_debug_zebra(p)) { int i; @@ -1517,27 +1478,28 @@ void bgp_zebra_announce(struct bgp_node *rn, struct prefix *p, buf[0], sizeof(buf[0])), p->prefixlen, api.metric, api.tag); for (i = 0; i < api.nexthop_num; i++) { + api_nh = &api.nexthops[i]; + label_buf[0] = '\0'; if (has_valid_label) sprintf(label_buf, "label %u", - api.label[i]); + api_nh->labels[0]); zlog_debug( " nhop [%d]: %s if %s %s", i + 1, inet_ntop(AF_INET6, - api.nexthop[i], + &api_nh->gate.ipv6, buf[1], sizeof(buf[1])), - ifindex2ifname(api.ifindex[i], + ifindex2ifname(api_nh->ifindex, bgp->vrf_id), label_buf); } } - zapi_ipv6_route( - valid_nh_count ? ZEBRA_IPV6_ROUTE_ADD - : ZEBRA_IPV6_ROUTE_DELETE, - zclient, (struct prefix_ipv6 *)p, NULL, &api); + zclient_route_send(valid_nh_count ? ZEBRA_ROUTE_ADD + : ZEBRA_ROUTE_DELETE, + zclient, &api); } } } @@ -1595,79 +1557,47 @@ void bgp_zebra_withdraw(struct prefix *p, struct bgp_info *info, safi_t safi) SET_FLAG(flags, ZEBRA_FLAG_INTERNAL); if (p->family == AF_INET) { - struct zapi_ipv4 api; + struct zapi_route api; + memset(&api, 0, sizeof(api)); api.vrf_id = peer->bgp->vrf_id; api.flags = flags; - api.type = ZEBRA_ROUTE_BGP; - api.instance = 0; - api.message = 0; api.safi = safi; - SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); - api.nexthop_num = 0; - api.nexthop = NULL; - api.label_num = 0; - api.label = NULL; - api.ifindex_num = 0; - SET_FLAG(api.message, ZAPI_MESSAGE_METRIC); - api.metric = info->attr->med; - api.tag = 0; - - if (info->attr->tag != 0) { - SET_FLAG(api.message, ZAPI_MESSAGE_TAG); - api.tag = info->attr->tag; - } + api.prefix = *p; if (bgp_debug_zebra(p)) { char buf[2][INET_ADDRSTRLEN]; - zlog_debug( - "Tx IPv4 route delete VRF %u %s/%d metric %u tag %" ROUTE_TAG_PRI, - peer->bgp->vrf_id, - inet_ntop(AF_INET, &p->u.prefix4, buf[0], - sizeof(buf[0])), - p->prefixlen, api.metric, api.tag); + zlog_debug("Tx IPv4 route delete VRF %u %s/%d", + peer->bgp->vrf_id, + inet_ntop(AF_INET, &p->u.prefix4, buf[0], + sizeof(buf[0])), + p->prefixlen); } - zapi_ipv4_route(ZEBRA_IPV4_ROUTE_DELETE, zclient, - (struct prefix_ipv4 *)p, &api); + zclient_route_send(ZEBRA_ROUTE_DELETE, zclient, &api); } /* We have to think about a IPv6 link-local address curse. */ if (p->family == AF_INET6) { - struct zapi_ipv6 api; + struct zapi_route api; + memset(&api, 0, sizeof(api)); api.vrf_id = peer->bgp->vrf_id; api.flags = flags; api.type = ZEBRA_ROUTE_BGP; - api.instance = 0; - api.message = 0; api.safi = safi; - SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); - api.nexthop_num = 0; - api.nexthop = NULL; - api.ifindex_num = 0; - api.label_num = 0; - SET_FLAG(api.message, ZAPI_MESSAGE_METRIC); - api.metric = info->attr->med; - api.tag = 0; - - if (info->attr->tag != 0) { - SET_FLAG(api.message, ZAPI_MESSAGE_TAG); - api.tag = info->attr->tag; - } + api.prefix = *p; if (bgp_debug_zebra(p)) { char buf[2][INET6_ADDRSTRLEN]; - zlog_debug( - "Tx IPv6 route delete VRF %u %s/%d metric %u tag %" ROUTE_TAG_PRI, - peer->bgp->vrf_id, - inet_ntop(AF_INET6, &p->u.prefix6, buf[0], - sizeof(buf[0])), - p->prefixlen, api.metric, api.tag); + zlog_debug("Tx IPv6 route delete VRF %u %s/%d", + peer->bgp->vrf_id, + inet_ntop(AF_INET6, &p->u.prefix6, buf[0], + sizeof(buf[0])), + p->prefixlen); } - zapi_ipv6_route(ZEBRA_IPV6_ROUTE_DELETE, zclient, - (struct prefix_ipv6 *)p, NULL, &api); + zclient_route_send(ZEBRA_ROUTE_DELETE, zclient, &api); } } @@ -2195,22 +2125,10 @@ void bgp_zebra_init(struct thread_master *master) zclient->local_vni_del = bgp_zebra_process_local_vni; zclient->local_macip_add = bgp_zebra_process_local_macip; zclient->local_macip_del = bgp_zebra_process_local_macip; - - bgp_nexthop_buf = stream_new(multipath_num * sizeof(struct in6_addr)); - bgp_ifindices_buf = stream_new(multipath_num * sizeof(unsigned int)); - bgp_label_buf = stream_new(multipath_num * sizeof(unsigned int)); } void bgp_zebra_destroy(void) { - - if (bgp_nexthop_buf) - stream_free(bgp_nexthop_buf); - if (bgp_ifindices_buf) - stream_free(bgp_ifindices_buf); - if (bgp_label_buf) - stream_free(bgp_label_buf); - if (zclient == NULL) return; zclient_stop(zclient); diff --git a/bgpd/rfapi/vnc_zebra.c b/bgpd/rfapi/vnc_zebra.c index 29652e59db..1b1a89b35f 100644 --- a/bgpd/rfapi/vnc_zebra.c +++ b/bgpd/rfapi/vnc_zebra.c @@ -501,21 +501,27 @@ static void vnc_zebra_route_msg(struct prefix *p, int nhp_count, void *nhp_ary, } if (p->family == AF_INET) { + struct zapi_route api; + struct zapi_nexthop *api_nh; + struct in_addr *nhp_ary4 = nhp_ary; + int i; - struct zapi_ipv4 api; - - api.flags = 0; + memset(&api, 0, sizeof(api)); api.vrf_id = VRF_DEFAULT; api.type = ZEBRA_ROUTE_VNC; - api.message = 0; - SET_FLAG(api.message, - ZAPI_MESSAGE_NEXTHOP); /* TBD what's it mean? */ - api.nexthop_num = nhp_count; - api.nexthop = nhp_ary; - api.ifindex_num = 0; - api.instance = 0; + api.prefix = *p; api.safi = SAFI_UNICAST; + /* Nexthops */ + SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); + api.nexthop_num = nhp_count; + for (i = 0; i < nhp_count; i++) { + api_nh = &api.nexthops[i]; + memcpy(&api_nh->gate.ipv4, &nhp_ary4[i], + sizeof(api_nh->gate.ipv4)); + api_nh->type = NEXTHOP_TYPE_IPV4; + } + if (BGP_DEBUG(zebra, ZEBRA)) { char buf[INET_ADDRSTRLEN]; @@ -527,29 +533,31 @@ static void vnc_zebra_route_msg(struct prefix *p, int nhp_count, void *nhp_ary, p->prefixlen, nhp_count); } - zapi_ipv4_route((add ? ZEBRA_IPV4_ROUTE_ADD - : ZEBRA_IPV4_ROUTE_DELETE), - zclient_vnc, (struct prefix_ipv4 *)p, &api); + zclient_route_send((add ? ZEBRA_ROUTE_ADD : ZEBRA_ROUTE_DELETE), + zclient_vnc, &api); } else if (p->family == AF_INET6) { + struct zapi_route api; + struct zapi_nexthop *api_nh; + struct in6_addr *nhp_ary6 = nhp_ary; + int i; - struct zapi_ipv6 api; - ifindex_t ifindex = 0; - - /* Make Zebra API structure. */ - api.flags = 0; + memset(&api, 0, sizeof(api)); api.vrf_id = VRF_DEFAULT; api.type = ZEBRA_ROUTE_VNC; - api.message = 0; - SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); /* TBD means? */ - api.nexthop_num = nhp_count; - api.nexthop = nhp_ary; - SET_FLAG(api.message, ZAPI_MESSAGE_IFINDEX); - api.ifindex_num = 1; - api.ifindex = &ifindex; - api.instance = 0; + api.prefix = *p; api.safi = SAFI_UNICAST; + /* Nexthops */ + SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); + api.nexthop_num = nhp_count; + for (i = 0; i < nhp_count; i++) { + api_nh = &api.nexthops[i]; + memcpy(&api_nh->gate.ipv6, &nhp_ary6[i], + sizeof(api_nh->gate.ipv6)); + api_nh->type = NEXTHOP_TYPE_IPV6; + } + if (BGP_DEBUG(zebra, ZEBRA)) { char buf[INET6_ADDRSTRLEN]; @@ -561,10 +569,8 @@ static void vnc_zebra_route_msg(struct prefix *p, int nhp_count, void *nhp_ary, p->prefixlen, nhp_count); } - zapi_ipv6_route((add ? ZEBRA_IPV6_ROUTE_ADD - : ZEBRA_IPV6_ROUTE_DELETE), - zclient_vnc, (struct prefix_ipv6 *)p, NULL, - &api); + zclient_route_send((add ? ZEBRA_ROUTE_ADD : ZEBRA_ROUTE_DELETE), + zclient_vnc, &api); } else { vnc_zlog_debug_verbose( "%s: unknown prefix address family, skipping", From f80dd32b13cf5b5a0559e2660de2e54f04b100c8 Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Sun, 20 Aug 2017 21:29:35 -0300 Subject: [PATCH 087/130] isisd: unify ipv4/ipv6 zebra-tx functions Signed-off-by: Renato Westphal --- isisd/isis_zebra.c | 129 ++++++++++++++------------------------------- 1 file changed, 39 insertions(+), 90 deletions(-) diff --git a/isisd/isis_zebra.c b/isisd/isis_zebra.c index 35b2091e98..e3537e2a0c 100644 --- a/isisd/isis_zebra.c +++ b/isisd/isis_zebra.c @@ -245,75 +245,12 @@ static int isis_zebra_link_params(int command, struct zclient *zclient, return 0; } -static void isis_zebra_route_add_ipv4(struct prefix *prefix, - struct isis_route_info *route_info) +static void isis_zebra_route_add_route(struct prefix *prefix, + struct isis_route_info *route_info) { struct zapi_route api; struct zapi_nexthop *api_nh; struct isis_nexthop *nexthop; - struct listnode *node; - int count = 0; - - if (CHECK_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED)) - return; - - memset(&api, 0, sizeof(api)); - api.vrf_id = VRF_DEFAULT; - api.type = ZEBRA_ROUTE_ISIS; - api.safi = SAFI_UNICAST; - api.prefix = *prefix; - SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); - SET_FLAG(api.message, ZAPI_MESSAGE_METRIC); - api.metric = route_info->cost; -#if 0 - SET_FLAG(api.message, ZAPI_MESSAGE_DISTANCE); - api.distance = route_info->depth; -#endif - - /* Nexthop, ifindex, distance and metric information */ - for (ALL_LIST_ELEMENTS_RO(route_info->nexthops, node, nexthop)) { - api_nh = &api.nexthops[count]; - /* FIXME: can it be ? */ - if (nexthop->ip.s_addr != INADDR_ANY) { - api_nh->type = NEXTHOP_TYPE_IPV4_IFINDEX; - api_nh->gate.ipv4 = nexthop->ip; - } else { - api_nh->type = NEXTHOP_TYPE_IFINDEX; - } - api_nh->ifindex = nexthop->ifindex; - count++; - } - if (!count) - return; - - api.nexthop_num = count; - - zclient_route_send(ZEBRA_ROUTE_ADD, zclient, &api); - SET_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED); - UNSET_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_RESYNC); -} - -static void isis_zebra_route_del_ipv4(struct prefix *prefix, - struct isis_route_info *route_info) -{ - struct zapi_route api; - - UNSET_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED); - - memset(&api, 0, sizeof(api)); - api.vrf_id = VRF_DEFAULT; - api.type = ZEBRA_ROUTE_ISIS; - api.safi = SAFI_UNICAST; - api.prefix = *prefix; - - zclient_route_send(ZEBRA_ROUTE_DELETE, zclient, &api); -} - -static void isis_zebra_route_add_ipv6(struct prefix *prefix, - struct isis_route_info *route_info) -{ - struct zapi_route api; - struct zapi_nexthop *api_nh; struct isis_nexthop6 *nexthop6; struct listnode *node; int count = 0; @@ -325,6 +262,7 @@ static void isis_zebra_route_add_ipv6(struct prefix *prefix, api.vrf_id = VRF_DEFAULT; api.type = ZEBRA_ROUTE_ISIS; api.safi = SAFI_UNICAST; + api.prefix = *prefix; SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); SET_FLAG(api.message, ZAPI_MESSAGE_METRIC); api.metric = route_info->cost; @@ -332,20 +270,39 @@ static void isis_zebra_route_add_ipv6(struct prefix *prefix, SET_FLAG(api.message, ZAPI_MESSAGE_DISTANCE); api.distance = route_info->depth; #endif - api.prefix = *prefix; - /* for each nexthop */ - for (ALL_LIST_ELEMENTS_RO(route_info->nexthops6, node, nexthop6)) { - if (!IN6_IS_ADDR_LINKLOCAL(&nexthop6->ip6) - && !IN6_IS_ADDR_UNSPECIFIED(&nexthop6->ip6)) { - continue; + /* Nexthops */ + switch (prefix->family) { + case AF_INET: + for (ALL_LIST_ELEMENTS_RO(route_info->nexthops, node, + nexthop)) { + api_nh = &api.nexthops[count]; + /* FIXME: can it be ? */ + if (nexthop->ip.s_addr != INADDR_ANY) { + api_nh->type = NEXTHOP_TYPE_IPV4_IFINDEX; + api_nh->gate.ipv4 = nexthop->ip; + } else { + api_nh->type = NEXTHOP_TYPE_IFINDEX; + } + api_nh->ifindex = nexthop->ifindex; + count++; } + break; + case AF_INET6: + for (ALL_LIST_ELEMENTS_RO(route_info->nexthops6, node, + nexthop6)) { + if (!IN6_IS_ADDR_LINKLOCAL(&nexthop6->ip6) + && !IN6_IS_ADDR_UNSPECIFIED(&nexthop6->ip6)) { + continue; + } - api_nh = &api.nexthops[count]; - api_nh->gate.ipv6 = nexthop6->ip6; - api_nh->ifindex = nexthop6->ifindex; - api_nh->type = NEXTHOP_TYPE_IPV6_IFINDEX; - count++; + api_nh = &api.nexthops[count]; + api_nh->gate.ipv6 = nexthop6->ip6; + api_nh->ifindex = nexthop6->ifindex; + api_nh->type = NEXTHOP_TYPE_IPV6_IFINDEX; + count++; + } + break; } if (!count) return; @@ -357,8 +314,8 @@ static void isis_zebra_route_add_ipv6(struct prefix *prefix, UNSET_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_RESYNC); } -static void isis_zebra_route_del_ipv6(struct prefix *prefix, - struct isis_route_info *route_info) +static void isis_zebra_route_del_route(struct prefix *prefix, + struct isis_route_info *route_info) { struct zapi_route api; @@ -381,18 +338,10 @@ void isis_zebra_route_update(struct prefix *prefix, if (zclient->sock < 0) return; - if (CHECK_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ACTIVE)) { - if (prefix->family == AF_INET) - isis_zebra_route_add_ipv4(prefix, route_info); - else if (prefix->family == AF_INET6) - isis_zebra_route_add_ipv6(prefix, route_info); - } else { - if (prefix->family == AF_INET) - isis_zebra_route_del_ipv4(prefix, route_info); - else if (prefix->family == AF_INET6) - isis_zebra_route_del_ipv6(prefix, route_info); - } - return; + if (CHECK_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ACTIVE)) + isis_zebra_route_add_route(prefix, route_info); + else + isis_zebra_route_del_route(prefix, route_info); } static int isis_zebra_read_ipv4(int command, struct zclient *zclient, From 9350687dc46509d0eadf26476d1a69070af90435 Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Sun, 20 Aug 2017 21:36:35 -0300 Subject: [PATCH 088/130] nhrpd: unify ipv4/ipv6 zebra-tx functions Signed-off-by: Renato Westphal --- nhrpd/nhrp_route.c | 99 +++++++++++++++++----------------------------- 1 file changed, 36 insertions(+), 63 deletions(-) diff --git a/nhrpd/nhrp_route.c b/nhrpd/nhrp_route.c index 3062b23a6d..b744218c9a 100644 --- a/nhrpd/nhrp_route.c +++ b/nhrpd/nhrp_route.c @@ -86,14 +86,20 @@ void nhrp_route_update_nhrp(const struct prefix *p, struct interface *ifp) void nhrp_route_announce(int add, enum nhrp_cache_type type, const struct prefix *p, struct interface *ifp, const union sockunion *nexthop, uint32_t mtu) { - int flags = 0; + struct zapi_route api; + struct zapi_nexthop *api_nh; if (zclient->sock < 0) return; + memset(&api, 0, sizeof(api)); + api.type = ZEBRA_ROUTE_NHRP; + api.safi = SAFI_UNICAST; + api.prefix = *p; + switch (type) { case NHRP_CACHE_NEGATIVE: - SET_FLAG(flags, ZEBRA_FLAG_REJECT); + SET_FLAG(api.flags, ZEBRA_FLAG_REJECT); break; case NHRP_CACHE_DYNAMIC: case NHRP_CACHE_NHS: @@ -102,23 +108,17 @@ void nhrp_route_announce(int add, enum nhrp_cache_type type, const struct prefix * to other routing daemons */ break; default: - SET_FLAG(flags, ZEBRA_FLAG_FIB_OVERRIDE); + SET_FLAG(api.flags, ZEBRA_FLAG_FIB_OVERRIDE); break; } - SET_FLAG(flags, ZEBRA_FLAG_INTERNAL); + SET_FLAG(api.flags, ZEBRA_FLAG_INTERNAL); - if (p->family == AF_INET) { - struct zapi_route api; - struct zapi_nexthop *api_nh = &api.nexthops[0];; + SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); + api.nexthop_num = 1; + api_nh = &api.nexthops[0]; - memset(&api, 0, sizeof(api)); - api.flags = flags; - api.type = ZEBRA_ROUTE_NHRP; - api.safi = SAFI_UNICAST; - api.prefix = *p; - - SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); - api.nexthop_num = 1; + switch (api.prefix.family) { + case AF_INET: if (nexthop) { api_nh->gate.ipv4 = nexthop->sin.sin_addr; api_nh->type = NEXTHOP_TYPE_IPV4; @@ -130,36 +130,8 @@ void nhrp_route_announce(int add, enum nhrp_cache_type type, const struct prefix else api_nh->type = NEXTHOP_TYPE_IFINDEX; } - if (mtu) { - SET_FLAG(api.message, ZAPI_MESSAGE_MTU); - api.mtu = mtu; - } - - if (unlikely(debug_flags & NHRP_DEBUG_ROUTE)) { - char buf[2][INET_ADDRSTRLEN]; - zlog_debug("Zebra send: IPv4 route %s %s/%d nexthop %s metric %u" - " count %d dev %s", - add ? "add" : "del", - inet_ntop(AF_INET, &p->u.prefix4, buf[0], sizeof(buf[0])), - p->prefixlen, - nexthop ? inet_ntop(AF_INET, &api_nh->gate.ipv4, buf[1], sizeof(buf[1])) : "", - api.metric, api.nexthop_num, ifp->name); - } - - zclient_route_send(add ? ZEBRA_ROUTE_ADD : ZEBRA_ROUTE_DELETE, - zclient, &api); - } else if (p->family == AF_INET6) { - struct zapi_route api; - struct zapi_nexthop *api_nh = &api.nexthops[0];; - - memset(&api, 0, sizeof(api)); - api.flags = flags; - api.type = ZEBRA_ROUTE_NHRP; - api.safi = SAFI_UNICAST; - api.prefix = *p; - - SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); - api.nexthop_num = 1; + break; + case AF_INET6: if (nexthop) { api_nh->gate.ipv6 = nexthop->sin6.sin6_addr; api_nh->type = NEXTHOP_TYPE_IPV6; @@ -171,25 +143,26 @@ void nhrp_route_announce(int add, enum nhrp_cache_type type, const struct prefix else api_nh->type = NEXTHOP_TYPE_IFINDEX; } - if (mtu) { - SET_FLAG(api.message, ZAPI_MESSAGE_MTU); - api.mtu = mtu; - } - - if (unlikely(debug_flags & NHRP_DEBUG_ROUTE)) { - char buf[2][INET6_ADDRSTRLEN]; - zlog_debug("Zebra send: IPv6 route %s %s/%d nexthop %s metric %u" - " count %d dev %s", - add ? "add" : "del", - inet_ntop(AF_INET6, &p->u.prefix6, buf[0], sizeof(buf[0])), - p->prefixlen, - nexthop ? inet_ntop(AF_INET6, &api_nh->gate.ipv6, buf[1], sizeof(buf[1])) : "", - api.metric, api.nexthop_num, ifp->name); - } - - zclient_route_send(add ? ZEBRA_ROUTE_ADD : ZEBRA_ROUTE_DELETE, - zclient, &api); + break; } + if (mtu) { + SET_FLAG(api.message, ZAPI_MESSAGE_MTU); + api.mtu = mtu; + } + + if (unlikely(debug_flags & NHRP_DEBUG_ROUTE)) { + char buf[2][PREFIX_STRLEN]; + + prefix2str(&api.prefix, buf[0], sizeof(buf[0])); + zlog_debug("Zebra send: route %s %s nexthop %s metric %u" + " count %d dev %s", + add ? "add" : "del", buf[0], + nexthop ? inet_ntop(api.prefix.family, &api_nh->gate, buf[1], sizeof(buf[1])) : "", + api.metric, api.nexthop_num, ifp->name); + } + + zclient_route_send(add ? ZEBRA_ROUTE_ADD : ZEBRA_ROUTE_DELETE, zclient, + &api); } int nhrp_route_read(int cmd, struct zclient *zclient, zebra_size_t length, vrf_id_t vrf_id) From 2ad4f0933c56483fd7a37e96beab1e02fd22afc8 Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Sun, 20 Aug 2017 21:36:44 -0300 Subject: [PATCH 089/130] bgpd: unify ipv4/ipv6 zebra-tx functions Signed-off-by: Renato Westphal --- bgpd/bgp_zebra.c | 340 +++++++++++------------------------------ bgpd/rfapi/vnc_zebra.c | 102 +++++-------- 2 files changed, 120 insertions(+), 322 deletions(-) diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c index 2e8188b537..1796975ad3 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -1150,8 +1150,9 @@ void bgp_zebra_announce(struct bgp_node *rn, struct prefix *p, { struct zapi_route api; struct zapi_nexthop *api_nh; + int nh_family; int valid_nh_count = 0; - + int has_valid_label = 0; u_char distance; struct peer *peer; struct bgp_info *mpinfo; @@ -1200,20 +1201,25 @@ void bgp_zebra_announce(struct bgp_node *rn, struct prefix *p, SET_FLAG(api.flags, ZEBRA_FLAG_INTERNAL); - if (p->family == AF_INET && !BGP_ATTR_NEXTHOP_AFI_IP6(info->attr)) { - struct in_addr *nexthop; - char buf[2][INET_ADDRSTRLEN]; - int has_valid_label = 0; + /* Get nexthop address-family */ + if (p->family == AF_INET && !BGP_ATTR_NEXTHOP_AFI_IP6(info->attr)) + nh_family = AF_INET; + else if (p->family == AF_INET6 + || (p->family == AF_INET + && BGP_ATTR_NEXTHOP_AFI_IP6(info->attr))) + nh_family = AF_INET6; + else + return; - nexthop = NULL; + if (bgp->table_map[afi][safi].name) + BGP_INFO_ATTR_BUF_INIT(); - if (bgp->table_map[afi][safi].name) - BGP_INFO_ATTR_BUF_INIT(); + /* Metric is currently based on the best-path only */ + metric = info->attr->med; + for (mpinfo = info; mpinfo; mpinfo = bgp_info_mpath_next(mpinfo)) { + if (nh_family == AF_INET) { + struct in_addr *nexthop; - /* Metric is currently based on the best-path only */ - metric = info->attr->med; - for (mpinfo = info; mpinfo; - mpinfo = bgp_info_mpath_next(mpinfo)) { nexthop = NULL; if (bgp->table_map[afi][safi].name) { @@ -1225,8 +1231,6 @@ void bgp_zebra_announce(struct bgp_node *rn, struct prefix *p, bgp->table_map[afi][safi].map, p, info_cp)) { if (mpinfo == info) { - /* Metric is currently based on - * the best-path only */ metric = info_cp->attr->med; tag = info_cp->attr->tag; } @@ -1242,98 +1246,10 @@ void bgp_zebra_announce(struct bgp_node *rn, struct prefix *p, api_nh = &api.nexthops[valid_nh_count]; api_nh->gate.ipv4 = *nexthop; api_nh->type = NEXTHOP_TYPE_IPV4; + } else { + ifindex_t ifindex; + struct in6_addr *nexthop; - if (mpinfo->extra - && bgp_is_valid_label(&mpinfo->extra->label)) { - has_valid_label = 1; - label = label_pton(&mpinfo->extra->label); - - api_nh->label_num = 1; - api_nh->labels[0] = label; - } - valid_nh_count++; - } - - if (has_valid_label) - SET_FLAG(api.message, ZAPI_MESSAGE_LABEL); - - /* Note that this currently only applies to Null0 routes for - * aggregates. - * ZEBRA_FLAG_BLACKHOLE signals zapi_ipv4_route to encode a - * special - * BLACKHOLE nexthop. We want to set api.nexthop_num to zero - * since we - * do not want to also encode the 0.0.0.0 nexthop for the - * aggregate route. - */ - if (CHECK_FLAG(api.flags, ZEBRA_FLAG_BLACKHOLE)) - api.nexthop_num = 0; - else - api.nexthop_num = valid_nh_count; - - SET_FLAG(api.message, ZAPI_MESSAGE_METRIC); - api.metric = metric; - - api.tag = 0; - if (tag) { - SET_FLAG(api.message, ZAPI_MESSAGE_TAG); - api.tag = tag; - } - - distance = bgp_distance_apply(p, info, afi, safi, bgp); - if (distance) { - SET_FLAG(api.message, ZAPI_MESSAGE_DISTANCE); - api.distance = distance; - } - - if (bgp_debug_zebra(p)) { - int i; - char label_buf[20]; - zlog_debug( - "Tx IPv4 route %s VRF %u %s/%d metric %u tag %" ROUTE_TAG_PRI - " count %d", - (valid_nh_count ? "add" : "delete"), - bgp->vrf_id, inet_ntop(AF_INET, &p->u.prefix4, - buf[0], sizeof(buf[0])), - p->prefixlen, api.metric, api.tag, - api.nexthop_num); - for (i = 0; i < api.nexthop_num; i++) { - api_nh = &api.nexthops[i]; - - label_buf[0] = '\0'; - if (has_valid_label) - sprintf(label_buf, "label %u", - api_nh->labels[0]); - zlog_debug(" nhop [%d]: %s %s", i + 1, - inet_ntop(AF_INET, - &api_nh->gate.ipv4, buf[1], - sizeof(buf[1])), - label_buf); - } - } - - zclient_route_send(valid_nh_count ? ZEBRA_ROUTE_ADD - : ZEBRA_ROUTE_DELETE, - zclient, &api); - } - - /* We have to think about a IPv6 link-local address curse. */ - if (p->family == AF_INET6 - || (p->family == AF_INET && BGP_ATTR_NEXTHOP_AFI_IP6(info->attr))) { - ifindex_t ifindex; - struct in6_addr *nexthop; - char buf[2][INET6_ADDRSTRLEN]; - int has_valid_label = 0; - - ifindex = 0; - nexthop = NULL; - - if (bgp->table_map[afi][safi].name) - BGP_INFO_ATTR_BUF_INIT(); - - metric = info->attr->med; - for (mpinfo = info; mpinfo; - mpinfo = bgp_info_mpath_next(mpinfo)) { ifindex = 0; nexthop = NULL; @@ -1385,123 +1301,68 @@ void bgp_zebra_announce(struct bgp_node *rn, struct prefix *p, api_nh->gate.ipv6 = *nexthop; api_nh->ifindex = ifindex; api_nh->type = NEXTHOP_TYPE_IPV6_IFINDEX; - - if (mpinfo->extra - && bgp_is_valid_label(&mpinfo->extra->label)) { - has_valid_label = 1; - label = label_pton(&mpinfo->extra->label); - - api_nh->label_num = 1; - api_nh->labels[0] = label; - } - valid_nh_count++; } - if (has_valid_label) - SET_FLAG(api.message, ZAPI_MESSAGE_LABEL); + if (mpinfo->extra + && bgp_is_valid_label(&mpinfo->extra->label)) { + has_valid_label = 1; + label = label_pton(&mpinfo->extra->label); - /* Note that this currently only applies to Null0 routes for - * aggregates. - * ZEBRA_FLAG_BLACKHOLE signals zapi_ipv6_route to encode a - * special - * BLACKHOLE nexthop. We want to set api.nexthop_num to zero - * since we - * do not want to also encode the :: nexthop for the aggregate - * route. - */ - if (CHECK_FLAG(api.flags, ZEBRA_FLAG_BLACKHOLE)) - api.nexthop_num = 0; - else - api.nexthop_num = valid_nh_count; - - SET_FLAG(api.message, ZAPI_MESSAGE_METRIC); - api.metric = metric; - - api.tag = 0; - if (tag) { - SET_FLAG(api.message, ZAPI_MESSAGE_TAG); - api.tag = tag; + api_nh->label_num = 1; + api_nh->labels[0] = label; } + valid_nh_count++; + } - distance = bgp_distance_apply(p, info, afi, safi, bgp); - if (distance) { - SET_FLAG(api.message, ZAPI_MESSAGE_DISTANCE); - api.distance = distance; - } + if (has_valid_label) + SET_FLAG(api.message, ZAPI_MESSAGE_LABEL); - if (p->family == AF_INET) { - if (bgp_debug_zebra(p)) { - int i; - char label_buf[20]; - zlog_debug( - "Tx IPv4 route %s VRF %u %s/%d metric %u tag %" ROUTE_TAG_PRI, - valid_nh_count ? "add" : "delete", - bgp->vrf_id, - inet_ntop(AF_INET, &p->u.prefix4, - buf[0], sizeof(buf[0])), - p->prefixlen, api.metric, api.tag); - for (i = 0; i < api.nexthop_num; i++) { - api_nh = &api.nexthops[i]; + if (!CHECK_FLAG(api.flags, ZEBRA_FLAG_BLACKHOLE)) + api.nexthop_num = valid_nh_count; - label_buf[0] = '\0'; - if (has_valid_label) - sprintf(label_buf, "label %u", - api_nh->labels[0]); - zlog_debug( - " nhop [%d]: %s if %s %s", - i + 1, - inet_ntop(AF_INET6, - &api_nh->gate.ipv6, - buf[1], - sizeof(buf[1])), - ifindex2ifname(api_nh->ifindex, - bgp->vrf_id), - label_buf); - } - } + SET_FLAG(api.message, ZAPI_MESSAGE_METRIC); + api.metric = metric; - if (valid_nh_count) - zclient_route_send(ZEBRA_ROUTE_ADD, zclient, - &api); - else - zclient_route_send(ZEBRA_ROUTE_DELETE, zclient, - &api); - } else { - if (bgp_debug_zebra(p)) { - int i; - char label_buf[20]; - zlog_debug( - "Tx IPv6 route %s VRF %u %s/%d metric %u tag %" ROUTE_TAG_PRI, - valid_nh_count ? "add" : "delete", - bgp->vrf_id, - inet_ntop(AF_INET6, &p->u.prefix6, - buf[0], sizeof(buf[0])), - p->prefixlen, api.metric, api.tag); - for (i = 0; i < api.nexthop_num; i++) { - api_nh = &api.nexthops[i]; + if (tag) { + SET_FLAG(api.message, ZAPI_MESSAGE_TAG); + api.tag = tag; + } - label_buf[0] = '\0'; - if (has_valid_label) - sprintf(label_buf, "label %u", - api_nh->labels[0]); - zlog_debug( - " nhop [%d]: %s if %s %s", - i + 1, - inet_ntop(AF_INET6, - &api_nh->gate.ipv6, - buf[1], - sizeof(buf[1])), - ifindex2ifname(api_nh->ifindex, - bgp->vrf_id), - label_buf); - } - } + distance = bgp_distance_apply(p, info, afi, safi, bgp); + if (distance) { + SET_FLAG(api.message, ZAPI_MESSAGE_DISTANCE); + api.distance = distance; + } - zclient_route_send(valid_nh_count ? ZEBRA_ROUTE_ADD - : ZEBRA_ROUTE_DELETE, - zclient, &api); + if (bgp_debug_zebra(p)) { + char prefix_buf[PREFIX_STRLEN]; + char nh_buf[INET6_ADDRSTRLEN]; + char label_buf[20]; + int i; + + prefix2str(&api.prefix, prefix_buf, sizeof(prefix_buf)); + zlog_debug("Tx route %s VRF %u %s metric %u tag %" ROUTE_TAG_PRI + " count %d", + valid_nh_count ? "add" : "delete", bgp->vrf_id, + prefix_buf, api.metric, api.tag, api.nexthop_num); + for (i = 0; i < api.nexthop_num; i++) { + api_nh = &api.nexthops[i]; + + inet_ntop(nh_family, &api_nh->gate, nh_buf, + sizeof(nh_buf)); + + label_buf[0] = '\0'; + if (has_valid_label) + sprintf(label_buf, "label %u", + api_nh->labels[0]); + zlog_debug(" nhop [%d]: %s %s", i + 1, nh_buf, + label_buf); } } + + zclient_route_send(valid_nh_count ? ZEBRA_ROUTE_ADD + : ZEBRA_ROUTE_DELETE, + zclient, &api); } /* Announce all routes of a table to zebra */ @@ -1532,7 +1393,7 @@ void bgp_zebra_announce_table(struct bgp *bgp, afi_t afi, safi_t safi) void bgp_zebra_withdraw(struct prefix *p, struct bgp_info *info, safi_t safi) { - u_int32_t flags; + struct zapi_route api; struct peer *peer; peer = info->peer; @@ -1544,61 +1405,30 @@ void bgp_zebra_withdraw(struct prefix *p, struct bgp_info *info, safi_t safi) if (!bgp_install_info_to_zebra(peer->bgp)) return; - flags = 0; + memset(&api, 0, sizeof(api)); + api.vrf_id = peer->bgp->vrf_id; + api.type = ZEBRA_ROUTE_BGP; + api.safi = safi; + api.prefix = *p; if (peer->sort == BGP_PEER_IBGP) { - SET_FLAG(flags, ZEBRA_FLAG_INTERNAL); - SET_FLAG(flags, ZEBRA_FLAG_IBGP); + SET_FLAG(api.flags, ZEBRA_FLAG_INTERNAL); + SET_FLAG(api.flags, ZEBRA_FLAG_IBGP); } if ((peer->sort == BGP_PEER_EBGP && peer->ttl != 1) || CHECK_FLAG(peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK) || bgp_flag_check(peer->bgp, BGP_FLAG_DISABLE_NH_CONNECTED_CHK)) - SET_FLAG(flags, ZEBRA_FLAG_INTERNAL); + SET_FLAG(api.flags, ZEBRA_FLAG_INTERNAL); - if (p->family == AF_INET) { - struct zapi_route api; + if (bgp_debug_zebra(p)) { + char buf[PREFIX_STRLEN]; - memset(&api, 0, sizeof(api)); - api.vrf_id = peer->bgp->vrf_id; - api.flags = flags; - api.type = ZEBRA_ROUTE_BGP; - api.safi = safi; - api.prefix = *p; - - if (bgp_debug_zebra(p)) { - char buf[2][INET_ADDRSTRLEN]; - zlog_debug("Tx IPv4 route delete VRF %u %s/%d", - peer->bgp->vrf_id, - inet_ntop(AF_INET, &p->u.prefix4, buf[0], - sizeof(buf[0])), - p->prefixlen); - } - - zclient_route_send(ZEBRA_ROUTE_DELETE, zclient, &api); + prefix2str(&api.prefix, buf, sizeof(buf)); + zlog_debug("Tx route delete VRF %u %s", peer->bgp->vrf_id, buf); } - /* We have to think about a IPv6 link-local address curse. */ - if (p->family == AF_INET6) { - struct zapi_route api; - memset(&api, 0, sizeof(api)); - api.vrf_id = peer->bgp->vrf_id; - api.flags = flags; - api.type = ZEBRA_ROUTE_BGP; - api.safi = safi; - api.prefix = *p; - - if (bgp_debug_zebra(p)) { - char buf[2][INET6_ADDRSTRLEN]; - zlog_debug("Tx IPv6 route delete VRF %u %s/%d", - peer->bgp->vrf_id, - inet_ntop(AF_INET6, &p->u.prefix6, buf[0], - sizeof(buf[0])), - p->prefixlen); - } - - zclient_route_send(ZEBRA_ROUTE_DELETE, zclient, &api); - } + zclient_route_send(ZEBRA_ROUTE_DELETE, zclient, &api); } struct bgp_redist *bgp_redist_lookup(struct bgp *bgp, afi_t afi, u_char type, diff --git a/bgpd/rfapi/vnc_zebra.c b/bgpd/rfapi/vnc_zebra.c index 1b1a89b35f..06dff27b58 100644 --- a/bgpd/rfapi/vnc_zebra.c +++ b/bgpd/rfapi/vnc_zebra.c @@ -494,89 +494,57 @@ static int vnc_zebra_read_ipv6(int command, struct zclient *zclient, static void vnc_zebra_route_msg(struct prefix *p, int nhp_count, void *nhp_ary, int add) /* 1 = add, 0 = del */ { + struct zapi_route api; + struct zapi_nexthop *api_nh; + int i; + if (!nhp_count) { vnc_zlog_debug_verbose("%s: empty nexthop list, skipping", __func__); return; } - if (p->family == AF_INET) { - struct zapi_route api; - struct zapi_nexthop *api_nh; - struct in_addr *nhp_ary4 = nhp_ary; - int i; + memset(&api, 0, sizeof(api)); + api.vrf_id = VRF_DEFAULT; + api.type = ZEBRA_ROUTE_VNC; + api.safi = SAFI_UNICAST; + api.prefix = *p; - memset(&api, 0, sizeof(api)); - api.vrf_id = VRF_DEFAULT; - api.type = ZEBRA_ROUTE_VNC; - api.prefix = *p; - api.safi = SAFI_UNICAST; + /* Nexthops */ + SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); + api.nexthop_num = nhp_count; + for (i = 0; i < nhp_count; i++) { + struct in_addr *nhp_ary4; + struct in6_addr *nhp_ary6; - /* Nexthops */ - SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); - api.nexthop_num = nhp_count; - for (i = 0; i < nhp_count; i++) { - api_nh = &api.nexthops[i]; + api_nh = &api.nexthops[i]; + switch (p->family) { + case AF_INET: + nhp_ary4 = nhp_ary; memcpy(&api_nh->gate.ipv4, &nhp_ary4[i], sizeof(api_nh->gate.ipv4)); api_nh->type = NEXTHOP_TYPE_IPV4; - } - - if (BGP_DEBUG(zebra, ZEBRA)) { - - char buf[INET_ADDRSTRLEN]; - vnc_zlog_debug_verbose( - "%s: Zebra send: IPv4 route %s %s/%d, nhp_count=%d", - __func__, (add ? "add" : "del"), - inet_ntop(AF_INET, &p->u.prefix4, buf, - sizeof(buf)), - p->prefixlen, nhp_count); - } - - zclient_route_send((add ? ZEBRA_ROUTE_ADD : ZEBRA_ROUTE_DELETE), - zclient_vnc, &api); - - } else if (p->family == AF_INET6) { - struct zapi_route api; - struct zapi_nexthop *api_nh; - struct in6_addr *nhp_ary6 = nhp_ary; - int i; - - memset(&api, 0, sizeof(api)); - api.vrf_id = VRF_DEFAULT; - api.type = ZEBRA_ROUTE_VNC; - api.prefix = *p; - api.safi = SAFI_UNICAST; - - /* Nexthops */ - SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); - api.nexthop_num = nhp_count; - for (i = 0; i < nhp_count; i++) { - api_nh = &api.nexthops[i]; + break; + case AF_INET6: + nhp_ary6 = nhp_ary; memcpy(&api_nh->gate.ipv6, &nhp_ary6[i], sizeof(api_nh->gate.ipv6)); api_nh->type = NEXTHOP_TYPE_IPV6; + break; } - - if (BGP_DEBUG(zebra, ZEBRA)) { - - char buf[INET6_ADDRSTRLEN]; - vnc_zlog_debug_verbose( - "%s: Zebra send: IPv6 route %s %s/%d nhp_count=%d", - __func__, (add ? "add" : "del"), - inet_ntop(AF_INET6, &p->u.prefix6, buf, - sizeof(buf)), - p->prefixlen, nhp_count); - } - - zclient_route_send((add ? ZEBRA_ROUTE_ADD : ZEBRA_ROUTE_DELETE), - zclient_vnc, &api); - } else { - vnc_zlog_debug_verbose( - "%s: unknown prefix address family, skipping", - __func__); - return; } + + if (BGP_DEBUG(zebra, ZEBRA)) { + char buf[PREFIX_STRLEN]; + + prefix2str(&api.prefix, buf, sizeof(buf)); + vnc_zlog_debug_verbose( + "%s: Zebra send: route %s %s, nhp_count=%d", __func__, + (add ? "add" : "del"), buf, nhp_count); + } + + zclient_route_send((add ? ZEBRA_ROUTE_ADD : ZEBRA_ROUTE_DELETE), + zclient_vnc, &api); } From 744899219f4214398a3078874a341000a372e29d Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Sun, 20 Aug 2017 22:10:50 -0300 Subject: [PATCH 090/130] *: use zapi_route to send/receive redistributed routes as well Some differences compared to the old API: * Now the redistributed routes are sent using address-family independent messages (ZEBRA_REDISTRIBUTE_ROUTE_ADD and ZEBRA_REDISTRIBUTE_ROUTE_DEL). This allows us to unify the ipv4/ipv6 zclient callbacks in the client daemons and thus remove a lot of duplicate code; * Now zebra sends all nexthops of the redistributed routes to the client daemons, not only the first one. This shouldn't have any noticeable performance implications and will allow us to remove an ugly exception we had for ldpd (which needs to know all nexthops of the redistributed routes). The other client daemons can simply ignore the nexthops if they want or consult just the first one (e.g. ospfd/ospf6d/ripd/ripngd). Signed-off-by: Renato Westphal --- babeld/babel_zebra.c | 123 +++------------------ babeld/xroute.c | 77 ++++++------- babeld/xroute.h | 10 +- bgpd/bgp_route.c | 20 ++-- bgpd/bgp_route.h | 4 +- bgpd/bgp_zebra.c | 239 +++++++---------------------------------- bgpd/rfapi/vnc_zebra.c | 171 ++++------------------------- eigrpd/eigrp_zebra.c | 52 +++------ isisd/isis_zebra.c | 122 +++------------------ ldpd/ldp_zebra.c | 106 +++++++----------- lib/log.c | 6 +- lib/zclient.c | 26 ++--- lib/zclient.h | 33 +++--- nhrpd/nhrp_route.c | 97 +++++------------ ospf6d/ospf6_zebra.c | 86 ++++----------- ospfd/ospf_zebra.c | 69 ++++-------- ripd/rip_zebra.c | 69 ++++-------- ripngd/ripng_zebra.c | 74 +++---------- zebra/redistribute.c | 17 +-- zebra/zserv.c | 221 +++++++++---------------------------- 20 files changed, 371 insertions(+), 1251 deletions(-) diff --git a/babeld/babel_zebra.c b/babeld/babel_zebra.c index 2b998940d7..337b7b3927 100644 --- a/babeld/babel_zebra.c +++ b/babeld/babel_zebra.c @@ -54,119 +54,24 @@ static struct { {0, 0, NULL} }; -/* Zebra route add and delete treatment (ipv6). */ +/* Zebra route add and delete treatment. */ static int -babel_zebra_read_ipv6 (int command, struct zclient *zclient, - zebra_size_t length, vrf_id_t vrf) +babel_zebra_read_route (int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf) { - struct stream *s; - struct zapi_ipv6 api; - unsigned long ifindex = -1; - struct in6_addr nexthop; - struct prefix_ipv6 prefix, src_p; + struct zapi_route api; - s = zclient->ibuf; - ifindex = 0; - memset (&nexthop, 0, sizeof (struct in6_addr)); - memset (&api, 0, sizeof(struct zapi_ipv6)); - memset (&prefix, 0, sizeof (struct prefix_ipv6)); + if (zapi_route_decode(zclient->ibuf, &api) < 0) + return -1; - /* Type, flags, message. */ - api.type = stream_getc (s); - api.instance = stream_getw (s); - api.flags = stream_getl (s); - api.message = stream_getc (s); - - /* IPv6 prefix. */ - prefix.family = AF_INET6; - prefix.prefixlen = MIN (IPV6_MAX_PREFIXLEN, stream_getc (s)); - stream_get (&prefix.prefix, s, PSIZE (prefix.prefixlen)); - - memset(&src_p, 0, sizeof(src_p)); - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX)) { - src_p.family = AF_INET6; - src_p.prefixlen = stream_getc(s); - stream_get(&src_p.prefix, s, PSIZE(src_p.prefixlen)); - } - if (src_p.prefixlen) - /* we completely ignore srcdest routes for now. */ + /* we completely ignore srcdest routes for now. */ + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX)) return 0; - /* Nexthop, ifindex, distance, metric. */ - if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP)) { - api.nexthop_num = stream_getc (s); - stream_get (&nexthop, s, sizeof(nexthop)); - } - if (CHECK_FLAG (api.message, ZAPI_MESSAGE_IFINDEX)) { - api.ifindex_num = stream_getc (s); - ifindex = stream_getl (s); - } - if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE)) - api.distance = stream_getc (s); - else - api.distance = 0; - if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC)) - api.metric = stream_getl (s); - else - api.metric = 0; - - if (command == ZEBRA_REDISTRIBUTE_IPV6_ADD) - babel_ipv6_route_add(&api, &prefix, ifindex, &nexthop); - else - babel_ipv6_route_delete(&api, &prefix, ifindex); - - return 0; -} - -static int -babel_zebra_read_ipv4 (int command, struct zclient *zclient, - zebra_size_t length, vrf_id_t vrf) -{ - struct stream *s; - struct zapi_ipv4 api; - unsigned long ifindex = -1; - struct in_addr nexthop; - struct prefix_ipv4 prefix; - - s = zclient->ibuf; - ifindex = 0; - memset (&nexthop, 0, sizeof (struct in_addr)); - memset (&api, 0, sizeof(struct zapi_ipv4)); - memset (&prefix, 0, sizeof (struct prefix_ipv4)); - - /* Type, flags, message. */ - api.type = stream_getc (s); - api.instance = stream_getw (s); - api.flags = stream_getl (s); - api.message = stream_getc (s); - - /* IPv4 prefix. */ - prefix.family = AF_INET; - prefix.prefixlen = MIN (IPV4_MAX_PREFIXLEN, stream_getc (s)); - stream_get (&prefix.prefix, s, PSIZE (prefix.prefixlen)); - - /* Nexthop, ifindex, distance, metric. */ - if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP)) { - api.nexthop_num = stream_getc (s); - stream_get (&nexthop, s, sizeof(nexthop)); - } - if (CHECK_FLAG (api.message, ZAPI_MESSAGE_IFINDEX)) { - api.ifindex_num = stream_getc (s); - ifindex = stream_getl (s); - } - if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE)) - api.distance = stream_getc (s); - else - api.distance = 0; - if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC)) - api.metric = stream_getl (s); - else - api.metric = 0; - - if (command == ZEBRA_REDISTRIBUTE_IPV4_ADD) { - babel_ipv4_route_add(&api, &prefix, ifindex, &nexthop); + if (command == ZEBRA_REDISTRIBUTE_ROUTE_ADD) { + babel_route_add(&api); } else { - babel_ipv4_route_delete(&api, &prefix, ifindex); + babel_route_delete(&api); } return 0; @@ -342,10 +247,8 @@ void babelz_zebra_init(void) zclient->interface_down = babel_interface_down; zclient->interface_address_add = babel_interface_address_add; zclient->interface_address_delete = babel_interface_address_delete; - zclient->redistribute_route_ipv4_add = babel_zebra_read_ipv4; - zclient->redistribute_route_ipv4_del = babel_zebra_read_ipv4; - zclient->redistribute_route_ipv6_add = babel_zebra_read_ipv6; - zclient->redistribute_route_ipv6_del = babel_zebra_read_ipv6; + zclient->redistribute_route_add = babel_zebra_read_route; + zclient->redistribute_route_del = babel_zebra_read_route; install_element(BABEL_NODE, &babel_redistribute_type_cmd); install_element(ENABLE_NODE, &debug_babel_cmd); diff --git a/babeld/xroute.c b/babeld/xroute.c index 2e123564ea..88e9479e4b 100644 --- a/babeld/xroute.c +++ b/babeld/xroute.c @@ -43,63 +43,54 @@ static int numxroutes = 0, maxxroutes = 0; /* Add redistributed route to Babel table. */ int -babel_ipv4_route_add (struct zapi_ipv4 *api, struct prefix_ipv4 *prefix, - unsigned int ifindex, struct in_addr *nexthop) +babel_route_add (struct zapi_route *api) { unsigned char uchar_prefix[16]; - inaddr_to_uchar(uchar_prefix, &prefix->prefix); - debugf(BABEL_DEBUG_ROUTE, "Adding new ipv4 route coming from Zebra."); - xroute_add_new_route(uchar_prefix, prefix->prefixlen + 96, - api->metric, ifindex, 0, 1); + switch (api->prefix.family) { + case AF_INET: + inaddr_to_uchar(uchar_prefix, &api->prefix.u.prefix4); + debugf(BABEL_DEBUG_ROUTE, "Adding new ipv4 route coming from Zebra."); + xroute_add_new_route(uchar_prefix, api->prefix.prefixlen + 96, + api->metric, api->nexthops[0].ifindex, 0, 1); + break; + case AF_INET6: + in6addr_to_uchar(uchar_prefix, &api->prefix.u.prefix6); + debugf(BABEL_DEBUG_ROUTE, "Adding new ipv6 route coming from Zebra."); + xroute_add_new_route(uchar_prefix, api->prefix.prefixlen, + api->metric, api->nexthops[0].ifindex, 0, 1); + break; + } + return 0; } /* Remove redistributed route from Babel table. */ int -babel_ipv4_route_delete (struct zapi_ipv4 *api, struct prefix_ipv4 *prefix, - unsigned int ifindex) +babel_route_delete (struct zapi_route *api) { unsigned char uchar_prefix[16]; struct xroute *xroute = NULL; - inaddr_to_uchar(uchar_prefix, &prefix->prefix); - xroute = find_xroute(uchar_prefix, prefix->prefixlen + 96); - if (xroute != NULL) { - debugf(BABEL_DEBUG_ROUTE, "Removing ipv4 route (from zebra)."); - flush_xroute(xroute); + switch (api->prefix.family) { + case AF_INET: + inaddr_to_uchar(uchar_prefix, &api->prefix.u.prefix4); + xroute = find_xroute(uchar_prefix, api->prefix.prefixlen + 96); + if (xroute != NULL) { + debugf(BABEL_DEBUG_ROUTE, "Removing ipv4 route (from zebra)."); + flush_xroute(xroute); + } + break; + case AF_INET6: + in6addr_to_uchar(uchar_prefix, &api->prefix.u.prefix6); + xroute = find_xroute(uchar_prefix, api->prefix.prefixlen); + if (xroute != NULL) { + debugf(BABEL_DEBUG_ROUTE, "Removing ipv6 route (from zebra)."); + flush_xroute(xroute); + } + break; } - return 0; -} -/* Add redistributed route to Babel table. */ -int -babel_ipv6_route_add (struct zapi_ipv6 *api, struct prefix_ipv6 *prefix, - unsigned int ifindex, struct in6_addr *nexthop) -{ - unsigned char uchar_prefix[16]; - - in6addr_to_uchar(uchar_prefix, &prefix->prefix); - debugf(BABEL_DEBUG_ROUTE, "Adding new route coming from Zebra."); - xroute_add_new_route(uchar_prefix, prefix->prefixlen, api->metric, ifindex, - 0, 1); - return 0; -} - -/* Remove redistributed route from Babel table. */ -int -babel_ipv6_route_delete (struct zapi_ipv6 *api, struct prefix_ipv6 *prefix, - unsigned int ifindex) -{ - unsigned char uchar_prefix[16]; - struct xroute *xroute = NULL; - - in6addr_to_uchar(uchar_prefix, &prefix->prefix); - xroute = find_xroute(uchar_prefix, prefix->prefixlen); - if (xroute != NULL) { - debugf(BABEL_DEBUG_ROUTE, "Removing route (from zebra)."); - flush_xroute(xroute); - } return 0; } diff --git a/babeld/xroute.h b/babeld/xroute.h index 27899e62a1..59afccb590 100644 --- a/babeld/xroute.h +++ b/babeld/xroute.h @@ -36,14 +36,8 @@ struct xroute_stream; struct xroute *find_xroute(const unsigned char *prefix, unsigned char plen); void flush_xroute(struct xroute *xroute); -int babel_ipv4_route_add (struct zapi_ipv4 *api, struct prefix_ipv4 *prefix, - unsigned int ifindex, struct in_addr *nexthop); -int babel_ipv4_route_delete (struct zapi_ipv4 *api, struct prefix_ipv4 *prefix, - unsigned int ifindex); -int babel_ipv6_route_add (struct zapi_ipv6 *api, struct prefix_ipv6 *prefix, - unsigned int ifindex, struct in6_addr *nexthop); -int babel_ipv6_route_delete (struct zapi_ipv6 *api, struct prefix_ipv6 *prefix, - unsigned int ifindex); +int babel_route_add (struct zapi_route *api); +int babel_route_delete (struct zapi_route *api); int xroutes_estimate(void); struct xroute_stream *xroute_stream(void); struct xroute *xroute_stream_next(struct xroute_stream *stream); diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index bb204b01f1..2256b069cb 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -6086,8 +6086,7 @@ DEFUN (no_ipv6_aggregate_address, /* Redistribute route treatment. */ void bgp_redistribute_add(struct bgp *bgp, struct prefix *p, - const struct in_addr *nexthop, - const struct in6_addr *nexthop6, unsigned int ifindex, + const union g_addr *nexthop, unsigned int ifindex, u_int32_t metric, u_char type, u_short instance, route_tag_t tag) { @@ -6103,14 +6102,17 @@ void bgp_redistribute_add(struct bgp *bgp, struct prefix *p, /* Make default attribute. */ bgp_attr_default_set(&attr, BGP_ORIGIN_INCOMPLETE); - if (nexthop) - attr.nexthop = *nexthop; - attr.nh_ifindex = ifindex; - - if (nexthop6) { - attr.mp_nexthop_global = *nexthop6; - attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL; + if (nexthop) { + switch (p->family) { + case AF_INET: + attr.nexthop = nexthop->ipv4; + break; + case AF_INET6: + attr.mp_nexthop_global = nexthop->ipv6; + attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL; + } } + attr.nh_ifindex = ifindex; attr.med = metric; attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC); diff --git a/bgpd/bgp_route.h b/bgpd/bgp_route.h index 1a1817bad3..55f812d4a0 100644 --- a/bgpd/bgp_route.h +++ b/bgpd/bgp_route.h @@ -22,6 +22,7 @@ #define _QUAGGA_BGP_ROUTE_H #include "queue.h" +#include "nexthop.h" #include "bgp_table.h" struct bgp_nexthop_cache; @@ -326,8 +327,7 @@ extern int bgp_nlri_parse_ip(struct peer *, struct attr *, struct bgp_nlri *); extern int bgp_maximum_prefix_overflow(struct peer *, afi_t, safi_t, int); extern void bgp_redistribute_add(struct bgp *, struct prefix *, - const struct in_addr *, - const struct in6_addr *, unsigned int ifindex, + const union g_addr *, unsigned int ifindex, u_int32_t, u_char, u_short, route_tag_t); extern void bgp_redistribute_delete(struct bgp *, struct prefix *, u_char, u_short); diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c index 1796975ad3..9a092404d5 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -554,75 +554,36 @@ static int bgp_interface_vrf_update(int command, struct zclient *zclient, } /* Zebra route add and delete treatment. */ -static int zebra_read_ipv4(int command, struct zclient *zclient, - zebra_size_t length, vrf_id_t vrf_id) +static int zebra_read_route(int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf_id) { - struct stream *s; - struct zapi_ipv4 api; - struct in_addr nexthop; - struct prefix_ipv4 p; + struct zapi_route api; + union g_addr nexthop; unsigned int ifindex; - int i; + int add, i; struct bgp *bgp; bgp = bgp_lookup_by_vrf_id(vrf_id); if (!bgp) return 0; - s = zclient->ibuf; - nexthop.s_addr = 0; + if (zapi_route_decode(zclient->ibuf, &api) < 0) + return -1; - /* Type, flags, message. */ - api.type = stream_getc(s); - api.instance = stream_getw(s); - api.flags = stream_getl(s); - api.message = stream_getc(s); + /* we completely ignore srcdest routes for now. */ + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX)) + return 0; - /* IPv4 prefix. */ - memset(&p, 0, sizeof(struct prefix_ipv4)); - p.family = AF_INET; - p.prefixlen = MIN(IPV4_MAX_PREFIXLEN, stream_getc(s)); - stream_get(&p.prefix, s, PSIZE(p.prefixlen)); + /* ignore link-local address. */ + if (api.prefix.family == AF_INET6 + && IN6_IS_ADDR_LINKLOCAL(&api.prefix.u.prefix6)) + return 0; - /* Nexthop, ifindex, distance, metric. */ - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP)) { - api.nexthop_num = stream_getc(s); - nexthop.s_addr = stream_get_ipv4(s); - } - - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_IFINDEX)) { - api.ifindex_num = stream_getc(s); - ifindex = stream_getl(s); /* ifindex, unused */ - } else { - ifindex = 0; - } - - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_DISTANCE)) - api.distance = stream_getc(s); - - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_METRIC)) - api.metric = stream_getl(s); - else - api.metric = 0; - - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_TAG)) - api.tag = stream_getl(s); - else - api.tag = 0; - - if (command == ZEBRA_REDISTRIBUTE_IPV4_ADD) { - if (bgp_debug_zebra((struct prefix *)&p)) { - char buf[2][INET_ADDRSTRLEN]; - zlog_debug( - "Rx IPv4 route add VRF %u %s[%d] %s/%d nexthop %s metric %u tag %" ROUTE_TAG_PRI, - vrf_id, zebra_route_string(api.type), - api.instance, inet_ntop(AF_INET, &p.prefix, - buf[0], sizeof(buf[0])), - p.prefixlen, inet_ntop(AF_INET, &nexthop, - buf[1], sizeof(buf[1])), - api.metric, api.tag); - } + nexthop = api.nexthops[0].gate; + ifindex = api.nexthops[0].ifindex; + add = (command == ZEBRA_REDISTRIBUTE_ROUTE_ADD); + if (add) { /* * The ADD message is actually an UPDATE and there is no * explicit DEL @@ -634,156 +595,30 @@ static int zebra_read_ipv4(int command, struct zclient *zclient, */ for (i = 0; i < ZEBRA_ROUTE_MAX; i++) { if (i != api.type) - bgp_redistribute_delete(bgp, - (struct prefix *)&p, i, + bgp_redistribute_delete(bgp, &api.prefix, i, api.instance); } /* Now perform the add/update. */ - bgp_redistribute_add(bgp, (struct prefix *)&p, &nexthop, NULL, - ifindex, api.metric, api.type, - api.instance, api.tag); - } else if (command == ZEBRA_REDISTRIBUTE_IPV4_DEL) { - if (bgp_debug_zebra((struct prefix *)&p)) { - char buf[2][INET_ADDRSTRLEN]; - zlog_debug( - "Rx IPv4 route delete VRF %u %s[%d] %s/%d " - "nexthop %s metric %u tag %" ROUTE_TAG_PRI, - vrf_id, zebra_route_string(api.type), - api.instance, inet_ntop(AF_INET, &p.prefix, - buf[0], sizeof(buf[0])), - p.prefixlen, inet_ntop(AF_INET, &nexthop, - buf[1], sizeof(buf[1])), - api.metric, api.tag); - } - bgp_redistribute_delete(bgp, (struct prefix *)&p, api.type, - api.instance); - } - - return 0; -} - -/* Zebra route add and delete treatment. */ -static int zebra_read_ipv6(int command, struct zclient *zclient, - zebra_size_t length, vrf_id_t vrf_id) -{ - struct stream *s; - struct zapi_ipv6 api; - struct in6_addr nexthop; - struct prefix_ipv6 p, src_p; - unsigned int ifindex; - int i; - struct bgp *bgp; - - bgp = bgp_lookup_by_vrf_id(vrf_id); - if (!bgp) - return 0; - - s = zclient->ibuf; - memset(&nexthop, 0, sizeof(struct in6_addr)); - - /* Type, flags, message. */ - api.type = stream_getc(s); - api.instance = stream_getw(s); - api.flags = stream_getl(s); - api.message = stream_getc(s); - - /* IPv6 prefix. */ - memset(&p, 0, sizeof(struct prefix_ipv6)); - p.family = AF_INET6; - p.prefixlen = MIN(IPV6_MAX_PREFIXLEN, stream_getc(s)); - stream_get(&p.prefix, s, PSIZE(p.prefixlen)); - - memset(&src_p, 0, sizeof(struct prefix_ipv6)); - src_p.family = AF_INET6; - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX)) { - src_p.prefixlen = stream_getc(s); - stream_get(&src_p.prefix, s, PSIZE(src_p.prefixlen)); - } - - if (src_p.prefixlen) - /* we completely ignore srcdest routes for now. */ - return 0; - - /* Nexthop, ifindex, distance, metric. */ - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP)) { - api.nexthop_num = stream_getc(s); - stream_get(&nexthop, s, 16); - } - - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_IFINDEX)) { - api.ifindex_num = stream_getc(s); - ifindex = stream_getl(s); /* ifindex, unused */ + bgp_redistribute_add(bgp, &api.prefix, &nexthop, ifindex, + api.metric, api.type, api.instance, + api.tag); } else { - ifindex = 0; + bgp_redistribute_delete(bgp, &api.prefix, api.type, + api.instance); } - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_DISTANCE)) - api.distance = stream_getc(s); - else - api.distance = 0; + if (bgp_debug_zebra(&api.prefix)) { + char buf[2][PREFIX_STRLEN]; - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_METRIC)) - api.metric = stream_getl(s); - else - api.metric = 0; - - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_TAG)) - api.tag = stream_getl(s); - else - api.tag = 0; - - /* Simply ignore link-local address. */ - if (IN6_IS_ADDR_LINKLOCAL(&p.prefix)) - return 0; - - if (command == ZEBRA_REDISTRIBUTE_IPV6_ADD) { - if (bgp_debug_zebra((struct prefix *)&p)) { - char buf[2][INET6_ADDRSTRLEN]; - zlog_debug( - "Rx IPv6 route add VRF %u %s[%d] %s/%d nexthop %s metric %u tag %" ROUTE_TAG_PRI, - vrf_id, zebra_route_string(api.type), - api.instance, inet_ntop(AF_INET6, &p.prefix, - buf[0], sizeof(buf[0])), - p.prefixlen, inet_ntop(AF_INET, &nexthop, - buf[1], sizeof(buf[1])), - api.metric, api.tag); - } - - /* - * The ADD message is actually an UPDATE and there is no - * explicit DEL - * for a prior redistributed route, if any. So, perform an - * implicit - * DEL processing for the same redistributed route from any - * other - * source type. - */ - for (i = 0; i < ZEBRA_ROUTE_MAX; i++) { - if (i != api.type) - bgp_redistribute_delete(bgp, - (struct prefix *)&p, i, - api.instance); - } - - bgp_redistribute_add(bgp, (struct prefix *)&p, NULL, &nexthop, - ifindex, api.metric, api.type, - api.instance, api.tag); - } else if (command == ZEBRA_REDISTRIBUTE_IPV6_DEL) { - if (bgp_debug_zebra((struct prefix *)&p)) { - char buf[2][INET6_ADDRSTRLEN]; - zlog_debug( - "Rx IPv6 route delete VRF %u %s[%d] %s/%d " - "nexthop %s metric %u tag %" ROUTE_TAG_PRI, - vrf_id, zebra_route_string(api.type), - api.instance, inet_ntop(AF_INET6, &p.prefix, - buf[0], sizeof(buf[0])), - p.prefixlen, inet_ntop(AF_INET6, &nexthop, - buf[1], sizeof(buf[1])), - api.metric, api.tag); - } - bgp_redistribute_delete(bgp, (struct prefix *)&p, api.type, - api.instance); + prefix2str(&api.prefix, buf[0], sizeof(buf[0])); + inet_ntop(api.prefix.family, &nexthop, buf[1], sizeof(buf[1])); + zlog_debug( + "Rx route %s VRF %u %s[%d] %s " + "nexthop %s metric %u tag %" ROUTE_TAG_PRI, + (add) ? "add" : "delete", vrf_id, + zebra_route_string(api.type), api.instance, buf[0], + buf[1], api.metric, api.tag); } return 0; @@ -1942,12 +1777,10 @@ void bgp_zebra_init(struct thread_master *master) zclient->interface_nbr_address_delete = bgp_interface_nbr_address_delete; zclient->interface_vrf_update = bgp_interface_vrf_update; - zclient->redistribute_route_ipv4_add = zebra_read_ipv4; - zclient->redistribute_route_ipv4_del = zebra_read_ipv4; + zclient->redistribute_route_add = zebra_read_route; + zclient->redistribute_route_del = zebra_read_route; zclient->interface_up = bgp_interface_up; zclient->interface_down = bgp_interface_down; - zclient->redistribute_route_ipv6_add = zebra_read_ipv6; - zclient->redistribute_route_ipv6_del = zebra_read_ipv6; zclient->nexthop_update = bgp_read_nexthop_update; zclient->import_check_update = bgp_read_import_check_update; zclient->fec_update = bgp_read_fec_update; diff --git a/bgpd/rfapi/vnc_zebra.c b/bgpd/rfapi/vnc_zebra.c index 06dff27b58..d472e06fa5 100644 --- a/bgpd/rfapi/vnc_zebra.c +++ b/bgpd/rfapi/vnc_zebra.c @@ -57,8 +57,8 @@ static struct zclient *zclient_vnc = NULL; /* * Routes coming from zebra get added to VNC here */ -static void vnc_redistribute_add(struct prefix *p, struct in_addr *nexthop, - u_int32_t metric, uint8_t type) +static void vnc_redistribute_add(struct prefix *p, u_int32_t metric, + uint8_t type) { struct bgp *bgp = bgp_get_default(); struct prefix_rd prd; @@ -329,156 +329,33 @@ static void vnc_redistribute_withdraw(struct bgp *bgp, afi_t afi, uint8_t type) * * Assumes 1 nexthop */ -static int vnc_zebra_read_ipv4(int command, struct zclient *zclient, - zebra_size_t length, vrf_id_t vrf_id) +static int vnc_zebra_read_route(int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf_id) { - struct stream *s; - struct zapi_ipv4 api; - struct in_addr nexthop; - struct prefix_ipv4 p; + struct zapi_route api; + int add; - s = zclient->ibuf; - nexthop.s_addr = 0; + if (zapi_route_decode(zclient->ibuf, &api) < 0) + return -1; - /* Type, flags, message. */ - api.type = stream_getc(s); - api.flags = stream_getc(s); - api.message = stream_getc(s); - - /* IPv4 prefix. */ - memset(&p, 0, sizeof(struct prefix_ipv4)); - p.family = AF_INET; - p.prefixlen = stream_getc(s); - stream_get(&p.prefix, s, PSIZE(p.prefixlen)); - - /* Nexthop, ifindex, distance, metric. */ - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP)) { - api.nexthop_num = stream_getc(s); - nexthop.s_addr = stream_get_ipv4(s); - } - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_IFINDEX)) { - api.ifindex_num = stream_getc(s); - stream_getl(s); - } - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_DISTANCE)) - api.distance = stream_getc(s); - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_METRIC)) - api.metric = stream_getl(s); - else - api.metric = 0; - - if (command == ZEBRA_REDISTRIBUTE_IPV4_ADD) { - if (BGP_DEBUG(zebra, ZEBRA)) { - char buf[2][INET_ADDRSTRLEN]; - vnc_zlog_debug_verbose( - "%s: Zebra rcvd: IPv4 route add %s %s/%d nexthop %s metric %u", - __func__, zebra_route_string(api.type), - inet_ntop(AF_INET, &p.prefix, buf[0], - sizeof(buf[0])), - p.prefixlen, inet_ntop(AF_INET, &nexthop, - buf[1], sizeof(buf[1])), - api.metric); - } - vnc_redistribute_add((struct prefix *)&p, &nexthop, api.metric, - api.type); - } else { - if (BGP_DEBUG(zebra, ZEBRA)) { - char buf[2][INET_ADDRSTRLEN]; - vnc_zlog_debug_verbose( - "%s: Zebra rcvd: IPv4 route delete %s %s/%d " - "nexthop %s metric %u", - __func__, zebra_route_string(api.type), - inet_ntop(AF_INET, &p.prefix, buf[0], - sizeof(buf[0])), - p.prefixlen, inet_ntop(AF_INET, &nexthop, - buf[1], sizeof(buf[1])), - api.metric); - } - vnc_redistribute_delete((struct prefix *)&p, api.type); - } - - return 0; -} - -/* Zebra route add and delete treatment. */ -static int vnc_zebra_read_ipv6(int command, struct zclient *zclient, - zebra_size_t length, vrf_id_t vrf_id) -{ - struct stream *s; - struct zapi_ipv6 api; - struct in6_addr nexthop; - struct prefix_ipv6 p, src_p; - - s = zclient->ibuf; - memset(&nexthop, 0, sizeof(struct in6_addr)); - - /* Type, flags, message. */ - api.type = stream_getc(s); - api.flags = stream_getc(s); - api.message = stream_getc(s); - - /* IPv6 prefix. */ - memset(&p, 0, sizeof(struct prefix_ipv6)); - p.family = AF_INET6; - p.prefixlen = stream_getc(s); - stream_get(&p.prefix, s, PSIZE(p.prefixlen)); - - memset(&src_p, 0, sizeof(struct prefix_ipv6)); - src_p.family = AF_INET6; - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX)) { - src_p.prefixlen = stream_getc(s); - stream_get(&src_p.prefix, s, PSIZE(src_p.prefixlen)); - } - - if (src_p.prefixlen) - /* we completely ignore srcdest routes for now. */ + /* we completely ignore srcdest routes for now. */ + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX)) return 0; - /* Nexthop, ifindex, distance, metric. */ - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP)) { - api.nexthop_num = stream_getc(s); - stream_get(&nexthop, s, 16); - } - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_IFINDEX)) { - api.ifindex_num = stream_getc(s); - stream_getl(s); - } - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_DISTANCE)) - api.distance = stream_getc(s); + add = (command == ZEBRA_REDISTRIBUTE_ROUTE_ADD); + if (add) + vnc_redistribute_add(&api.prefix, api.metric, api.type); else - api.distance = 0; - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_METRIC)) - api.metric = stream_getl(s); - else - api.metric = 0; + vnc_redistribute_delete(&api.prefix, api.type); - /* Simply ignore link-local address. */ - if (IN6_IS_ADDR_LINKLOCAL(&p.prefix)) - return 0; + if (BGP_DEBUG(zebra, ZEBRA)) { + char buf[PREFIX_STRLEN]; - if (command == ZEBRA_REDISTRIBUTE_IPV6_ADD) { - if (BGP_DEBUG(zebra, ZEBRA)) { - char buf[INET6_ADDRSTRLEN]; - vnc_zlog_debug_verbose( - "Zebra rcvd: IPv6 route add %s %s/%d metric %u", - zebra_route_string(api.type), - inet_ntop(AF_INET6, &p.prefix, buf, - sizeof(buf)), - p.prefixlen, api.metric); - } - vnc_redistribute_add((struct prefix *)&p, NULL, api.metric, - api.type); - } else { - if (BGP_DEBUG(zebra, ZEBRA)) { - char buf[INET6_ADDRSTRLEN]; - vnc_zlog_debug_verbose( - "Zebra rcvd: IPv6 route delete %s %s/%d metric %u", - zebra_route_string(api.type), - inet_ntop(AF_INET6, &p.prefix, buf, - sizeof(buf)), - p.prefixlen, api.metric); - } - vnc_redistribute_delete((struct prefix *)&p, api.type); + prefix2str(&api.prefix, buf, sizeof(buf)); + vnc_zlog_debug_verbose( + "%s: Zebra rcvd: route delete %s %s metric %u", + __func__, zebra_route_string(api.type), buf, + api.metric); } return 0; @@ -1016,10 +893,8 @@ void vnc_zebra_init(struct thread_master *master) zclient_vnc = zclient_new(master); zclient_init(zclient_vnc, ZEBRA_ROUTE_VNC, 0); - zclient_vnc->redistribute_route_ipv4_add = vnc_zebra_read_ipv4; - zclient_vnc->redistribute_route_ipv4_del = vnc_zebra_read_ipv4; - zclient_vnc->redistribute_route_ipv6_add = vnc_zebra_read_ipv6; - zclient_vnc->redistribute_route_ipv6_del = vnc_zebra_read_ipv6; + zclient_vnc->redistribute_route_add = vnc_zebra_read_route; + zclient_vnc->redistribute_route_del = vnc_zebra_read_route; } void vnc_zebra_destroy(void) diff --git a/eigrpd/eigrp_zebra.c b/eigrpd/eigrp_zebra.c index 2e386fbf2e..5aa7821e18 100644 --- a/eigrpd/eigrp_zebra.c +++ b/eigrpd/eigrp_zebra.c @@ -66,8 +66,8 @@ static int eigrp_interface_state_down(int, struct zclient *, zebra_size_t, vrf_id_t vrf_id); static struct interface *zebra_interface_if_lookup(struct stream *); -static int eigrp_zebra_read_ipv4(int, struct zclient *, zebra_size_t, - vrf_id_t vrf_id); +static int eigrp_zebra_read_route(int, struct zclient *, zebra_size_t, + vrf_id_t vrf_id); /* Zebra structure to hold current status. */ struct zclient *zclient = NULL; @@ -112,59 +112,31 @@ void eigrp_zebra_init(void) zclient->interface_down = eigrp_interface_state_down; zclient->interface_address_add = eigrp_interface_address_add; zclient->interface_address_delete = eigrp_interface_address_delete; - zclient->redistribute_route_ipv4_add = eigrp_zebra_read_ipv4; - zclient->redistribute_route_ipv4_del = eigrp_zebra_read_ipv4; + zclient->redistribute_route_add = eigrp_zebra_read_route; + zclient->redistribute_route_del = eigrp_zebra_read_route; } /* Zebra route add and delete treatment. */ -static int eigrp_zebra_read_ipv4(int command, struct zclient *zclient, - zebra_size_t length, vrf_id_t vrf_id) +static int eigrp_zebra_read_route(int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf_id) { - struct stream *s; - struct zapi_ipv4 api; - struct prefix_ipv4 p; + struct zapi_route api; struct eigrp *eigrp; - s = zclient->ibuf; + if (zapi_route_decode(zclient->ibuf, &api) < 0) + return -1; - /* Type, flags, message. */ - api.type = stream_getc(s); - api.instance = stream_getw(s); - api.flags = stream_getc(s); - api.message = stream_getc(s); - - /* IPv4 prefix. */ - memset(&p, 0, sizeof(struct prefix_ipv4)); - p.family = AF_INET; - p.prefixlen = MIN(IPV4_MAX_PREFIXLEN, stream_getc(s)); - stream_get(&p.prefix, s, PSIZE(p.prefixlen)); - - if (IPV4_NET127(ntohl(p.prefix.s_addr))) + if (IPV4_NET127(ntohl(api.prefix.u.prefix4.s_addr))) return 0; - /* Nexthop, ifindex, distance, metric. */ - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP)) { - api.nexthop_num = stream_getc(s); - stream_get_ipv4(s); - } - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_IFINDEX)) { - api.ifindex_num = stream_getc(s); - /* XXX assert(api.ifindex_num == 1); */ - stream_getl(s); /* ifindex, unused */ - } - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_DISTANCE)) - api.distance = stream_getc(s); - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_METRIC)) - api.metric = stream_getl(s); - eigrp = eigrp_lookup(); if (eigrp == NULL) return 0; - if (command == ZEBRA_REDISTRIBUTE_IPV4_ADD) { + if (command == ZEBRA_REDISTRIBUTE_ROUTE_ADD) { - } else /* if (command == ZEBRA_REDISTRIBUTE_IPV4_DEL) */ + } else /* if (command == ZEBRA_REDISTRIBUTE_ROUTE_DEL) */ { } diff --git a/isisd/isis_zebra.c b/isisd/isis_zebra.c index e3537e2a0c..ed96bd31c2 100644 --- a/isisd/isis_zebra.c +++ b/isisd/isis_zebra.c @@ -344,122 +344,32 @@ void isis_zebra_route_update(struct prefix *prefix, isis_zebra_route_del_route(prefix, route_info); } -static int isis_zebra_read_ipv4(int command, struct zclient *zclient, - zebra_size_t length, vrf_id_t vrf_id) +static int isis_zebra_read(int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf_id) { - struct stream *stream; - struct zapi_ipv4 api; - struct prefix_ipv4 p; - struct prefix *p_generic = (struct prefix *)&p; + struct zapi_route api; - stream = zclient->ibuf; - memset(&api, 0, sizeof(api)); - memset(&p, 0, sizeof(struct prefix_ipv4)); + if (zapi_route_decode(zclient->ibuf, &api) < 0) + return -1; - api.type = stream_getc(stream); - api.instance = stream_getw(stream); - api.flags = stream_getl(stream); - api.message = stream_getc(stream); - - p.family = AF_INET; - p.prefixlen = MIN(IPV4_MAX_PREFIXLEN, stream_getc(stream)); - stream_get(&p.prefix, stream, PSIZE(p.prefixlen)); - - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP)) { - api.nexthop_num = stream_getc(stream); - (void)stream_get_ipv4(stream); - } - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_IFINDEX)) { - api.ifindex_num = stream_getc(stream); - stream_getl(stream); - } - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_DISTANCE)) - api.distance = stream_getc(stream); - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_METRIC)) - api.metric = stream_getl(stream); - - /* - * Avoid advertising a false default reachability. (A default - * route installed by IS-IS gets redistributed from zebra back - * into IS-IS causing us to start advertising default reachabity - * without this check) - */ - if (p.prefixlen == 0 && api.type == ZEBRA_ROUTE_ISIS) - command = ZEBRA_REDISTRIBUTE_IPV4_DEL; - - if (command == ZEBRA_REDISTRIBUTE_IPV4_ADD) - isis_redist_add(api.type, p_generic, api.distance, api.metric); - else - isis_redist_delete(api.type, p_generic); - - return 0; -} - -static int isis_zebra_read_ipv6(int command, struct zclient *zclient, - zebra_size_t length, vrf_id_t vrf_id) -{ - struct stream *stream; - struct zapi_ipv6 api; - struct prefix_ipv6 p; - struct prefix src_p; - struct prefix *p_generic = (struct prefix *)&p; - struct in6_addr nexthop; - unsigned long ifindex __attribute__((unused)); - - stream = zclient->ibuf; - memset(&api, 0, sizeof(api)); - memset(&p, 0, sizeof(struct prefix_ipv6)); - memset(&nexthop, 0, sizeof(nexthop)); - ifindex = 0; - - api.type = stream_getc(stream); - api.instance = stream_getw(stream); - api.flags = stream_getl(stream); - api.message = stream_getc(stream); - - p.family = AF_INET6; - p.prefixlen = stream_getc(stream); - stream_get(&p.prefix, stream, PSIZE(p.prefixlen)); - - memset(&src_p, 0, sizeof(struct prefix)); - src_p.family = AF_INET6; - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX)) { - src_p.prefixlen = stream_getc(stream); - stream_get(&src_p.u.prefix6, stream, PSIZE(src_p.prefixlen)); - } - - if (src_p.prefixlen) - /* we completely ignore srcdest routes for now. */ + /* we completely ignore srcdest routes for now. */ + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX)) return 0; - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP)) { - api.nexthop_num = stream_getc(stream); /* this is always 1 */ - stream_get(&nexthop, stream, sizeof(nexthop)); - } - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_IFINDEX)) { - api.ifindex_num = stream_getc(stream); - ifindex = stream_getl(stream); - } - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_DISTANCE)) - api.distance = stream_getc(stream); - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_METRIC)) - api.metric = stream_getl(stream); - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_TAG)) - api.tag = stream_getl(stream); - /* * Avoid advertising a false default reachability. (A default * route installed by IS-IS gets redistributed from zebra back * into IS-IS causing us to start advertising default reachabity * without this check) */ - if (p.prefixlen == 0 && api.type == ZEBRA_ROUTE_ISIS) - command = ZEBRA_REDISTRIBUTE_IPV6_DEL; + if (api.prefix.prefixlen == 0 && api.type == ZEBRA_ROUTE_ISIS) + command = ZEBRA_REDISTRIBUTE_ROUTE_DEL; - if (command == ZEBRA_REDISTRIBUTE_IPV6_ADD) - isis_redist_add(api.type, p_generic, api.distance, api.metric); + if (command == ZEBRA_REDISTRIBUTE_ROUTE_ADD) + isis_redist_add(api.type, &api.prefix, api.distance, + api.metric); else - isis_redist_delete(api.type, p_generic); + isis_redist_delete(api.type, &api.prefix); return 0; } @@ -507,10 +417,8 @@ void isis_zebra_init(struct thread_master *master) zclient->interface_address_add = isis_zebra_if_address_add; zclient->interface_address_delete = isis_zebra_if_address_del; zclient->interface_link_params = isis_zebra_link_params; - zclient->redistribute_route_ipv4_add = isis_zebra_read_ipv4; - zclient->redistribute_route_ipv4_del = isis_zebra_read_ipv4; - zclient->redistribute_route_ipv6_add = isis_zebra_read_ipv6; - zclient->redistribute_route_ipv6_del = isis_zebra_read_ipv6; + zclient->redistribute_route_add = isis_zebra_read; + zclient->redistribute_route_del = isis_zebra_read; return; } diff --git a/ldpd/ldp_zebra.c b/ldpd/ldp_zebra.c index 54c5af62a4..c50cc0fda2 100644 --- a/ldpd/ldp_zebra.c +++ b/ldpd/ldp_zebra.c @@ -396,19 +396,34 @@ static int ldp_zebra_read_route(int command, struct zclient *zclient, zebra_size_t length, vrf_id_t vrf_id) { - struct stream *s; - u_char type; - u_char message_flags; + struct zapi_route api; + struct zapi_nexthop *api_nh; struct kroute kr; - int nhnum = 0, nhlen; - size_t nhmark; - int add = 0; + int i, add = 0; + + if (zapi_route_decode(zclient->ibuf, &api) < 0) + return -1; + + /* we completely ignore srcdest routes for now. */ + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX)) + return (0); memset(&kr, 0, sizeof(kr)); - s = zclient->ibuf; + kr.af = api.prefix.family; + switch (kr.af) { + case AF_INET: + kr.prefix.v4 = api.prefix.u.prefix4; + break; + case AF_INET6: + kr.prefix.v6 = api.prefix.u.prefix6; + break; + default: + break; + } + kr.prefixlen = api.prefix.prefixlen; + kr.priority = api.distance; - type = stream_getc(s); - switch (type) { + switch (api.type) { case ZEBRA_ROUTE_CONNECT: kr.flags |= F_CONNECTED; break; @@ -419,85 +434,38 @@ ldp_zebra_read_route(int command, struct zclient *zclient, zebra_size_t length, break; } - stream_getl(s); /* flags, unused */ - stream_getw(s); /* instance, unused */ - message_flags = stream_getc(s); - - switch (command) { - case ZEBRA_REDISTRIBUTE_IPV4_ADD: - case ZEBRA_REDISTRIBUTE_IPV4_DEL: - kr.af = AF_INET; - kr.prefixlen = MIN(IPV4_MAX_PREFIXLEN, stream_getc(s)); - nhlen = sizeof(struct in_addr); - break; - case ZEBRA_REDISTRIBUTE_IPV6_ADD: - case ZEBRA_REDISTRIBUTE_IPV6_DEL: - kr.af = AF_INET6; - kr.prefixlen = MIN(IPV6_MAX_PREFIXLEN, stream_getc(s)); - nhlen = sizeof(struct in6_addr); - break; - default: - fatalx("ldp_zebra_read_route: unknown command"); - } - stream_get(&kr.prefix, s, PSIZE(kr.prefixlen)); - if (bad_addr(kr.af, &kr.prefix) || (kr.af == AF_INET6 && IN6_IS_SCOPE_EMBED(&kr.prefix.v6))) return (0); - if (kr.af == AF_INET6 && - CHECK_FLAG(message_flags, ZAPI_MESSAGE_SRCPFX)) { - uint8_t src_prefixlen; - - src_prefixlen = stream_getc(s); - - /* we completely ignore srcdest routes for now. */ - if (src_prefixlen) - return (0); - } - - if (CHECK_FLAG(message_flags, ZAPI_MESSAGE_NEXTHOP)) { - nhnum = stream_getc(s); - nhmark = stream_get_getp(s); - stream_set_getp(s, nhmark + nhnum * (nhlen + 5)); - } - - if (CHECK_FLAG(message_flags, ZAPI_MESSAGE_DISTANCE)) - kr.priority = stream_getc(s); - if (CHECK_FLAG(message_flags, ZAPI_MESSAGE_METRIC)) - stream_getl(s); /* metric, not used */ - - if (CHECK_FLAG(message_flags, ZAPI_MESSAGE_NEXTHOP)) - stream_set_getp(s, nhmark); - - if (command == ZEBRA_REDISTRIBUTE_IPV4_ADD || - command == ZEBRA_REDISTRIBUTE_IPV6_ADD) + if (command == ZEBRA_REDISTRIBUTE_ROUTE_ADD) add = 1; - if (nhnum == 0) + if (api.nexthop_num == 0) debug_zebra_in("route %s %s/%d (%s)", (add) ? "add" : "delete", log_addr(kr.af, &kr.prefix), kr.prefixlen, - zebra_route_string(type)); + zebra_route_string(api.type)); /* loop through all the nexthops */ - for (; nhnum > 0; nhnum--) { + for (i = 0; i < api.nexthop_num; i++) { + api_nh = &api.nexthops[i]; + switch (kr.af) { case AF_INET: - kr.nexthop.v4.s_addr = stream_get_ipv4(s); + kr.nexthop.v4 = api_nh->gate.ipv4; break; case AF_INET6: - stream_get(&kr.nexthop.v6, s, sizeof(kr.nexthop.v6)); + kr.nexthop.v6 = api_nh->gate.ipv6; break; default: break; } - stream_getc(s); /* ifindex_num, unused. */ - kr.ifindex = stream_getl(s); + kr.ifindex = api_nh->ifindex;; debug_zebra_in("route %s %s/%d nexthop %s ifindex %u (%s)", (add) ? "add" : "delete", log_addr(kr.af, &kr.prefix), kr.prefixlen, log_addr(kr.af, &kr.nexthop), kr.ifindex, - zebra_route_string(type)); + zebra_route_string(api.type)); if (add) main_imsg_compose_lde(IMSG_NETWORK_ADD, 0, &kr, @@ -554,10 +522,8 @@ ldp_zebra_init(struct thread_master *master) zclient->interface_down = ldp_interface_status_change; zclient->interface_address_add = ldp_interface_address_add; zclient->interface_address_delete = ldp_interface_address_delete; - zclient->redistribute_route_ipv4_add = ldp_zebra_read_route; - zclient->redistribute_route_ipv4_del = ldp_zebra_read_route; - zclient->redistribute_route_ipv6_add = ldp_zebra_read_route; - zclient->redistribute_route_ipv6_del = ldp_zebra_read_route; + zclient->redistribute_route_add = ldp_zebra_read_route; + zclient->redistribute_route_del = ldp_zebra_read_route; zclient->pw_status_update = ldp_zebra_read_pw_status_update; } diff --git a/lib/log.c b/lib/log.c index 92b2d3b66b..0ea52ed401 100644 --- a/lib/log.c +++ b/lib/log.c @@ -895,10 +895,8 @@ static const struct zebra_desc_table command_types[] = { DESC_ENTRY(ZEBRA_BFD_DEST_DEREGISTER), DESC_ENTRY(ZEBRA_BFD_DEST_UPDATE), DESC_ENTRY(ZEBRA_BFD_DEST_REPLAY), - DESC_ENTRY(ZEBRA_REDISTRIBUTE_IPV4_ADD), - DESC_ENTRY(ZEBRA_REDISTRIBUTE_IPV4_DEL), - DESC_ENTRY(ZEBRA_REDISTRIBUTE_IPV6_ADD), - DESC_ENTRY(ZEBRA_REDISTRIBUTE_IPV6_DEL), + DESC_ENTRY(ZEBRA_REDISTRIBUTE_ROUTE_ADD), + DESC_ENTRY(ZEBRA_REDISTRIBUTE_ROUTE_DEL), DESC_ENTRY(ZEBRA_VRF_UNREGISTER), DESC_ENTRY(ZEBRA_VRF_ADD), DESC_ENTRY(ZEBRA_VRF_DELETE), diff --git a/lib/zclient.c b/lib/zclient.c index e063c7151f..75005d656b 100644 --- a/lib/zclient.c +++ b/lib/zclient.c @@ -2112,25 +2112,15 @@ static int zclient_read(struct thread *thread) (*zclient->bfd_dest_replay)(command, zclient, length, vrf_id); break; - case ZEBRA_REDISTRIBUTE_IPV4_ADD: - if (zclient->redistribute_route_ipv4_add) - (*zclient->redistribute_route_ipv4_add)( - command, zclient, length, vrf_id); + case ZEBRA_REDISTRIBUTE_ROUTE_ADD: + if (zclient->redistribute_route_add) + (*zclient->redistribute_route_add)(command, zclient, + length, vrf_id); break; - case ZEBRA_REDISTRIBUTE_IPV4_DEL: - if (zclient->redistribute_route_ipv4_del) - (*zclient->redistribute_route_ipv4_del)( - command, zclient, length, vrf_id); - break; - case ZEBRA_REDISTRIBUTE_IPV6_ADD: - if (zclient->redistribute_route_ipv6_add) - (*zclient->redistribute_route_ipv6_add)( - command, zclient, length, vrf_id); - break; - case ZEBRA_REDISTRIBUTE_IPV6_DEL: - if (zclient->redistribute_route_ipv6_del) - (*zclient->redistribute_route_ipv6_del)( - command, zclient, length, vrf_id); + case ZEBRA_REDISTRIBUTE_ROUTE_DEL: + if (zclient->redistribute_route_del) + (*zclient->redistribute_route_del)(command, zclient, + length, vrf_id); break; case ZEBRA_INTERFACE_LINK_PARAMS: if (zclient->interface_link_params) diff --git a/lib/zclient.h b/lib/zclient.h index 40ddbf62df..f454a9d8ac 100644 --- a/lib/zclient.h +++ b/lib/zclient.h @@ -21,7 +21,7 @@ #ifndef _ZEBRA_ZCLIENT_H #define _ZEBRA_ZCLIENT_H -/* For struct zapi_ipv{4,6}. */ +/* For struct zapi_route. */ #include "prefix.h" /* For struct interface and struct connected. */ @@ -87,10 +87,8 @@ typedef enum { ZEBRA_BFD_DEST_DEREGISTER, ZEBRA_BFD_DEST_UPDATE, ZEBRA_BFD_DEST_REPLAY, - ZEBRA_REDISTRIBUTE_IPV4_ADD, - ZEBRA_REDISTRIBUTE_IPV4_DEL, - ZEBRA_REDISTRIBUTE_IPV6_ADD, - ZEBRA_REDISTRIBUTE_IPV6_DEL, + ZEBRA_REDISTRIBUTE_ROUTE_ADD, + ZEBRA_REDISTRIBUTE_ROUTE_DEL, ZEBRA_VRF_UNREGISTER, ZEBRA_VRF_ADD, ZEBRA_VRF_DELETE, @@ -188,14 +186,10 @@ struct zclient { int (*nexthop_update)(int, struct zclient *, uint16_t, vrf_id_t); int (*import_check_update)(int, struct zclient *, uint16_t, vrf_id_t); int (*bfd_dest_replay)(int, struct zclient *, uint16_t, vrf_id_t); - int (*redistribute_route_ipv4_add)(int, struct zclient *, uint16_t, - vrf_id_t); - int (*redistribute_route_ipv4_del)(int, struct zclient *, uint16_t, - vrf_id_t); - int (*redistribute_route_ipv6_add)(int, struct zclient *, uint16_t, - vrf_id_t); - int (*redistribute_route_ipv6_del)(int, struct zclient *, uint16_t, - vrf_id_t); + int (*redistribute_route_add)(int, struct zclient *, uint16_t, + vrf_id_t); + int (*redistribute_route_del)(int, struct zclient *, uint16_t, + vrf_id_t); int (*fec_update)(int, struct zclient *, uint16_t); int (*local_vni_add)(int, struct zclient *, uint16_t, vrf_id_t); int (*local_vni_del)(int, struct zclient *, uint16_t, vrf_id_t); @@ -206,13 +200,12 @@ struct zclient { /* Zebra API message flag. */ #define ZAPI_MESSAGE_NEXTHOP 0x01 -#define ZAPI_MESSAGE_IFINDEX 0x02 -#define ZAPI_MESSAGE_DISTANCE 0x04 -#define ZAPI_MESSAGE_METRIC 0x08 -#define ZAPI_MESSAGE_TAG 0x10 -#define ZAPI_MESSAGE_MTU 0x20 -#define ZAPI_MESSAGE_SRCPFX 0x40 -#define ZAPI_MESSAGE_LABEL 0x80 +#define ZAPI_MESSAGE_DISTANCE 0x02 +#define ZAPI_MESSAGE_METRIC 0x04 +#define ZAPI_MESSAGE_TAG 0x08 +#define ZAPI_MESSAGE_MTU 0x10 +#define ZAPI_MESSAGE_SRCPFX 0x20 +#define ZAPI_MESSAGE_LABEL 0x40 /* Zserv protocol message header */ struct zserv_header { diff --git a/nhrpd/nhrp_route.c b/nhrpd/nhrp_route.c index b744218c9a..4b86bca5f7 100644 --- a/nhrpd/nhrp_route.c +++ b/nhrpd/nhrp_route.c @@ -167,83 +167,47 @@ void nhrp_route_announce(int add, enum nhrp_cache_type type, const struct prefix int nhrp_route_read(int cmd, struct zclient *zclient, zebra_size_t length, vrf_id_t vrf_id) { - struct stream *s; + struct zapi_route api; + struct zapi_nexthop *api_nh; struct interface *ifp = NULL; - struct prefix prefix; - struct prefix_ipv6 src_p; union sockunion nexthop_addr; - unsigned char message, nexthop_num, ifindex_num; - unsigned ifindex; char buf[2][PREFIX_STRLEN]; - int i, afaddrlen, added; + int added; - s = zclient->ibuf; - memset(&prefix, 0, sizeof(prefix)); - sockunion_family(&nexthop_addr) = AF_UNSPEC; - - /* Type, flags, message. */ - /*type =*/ stream_getc(s); - /*instance =*/ stream_getw(s); - /*flags =*/ stream_getl(s); - message = stream_getc(s); - - /* Prefix */ - switch (cmd) { - case ZEBRA_REDISTRIBUTE_IPV4_ADD: - case ZEBRA_REDISTRIBUTE_IPV4_DEL: - prefix.family = AF_INET; - prefix.prefixlen = MIN(IPV4_MAX_PREFIXLEN, stream_getc(s)); - break; - case ZEBRA_REDISTRIBUTE_IPV6_ADD: - case ZEBRA_REDISTRIBUTE_IPV6_DEL: - prefix.family = AF_INET6; - prefix.prefixlen = MIN(IPV6_MAX_PREFIXLEN, stream_getc(s)); - break; - default: + if (zapi_route_decode(zclient->ibuf, &api) < 0) return -1; - } - afaddrlen = family2addrsize(prefix.family); - stream_get(&prefix.u.val, s, PSIZE(prefix.prefixlen)); - memset(&src_p, 0, sizeof(src_p)); - if (prefix.family == AF_INET6 && - CHECK_FLAG(message, ZAPI_MESSAGE_SRCPFX)) { - src_p.family = AF_INET6; - src_p.prefixlen = stream_getc(s); - stream_get(&src_p.prefix, s, PSIZE(src_p.prefixlen)); - } - if (src_p.prefixlen) - /* we completely ignore srcdest routes for now. */ + /* we completely ignore srcdest routes for now. */ + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX)) return 0; - /* Nexthop, ifindex, distance, metric. */ - if (CHECK_FLAG(message, ZAPI_MESSAGE_NEXTHOP|ZAPI_MESSAGE_IFINDEX)) { - nexthop_num = stream_getc(s); - for (i = 0; i < nexthop_num; i++) { - stream_get(buf[0], s, afaddrlen); - if (i == 0) sockunion_set(&nexthop_addr, prefix.family, (u_char*) buf[0], afaddrlen); - } - ifindex_num = stream_getc(s); - for (i = 0; i < ifindex_num; i++) { - ifindex = stream_getl(s); - if (i == 0 && ifindex != IFINDEX_INTERNAL) - ifp = if_lookup_by_index(ifindex, VRF_DEFAULT); - } - } - if (CHECK_FLAG(message, ZAPI_MESSAGE_DISTANCE)) - /*distance =*/ stream_getc(s); - if (CHECK_FLAG(message, ZAPI_MESSAGE_METRIC)) - /*metric =*/ stream_getl(s); + sockunion_family(&nexthop_addr) = AF_UNSPEC; + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP)) { + api_nh = &api.nexthops[0]; - added = (cmd == ZEBRA_REDISTRIBUTE_IPV4_ADD || cmd == ZEBRA_REDISTRIBUTE_IPV6_ADD); + nexthop_addr.sa.sa_family = api.prefix.family; + switch (nexthop_addr.sa.sa_family) { + case AF_INET: + nexthop_addr.sin.sin_addr = api_nh->gate.ipv4; + break; + case AF_INET6: + nexthop_addr.sin6.sin6_addr = api_nh->gate.ipv6; + break; + } + + if (api_nh->ifindex != IFINDEX_INTERNAL) + ifp = if_lookup_by_index(api_nh->ifindex, VRF_DEFAULT); + } + + added = (cmd == ZEBRA_REDISTRIBUTE_ROUTE_ADD); debugf(NHRP_DEBUG_ROUTE, "if-route-%s: %s via %s dev %s", added ? "add" : "del", - prefix2str(&prefix, buf[0], sizeof buf[0]), + prefix2str(&api.prefix, buf[0], sizeof buf[0]), sockunion2str(&nexthop_addr, buf[1], sizeof buf[1]), ifp ? ifp->name : "(none)"); - nhrp_route_update_zebra(&prefix, &nexthop_addr, ifp); - nhrp_shortcut_prefix_change(&prefix, !added); + nhrp_route_update_zebra(&api.prefix, &nexthop_addr, ifp); + nhrp_shortcut_prefix_change(&api.prefix, !added); return 0; } @@ -356,10 +320,8 @@ void nhrp_zebra_init(void) zclient->interface_down = nhrp_interface_down; zclient->interface_address_add = nhrp_interface_address_add; zclient->interface_address_delete = nhrp_interface_address_delete; - zclient->redistribute_route_ipv4_add = nhrp_route_read; - zclient->redistribute_route_ipv4_del = nhrp_route_read; - zclient->redistribute_route_ipv6_add = nhrp_route_read; - zclient->redistribute_route_ipv6_del = nhrp_route_read; + zclient->redistribute_route_add = nhrp_route_read; + zclient->redistribute_route_del = nhrp_route_read; zclient_init(zclient, ZEBRA_ROUTE_NHRP, 0); } @@ -371,4 +333,3 @@ void nhrp_zebra_terminate(void) route_table_finish(zebra_rib[AFI_IP]); route_table_finish(zebra_rib[AFI_IP6]); } - diff --git a/ospf6d/ospf6_zebra.c b/ospf6d/ospf6_zebra.c index 5655502879..3443bc47b6 100644 --- a/ospf6d/ospf6_zebra.c +++ b/ospf6d/ospf6_zebra.c @@ -207,75 +207,30 @@ static int ospf6_zebra_if_address_update_delete(int command, return 0; } -static int ospf6_zebra_read_ipv6(int command, struct zclient *zclient, - zebra_size_t length, vrf_id_t vrf_id) +static int ospf6_zebra_read_route(int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf_id) { - struct stream *s; - struct zapi_ipv6 api; + struct zapi_route api; unsigned long ifindex; - struct prefix p, src_p; struct in6_addr *nexthop; if (ospf6 == NULL) return 0; - s = zclient->ibuf; - ifindex = 0; - nexthop = NULL; - memset(&api, 0, sizeof(api)); + if (zapi_route_decode(zclient->ibuf, &api) < 0) + return -1; - /* Type, flags, message. */ - api.type = stream_getc(s); - api.instance = stream_getw(s); - api.flags = stream_getl(s); - api.message = stream_getc(s); - - /* IPv6 prefix. */ - memset(&p, 0, sizeof(struct prefix)); - p.family = AF_INET6; - p.prefixlen = MIN(IPV6_MAX_PREFIXLEN, stream_getc(s)); - stream_get(&p.u.prefix6, s, PSIZE(p.prefixlen)); - - memset(&src_p, 0, sizeof(struct prefix)); - src_p.family = AF_INET6; - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX)) { - src_p.prefixlen = stream_getc(s); - stream_get(&src_p.u.prefix6, s, PSIZE(src_p.prefixlen)); - } - - if (src_p.prefixlen) - /* we completely ignore srcdest routes for now. */ + /* we completely ignore srcdest routes for now. */ + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX)) return 0; - /* Nexthop, ifindex, distance, metric. */ - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP)) { - api.nexthop_num = stream_getc(s); - nexthop = (struct in6_addr *)malloc(api.nexthop_num - * sizeof(struct in6_addr)); - stream_get(nexthop, s, - api.nexthop_num * sizeof(struct in6_addr)); - } - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_IFINDEX)) { - api.ifindex_num = stream_getc(s); - ifindex = stream_getl(s); - } - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_DISTANCE)) - api.distance = stream_getc(s); - else - api.distance = 0; - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_METRIC)) - api.metric = stream_getl(s); - else - api.metric = 0; - - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_TAG)) - api.tag = stream_getl(s); - else - api.tag = 0; + ifindex = api.nexthops[0].ifindex; + nexthop = &api.nexthops[0].gate.ipv6; if (IS_OSPF6_DEBUG_ZEBRA(RECV)) { char prefixstr[PREFIX2STR_BUFFER], nexthopstr[128]; - prefix2str((struct prefix *)&p, prefixstr, sizeof(prefixstr)); + prefix2str((struct prefix *)&api.prefix, prefixstr, + sizeof(prefixstr)); if (nexthop) inet_ntop(AF_INET6, nexthop, nexthopstr, sizeof(nexthopstr)); @@ -284,20 +239,17 @@ static int ospf6_zebra_read_ipv6(int command, struct zclient *zclient, zlog_debug( "Zebra Receive route %s: %s %s nexthop %s ifindex %ld tag %" ROUTE_TAG_PRI, - (command == ZEBRA_REDISTRIBUTE_IPV6_ADD ? "add" - : "delete"), + (command == ZEBRA_REDISTRIBUTE_ROUTE_ADD ? "add" + : "delete"), zebra_route_string(api.type), prefixstr, nexthopstr, ifindex, api.tag); } - if (command == ZEBRA_REDISTRIBUTE_IPV6_ADD) - ospf6_asbr_redistribute_add(api.type, ifindex, &p, + if (command == ZEBRA_REDISTRIBUTE_ROUTE_ADD) + ospf6_asbr_redistribute_add(api.type, ifindex, &api.prefix, api.nexthop_num, nexthop, api.tag); else - ospf6_asbr_redistribute_remove(api.type, ifindex, &p); - - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP)) - free(nexthop); + ospf6_asbr_redistribute_remove(api.type, ifindex, &api.prefix); return 0; } @@ -646,10 +598,8 @@ void ospf6_zebra_init(struct thread_master *master) zclient->interface_address_add = ospf6_zebra_if_address_update_add; zclient->interface_address_delete = ospf6_zebra_if_address_update_delete; - zclient->redistribute_route_ipv4_add = NULL; - zclient->redistribute_route_ipv4_del = NULL; - zclient->redistribute_route_ipv6_add = ospf6_zebra_read_ipv6; - zclient->redistribute_route_ipv6_del = ospf6_zebra_read_ipv6; + zclient->redistribute_route_add = ospf6_zebra_read_route; + zclient->redistribute_route_del = ospf6_zebra_read_route; /* Install command element for zebra node. */ install_element(VIEW_NODE, &show_ospf6_zebra_cmd); diff --git a/ospfd/ospf_zebra.c b/ospfd/ospf_zebra.c index 53b68a022b..dcb392f1ad 100644 --- a/ospfd/ospf_zebra.c +++ b/ospfd/ospf_zebra.c @@ -873,61 +873,32 @@ void ospf_routemap_unset(struct ospf_redist *red) } /* Zebra route add and delete treatment. */ -static int ospf_zebra_read_ipv4(int command, struct zclient *zclient, - zebra_size_t length, vrf_id_t vrf_id) +static int ospf_zebra_read_route(int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf_id) { - struct stream *s; - struct zapi_ipv4 api; + struct zapi_route api; + struct prefix_ipv4 p; unsigned long ifindex; struct in_addr nexthop; - struct prefix_ipv4 p; struct external_info *ei; struct ospf *ospf; int i; - s = zclient->ibuf; - ifindex = 0; - nexthop.s_addr = 0; - - /* Type, flags, message. */ - api.type = stream_getc(s); - api.instance = stream_getw(s); - api.flags = stream_getl(s); - api.message = stream_getc(s); - - /* IPv4 prefix. */ - memset(&p, 0, sizeof(struct prefix_ipv4)); - p.family = AF_INET; - p.prefixlen = MIN(IPV4_MAX_PREFIXLEN, stream_getc(s)); - stream_get(&p.prefix, s, PSIZE(p.prefixlen)); - - if (IPV4_NET127(ntohl(p.prefix.s_addr))) - return 0; - - /* Nexthop, ifindex, distance, metric. */ - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP)) { - api.nexthop_num = stream_getc(s); - nexthop.s_addr = stream_get_ipv4(s); - } - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_IFINDEX)) { - api.ifindex_num = stream_getc(s); - /* XXX assert(api.ifindex_num == 1); */ - ifindex = stream_getl(s); - } - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_DISTANCE)) - api.distance = stream_getc(s); - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_METRIC)) - api.metric = stream_getl(s); - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_TAG)) - api.tag = stream_getl(s); - else - api.tag = 0; - ospf = ospf_lookup(); if (ospf == NULL) return 0; - if (command == ZEBRA_REDISTRIBUTE_IPV4_ADD) { + if (zapi_route_decode(zclient->ibuf, &api) < 0) + return -1; + + ifindex = api.nexthops[0].ifindex; + nexthop = api.nexthops[0].gate.ipv4; + + memcpy(&p, &api.prefix, sizeof(p)); + if (IPV4_NET127(ntohl(p.prefix.s_addr))) + return 0; + + if (command == ZEBRA_REDISTRIBUTE_ROUTE_ADD) { /* XXX|HACK|TODO|FIXME: * Maybe we should ignore reject/blackhole routes? Testing shows * that @@ -942,7 +913,7 @@ static int ospf_zebra_read_ipv4(int command, struct zclient *zclient, * return 0; */ - /* Protocol tag overwrites all other tag value send by zebra */ + /* Protocol tag overwrites all other tag value sent by zebra */ if (ospf->dtag[api.type] > 0) api.tag = ospf->dtag[api.type]; @@ -984,7 +955,7 @@ static int ospf_zebra_read_ipv4(int command, struct zclient *zclient, zebra, ZEBRA_REDISTRIBUTE)) zlog_debug( - "ospf_zebra_read_ipv4() : %s refreshing LSA", + "ospf_zebra_read_route() : %s refreshing LSA", inet_ntoa( p.prefix)); ospf_external_lsa_refresh( @@ -994,7 +965,7 @@ static int ospf_zebra_read_ipv4(int command, struct zclient *zclient, } } } - } else /* if (command == ZEBRA_REDISTRIBUTE_IPV4_DEL) */ + } else /* if (command == ZEBRA_REDISTRIBUTE_ROUTE_DEL) */ { ospf_external_info_delete(api.type, api.instance, p); if (is_prefix_default(&p)) @@ -1410,8 +1381,8 @@ void ospf_zebra_init(struct thread_master *master, u_short instance) zclient->interface_address_delete = ospf_interface_address_delete; zclient->interface_link_params = ospf_interface_link_params; - zclient->redistribute_route_ipv4_add = ospf_zebra_read_ipv4; - zclient->redistribute_route_ipv4_del = ospf_zebra_read_ipv4; + zclient->redistribute_route_add = ospf_zebra_read_route; + zclient->redistribute_route_del = ospf_zebra_read_route; access_list_add_hook(ospf_filter_update); access_list_delete_hook(ospf_filter_update); diff --git a/ripd/rip_zebra.c b/ripd/rip_zebra.c index 9a9bac51e0..2140e8b110 100644 --- a/ripd/rip_zebra.c +++ b/ripd/rip_zebra.c @@ -115,64 +115,31 @@ void rip_zebra_ipv4_delete(struct route_node *rp) } /* Zebra route add and delete treatment. */ -static int rip_zebra_read_ipv4(int command, struct zclient *zclient, - zebra_size_t length, vrf_id_t vrf_id) +static int rip_zebra_read_route(int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf_id) { - struct stream *s; - struct zapi_ipv4 api; - unsigned long ifindex; + struct zapi_route api; struct in_addr nexthop; - struct prefix_ipv4 p; + unsigned long ifindex; if (!rip) return 0; - s = zclient->ibuf; - ifindex = 0; - nexthop.s_addr = 0; + if (zapi_route_decode(zclient->ibuf, &api) < 0) + return -1; - /* Type, flags, message. */ - api.type = stream_getc(s); - api.instance = stream_getw(s); - api.flags = stream_getl(s); - api.message = stream_getc(s); - - /* IPv4 prefix. */ - memset(&p, 0, sizeof(struct prefix_ipv4)); - p.family = AF_INET; - p.prefixlen = MIN(IPV4_MAX_PREFIXLEN, stream_getc(s)); - stream_get(&p.prefix, s, PSIZE(p.prefixlen)); - - /* Nexthop, ifindex, distance, metric. */ - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP)) { - api.nexthop_num = stream_getc(s); - nexthop.s_addr = stream_get_ipv4(s); - } - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_IFINDEX)) { - api.ifindex_num = stream_getc(s); - ifindex = stream_getl(s); - } - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_DISTANCE)) - api.distance = stream_getc(s); - else - api.distance = 255; - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_METRIC)) - api.metric = stream_getl(s); - else - api.metric = 0; - - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_TAG)) - api.tag = stream_getl(s); - else - api.tag = 0; + nexthop = api.nexthops[0].gate.ipv4; + ifindex = api.nexthops[0].ifindex; /* Then fetch IPv4 prefixes. */ - if (command == ZEBRA_REDISTRIBUTE_IPV4_ADD) - rip_redistribute_add(api.type, RIP_ROUTE_REDISTRIBUTE, &p, - ifindex, &nexthop, api.metric, - api.distance, api.tag); - else if (command == ZEBRA_REDISTRIBUTE_IPV4_DEL) - rip_redistribute_delete(api.type, RIP_ROUTE_REDISTRIBUTE, &p, + if (command == ZEBRA_REDISTRIBUTE_ROUTE_ADD) + rip_redistribute_add(api.type, RIP_ROUTE_REDISTRIBUTE, + (struct prefix_ipv4 *)&api.prefix, ifindex, + &nexthop, api.metric, api.distance, + api.tag); + else if (command == ZEBRA_REDISTRIBUTE_ROUTE_DEL) + rip_redistribute_delete(api.type, RIP_ROUTE_REDISTRIBUTE, + (struct prefix_ipv4 *)&api.prefix, ifindex); return 0; @@ -625,8 +592,8 @@ void rip_zclient_init(struct thread_master *master) zclient->interface_address_delete = rip_interface_address_delete; zclient->interface_up = rip_interface_up; zclient->interface_down = rip_interface_down; - zclient->redistribute_route_ipv4_add = rip_zebra_read_ipv4; - zclient->redistribute_route_ipv4_del = rip_zebra_read_ipv4; + zclient->redistribute_route_add = rip_zebra_read_route; + zclient->redistribute_route_del = rip_zebra_read_route; /* Install command elements to rip node. */ install_element(RIP_NODE, &rip_redistribute_type_cmd); diff --git a/ripngd/ripng_zebra.c b/ripngd/ripng_zebra.c index a5ed5c7b2c..283d8691a3 100644 --- a/ripngd/ripng_zebra.c +++ b/ripngd/ripng_zebra.c @@ -109,71 +109,31 @@ void ripng_zebra_ipv6_delete(struct route_node *rp) } /* Zebra route add and delete treatment. */ -static int ripng_zebra_read_ipv6(int command, struct zclient *zclient, - zebra_size_t length, vrf_id_t vrf_id) +static int ripng_zebra_read_route(int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf_id) { - struct stream *s; - struct zapi_ipv6 api; - unsigned long ifindex; + struct zapi_route api; struct in6_addr nexthop; - struct prefix_ipv6 p, src_p; + unsigned long ifindex; - s = zclient->ibuf; - ifindex = 0; - memset(&nexthop, 0, sizeof(struct in6_addr)); + if (zapi_route_decode(zclient->ibuf, &api) < 0) + return -1; - /* Type, flags, message. */ - api.type = stream_getc(s); - api.instance = stream_getw(s); - api.flags = stream_getl(s); - api.message = stream_getc(s); - - /* IPv6 prefix. */ - memset(&p, 0, sizeof(struct prefix_ipv6)); - p.family = AF_INET6; - p.prefixlen = MIN(IPV6_MAX_PREFIXLEN, stream_getc(s)); - stream_get(&p.prefix, s, PSIZE(p.prefixlen)); - - memset(&src_p, 0, sizeof(struct prefix_ipv6)); - src_p.family = AF_INET6; - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX)) { - src_p.prefixlen = stream_getc(s); - stream_get(&src_p.prefix, s, PSIZE(src_p.prefixlen)); - } - - if (src_p.prefixlen) - /* we completely ignore srcdest routes for now. */ + /* we completely ignore srcdest routes for now. */ + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX)) return 0; - /* Nexthop, ifindex, distance, metric. */ - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP)) { - api.nexthop_num = stream_getc(s); - stream_get(&nexthop, s, 16); - } - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_IFINDEX)) { - api.ifindex_num = stream_getc(s); - ifindex = stream_getl(s); - } - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_DISTANCE)) - api.distance = stream_getc(s); - else - api.distance = 0; - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_METRIC)) - api.metric = stream_getl(s); - else - api.metric = 0; + nexthop = api.nexthops[0].gate.ipv6; + ifindex = api.nexthops[0].ifindex; - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_TAG)) - api.tag = stream_getl(s); - else - api.tag = 0; - - if (command == ZEBRA_REDISTRIBUTE_IPV6_ADD) - ripng_redistribute_add(api.type, RIPNG_ROUTE_REDISTRIBUTE, &p, + if (command == ZEBRA_REDISTRIBUTE_ROUTE_ADD) + ripng_redistribute_add(api.type, RIPNG_ROUTE_REDISTRIBUTE, + (struct prefix_ipv6 *)&api.prefix, ifindex, &nexthop, api.tag); else ripng_redistribute_delete(api.type, RIPNG_ROUTE_REDISTRIBUTE, - &p, ifindex); + (struct prefix_ipv6 *)&api.prefix, + ifindex); return 0; } @@ -461,8 +421,8 @@ void zebra_init(struct thread_master *master) zclient->interface_delete = ripng_interface_delete; zclient->interface_address_add = ripng_interface_address_add; zclient->interface_address_delete = ripng_interface_address_delete; - zclient->redistribute_route_ipv6_add = ripng_zebra_read_ipv6; - zclient->redistribute_route_ipv6_del = ripng_zebra_read_ipv6; + zclient->redistribute_route_add = ripng_zebra_read_route; + zclient->redistribute_route_del = ripng_zebra_read_route; /* Install command elements to ripng node */ install_element(RIPNG_NODE, &ripng_redistribute_type_cmd); diff --git a/zebra/redistribute.c b/zebra/redistribute.c index 410ddcd4a0..9b21eb4d8c 100644 --- a/zebra/redistribute.c +++ b/zebra/redistribute.c @@ -95,8 +95,8 @@ static void zebra_redistribute_default(struct zserv *client, vrf_id_t vrf_id) RNODE_FOREACH_RE(rn, newre) if (CHECK_FLAG(newre->flags, ZEBRA_FLAG_SELECTED) && newre->distance != DISTANCE_INFINITY) - zsend_redistribute_route(1, client, &rn->p, NULL, - newre); + zsend_redistribute_route(ZEBRA_REDISTRIBUTE_ROUTE_ADD, + client, &rn->p, NULL, newre); route_unlock_node(rn); } @@ -141,8 +141,8 @@ static void zebra_redistribute(struct zserv *client, int type, u_short instance, if (!zebra_check_addr(dst_p)) continue; - zsend_redistribute_route(1, client, dst_p, src_p, - newre); + zsend_redistribute_route(ZEBRA_REDISTRIBUTE_ROUTE_ADD, + client, dst_p, src_p, newre); } } @@ -191,7 +191,8 @@ void redistribute_update(struct prefix *p, struct prefix *src_p, send_redistribute = 1; if (send_redistribute) { - zsend_redistribute_route(1, client, p, src_p, re); + zsend_redistribute_route(ZEBRA_REDISTRIBUTE_ROUTE_ADD, + client, p, src_p, re); } else if (prev_re && ((re->instance && redist_check_instance( @@ -201,7 +202,8 @@ void redistribute_update(struct prefix *p, struct prefix *src_p, || vrf_bitmap_check( client->redist[afi][prev_re->type], re->vrf_id))) { - zsend_redistribute_route(0, client, p, src_p, prev_re); + zsend_redistribute_route(ZEBRA_REDISTRIBUTE_ROUTE_DEL, + client, p, src_p, prev_re); } } } @@ -242,7 +244,8 @@ void redistribute_delete(struct prefix *p, struct prefix *src_p, re->instance)) || vrf_bitmap_check(client->redist[afi][re->type], re->vrf_id)) { - zsend_redistribute_route(0, client, p, src_p, re); + zsend_redistribute_route(ZEBRA_REDISTRIBUTE_ROUTE_DEL, + client, p, src_p, re); } } } diff --git a/zebra/zserv.c b/zebra/zserv.c index de475dccfd..56cca10654 100644 --- a/zebra/zserv.c +++ b/zebra/zserv.c @@ -592,193 +592,76 @@ int zsend_interface_update(int cmd, struct zserv *client, struct interface *ifp) return zebra_server_send_message(client); } -/* - * This is the new function to announce and withdraw redistributed routes, used - * by Zebra. This is the old zsend_route_multipath() function. That function - * was duplicating code to send a lot of information that was essentially thrown - * away or ignored by the receiver. This is the leaner function that is not a - * duplicate of the zapi_ipv4_route_add/del. - * - * The primary difference is that this function merely sends a single NH instead - * of - * all the nexthops. - */ -int zsend_redistribute_route(int add, struct zserv *client, struct prefix *p, +int zsend_redistribute_route(int cmd, struct zserv *client, struct prefix *p, struct prefix *src_p, struct route_entry *re) { - afi_t afi; - int cmd; - int psize; - struct stream *s; + struct zapi_route api; + struct zapi_nexthop *api_nh; struct nexthop *nexthop; - unsigned long nhnummark = 0, messmark = 0; - int nhnum = 0; - u_char zapi_flags = 0; - struct nexthop dummy_nh; + int count = 0; - afi = family2afi(p->family); - if (add) { - switch (afi) { - case AFI_IP: - cmd = ZEBRA_REDISTRIBUTE_IPV4_ADD; - client->redist_v4_add_cnt++; - break; - case AFI_IP6: - cmd = ZEBRA_REDISTRIBUTE_IPV6_ADD; - client->redist_v6_add_cnt++; - break; - default: - return -1; - } - } else { - switch (afi) { - case AFI_IP: - cmd = ZEBRA_REDISTRIBUTE_IPV4_DEL; - client->redist_v4_del_cnt++; - break; - case AFI_IP6: - cmd = ZEBRA_REDISTRIBUTE_IPV6_DEL; - client->redist_v6_del_cnt++; - break; - default: - return -1; - } - } - - s = client->obuf; - stream_reset(s); - memset(&dummy_nh, 0, sizeof(struct nexthop)); - - zserv_create_header(s, cmd, re->vrf_id); - - /* Put type and nexthop. */ - stream_putc(s, re->type); - stream_putw(s, re->instance); - stream_putl(s, re->flags); - - /* marker for message flags field */ - messmark = stream_get_endp(s); - stream_putc(s, 0); + memset(&api, 0, sizeof(api)); + api.vrf_id = VRF_DEFAULT; + api.type = re->type; + api.instance = re->instance; + api.flags = re->flags; /* Prefix. */ - psize = PSIZE(p->prefixlen); - stream_putc(s, p->prefixlen); - stream_write(s, (u_char *)&p->u.prefix, psize); - + api.prefix = *p; if (src_p) { - SET_FLAG(zapi_flags, ZAPI_MESSAGE_SRCPFX); - psize = PSIZE(src_p->prefixlen); - stream_putc(s, src_p->prefixlen); - stream_write(s, (u_char *)&src_p->u.prefix, psize); + SET_FLAG(api.message, ZAPI_MESSAGE_SRCPFX); + memcpy(&api.src_prefix, src_p, sizeof(api.src_prefix)); } + /* Nexthops. */ + if (re->nexthop_active_num) { + SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); + api.nexthop_num = re->nexthop_active_num; + } for (nexthop = re->nexthop; nexthop; nexthop = nexthop->next) { - /* We don't send any nexthops when there's a multipath */ - if (re->nexthop_active_num > 1 - && client->proto != ZEBRA_ROUTE_LDP) { - SET_FLAG(zapi_flags, ZAPI_MESSAGE_NEXTHOP); - SET_FLAG(zapi_flags, ZAPI_MESSAGE_IFINDEX); + if (!CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE)) + continue; - stream_putc(s, 1); - if (p->family == AF_INET) { - stream_put_in_addr(s, &dummy_nh.gate.ipv4); - } else if (p->family == AF_INET6) { - stream_write(s, (u_char *)&dummy_nh.gate.ipv6, - 16); - } else { - /* We don't handle anything else now, abort */ - zlog_err( - "%s: Unable to redistribute route of unknown family, %d\n", - __func__, p->family); - return -1; - } - stream_putc(s, 1); - stream_putl(s, 0); /* dummy ifindex */ + api_nh = &api.nexthops[count]; + api_nh->type = nexthop->type; + switch (nexthop->type) { + case NEXTHOP_TYPE_BLACKHOLE: break; + case NEXTHOP_TYPE_IPV4: + api_nh->gate.ipv4 = nexthop->gate.ipv4; + break; + case NEXTHOP_TYPE_IPV4_IFINDEX: + api_nh->gate.ipv4 = nexthop->gate.ipv4; + api_nh->ifindex = nexthop->ifindex; + break; + case NEXTHOP_TYPE_IFINDEX: + api_nh->ifindex = nexthop->ifindex; + break; + case NEXTHOP_TYPE_IPV6: + api_nh->gate.ipv6 = nexthop->gate.ipv6; + break; + case NEXTHOP_TYPE_IPV6_IFINDEX: + api_nh->gate.ipv6 = nexthop->gate.ipv6; + api_nh->ifindex = nexthop->ifindex; } - - if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE)) { - SET_FLAG(zapi_flags, ZAPI_MESSAGE_NEXTHOP); - SET_FLAG(zapi_flags, ZAPI_MESSAGE_IFINDEX); - if (nhnummark == 0) { - nhnummark = stream_get_endp(s); - stream_putc(s, 1); /* placeholder */ - } - nhnum++; - - switch (nexthop->type) { - case NEXTHOP_TYPE_IPV4: - case NEXTHOP_TYPE_IPV4_IFINDEX: - stream_put_in_addr(s, &nexthop->gate.ipv4); - break; - case NEXTHOP_TYPE_IPV6: - case NEXTHOP_TYPE_IPV6_IFINDEX: - /* Only BGP supports IPv4 prefix with IPv6 NH, - * so kill this */ - if (p->family == AF_INET) - stream_put_in_addr(s, - &dummy_nh.gate.ipv4); - else - stream_write( - s, - (u_char *)&nexthop->gate.ipv6, - 16); - break; - default: - if (cmd == ZEBRA_REDISTRIBUTE_IPV4_ADD - || cmd == ZEBRA_REDISTRIBUTE_IPV4_DEL) { - struct in_addr empty; - memset(&empty, 0, - sizeof(struct in_addr)); - stream_write(s, (u_char *)&empty, - IPV4_MAX_BYTELEN); - } else { - struct in6_addr empty; - memset(&empty, 0, - sizeof(struct in6_addr)); - stream_write(s, (u_char *)&empty, - IPV6_MAX_BYTELEN); - } - } - - /* Interface index. */ - stream_putc(s, 1); - stream_putl(s, nexthop->ifindex); - - /* ldpd needs all nexthops */ - if (client->proto != ZEBRA_ROUTE_LDP) - break; - } + count++; } - /* Distance */ - SET_FLAG(zapi_flags, ZAPI_MESSAGE_DISTANCE); - stream_putc(s, re->distance); - - /* Metric */ - SET_FLAG(zapi_flags, ZAPI_MESSAGE_METRIC); - stream_putl(s, re->metric); - - /* Tag */ + /* Attributes. */ + SET_FLAG(api.message, ZAPI_MESSAGE_DISTANCE); + api.distance = re->distance; + SET_FLAG(api.message, ZAPI_MESSAGE_METRIC); + api.metric = re->metric; if (re->tag) { - SET_FLAG(zapi_flags, ZAPI_MESSAGE_TAG); - stream_putl(s, re->tag); + SET_FLAG(api.message, ZAPI_MESSAGE_TAG); + api.tag = re->tag; } + SET_FLAG(api.message, ZAPI_MESSAGE_MTU); + api.mtu = re->mtu; - /* MTU */ - SET_FLAG(zapi_flags, ZAPI_MESSAGE_MTU); - stream_putl(s, re->mtu); - - /* write real message flags value */ - stream_putc_at(s, messmark, zapi_flags); - - /* Write next-hop number */ - if (nhnummark) - stream_putc_at(s, nhnummark, nhnum); - - /* Write packet size. */ - stream_putw_at(s, 0, stream_get_endp(s)); - + /* Encode route and send. */ + if (zapi_route_encode(cmd, client->obuf, &api) < 0) + return -1; return zebra_server_send_message(client); } From b30f3b91d4d91e5d58f2f999e2f673aeaf15d653 Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Mon, 21 Aug 2017 19:43:43 -0300 Subject: [PATCH 091/130] ospf6d: fix regression detected by topotest With the old API, ospf6d always needed to send a nexthop address and a nexthop interface when advertising a route to zebra. In the case where the nexthop address didn't exist (e.g. connected route), zebra would take care of ignore it in the zread_ipv6_add() function. Now, if we have a nexthop interface but not a nexthop address, we not only can but we should send a nexthop of type NEXTHOP_TYPE_IFINDEX. zebra won't fix bad nexthops anymore because the clients have a proper API to send correct messages. Signed-off-by: Renato Westphal --- ospf6d/ospf6_route.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/ospf6d/ospf6_route.c b/ospf6d/ospf6_route.c index 03791ad7a0..e58eab2b15 100644 --- a/ospf6d/ospf6_route.c +++ b/ospf6d/ospf6_route.c @@ -305,14 +305,16 @@ void ospf6_route_zebra_copy_nexthops(struct ospf6_route *route, zlog_debug(" nexthop: %s%%%.*s(%d)", buf, IFNAMSIZ, ifname, nh->ifindex); } - if (i < entries) { - nexthops[i].gate.ipv6 = nh->address; - nexthops[i].ifindex = nh->ifindex; - nexthops[i].type = NEXTHOP_TYPE_IPV6_IFINDEX; - i++; - } else { + if (i >= entries) return; - } + + nexthops[i].ifindex = nh->ifindex; + if (!IN6_IS_ADDR_UNSPECIFIED(&nh->address)) { + nexthops[i].gate.ipv6 = nh->address; + nexthops[i].type = NEXTHOP_TYPE_IPV6_IFINDEX; + } else + nexthops[i].type = NEXTHOP_TYPE_IFINDEX; + i++; } } } From f474e08be0c3c6e92bf265700d013388183f0acb Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Wed, 23 Aug 2017 19:12:48 -0300 Subject: [PATCH 092/130] lib: mark the old zebra API for route advertisement as deprecated Signed-off-by: Renato Westphal --- lib/zclient.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/zclient.h b/lib/zclient.h index f454a9d8ac..bae52a441b 100644 --- a/lib/zclient.h +++ b/lib/zclient.h @@ -369,7 +369,7 @@ extern struct interface *zebra_interface_vrf_update_read(struct stream *s, extern void zebra_interface_if_set_value(struct stream *, struct interface *); extern void zebra_router_id_update_read(struct stream *s, struct prefix *rid); extern int zapi_ipv4_route(u_char, struct zclient *, struct prefix_ipv4 *, - struct zapi_ipv4 *); + struct zapi_ipv4 *) __attribute__((deprecated)); extern struct interface *zebra_interface_link_params_read(struct stream *); extern size_t zebra_interface_link_params_write(struct stream *, @@ -420,10 +420,11 @@ struct zapi_ipv6 { extern int zapi_ipv6_route(u_char cmd, struct zclient *zclient, struct prefix_ipv6 *p, struct prefix_ipv6 *src_p, - struct zapi_ipv6 *api); + struct zapi_ipv6 *api) __attribute__((deprecated)); extern int zapi_ipv4_route_ipv6_nexthop(u_char, struct zclient *, struct prefix_ipv4 *, - struct zapi_ipv6 *); + struct zapi_ipv6 *) + __attribute__((deprecated)); extern int zclient_route_send(u_char, struct zclient *, struct zapi_route *); extern int zapi_route_encode(u_char, struct stream *, struct zapi_route *); extern int zapi_route_decode(struct stream *, struct zapi_route *); From 98ca91e95a8c0dbc3febe5e2ce84e1a6640c9459 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 24 Aug 2017 08:02:27 -0400 Subject: [PATCH 093/130] zebra: Fix compiler warnings Signed-off-by: Donald Sharp --- zebra/zserv.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/zebra/zserv.c b/zebra/zserv.c index 56cca10654..7899a8375c 100644 --- a/zebra/zserv.c +++ b/zebra/zserv.c @@ -1049,7 +1049,7 @@ static int zread_route_add(struct zserv *client, u_short length, afi_t afi; struct prefix_ipv6 *src_p = NULL; struct route_entry *re; - struct nexthop *nexthop; + struct nexthop *nexthop = NULL; int i, ret; s = client->ibuf; @@ -1364,7 +1364,7 @@ static int zread_ipv4_route_ipv6_nexthop_add(struct zserv *client, static unsigned int ifindices[MULTIPATH_NUM]; int ret; static mpls_label_t labels[MULTIPATH_NUM]; - enum lsp_types_t label_type; + enum lsp_types_t label_type = ZEBRA_LSP_NONE; mpls_label_t label; struct nexthop *nexthop; @@ -1513,7 +1513,7 @@ static int zread_ipv6_add(struct zserv *client, u_short length, static unsigned int ifindices[MULTIPATH_NUM]; int ret; static mpls_label_t labels[MULTIPATH_NUM]; - enum lsp_types_t label_type; + enum lsp_types_t label_type = ZEBRA_LSP_NONE; mpls_label_t label; struct nexthop *nexthop; From cd0442479369e53f3b8451163a8679a00f4c0d25 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Tue, 22 Aug 2017 14:40:24 -0400 Subject: [PATCH 094/130] eigrpd: Start split-horizon EIGRP was not handling split-horizon. This code starts down the path of properly considering it. There still exists situations where we are not properly handling it though. Signed-off-by: Donald Sharp --- eigrpd/eigrp_neighbor.c | 8 ++++++++ eigrpd/eigrp_neighbor.h | 2 ++ eigrpd/eigrp_update.c | 8 ++++++-- 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/eigrpd/eigrp_neighbor.c b/eigrpd/eigrp_neighbor.c index d5fc6a2996..5d78dc375c 100644 --- a/eigrpd/eigrp_neighbor.c +++ b/eigrpd/eigrp_neighbor.c @@ -357,3 +357,11 @@ void eigrp_nbr_hard_restart(struct eigrp_neighbor *nbr, struct vty *vty) /* delete neighbor */ eigrp_nbr_delete(nbr); } + +int eigrp_nbr_split_horizon_check(struct eigrp_neighbor_entry *ne, struct eigrp_interface *ei) +{ + if (ne->distance == EIGRP_MAX_METRIC) + return 0; + + return (ne->ei == ei); +} diff --git a/eigrpd/eigrp_neighbor.h b/eigrpd/eigrp_neighbor.h index 006aa9ab75..6467fb24a9 100644 --- a/eigrpd/eigrp_neighbor.h +++ b/eigrpd/eigrp_neighbor.h @@ -53,4 +53,6 @@ extern struct eigrp_neighbor *eigrp_nbr_lookup_by_addr_process(struct eigrp *, struct in_addr); extern void eigrp_nbr_hard_restart(struct eigrp_neighbor *nbr, struct vty *vty); +extern int eigrp_nbr_split_horizon_check(struct eigrp_neighbor_entry *ne, + struct eigrp_interface *ei); #endif /* _ZEBRA_EIGRP_NEIGHBOR_H */ diff --git a/eigrpd/eigrp_update.c b/eigrpd/eigrp_update.c index d0c6520c4e..2934c6c652 100644 --- a/eigrpd/eigrp_update.c +++ b/eigrpd/eigrp_update.c @@ -610,8 +610,7 @@ void eigrp_update_send_EOT(struct eigrp_neighbor *nbr) for (ALL_LIST_ELEMENTS(nbr->ei->eigrp->topology_table, node, nnode, pe)) { for (ALL_LIST_ELEMENTS(pe->entries, node2, nnode2, te)) { - if ((te->ei == nbr->ei) - && (te->prefix->nt == EIGRP_TOPOLOGY_TYPE_REMOTE)) + if (eigrp_nbr_split_horizon_check(te, nbr->ei)) continue; if ((length + 0x001D) > (u_int16_t)nbr->ei->ifp->mtu) { @@ -701,10 +700,15 @@ void eigrp_update_send(struct eigrp_interface *ei) has_tlv = 0; for (ALL_LIST_ELEMENTS(ei->eigrp->topology_changes_internalIPV4, node, nnode, pe)) { + struct eigrp_neighbor_entry *ne; if (!(pe->req_action & EIGRP_FSM_NEED_UPDATE)) continue; + ne = listnode_head(pe->entries); + if (eigrp_nbr_split_horizon_check(ne, ei)) + continue; + if ((length + 0x001D) > (u_int16_t)ei->ifp->mtu) { if ((IF_DEF_PARAMS(ei->ifp)->auth_type == EIGRP_AUTH_TYPE_MD5) && (IF_DEF_PARAMS(ei->ifp)->auth_keychain != NULL)) { From c1c32a78034c63e149769c8b5e6799bec2040cf1 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Tue, 22 Aug 2017 14:42:43 -0400 Subject: [PATCH 095/130] eigrpd: Remove unnecessary check Signed-off-by: Donald Sharp --- eigrpd/eigrp_interface.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/eigrpd/eigrp_interface.c b/eigrpd/eigrp_interface.c index 22b6fa394f..b316a22d88 100644 --- a/eigrpd/eigrp_interface.c +++ b/eigrpd/eigrp_interface.c @@ -315,9 +315,7 @@ int eigrp_if_up(struct eigrp_interface *ei) eigrp_neighbor_entry_add(pe, ne); for (ALL_LIST_ELEMENTS(eigrp->eiflist, node, nnode, ei2)) { - if (ei2->nbrs->count != 0) { - eigrp_update_send(ei2); - } + eigrp_update_send(ei2); } pe->req_action &= ~EIGRP_FSM_NEED_UPDATE; From 695ff37babda771517c85a20c714d8215ece0c63 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Tue, 22 Aug 2017 14:53:14 -0400 Subject: [PATCH 096/130] eigrpd: Cleanup list accessors Signed-off-by: Donald Sharp --- eigrpd/eigrp_fsm.c | 92 +++++++++++++++++++--------------------------- 1 file changed, 38 insertions(+), 54 deletions(-) diff --git a/eigrpd/eigrp_fsm.c b/eigrpd/eigrp_fsm.c index ba2d1f7e8d..178b2b0cd7 100644 --- a/eigrpd/eigrp_fsm.c +++ b/eigrpd/eigrp_fsm.c @@ -204,8 +204,7 @@ int eigrp_get_fsm_event(struct eigrp_fsm_action_message *msg) switch (actual_state) { case EIGRP_FSM_STATE_PASSIVE: { struct eigrp_neighbor_entry *head = - (struct eigrp_neighbor_entry *) - entry->prefix->entries->head->data; + listnode_head(prefix->entries); if (head->reported_distance < prefix->fdistance) { return EIGRP_FSM_KEEP_STATE; @@ -226,8 +225,7 @@ int eigrp_get_fsm_event(struct eigrp_fsm_action_message *msg) case EIGRP_FSM_STATE_ACTIVE_0: { if (msg->packet_type == EIGRP_OPC_REPLY) { struct eigrp_neighbor_entry *head = - (struct eigrp_neighbor_entry *) - entry->prefix->entries->head->data; + listnode_head(prefix->entries); listnode_delete(prefix->rij, entry->adv_router); if (prefix->rij->count) @@ -279,8 +277,7 @@ int eigrp_get_fsm_event(struct eigrp_fsm_action_message *msg) case EIGRP_FSM_STATE_ACTIVE_2: { if (msg->packet_type == EIGRP_OPC_REPLY) { struct eigrp_neighbor_entry *head = - (struct eigrp_neighbor_entry *) - prefix->entries->head->data; + listnode_head(prefix->entries); listnode_delete(prefix->rij, entry->adv_router); if (prefix->rij->count) { @@ -350,16 +347,15 @@ int eigrp_fsm_event_nq_fcn(struct eigrp_fsm_action_message *msg) struct eigrp *eigrp = msg->eigrp; struct eigrp_prefix_entry *prefix = msg->prefix; struct list *successors = eigrp_topology_get_successor(prefix); + struct eigrp_neighbor_entry *ne; assert(successors); // If this is NULL we have shit the bed, fun huh? + ne = listnode_head(successors); prefix->state = EIGRP_FSM_STATE_ACTIVE_1; prefix->rdistance = prefix->distance = prefix->fdistance = - ((struct eigrp_neighbor_entry *)successors->head->data) - ->distance; - prefix->reported_metric = - ((struct eigrp_neighbor_entry *)successors->head->data) - ->total_metric; + ne->distance; + prefix->reported_metric = ne->total_metric; if (eigrp_nbr_count_get()) { prefix->req_action |= EIGRP_FSM_NEED_QUERY; @@ -379,16 +375,15 @@ int eigrp_fsm_event_q_fcn(struct eigrp_fsm_action_message *msg) struct eigrp *eigrp = msg->eigrp; struct eigrp_prefix_entry *prefix = msg->prefix; struct list *successors = eigrp_topology_get_successor(prefix); + struct eigrp_neighbor_entry *ne; assert(successors); // If this is NULL somebody poked us in the eye. + ne = listnode_head(successors); prefix->state = EIGRP_FSM_STATE_ACTIVE_3; prefix->rdistance = prefix->distance = prefix->fdistance = - ((struct eigrp_neighbor_entry *)successors->head->data) - ->distance; - prefix->reported_metric = - ((struct eigrp_neighbor_entry *)successors->head->data) - ->total_metric; + ne->distance; + prefix->reported_metric = ne->total_metric; if (eigrp_nbr_count_get()) { prefix->req_action |= EIGRP_FSM_NEED_QUERY; listnode_add(eigrp->topology_changes_internalIPV4, prefix); @@ -405,21 +400,15 @@ int eigrp_fsm_event_q_fcn(struct eigrp_fsm_action_message *msg) int eigrp_fsm_event_keep_state(struct eigrp_fsm_action_message *msg) { struct eigrp_prefix_entry *prefix = msg->prefix; + struct eigrp_neighbor_entry *ne = listnode_head(prefix->entries); if (prefix->state == EIGRP_FSM_STATE_PASSIVE) { if (!eigrp_metrics_is_same(prefix->reported_metric, - ((struct eigrp_neighbor_entry *) - prefix->entries->head->data) - ->total_metric)) { + ne->total_metric)) { prefix->rdistance = prefix->fdistance = - prefix->distance = - ((struct eigrp_neighbor_entry *) - prefix->entries->head->data) - ->distance; + prefix->distance = ne->distance; prefix->reported_metric = - ((struct eigrp_neighbor_entry *) - prefix->entries->head->data) - ->total_metric; + ne->total_metric; if (msg->packet_type == EIGRP_OPC_QUERY) eigrp_send_reply(msg->adv_router, prefix); prefix->req_action |= EIGRP_FSM_NEED_UPDATE; @@ -441,22 +430,20 @@ int eigrp_fsm_event_lr(struct eigrp_fsm_action_message *msg) { struct eigrp *eigrp = msg->eigrp; struct eigrp_prefix_entry *prefix = msg->prefix; + struct eigrp_neighbor_entry *ne = listnode_head(prefix->entries); + prefix->fdistance = prefix->distance = prefix->rdistance = - ((struct eigrp_neighbor_entry *)(prefix->entries->head->data)) - ->distance; - prefix->reported_metric = - ((struct eigrp_neighbor_entry *)(prefix->entries->head->data)) - ->total_metric; + ne->distance; + prefix->reported_metric = ne->total_metric; if (prefix->state == EIGRP_FSM_STATE_ACTIVE_3) { struct list *successors = eigrp_topology_get_successor(prefix); assert(successors); // It's like Napolean and Waterloo - eigrp_send_reply( - ((struct eigrp_neighbor_entry *)successors->head->data) - ->adv_router, - prefix); + ne = listnode_head(successors); + eigrp_send_reply(ne->adv_router, + prefix); list_delete(successors); } @@ -473,15 +460,15 @@ int eigrp_fsm_event_lr(struct eigrp_fsm_action_message *msg) int eigrp_fsm_event_dinc(struct eigrp_fsm_action_message *msg) { struct list *successors = eigrp_topology_get_successor(msg->prefix); + struct eigrp_neighbor_entry *ne; assert(successors); // Trump and his big hands + ne = listnode_head(successors); msg->prefix->state = msg->prefix->state == EIGRP_FSM_STATE_ACTIVE_1 ? EIGRP_FSM_STATE_ACTIVE_0 : EIGRP_FSM_STATE_ACTIVE_2; - msg->prefix->distance = - ((struct eigrp_neighbor_entry *)successors->head->data) - ->distance; + msg->prefix->distance = ne->distance; if (!msg->prefix->rij->count) (*(NSM[msg->prefix->state][eigrp_get_fsm_event(msg)].func))( msg); @@ -495,13 +482,11 @@ int eigrp_fsm_event_lr_fcs(struct eigrp_fsm_action_message *msg) { struct eigrp *eigrp = msg->eigrp; struct eigrp_prefix_entry *prefix = msg->prefix; + struct eigrp_neighbor_entry *ne = listnode_head(prefix->entries); + prefix->state = EIGRP_FSM_STATE_PASSIVE; - prefix->distance = prefix->rdistance = - ((struct eigrp_neighbor_entry *)(prefix->entries->head->data)) - ->distance; - prefix->reported_metric = - ((struct eigrp_neighbor_entry *)(prefix->entries->head->data)) - ->total_metric; + prefix->distance = prefix->rdistance = ne->distance; + prefix->reported_metric = ne->total_metric; prefix->fdistance = prefix->fdistance > prefix->distance ? prefix->distance : prefix->fdistance; @@ -510,11 +495,9 @@ int eigrp_fsm_event_lr_fcs(struct eigrp_fsm_action_message *msg) assert(successors); // Having a spoon and all you need is a // knife - - eigrp_send_reply( - ((struct eigrp_neighbor_entry *)successors->head->data) - ->adv_router, - prefix); + ne = listnode_head(successors); + eigrp_send_reply(ne->adv_router, + prefix); list_delete(successors); } @@ -531,6 +514,7 @@ int eigrp_fsm_event_lr_fcn(struct eigrp_fsm_action_message *msg) { struct eigrp *eigrp = msg->eigrp; struct eigrp_prefix_entry *prefix = msg->prefix; + struct eigrp_neighbor_entry *best_successor; struct list *successors = eigrp_topology_get_successor(prefix); assert(successors); // Routing without a stack @@ -538,8 +522,8 @@ int eigrp_fsm_event_lr_fcn(struct eigrp_fsm_action_message *msg) prefix->state = prefix->state == EIGRP_FSM_STATE_ACTIVE_0 ? EIGRP_FSM_STATE_ACTIVE_1 : EIGRP_FSM_STATE_ACTIVE_3; - struct eigrp_neighbor_entry *best_successor = - ((struct eigrp_neighbor_entry *)(successors->head->data)); + + best_successor = listnode_head(successors); prefix->rdistance = prefix->distance = best_successor->distance; prefix->reported_metric = best_successor->total_metric; @@ -559,13 +543,13 @@ int eigrp_fsm_event_lr_fcn(struct eigrp_fsm_action_message *msg) int eigrp_fsm_event_qact(struct eigrp_fsm_action_message *msg) { struct list *successors = eigrp_topology_get_successor(msg->prefix); + struct eigrp_neighbor_entry *ne; assert(successors); // Cats and no Dogs + ne = listnode_head(successors); msg->prefix->state = EIGRP_FSM_STATE_ACTIVE_2; - msg->prefix->distance = - ((struct eigrp_neighbor_entry *)(successors->head->data)) - ->distance; + msg->prefix->distance = ne->distance; list_delete(successors); return 1; From 92035b1db4a91d0fc95118a1e0ff73cfa6120b1b Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Tue, 22 Aug 2017 15:39:18 -0400 Subject: [PATCH 097/130] eigrpd: Fix memory leak in FSM The FSM was never freeing the msg. Since we do not have a special queue for it, just don't allocate the memory. In the future we can put this back. Signed-off-by: Donald Sharp --- eigrpd/eigrp_query.c | 23 ++++++-------- eigrpd/eigrp_reply.c | 22 ++++++------- eigrpd/eigrp_siaquery.c | 23 ++++++-------- eigrpd/eigrp_siareply.c | 23 ++++++-------- eigrpd/eigrp_topology.c | 23 ++++++-------- eigrpd/eigrp_update.c | 68 ++++++++++++++++++----------------------- 6 files changed, 80 insertions(+), 102 deletions(-) diff --git a/eigrpd/eigrp_query.c b/eigrpd/eigrp_query.c index 00f9ee1267..c82c90589b 100644 --- a/eigrpd/eigrp_query.c +++ b/eigrpd/eigrp_query.c @@ -125,22 +125,19 @@ void eigrp_query_receive(struct eigrp *eigrp, struct ip *iph, /* If the destination exists (it should, but one never * know)*/ if (dest != NULL) { - struct eigrp_fsm_action_message *msg; - msg = XCALLOC(MTYPE_EIGRP_FSM_MSG, - sizeof(struct - eigrp_fsm_action_message)); + struct eigrp_fsm_action_message msg; struct eigrp_neighbor_entry *entry = eigrp_prefix_entry_lookup(dest->entries, nbr); - msg->packet_type = EIGRP_OPC_QUERY; - msg->eigrp = eigrp; - msg->data_type = EIGRP_TLV_IPv4_INT; - msg->adv_router = nbr; - msg->data.ipv4_int_type = tlv; - msg->entry = entry; - msg->prefix = dest; - int event = eigrp_get_fsm_event(msg); - eigrp_fsm_event(msg, event); + msg.packet_type = EIGRP_OPC_QUERY; + msg.eigrp = eigrp; + msg.data_type = EIGRP_TLV_IPv4_INT; + msg.adv_router = nbr; + msg.data.ipv4_int_type = tlv; + msg.entry = entry; + msg.prefix = dest; + int event = eigrp_get_fsm_event(&msg); + eigrp_fsm_event(&msg, event); } eigrp_IPv4_InternalTLV_free(tlv); break; diff --git a/eigrpd/eigrp_reply.c b/eigrpd/eigrp_reply.c index e59db80393..4e909283d6 100644 --- a/eigrpd/eigrp_reply.c +++ b/eigrpd/eigrp_reply.c @@ -196,9 +196,7 @@ void eigrp_reply_receive(struct eigrp *eigrp, struct ip *iph, */ assert(dest); - struct eigrp_fsm_action_message *msg; - msg = XCALLOC(MTYPE_EIGRP_FSM_MSG, - sizeof(struct eigrp_fsm_action_message)); + struct eigrp_fsm_action_message msg; struct eigrp_neighbor_entry *entry = eigrp_prefix_entry_lookup(dest->entries, nbr); @@ -237,15 +235,15 @@ void eigrp_reply_receive(struct eigrp *eigrp, struct ip *iph, * End of filtering */ - msg->packet_type = EIGRP_OPC_REPLY; - msg->eigrp = eigrp; - msg->data_type = EIGRP_TLV_IPv4_INT; - msg->adv_router = nbr; - msg->data.ipv4_int_type = tlv; - msg->entry = entry; - msg->prefix = dest; - int event = eigrp_get_fsm_event(msg); - eigrp_fsm_event(msg, event); + msg.packet_type = EIGRP_OPC_REPLY; + msg.eigrp = eigrp; + msg.data_type = EIGRP_TLV_IPv4_INT; + msg.adv_router = nbr; + msg.data.ipv4_int_type = tlv; + msg.entry = entry; + msg.prefix = dest; + int event = eigrp_get_fsm_event(&msg); + eigrp_fsm_event(&msg, event); eigrp_IPv4_InternalTLV_free(tlv); diff --git a/eigrpd/eigrp_siaquery.c b/eigrpd/eigrp_siaquery.c index 30f65ee87d..85b6ca9fe4 100644 --- a/eigrpd/eigrp_siaquery.c +++ b/eigrpd/eigrp_siaquery.c @@ -94,22 +94,19 @@ void eigrp_siaquery_receive(struct eigrp *eigrp, struct ip *iph, /* If the destination exists (it should, but one never * know)*/ if (dest != NULL) { - struct eigrp_fsm_action_message *msg; - msg = XCALLOC(MTYPE_EIGRP_FSM_MSG, - sizeof(struct - eigrp_fsm_action_message)); + struct eigrp_fsm_action_message msg; struct eigrp_neighbor_entry *entry = eigrp_prefix_entry_lookup(dest->entries, nbr); - msg->packet_type = EIGRP_OPC_SIAQUERY; - msg->eigrp = eigrp; - msg->data_type = EIGRP_TLV_IPv4_INT; - msg->adv_router = nbr; - msg->data.ipv4_int_type = tlv; - msg->entry = entry; - msg->prefix = dest; - int event = eigrp_get_fsm_event(msg); - eigrp_fsm_event(msg, event); + msg.packet_type = EIGRP_OPC_SIAQUERY; + msg.eigrp = eigrp; + msg.data_type = EIGRP_TLV_IPv4_INT; + msg.adv_router = nbr; + msg.data.ipv4_int_type = tlv; + msg.entry = entry; + msg.prefix = dest; + int event = eigrp_get_fsm_event(&msg); + eigrp_fsm_event(&msg, event); } eigrp_IPv4_InternalTLV_free(tlv); } diff --git a/eigrpd/eigrp_siareply.c b/eigrpd/eigrp_siareply.c index 3050b91032..c03a34322e 100644 --- a/eigrpd/eigrp_siareply.c +++ b/eigrpd/eigrp_siareply.c @@ -93,22 +93,19 @@ void eigrp_siareply_receive(struct eigrp *eigrp, struct ip *iph, /* If the destination exists (it should, but one never * know)*/ if (dest != NULL) { - struct eigrp_fsm_action_message *msg; - msg = XCALLOC(MTYPE_EIGRP_FSM_MSG, - sizeof(struct - eigrp_fsm_action_message)); + struct eigrp_fsm_action_message msg; struct eigrp_neighbor_entry *entry = eigrp_prefix_entry_lookup(dest->entries, nbr); - msg->packet_type = EIGRP_OPC_SIAQUERY; - msg->eigrp = eigrp; - msg->data_type = EIGRP_TLV_IPv4_INT; - msg->adv_router = nbr; - msg->data.ipv4_int_type = tlv; - msg->entry = entry; - msg->prefix = dest; - int event = eigrp_get_fsm_event(msg); - eigrp_fsm_event(msg, event); + msg.packet_type = EIGRP_OPC_SIAQUERY; + msg.eigrp = eigrp; + msg.data_type = EIGRP_TLV_IPv4_INT; + msg.adv_router = nbr; + msg.data.ipv4_int_type = tlv; + msg.entry = entry; + msg.prefix = dest; + int event = eigrp_get_fsm_event(&msg); + eigrp_fsm_event(&msg, event); } eigrp_IPv4_InternalTLV_free(tlv); } diff --git a/eigrpd/eigrp_topology.c b/eigrpd/eigrp_topology.c index 50d83430a8..f78a43739d 100644 --- a/eigrpd/eigrp_topology.c +++ b/eigrpd/eigrp_topology.c @@ -486,22 +486,19 @@ void eigrp_topology_neighbor_down(struct eigrp *eigrp, for (ALL_LIST_ELEMENTS(eigrp->topology_table, node1, node11, prefix)) { for (ALL_LIST_ELEMENTS(prefix->entries, node2, node22, entry)) { if (entry->adv_router == nbr) { - struct eigrp_fsm_action_message *msg; - msg = XCALLOC(MTYPE_EIGRP_FSM_MSG, - sizeof(struct - eigrp_fsm_action_message)); + struct eigrp_fsm_action_message msg; struct TLV_IPv4_Internal_type *tlv = eigrp_IPv4_InternalTLV_new(); tlv->metric.delay = EIGRP_MAX_METRIC; - msg->packet_type = EIGRP_OPC_UPDATE; - msg->eigrp = eigrp; - msg->data_type = EIGRP_TLV_IPv4_INT; - msg->adv_router = nbr; - msg->data.ipv4_int_type = tlv; - msg->entry = entry; - msg->prefix = prefix; - int event = eigrp_get_fsm_event(msg); - eigrp_fsm_event(msg, event); + msg.packet_type = EIGRP_OPC_UPDATE; + msg.eigrp = eigrp; + msg.data_type = EIGRP_TLV_IPv4_INT; + msg.adv_router = nbr; + msg.data.ipv4_int_type = tlv; + msg.entry = entry; + msg.prefix = prefix; + int event = eigrp_get_fsm_event(&msg); + eigrp_fsm_event(&msg, event); } } } diff --git a/eigrpd/eigrp_update.c b/eigrpd/eigrp_update.c index 2934c6c652..a3d6210e71 100644 --- a/eigrpd/eigrp_update.c +++ b/eigrpd/eigrp_update.c @@ -132,24 +132,22 @@ static void eigrp_update_receive_GR_ask(struct eigrp *eigrp, /* prepare message for FSM */ - struct eigrp_fsm_action_message *fsm_msg; - fsm_msg = XCALLOC(MTYPE_EIGRP_FSM_MSG, - sizeof(struct eigrp_fsm_action_message)); + struct eigrp_fsm_action_message fsm_msg; struct eigrp_neighbor_entry *entry = eigrp_prefix_entry_lookup(prefix->entries, nbr); - fsm_msg->packet_type = EIGRP_OPC_UPDATE; - fsm_msg->eigrp = eigrp; - fsm_msg->data_type = EIGRP_TLV_IPv4_INT; - fsm_msg->adv_router = nbr; - fsm_msg->data.ipv4_int_type = tlv_max; - fsm_msg->entry = entry; - fsm_msg->prefix = prefix; + fsm_msg.packet_type = EIGRP_OPC_UPDATE; + fsm_msg.eigrp = eigrp; + fsm_msg.data_type = EIGRP_TLV_IPv4_INT; + fsm_msg.adv_router = nbr; + fsm_msg.data.ipv4_int_type = tlv_max; + fsm_msg.entry = entry; + fsm_msg.prefix = prefix; /* send message to FSM */ - int event = eigrp_get_fsm_event(fsm_msg); - eigrp_fsm_event(fsm_msg, event); + int event = eigrp_get_fsm_event(&fsm_msg); + eigrp_fsm_event(&fsm_msg, event); /* free memory used by TLV */ eigrp_IPv4_InternalTLV_free(tlv_max); @@ -311,23 +309,20 @@ void eigrp_update_receive(struct eigrp *eigrp, struct ip *iph, remove_received_prefix_gr(nbr_prefixes, dest); - struct eigrp_fsm_action_message *msg; - msg = XCALLOC(MTYPE_EIGRP_FSM_MSG, - sizeof(struct - eigrp_fsm_action_message)); + struct eigrp_fsm_action_message msg; struct eigrp_neighbor_entry *entry = eigrp_prefix_entry_lookup(dest->entries, nbr); - msg->packet_type = EIGRP_OPC_UPDATE; - msg->eigrp = eigrp; - msg->data_type = EIGRP_TLV_IPv4_INT; - msg->adv_router = nbr; - msg->data.ipv4_int_type = tlv; - msg->entry = entry; - msg->prefix = dest; - int event = eigrp_get_fsm_event(msg); - eigrp_fsm_event(msg, event); + msg.packet_type = EIGRP_OPC_UPDATE; + msg.eigrp = eigrp; + msg.data_type = EIGRP_TLV_IPv4_INT; + msg.adv_router = nbr; + msg.data.ipv4_int_type = tlv; + msg.entry = entry; + msg.prefix = dest; + int event = eigrp_get_fsm_event(&msg); + eigrp_fsm_event(&msg, event); } else { /*Here comes topology information save*/ pe = eigrp_prefix_entry_new(); @@ -978,25 +973,22 @@ static void eigrp_update_send_GR_part(struct eigrp_neighbor *nbr) pe->destination_ipv4->prefixlen; /* prepare message for FSM */ - struct eigrp_fsm_action_message *fsm_msg; - fsm_msg = XCALLOC( - MTYPE_EIGRP_FSM_MSG, - sizeof(struct eigrp_fsm_action_message)); + struct eigrp_fsm_action_message fsm_msg; struct eigrp_neighbor_entry *entry = eigrp_prefix_entry_lookup(pe->entries, nbr); - fsm_msg->packet_type = EIGRP_OPC_UPDATE; - fsm_msg->eigrp = e; - fsm_msg->data_type = EIGRP_TLV_IPv4_INT; - fsm_msg->adv_router = nbr; - fsm_msg->data.ipv4_int_type = tlv_max; - fsm_msg->entry = entry; - fsm_msg->prefix = pe; + fsm_msg.packet_type = EIGRP_OPC_UPDATE; + fsm_msg.eigrp = e; + fsm_msg.data_type = EIGRP_TLV_IPv4_INT; + fsm_msg.adv_router = nbr; + fsm_msg.data.ipv4_int_type = tlv_max; + fsm_msg.entry = entry; + fsm_msg.prefix = pe; /* send message to FSM */ - int event = eigrp_get_fsm_event(fsm_msg); - eigrp_fsm_event(fsm_msg, event); + int event = eigrp_get_fsm_event(&fsm_msg); + eigrp_fsm_event(&fsm_msg, event); /* free memory used by TLV */ eigrp_IPv4_InternalTLV_free(tlv_max); From 6118272f14f91ad4b315c6cd1ad13f4aa8e77a2d Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Tue, 22 Aug 2017 15:43:30 -0400 Subject: [PATCH 098/130] eigrpd: Refactor FSM calling Signed-off-by: Donald Sharp --- eigrpd/eigrp_fsm.c | 5 +++-- eigrpd/eigrp_fsm.h | 3 +-- eigrpd/eigrp_query.c | 3 +-- eigrpd/eigrp_reply.c | 3 +-- eigrpd/eigrp_siaquery.c | 3 +-- eigrpd/eigrp_siareply.c | 3 +-- eigrpd/eigrp_topology.c | 3 +-- eigrpd/eigrp_update.c | 9 +++------ 8 files changed, 12 insertions(+), 20 deletions(-) diff --git a/eigrpd/eigrp_fsm.c b/eigrpd/eigrp_fsm.c index 178b2b0cd7..47cd112cf5 100644 --- a/eigrpd/eigrp_fsm.c +++ b/eigrpd/eigrp_fsm.c @@ -178,7 +178,7 @@ struct { * Return number of occurred event (arrow in diagram). * */ -int eigrp_get_fsm_event(struct eigrp_fsm_action_message *msg) +static int eigrp_get_fsm_event(struct eigrp_fsm_action_message *msg) { // Loading base information from message // struct eigrp *eigrp = msg->eigrp; @@ -328,8 +328,9 @@ int eigrp_get_fsm_event(struct eigrp_fsm_action_message *msg) * Function made to execute in separate thread. * Load argument from thread and execute proper NSM function */ -int eigrp_fsm_event(struct eigrp_fsm_action_message *msg, int event) +int eigrp_fsm_event(struct eigrp_fsm_action_message *msg) { + int event = eigrp_get_fsm_event(msg); zlog_info("EIGRP AS: %d State: %d Event: %d Network: %s", msg->eigrp->AS, msg->prefix->state, event, eigrp_topology_ip_string(msg->prefix)); diff --git a/eigrpd/eigrp_fsm.h b/eigrpd/eigrp_fsm.h index 97a1f49281..8fad9d1f51 100644 --- a/eigrpd/eigrp_fsm.h +++ b/eigrpd/eigrp_fsm.h @@ -28,8 +28,7 @@ #ifndef _ZEBRA_EIGRP_FSM_H #define _ZEBRA_EIGRP_FSM_H -extern int eigrp_get_fsm_event(struct eigrp_fsm_action_message *); -extern int eigrp_fsm_event(struct eigrp_fsm_action_message *, int); +extern int eigrp_fsm_event(struct eigrp_fsm_action_message *msg); #endif /* _ZEBRA_EIGRP_DUAL_H */ diff --git a/eigrpd/eigrp_query.c b/eigrpd/eigrp_query.c index c82c90589b..b9351ed896 100644 --- a/eigrpd/eigrp_query.c +++ b/eigrpd/eigrp_query.c @@ -136,8 +136,7 @@ void eigrp_query_receive(struct eigrp *eigrp, struct ip *iph, msg.data.ipv4_int_type = tlv; msg.entry = entry; msg.prefix = dest; - int event = eigrp_get_fsm_event(&msg); - eigrp_fsm_event(&msg, event); + eigrp_fsm_event(&msg); } eigrp_IPv4_InternalTLV_free(tlv); break; diff --git a/eigrpd/eigrp_reply.c b/eigrpd/eigrp_reply.c index 4e909283d6..7015413f56 100644 --- a/eigrpd/eigrp_reply.c +++ b/eigrpd/eigrp_reply.c @@ -242,8 +242,7 @@ void eigrp_reply_receive(struct eigrp *eigrp, struct ip *iph, msg.data.ipv4_int_type = tlv; msg.entry = entry; msg.prefix = dest; - int event = eigrp_get_fsm_event(&msg); - eigrp_fsm_event(&msg, event); + eigrp_fsm_event(&msg); eigrp_IPv4_InternalTLV_free(tlv); diff --git a/eigrpd/eigrp_siaquery.c b/eigrpd/eigrp_siaquery.c index 85b6ca9fe4..9447efb2e2 100644 --- a/eigrpd/eigrp_siaquery.c +++ b/eigrpd/eigrp_siaquery.c @@ -105,8 +105,7 @@ void eigrp_siaquery_receive(struct eigrp *eigrp, struct ip *iph, msg.data.ipv4_int_type = tlv; msg.entry = entry; msg.prefix = dest; - int event = eigrp_get_fsm_event(&msg); - eigrp_fsm_event(&msg, event); + eigrp_fsm_event(&msg); } eigrp_IPv4_InternalTLV_free(tlv); } diff --git a/eigrpd/eigrp_siareply.c b/eigrpd/eigrp_siareply.c index c03a34322e..2cf7520a96 100644 --- a/eigrpd/eigrp_siareply.c +++ b/eigrpd/eigrp_siareply.c @@ -104,8 +104,7 @@ void eigrp_siareply_receive(struct eigrp *eigrp, struct ip *iph, msg.data.ipv4_int_type = tlv; msg.entry = entry; msg.prefix = dest; - int event = eigrp_get_fsm_event(&msg); - eigrp_fsm_event(&msg, event); + eigrp_fsm_event(&msg); } eigrp_IPv4_InternalTLV_free(tlv); } diff --git a/eigrpd/eigrp_topology.c b/eigrpd/eigrp_topology.c index f78a43739d..d4d55393a8 100644 --- a/eigrpd/eigrp_topology.c +++ b/eigrpd/eigrp_topology.c @@ -497,8 +497,7 @@ void eigrp_topology_neighbor_down(struct eigrp *eigrp, msg.data.ipv4_int_type = tlv; msg.entry = entry; msg.prefix = prefix; - int event = eigrp_get_fsm_event(&msg); - eigrp_fsm_event(&msg, event); + eigrp_fsm_event(&msg); } } } diff --git a/eigrpd/eigrp_update.c b/eigrpd/eigrp_update.c index a3d6210e71..89b8ecd928 100644 --- a/eigrpd/eigrp_update.c +++ b/eigrpd/eigrp_update.c @@ -146,8 +146,7 @@ static void eigrp_update_receive_GR_ask(struct eigrp *eigrp, fsm_msg.prefix = prefix; /* send message to FSM */ - int event = eigrp_get_fsm_event(&fsm_msg); - eigrp_fsm_event(&fsm_msg, event); + eigrp_fsm_event(&fsm_msg); /* free memory used by TLV */ eigrp_IPv4_InternalTLV_free(tlv_max); @@ -321,8 +320,7 @@ void eigrp_update_receive(struct eigrp *eigrp, struct ip *iph, msg.data.ipv4_int_type = tlv; msg.entry = entry; msg.prefix = dest; - int event = eigrp_get_fsm_event(&msg); - eigrp_fsm_event(&msg, event); + eigrp_fsm_event(&msg); } else { /*Here comes topology information save*/ pe = eigrp_prefix_entry_new(); @@ -987,8 +985,7 @@ static void eigrp_update_send_GR_part(struct eigrp_neighbor *nbr) fsm_msg.prefix = pe; /* send message to FSM */ - int event = eigrp_get_fsm_event(&fsm_msg); - eigrp_fsm_event(&fsm_msg, event); + eigrp_fsm_event(&fsm_msg); /* free memory used by TLV */ eigrp_IPv4_InternalTLV_free(tlv_max); From 7cfa4322558c56b5a0801b17e60598c5a49779dd Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Tue, 22 Aug 2017 16:19:23 -0400 Subject: [PATCH 099/130] eigrpd: make fsm msg data_type an enum We need to eventually be able to handle multiple data types to figure out if the distance is better worse. Signed-off-by: Donald Sharp --- eigrpd/eigrp_query.c | 2 +- eigrpd/eigrp_reply.c | 2 +- eigrpd/eigrp_siaquery.c | 2 +- eigrpd/eigrp_siareply.c | 2 +- eigrpd/eigrp_structs.h | 7 ++++- eigrpd/eigrp_topology.c | 57 +++++++++++++++++++++++++---------------- eigrpd/eigrp_update.c | 6 ++--- 7 files changed, 48 insertions(+), 30 deletions(-) diff --git a/eigrpd/eigrp_query.c b/eigrpd/eigrp_query.c index b9351ed896..92aa7f9855 100644 --- a/eigrpd/eigrp_query.c +++ b/eigrpd/eigrp_query.c @@ -131,7 +131,7 @@ void eigrp_query_receive(struct eigrp *eigrp, struct ip *iph, nbr); msg.packet_type = EIGRP_OPC_QUERY; msg.eigrp = eigrp; - msg.data_type = EIGRP_TLV_IPv4_INT; + msg.data_type = EIGRP_INT; msg.adv_router = nbr; msg.data.ipv4_int_type = tlv; msg.entry = entry; diff --git a/eigrpd/eigrp_reply.c b/eigrpd/eigrp_reply.c index 7015413f56..92cea77305 100644 --- a/eigrpd/eigrp_reply.c +++ b/eigrpd/eigrp_reply.c @@ -237,7 +237,7 @@ void eigrp_reply_receive(struct eigrp *eigrp, struct ip *iph, msg.packet_type = EIGRP_OPC_REPLY; msg.eigrp = eigrp; - msg.data_type = EIGRP_TLV_IPv4_INT; + msg.data_type = EIGRP_INT; msg.adv_router = nbr; msg.data.ipv4_int_type = tlv; msg.entry = entry; diff --git a/eigrpd/eigrp_siaquery.c b/eigrpd/eigrp_siaquery.c index 9447efb2e2..60decc5bef 100644 --- a/eigrpd/eigrp_siaquery.c +++ b/eigrpd/eigrp_siaquery.c @@ -100,7 +100,7 @@ void eigrp_siaquery_receive(struct eigrp *eigrp, struct ip *iph, nbr); msg.packet_type = EIGRP_OPC_SIAQUERY; msg.eigrp = eigrp; - msg.data_type = EIGRP_TLV_IPv4_INT; + msg.data_type = EIGRP_INT; msg.adv_router = nbr; msg.data.ipv4_int_type = tlv; msg.entry = entry; diff --git a/eigrpd/eigrp_siareply.c b/eigrpd/eigrp_siareply.c index 2cf7520a96..e960940200 100644 --- a/eigrpd/eigrp_siareply.c +++ b/eigrpd/eigrp_siareply.c @@ -99,7 +99,7 @@ void eigrp_siareply_receive(struct eigrp *eigrp, struct ip *iph, nbr); msg.packet_type = EIGRP_OPC_SIAQUERY; msg.eigrp = eigrp; - msg.data_type = EIGRP_TLV_IPv4_INT; + msg.data_type = EIGRP_INT; msg.adv_router = nbr; msg.data.ipv4_int_type = tlv; msg.entry = entry; diff --git a/eigrpd/eigrp_structs.h b/eigrpd/eigrp_structs.h index 0c15436d4f..c81dfebb46 100644 --- a/eigrpd/eigrp_structs.h +++ b/eigrpd/eigrp_structs.h @@ -499,6 +499,11 @@ struct eigrp_neighbor_entry { }; //--------------------------------------------------------------------------------------------------------------------------------------------- +typedef enum { + EIGRP_CONNECTED, + EIGRP_INT, + EIGRP_EXT, +} msg_data_t; /* EIGRP Finite State Machine */ @@ -508,7 +513,7 @@ struct eigrp_fsm_action_message { struct eigrp_neighbor *adv_router; // advertising neighbor struct eigrp_neighbor_entry *entry; struct eigrp_prefix_entry *prefix; - int data_type; // internal or external tlv type + msg_data_t data_type; // internal or external tlv type union { struct TLV_IPv4_External_type *ipv4_ext_data; struct TLV_IPv4_Internal_type *ipv4_int_type; diff --git a/eigrpd/eigrp_topology.c b/eigrpd/eigrp_topology.c index d4d55393a8..d1c09d6612 100644 --- a/eigrpd/eigrp_topology.c +++ b/eigrpd/eigrp_topology.c @@ -384,32 +384,45 @@ enum metric_change eigrp_topology_update_distance(struct eigrp_fsm_action_messag struct TLV_IPv4_External_type *ext_data = NULL; struct TLV_IPv4_Internal_type *int_data = NULL; - if (msg->data_type == EIGRP_TLV_IPv4_INT) { - u_int32_t new_reported_distance; + switch(msg->data_type) { + case EIGRP_CONNECTED: + break; + case EIGRP_INT: + { + u_int32_t new_reported_distance; - int_data = msg->data.ipv4_int_type; - if (eigrp_metrics_is_same(int_data->metric, - entry->reported_metric)) { - return change; // No change - } + int_data = msg->data.ipv4_int_type; + if (eigrp_metrics_is_same(int_data->metric, + entry->reported_metric)) { + return change; // No change + } - new_reported_distance = eigrp_calculate_metrics(eigrp, - int_data->metric); + new_reported_distance = eigrp_calculate_metrics(eigrp, + int_data->metric); - if (entry->reported_distance < new_reported_distance) - change = METRIC_INCREASE; - else - change = METRIC_DECREASE; + if (entry->reported_distance < new_reported_distance) + change = METRIC_INCREASE; + else + change = METRIC_DECREASE; - entry->reported_metric = int_data->metric; - entry->reported_distance = new_reported_distance; + entry->reported_metric = int_data->metric; + entry->reported_distance = new_reported_distance; eigrp_calculate_metrics(eigrp, int_data->metric); - entry->distance = eigrp_calculate_total_metrics(eigrp, entry); - } else { - ext_data = msg->data.ipv4_ext_data; - if (eigrp_metrics_is_same(ext_data->metric, - entry->reported_metric)) - return change; + entry->distance = eigrp_calculate_total_metrics(eigrp, entry); + break; + } + case EIGRP_EXT: + { + ext_data = msg->data.ipv4_ext_data; + if (eigrp_metrics_is_same(ext_data->metric, + entry->reported_metric)) + return change; + + break; + } + default: + zlog_err("%s: Please implement handler", __PRETTY_FUNCTION__); + break; } /* * Move to correct position in list according to new distance @@ -492,7 +505,7 @@ void eigrp_topology_neighbor_down(struct eigrp *eigrp, tlv->metric.delay = EIGRP_MAX_METRIC; msg.packet_type = EIGRP_OPC_UPDATE; msg.eigrp = eigrp; - msg.data_type = EIGRP_TLV_IPv4_INT; + msg.data_type = EIGRP_INT; msg.adv_router = nbr; msg.data.ipv4_int_type = tlv; msg.entry = entry; diff --git a/eigrpd/eigrp_update.c b/eigrpd/eigrp_update.c index 89b8ecd928..ba54fa5727 100644 --- a/eigrpd/eigrp_update.c +++ b/eigrpd/eigrp_update.c @@ -139,7 +139,7 @@ static void eigrp_update_receive_GR_ask(struct eigrp *eigrp, fsm_msg.packet_type = EIGRP_OPC_UPDATE; fsm_msg.eigrp = eigrp; - fsm_msg.data_type = EIGRP_TLV_IPv4_INT; + fsm_msg.data_type = EIGRP_INT; fsm_msg.adv_router = nbr; fsm_msg.data.ipv4_int_type = tlv_max; fsm_msg.entry = entry; @@ -315,7 +315,7 @@ void eigrp_update_receive(struct eigrp *eigrp, struct ip *iph, msg.packet_type = EIGRP_OPC_UPDATE; msg.eigrp = eigrp; - msg.data_type = EIGRP_TLV_IPv4_INT; + msg.data_type = EIGRP_INT; msg.adv_router = nbr; msg.data.ipv4_int_type = tlv; msg.entry = entry; @@ -978,7 +978,7 @@ static void eigrp_update_send_GR_part(struct eigrp_neighbor *nbr) fsm_msg.packet_type = EIGRP_OPC_UPDATE; fsm_msg.eigrp = e; - fsm_msg.data_type = EIGRP_TLV_IPv4_INT; + fsm_msg.data_type = EIGRP_INT; fsm_msg.adv_router = nbr; fsm_msg.data.ipv4_int_type = tlv_max; fsm_msg.entry = entry; From 3aea4e507bc6c129e1bdcfbaaefca6a829ee1825 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Tue, 22 Aug 2017 16:24:23 -0400 Subject: [PATCH 100/130] eigrpd: Improve external route distance comparison If the new nexthop is external while the previous best was Internal or Connected, it should always loose. Signed-off-by: Donald Sharp --- eigrpd/eigrp_topology.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/eigrpd/eigrp_topology.c b/eigrpd/eigrp_topology.c index d1c09d6612..9f62e5e899 100644 --- a/eigrpd/eigrp_topology.c +++ b/eigrpd/eigrp_topology.c @@ -414,9 +414,13 @@ enum metric_change eigrp_topology_update_distance(struct eigrp_fsm_action_messag case EIGRP_EXT: { ext_data = msg->data.ipv4_ext_data; - if (eigrp_metrics_is_same(ext_data->metric, - entry->reported_metric)) - return change; + + if (prefix->nt == EIGRP_TOPOLOGY_TYPE_REMOTE_EXTERNAL) { + if (eigrp_metrics_is_same(ext_data->metric, + entry->reported_metric)) + return change; + } else + change = METRIC_INCREASE; break; } From db6ec9ff6e8e1641c586ce32b4422b6e0c896500 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Tue, 22 Aug 2017 19:19:10 -0400 Subject: [PATCH 101/130] eigrpd: Remove union from FSM msg Remove the union of passing the TLV and just pass the metric in. Signed-off-by: Donald Sharp --- eigrpd/eigrp_query.c | 2 +- eigrpd/eigrp_reply.c | 2 +- eigrpd/eigrp_siaquery.c | 2 +- eigrpd/eigrp_siareply.c | 2 +- eigrpd/eigrp_structs.h | 5 +--- eigrpd/eigrp_topology.c | 65 +++++++++++++++++++---------------------- eigrpd/eigrp_update.c | 6 ++-- 7 files changed, 38 insertions(+), 46 deletions(-) diff --git a/eigrpd/eigrp_query.c b/eigrpd/eigrp_query.c index 92aa7f9855..4757097315 100644 --- a/eigrpd/eigrp_query.c +++ b/eigrpd/eigrp_query.c @@ -133,7 +133,7 @@ void eigrp_query_receive(struct eigrp *eigrp, struct ip *iph, msg.eigrp = eigrp; msg.data_type = EIGRP_INT; msg.adv_router = nbr; - msg.data.ipv4_int_type = tlv; + msg.metrics = tlv->metric; msg.entry = entry; msg.prefix = dest; eigrp_fsm_event(&msg); diff --git a/eigrpd/eigrp_reply.c b/eigrpd/eigrp_reply.c index 92cea77305..304a1a5242 100644 --- a/eigrpd/eigrp_reply.c +++ b/eigrpd/eigrp_reply.c @@ -239,7 +239,7 @@ void eigrp_reply_receive(struct eigrp *eigrp, struct ip *iph, msg.eigrp = eigrp; msg.data_type = EIGRP_INT; msg.adv_router = nbr; - msg.data.ipv4_int_type = tlv; + msg.metrics = tlv->metric; msg.entry = entry; msg.prefix = dest; eigrp_fsm_event(&msg); diff --git a/eigrpd/eigrp_siaquery.c b/eigrpd/eigrp_siaquery.c index 60decc5bef..cd04f88595 100644 --- a/eigrpd/eigrp_siaquery.c +++ b/eigrpd/eigrp_siaquery.c @@ -102,7 +102,7 @@ void eigrp_siaquery_receive(struct eigrp *eigrp, struct ip *iph, msg.eigrp = eigrp; msg.data_type = EIGRP_INT; msg.adv_router = nbr; - msg.data.ipv4_int_type = tlv; + msg.metrics = tlv->metric; msg.entry = entry; msg.prefix = dest; eigrp_fsm_event(&msg); diff --git a/eigrpd/eigrp_siareply.c b/eigrpd/eigrp_siareply.c index e960940200..5e83549488 100644 --- a/eigrpd/eigrp_siareply.c +++ b/eigrpd/eigrp_siareply.c @@ -101,7 +101,7 @@ void eigrp_siareply_receive(struct eigrp *eigrp, struct ip *iph, msg.eigrp = eigrp; msg.data_type = EIGRP_INT; msg.adv_router = nbr; - msg.data.ipv4_int_type = tlv; + msg.metrics = tlv->metric; msg.entry = entry; msg.prefix = dest; eigrp_fsm_event(&msg); diff --git a/eigrpd/eigrp_structs.h b/eigrpd/eigrp_structs.h index c81dfebb46..6bb0c5cc2b 100644 --- a/eigrpd/eigrp_structs.h +++ b/eigrpd/eigrp_structs.h @@ -514,10 +514,7 @@ struct eigrp_fsm_action_message { struct eigrp_neighbor_entry *entry; struct eigrp_prefix_entry *prefix; msg_data_t data_type; // internal or external tlv type - union { - struct TLV_IPv4_External_type *ipv4_ext_data; - struct TLV_IPv4_Internal_type *ipv4_int_type; - } data; + struct eigrp_metrics metrics; }; #endif /* _ZEBRA_EIGRP_STRUCTURES_H_ */ diff --git a/eigrpd/eigrp_topology.c b/eigrpd/eigrp_topology.c index 9f62e5e899..4555ced477 100644 --- a/eigrpd/eigrp_topology.c +++ b/eigrpd/eigrp_topology.c @@ -380,50 +380,45 @@ enum metric_change eigrp_topology_update_distance(struct eigrp_fsm_action_messag struct eigrp_prefix_entry *prefix = msg->prefix; struct eigrp_neighbor_entry *entry = msg->entry; enum metric_change change = METRIC_SAME; + u_int32_t new_reported_distance; + assert(entry); - struct TLV_IPv4_External_type *ext_data = NULL; - struct TLV_IPv4_Internal_type *int_data = NULL; switch(msg->data_type) { case EIGRP_CONNECTED: + if (prefix->nt == EIGRP_TOPOLOGY_TYPE_CONNECTED) + return change; + + change = METRIC_DECREASE; break; case EIGRP_INT: - { - u_int32_t new_reported_distance; - - int_data = msg->data.ipv4_int_type; - if (eigrp_metrics_is_same(int_data->metric, - entry->reported_metric)) { - return change; // No change - } - - new_reported_distance = eigrp_calculate_metrics(eigrp, - int_data->metric); - - if (entry->reported_distance < new_reported_distance) - change = METRIC_INCREASE; - else - change = METRIC_DECREASE; - - entry->reported_metric = int_data->metric; - entry->reported_distance = new_reported_distance; - eigrp_calculate_metrics(eigrp, int_data->metric); - entry->distance = eigrp_calculate_total_metrics(eigrp, entry); - break; + if (eigrp_metrics_is_same(msg->metrics, + entry->reported_metric)) { + return change; // No change } + + new_reported_distance = eigrp_calculate_metrics(eigrp, + msg->metrics); + + if (entry->reported_distance < new_reported_distance) + change = METRIC_INCREASE; + else + change = METRIC_DECREASE; + + entry->reported_metric = msg->metrics; + entry->reported_distance = new_reported_distance; + eigrp_calculate_metrics(eigrp, msg->metrics); + entry->distance = eigrp_calculate_total_metrics(eigrp, entry); + break; case EIGRP_EXT: - { - ext_data = msg->data.ipv4_ext_data; - - if (prefix->nt == EIGRP_TOPOLOGY_TYPE_REMOTE_EXTERNAL) { - if (eigrp_metrics_is_same(ext_data->metric, - entry->reported_metric)) - return change; - } else - change = METRIC_INCREASE; + if (prefix->nt == EIGRP_TOPOLOGY_TYPE_REMOTE_EXTERNAL) { + if (eigrp_metrics_is_same(msg->metrics, + entry->reported_metric)) + return change; + } else + change = METRIC_INCREASE; break; - } default: zlog_err("%s: Please implement handler", __PRETTY_FUNCTION__); break; @@ -511,7 +506,7 @@ void eigrp_topology_neighbor_down(struct eigrp *eigrp, msg.eigrp = eigrp; msg.data_type = EIGRP_INT; msg.adv_router = nbr; - msg.data.ipv4_int_type = tlv; + msg.metrics = tlv->metric; msg.entry = entry; msg.prefix = prefix; eigrp_fsm_event(&msg); diff --git a/eigrpd/eigrp_update.c b/eigrpd/eigrp_update.c index ba54fa5727..98bfc95e4d 100644 --- a/eigrpd/eigrp_update.c +++ b/eigrpd/eigrp_update.c @@ -141,7 +141,7 @@ static void eigrp_update_receive_GR_ask(struct eigrp *eigrp, fsm_msg.eigrp = eigrp; fsm_msg.data_type = EIGRP_INT; fsm_msg.adv_router = nbr; - fsm_msg.data.ipv4_int_type = tlv_max; + fsm_msg.metrics = tlv_max->metric; fsm_msg.entry = entry; fsm_msg.prefix = prefix; @@ -317,7 +317,7 @@ void eigrp_update_receive(struct eigrp *eigrp, struct ip *iph, msg.eigrp = eigrp; msg.data_type = EIGRP_INT; msg.adv_router = nbr; - msg.data.ipv4_int_type = tlv; + msg.metrics = tlv->metric; msg.entry = entry; msg.prefix = dest; eigrp_fsm_event(&msg); @@ -980,7 +980,7 @@ static void eigrp_update_send_GR_part(struct eigrp_neighbor *nbr) fsm_msg.eigrp = e; fsm_msg.data_type = EIGRP_INT; fsm_msg.adv_router = nbr; - fsm_msg.data.ipv4_int_type = tlv_max; + fsm_msg.metrics = tlv_max->metric; fsm_msg.entry = entry; fsm_msg.prefix = pe; From 5ca6df7822a8cddd1a10b27760f6b6e274aced5d Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Tue, 22 Aug 2017 19:48:23 -0400 Subject: [PATCH 102/130] eigrpd: No need to create TLV type There is no need to create a TLV type to pass in for the FSM message. Signed-off-by: Donald Sharp --- eigrpd/eigrp_packet.c | 20 ++++++++++---------- eigrpd/eigrp_packet.h | 1 - eigrpd/eigrp_topology.c | 27 +++++++++++++-------------- eigrpd/eigrp_update.c | 38 ++++++-------------------------------- 4 files changed, 29 insertions(+), 57 deletions(-) diff --git a/eigrpd/eigrp_packet.c b/eigrpd/eigrp_packet.c index 72aaef1b37..d4e8264f20 100644 --- a/eigrpd/eigrp_packet.c +++ b/eigrpd/eigrp_packet.c @@ -1101,6 +1101,16 @@ struct eigrp_packet *eigrp_packet_duplicate(struct eigrp_packet *old, return new; } +static struct TLV_IPv4_Internal_type *eigrp_IPv4_InternalTLV_new() +{ + struct TLV_IPv4_Internal_type *new; + + new = XCALLOC(MTYPE_EIGRP_IPV4_INT_TLV, + sizeof(struct TLV_IPv4_Internal_type)); + + return new; +} + struct TLV_IPv4_Internal_type *eigrp_read_ipv4_tlv(struct stream *s) { struct TLV_IPv4_Internal_type *tlv; @@ -1332,16 +1342,6 @@ void eigrp_authTLV_SHA256_free(struct TLV_SHA256_Authentication_Type *authTLV) XFREE(MTYPE_EIGRP_AUTH_SHA256_TLV, authTLV); } -struct TLV_IPv4_Internal_type *eigrp_IPv4_InternalTLV_new() -{ - struct TLV_IPv4_Internal_type *new; - - new = XCALLOC(MTYPE_EIGRP_IPV4_INT_TLV, - sizeof(struct TLV_IPv4_Internal_type)); - - return new; -} - void eigrp_IPv4_InternalTLV_free( struct TLV_IPv4_Internal_type *IPv4_InternalTLV) { diff --git a/eigrpd/eigrp_packet.h b/eigrpd/eigrp_packet.h index e72048ecc3..e52fd268fa 100644 --- a/eigrpd/eigrp_packet.h +++ b/eigrpd/eigrp_packet.h @@ -152,7 +152,6 @@ extern int eigrp_check_sha256_digest(struct stream *, struct eigrp_neighbor *, u_char); -extern struct TLV_IPv4_Internal_type *eigrp_IPv4_InternalTLV_new(void); extern void eigrp_IPv4_InternalTLV_free(struct TLV_IPv4_Internal_type *); extern struct TLV_Sequence_Type *eigrp_SequenceTLV_new(void); diff --git a/eigrpd/eigrp_topology.c b/eigrpd/eigrp_topology.c index 4555ced477..3ba8c5b5fd 100644 --- a/eigrpd/eigrp_topology.c +++ b/eigrpd/eigrp_topology.c @@ -497,20 +497,19 @@ void eigrp_topology_neighbor_down(struct eigrp *eigrp, for (ALL_LIST_ELEMENTS(eigrp->topology_table, node1, node11, prefix)) { for (ALL_LIST_ELEMENTS(prefix->entries, node2, node22, entry)) { - if (entry->adv_router == nbr) { - struct eigrp_fsm_action_message msg; - struct TLV_IPv4_Internal_type *tlv = - eigrp_IPv4_InternalTLV_new(); - tlv->metric.delay = EIGRP_MAX_METRIC; - msg.packet_type = EIGRP_OPC_UPDATE; - msg.eigrp = eigrp; - msg.data_type = EIGRP_INT; - msg.adv_router = nbr; - msg.metrics = tlv->metric; - msg.entry = entry; - msg.prefix = prefix; - eigrp_fsm_event(&msg); - } + struct eigrp_fsm_action_message msg; + + if (entry->adv_router != nbr) + continue; + + msg.metrics.delay = EIGRP_MAX_METRIC; + msg.packet_type = EIGRP_OPC_UPDATE; + msg.eigrp = eigrp; + msg.data_type = EIGRP_INT; + msg.adv_router = nbr; + msg.entry = entry; + msg.prefix = prefix; + eigrp_fsm_event(&msg); } } diff --git a/eigrpd/eigrp_update.c b/eigrpd/eigrp_update.c index 98bfc95e4d..e4b7883741 100644 --- a/eigrpd/eigrp_update.c +++ b/eigrpd/eigrp_update.c @@ -112,7 +112,7 @@ static void eigrp_update_receive_GR_ask(struct eigrp *eigrp, { struct listnode *node1; struct eigrp_prefix_entry *prefix; - struct TLV_IPv4_Internal_type *tlv_max; + struct eigrp_fsm_action_message fsm_msg; /* iterate over all prefixes which weren't advertised by neighbor */ for (ALL_LIST_ELEMENTS_RO(nbr_prefixes, node1, prefix)) { @@ -120,19 +120,9 @@ static void eigrp_update_receive_GR_ask(struct eigrp *eigrp, inet_ntoa(prefix->destination_ipv4->prefix), prefix->destination_ipv4->prefixlen); - /* create internal IPv4 TLV with infinite delay */ - tlv_max = eigrp_IPv4_InternalTLV_new(); - tlv_max->type = EIGRP_TLV_IPv4_INT; - tlv_max->length = 28U; - tlv_max->metric = prefix->reported_metric; + fsm_msg.metrics = prefix->reported_metric; /* set delay to MAX */ - tlv_max->metric.delay = EIGRP_MAX_METRIC; - tlv_max->destination = prefix->destination_ipv4->prefix; - tlv_max->prefix_length = prefix->destination_ipv4->prefixlen; - - - /* prepare message for FSM */ - struct eigrp_fsm_action_message fsm_msg; + fsm_msg.metrics.delay = EIGRP_MAX_METRIC; struct eigrp_neighbor_entry *entry = eigrp_prefix_entry_lookup(prefix->entries, nbr); @@ -141,15 +131,11 @@ static void eigrp_update_receive_GR_ask(struct eigrp *eigrp, fsm_msg.eigrp = eigrp; fsm_msg.data_type = EIGRP_INT; fsm_msg.adv_router = nbr; - fsm_msg.metrics = tlv_max->metric; fsm_msg.entry = entry; fsm_msg.prefix = prefix; /* send message to FSM */ eigrp_fsm_event(&fsm_msg); - - /* free memory used by TLV */ - eigrp_IPv4_InternalTLV_free(tlv_max); } } @@ -845,7 +831,6 @@ static void eigrp_update_send_GR_part(struct eigrp_neighbor *nbr) struct list *prefixes; u_int32_t flags; unsigned int send_prefixes; - struct TLV_IPv4_Internal_type *tlv_max; /* get prefixes to send to neighbor */ prefixes = nbr->nbr_gr_prefixes_send; @@ -960,16 +945,6 @@ static void eigrp_update_send_GR_part(struct eigrp_neighbor *nbr) zlog_info("Filtered prefix %s will be removed.", inet_ntoa(dest_addr->prefix)); - tlv_max = eigrp_IPv4_InternalTLV_new(); - tlv_max->type = EIGRP_TLV_IPv4_INT; - tlv_max->length = 28U; - tlv_max->metric = pe->reported_metric; - /* set delay to MAX */ - tlv_max->metric.delay = EIGRP_MAX_METRIC; - tlv_max->destination = pe->destination_ipv4->prefix; - tlv_max->prefix_length = - pe->destination_ipv4->prefixlen; - /* prepare message for FSM */ struct eigrp_fsm_action_message fsm_msg; @@ -980,15 +955,14 @@ static void eigrp_update_send_GR_part(struct eigrp_neighbor *nbr) fsm_msg.eigrp = e; fsm_msg.data_type = EIGRP_INT; fsm_msg.adv_router = nbr; - fsm_msg.metrics = tlv_max->metric; + fsm_msg.metrics = pe->reported_metric; + /* Set delay to MAX */ + fsm_msg.metrics.delay = EIGRP_MAX_METRIC; fsm_msg.entry = entry; fsm_msg.prefix = pe; /* send message to FSM */ eigrp_fsm_event(&fsm_msg); - - /* free memory used by TLV */ - eigrp_IPv4_InternalTLV_free(tlv_max); } /* * End of filtering From 348addb4e7e44f614f84d75d41a0af1a8ad2e6c1 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 23 Aug 2017 13:26:50 -0400 Subject: [PATCH 103/130] eigrpd: Use FSM for interface pe already known. There exists a case where a switch already has a eigrp_prefix_entry for a interface that is coming up. In this situation, we need to use the FSM to let the connected route take precedence instead of blindly just updating the world about it. Signed-off-by: Donald Sharp --- eigrpd/eigrp_interface.c | 49 +++++++++++++++++++++++++++------------- 1 file changed, 33 insertions(+), 16 deletions(-) diff --git a/eigrpd/eigrp_interface.c b/eigrpd/eigrp_interface.c index b316a22d88..207001778d 100644 --- a/eigrpd/eigrp_interface.c +++ b/eigrpd/eigrp_interface.c @@ -53,6 +53,7 @@ #include "eigrpd/eigrp_network.h" #include "eigrpd/eigrp_topology.h" #include "eigrpd/eigrp_memory.h" +#include "eigrpd/eigrp_fsm.h" static void eigrp_delete_from_if(struct interface *, struct eigrp_interface *); @@ -279,6 +280,15 @@ int eigrp_if_up(struct eigrp_interface *ei) /*Add connected entry to topology table*/ + ne = eigrp_neighbor_entry_new(); + ne->ei = ei; + ne->reported_metric = metric; + ne->total_metric = metric; + ne->distance = eigrp_calculate_metrics(eigrp, metric); + ne->reported_distance = 0; + ne->adv_router = eigrp->neighbor_self; + ne->flags = EIGRP_NEIGHBOR_ENTRY_SUCCESSOR_FLAG; + struct prefix_ipv4 dest_addr; dest_addr.family = AF_INET; @@ -297,29 +307,36 @@ int eigrp_if_up(struct eigrp_interface *ei) pe->af = AF_INET; pe->nt = EIGRP_TOPOLOGY_TYPE_CONNECTED; + ne->prefix = pe; pe->state = EIGRP_FSM_STATE_PASSIVE; pe->fdistance = eigrp_calculate_metrics(eigrp, metric); pe->req_action |= EIGRP_FSM_NEED_UPDATE; eigrp_prefix_entry_add(eigrp->topology_table, pe); listnode_add(eigrp->topology_changes_internalIPV4, pe); - } - ne = eigrp_neighbor_entry_new(); - ne->ei = ei; - ne->reported_metric = metric; - ne->total_metric = metric; - ne->distance = eigrp_calculate_metrics(eigrp, metric); - ne->reported_distance = 0; - ne->prefix = pe; - ne->adv_router = eigrp->neighbor_self; - ne->flags = EIGRP_NEIGHBOR_ENTRY_SUCCESSOR_FLAG; - eigrp_neighbor_entry_add(pe, ne); - for (ALL_LIST_ELEMENTS(eigrp->eiflist, node, nnode, ei2)) { - eigrp_update_send(ei2); - } + eigrp_neighbor_entry_add(pe, ne); - pe->req_action &= ~EIGRP_FSM_NEED_UPDATE; - listnode_delete(eigrp->topology_changes_internalIPV4, pe); + for (ALL_LIST_ELEMENTS(eigrp->eiflist, node, nnode, ei2)) { + eigrp_update_send(ei2); + } + + pe->req_action &= ~EIGRP_FSM_NEED_UPDATE; + listnode_delete(eigrp->topology_changes_internalIPV4, pe); + } else { + struct eigrp_fsm_action_message msg; + + ne->prefix = pe; + eigrp_neighbor_entry_add(pe, ne); + + msg.packet_type = EIGRP_OPC_UPDATE; + msg.eigrp = eigrp; + msg.data_type = EIGRP_CONNECTED; + msg.adv_router = NULL; + msg.entry = ne; + msg.prefix = pe; + + eigrp_fsm_event(&msg); + } return 1; } From 02b459988199f05c81d4353d6fd6812c196c7a5d Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 23 Aug 2017 14:19:45 -0400 Subject: [PATCH 104/130] eigrpd: Convert pe->destination_ipv4 to pe->destination Convert the destination_ipv4 to a struct prefix and just call it destination. Signed-off-by: Donald Sharp --- eigrpd/eigrp_dump.c | 7 +++-- eigrpd/eigrp_interface.c | 13 ++++----- eigrpd/eigrp_packet.c | 44 ++++++++++------------------- eigrpd/eigrp_reply.c | 8 +++--- eigrpd/eigrp_structs.h | 5 +--- eigrpd/eigrp_topology.c | 60 ++++++++++++++++++---------------------- eigrpd/eigrp_update.c | 48 +++++++++++++++----------------- 7 files changed, 78 insertions(+), 107 deletions(-) diff --git a/eigrpd/eigrp_dump.c b/eigrpd/eigrp_dump.c index 0cb1ee5876..74515c98cb 100644 --- a/eigrpd/eigrp_dump.c +++ b/eigrpd/eigrp_dump.c @@ -158,7 +158,7 @@ const char *eigrp_topology_ip_string(struct eigrp_prefix_entry *tn) static char buf[EIGRP_IF_STRING_MAXLEN] = ""; u_int32_t ifaddr; - ifaddr = ntohl(tn->destination_ipv4->prefix.s_addr); + ifaddr = ntohl(tn->destination->u.prefix4.s_addr); snprintf(buf, EIGRP_IF_STRING_MAXLEN, "%u.%u.%u.%u", (ifaddr >> 24) & 0xff, (ifaddr >> 16) & 0xff, (ifaddr >> 8) & 0xff, ifaddr & 0xff); @@ -289,11 +289,12 @@ void show_ip_eigrp_topology_header(struct vty *vty, struct eigrp *eigrp) void show_ip_eigrp_prefix_entry(struct vty *vty, struct eigrp_prefix_entry *tn) { struct list *successors = eigrp_topology_get_successor(tn); + char buffer[PREFIX_STRLEN]; vty_out(vty, "%-3c", (tn->state > 0) ? 'A' : 'P'); - vty_out(vty, "%s/%u, ", inet_ntoa(tn->destination_ipv4->prefix), - tn->destination_ipv4->prefixlen); + vty_out(vty, "%s, ", + prefix2str(tn->destination, buffer, PREFIX_STRLEN)); vty_out(vty, "%u successors, ", successors->count); vty_out(vty, "FD is %u, serno: %" PRIu64 " \n", tn->fdistance, tn->serno); diff --git a/eigrpd/eigrp_interface.c b/eigrpd/eigrp_interface.c index 207001778d..bc9172dee6 100644 --- a/eigrpd/eigrp_interface.c +++ b/eigrpd/eigrp_interface.c @@ -289,21 +289,20 @@ int eigrp_if_up(struct eigrp_interface *ei) ne->adv_router = eigrp->neighbor_self; ne->flags = EIGRP_NEIGHBOR_ENTRY_SUCCESSOR_FLAG; - struct prefix_ipv4 dest_addr; + struct prefix dest_addr; dest_addr.family = AF_INET; - dest_addr.prefix = ei->connected->address->u.prefix4; + dest_addr.u.prefix4 = ei->connected->address->u.prefix4; dest_addr.prefixlen = ei->connected->address->prefixlen; - apply_mask_ipv4(&dest_addr); + apply_mask(&dest_addr); pe = eigrp_topology_table_lookup_ipv4(eigrp->topology_table, - &dest_addr); + (struct prefix_ipv4 *)&dest_addr); if (pe == NULL) { pe = eigrp_prefix_entry_new(); pe->serno = eigrp->serno; - pe->destination_ipv4 = prefix_ipv4_new(); - prefix_copy((struct prefix *)pe->destination_ipv4, - (struct prefix *)&dest_addr); + pe->destination = (struct prefix *)prefix_ipv4_new(); + prefix_copy(pe->destination, &dest_addr); pe->af = AF_INET; pe->nt = EIGRP_TOPOLOGY_TYPE_CONNECTED; diff --git a/eigrpd/eigrp_packet.c b/eigrpd/eigrp_packet.c index d4e8264f20..68e7cdcbbe 100644 --- a/eigrpd/eigrp_packet.c +++ b/eigrpd/eigrp_packet.c @@ -1167,21 +1167,21 @@ u_int16_t eigrp_add_internalTLV_to_stream(struct stream *s, u_int16_t length; stream_putw(s, EIGRP_TLV_IPv4_INT); - if (pe->destination_ipv4->prefixlen <= 8) { + if (pe->destination->prefixlen <= 8) { stream_putw(s, 0x001A); length = 0x001A; } - if ((pe->destination_ipv4->prefixlen > 8) - && (pe->destination_ipv4->prefixlen <= 16)) { + if ((pe->destination->prefixlen > 8) + && (pe->destination->prefixlen <= 16)) { stream_putw(s, 0x001B); length = 0x001B; } - if ((pe->destination_ipv4->prefixlen > 16) - && (pe->destination_ipv4->prefixlen <= 24)) { + if ((pe->destination->prefixlen > 16) + && (pe->destination->prefixlen <= 24)) { stream_putw(s, 0x001C); length = 0x001C; } - if (pe->destination_ipv4->prefixlen > 24) { + if (pe->destination->prefixlen > 24) { stream_putw(s, 0x001D); length = 0x001D; } @@ -1200,34 +1200,18 @@ u_int16_t eigrp_add_internalTLV_to_stream(struct stream *s, stream_putc(s, pe->reported_metric.tag); stream_putc(s, pe->reported_metric.flags); - stream_putc(s, pe->destination_ipv4->prefixlen); + stream_putc(s, pe->destination->prefixlen); - if (pe->destination_ipv4->prefixlen <= 8) { - stream_putc(s, pe->destination_ipv4->prefix.s_addr & 0xFF); - } - if ((pe->destination_ipv4->prefixlen > 8) - && (pe->destination_ipv4->prefixlen <= 16)) { - stream_putc(s, pe->destination_ipv4->prefix.s_addr & 0xFF); + stream_putc(s, pe->destination->u.prefix4.s_addr & 0xFF); + if (pe->destination->prefixlen > 8) stream_putc(s, - (pe->destination_ipv4->prefix.s_addr >> 8) & 0xFF); - } - if ((pe->destination_ipv4->prefixlen > 16) - && (pe->destination_ipv4->prefixlen <= 24)) { - stream_putc(s, pe->destination_ipv4->prefix.s_addr & 0xFF); + (pe->destination->u.prefix4.s_addr >> 8) & 0xFF); + if (pe->destination->prefixlen > 16) stream_putc(s, - (pe->destination_ipv4->prefix.s_addr >> 8) & 0xFF); + (pe->destination->u.prefix4.s_addr >> 16) & 0xFF); + if (pe->destination->prefixlen > 24) stream_putc(s, - (pe->destination_ipv4->prefix.s_addr >> 16) & 0xFF); - } - if (pe->destination_ipv4->prefixlen > 24) { - stream_putc(s, pe->destination_ipv4->prefix.s_addr & 0xFF); - stream_putc(s, - (pe->destination_ipv4->prefix.s_addr >> 8) & 0xFF); - stream_putc(s, - (pe->destination_ipv4->prefix.s_addr >> 16) & 0xFF); - stream_putc(s, - (pe->destination_ipv4->prefix.s_addr >> 24) & 0xFF); - } + (pe->destination->u.prefix4.s_addr >> 24) & 0xFF); return length; } diff --git a/eigrpd/eigrp_reply.c b/eigrpd/eigrp_reply.c index 304a1a5242..cc70d1cfee 100644 --- a/eigrpd/eigrp_reply.c +++ b/eigrpd/eigrp_reply.c @@ -87,19 +87,19 @@ void eigrp_send_reply(struct eigrp_neighbor *nbr, struct eigrp_prefix_entry *pe) /* Check if any list fits */ if ((alist - && access_list_apply(alist, (struct prefix *)pe2->destination_ipv4) + && access_list_apply(alist, pe2->destination) == FILTER_DENY) || (plist && prefix_list_apply(plist, - (struct prefix *)pe2->destination_ipv4) + pe2->destination) == PREFIX_DENY) || (alist_i && access_list_apply(alist_i, - (struct prefix *)pe2->destination_ipv4) + pe2->destination) == FILTER_DENY) || (plist_i && prefix_list_apply(plist_i, - (struct prefix *)pe2->destination_ipv4) + pe2->destination) == PREFIX_DENY)) { zlog_info("REPLY SEND: Setting Metric to max"); pe2->reported_metric.delay = EIGRP_MAX_METRIC; diff --git a/eigrpd/eigrp_structs.h b/eigrpd/eigrp_structs.h index 6bb0c5cc2b..b769774a03 100644 --- a/eigrpd/eigrp_structs.h +++ b/eigrpd/eigrp_structs.h @@ -469,10 +469,7 @@ struct eigrp_prefix_entry { u_char af; // address family u_char req_action; // required action - struct prefix_ipv4 - *destination_ipv4; // pointer to struct with ipv4 address - struct prefix_ipv6 - *destination_ipv6; // pointer to struct with ipv6 address + struct prefix *destination; // If network type is REMOTE_EXTERNAL, pointer will have reference to // its external TLV diff --git a/eigrpd/eigrp_topology.c b/eigrpd/eigrp_topology.c index 3ba8c5b5fd..e2f47ced31 100644 --- a/eigrpd/eigrp_topology.c +++ b/eigrpd/eigrp_topology.c @@ -81,25 +81,18 @@ static int eigrp_prefix_entry_cmp(struct eigrp_prefix_entry *node1, { if (node1->af == AF_INET) { if (node2->af == AF_INET) { - if (node1->destination_ipv4->prefix.s_addr - < node2->destination_ipv4->prefix.s_addr) { - return -1; // if it belong above node2 - } else { - if (node1->destination_ipv4->prefix.s_addr - > node2->destination_ipv4->prefix.s_addr) { - return 1; // if it belongs under node2 - } else { - return 0; // same value... ERROR...in - // case of adding same prefix - // again - } - } - } else { + if (node1->destination->u.prefix4.s_addr + < node2->destination->u.prefix4.s_addr) + return -1; + if (node1->destination->u.prefix4.s_addr + > node2->destination->u.prefix4.s_addr) + return 1; + else + return 0; + } else return 1; - } - } else { // TODO check if the prefix dont exists - return 1; // add to end - } + } else + return 1; } /* @@ -125,8 +118,7 @@ struct eigrp_prefix_entry *eigrp_prefix_entry_new() new->rij = list_new(); new->entries->cmp = (int (*)(void *, void *))eigrp_neighbor_entry_cmp; new->distance = new->fdistance = new->rdistance = EIGRP_MAX_METRIC; - new->destination_ipv4 = NULL; - new->destination_ipv6 = NULL; + new->destination = NULL; return new; } @@ -137,9 +129,8 @@ struct eigrp_prefix_entry *eigrp_prefix_entry_new() static int eigrp_neighbor_entry_cmp(struct eigrp_neighbor_entry *entry1, struct eigrp_neighbor_entry *entry2) { - if (entry1->distance - < entry2->distance) // parameter used in list_add_sort () - return -1; // actually set to sort by distance + if (entry1->distance < entry2->distance) + return -1; if (entry1->distance > entry2->distance) return 1; @@ -205,7 +196,8 @@ void eigrp_neighbor_entry_add(struct eigrp_prefix_entry *node, listnode_add_sort(node->entries, entry); entry->prefix = node; - eigrp_zebra_route_add(node->destination_ipv4, l); + eigrp_zebra_route_add((struct prefix_ipv4 *) + node->destination, l); } list_delete(l); @@ -230,7 +222,8 @@ void eigrp_prefix_entry_delete(struct list *topology, list_free(node->entries); list_free(node->rij); listnode_delete(topology, node); - eigrp_zebra_route_delete(node->destination_ipv4); + eigrp_zebra_route_delete((struct prefix_ipv4 *) + node->destination); XFREE(MTYPE_EIGRP_PREFIX_ENTRY, node); } } @@ -243,7 +236,8 @@ void eigrp_neighbor_entry_delete(struct eigrp_prefix_entry *node, { if (listnode_lookup(node->entries, entry) != NULL) { listnode_delete(node->entries, entry); - eigrp_zebra_route_delete(node->destination_ipv4); + eigrp_zebra_route_delete((struct prefix_ipv4 *) + node->destination); XFREE(MTYPE_EIGRP_NEIGHBOR_ENTRY, entry); } } @@ -275,11 +269,8 @@ eigrp_topology_table_lookup_ipv4(struct list *topology_table, struct eigrp_prefix_entry *data; struct listnode *node; for (ALL_LIST_ELEMENTS_RO(topology_table, node, data)) { - if ((data->af == AF_INET) - && (data->destination_ipv4->prefix.s_addr - == address->prefix.s_addr) - && (data->destination_ipv4->prefixlen - == address->prefixlen)) + if (prefix_same(data->destination, + (struct prefix *)address)) return data; } @@ -476,13 +467,16 @@ void eigrp_update_routing_table(struct eigrp_prefix_entry *prefix) struct eigrp_neighbor_entry *entry; if (successors) { - eigrp_zebra_route_add(prefix->destination_ipv4, successors); + eigrp_zebra_route_add((struct prefix_ipv4 *) + prefix->destination, + successors); for (ALL_LIST_ELEMENTS_RO(successors, node, entry)) entry->flags |= EIGRP_NEIGHBOR_ENTRY_INTABLE_FLAG; list_delete(successors); } else { - eigrp_zebra_route_delete(prefix->destination_ipv4); + eigrp_zebra_route_delete((struct prefix_ipv4 *) + prefix->destination); for (ALL_LIST_ELEMENTS_RO(prefix->entries, node, entry)) entry->flags &= ~EIGRP_NEIGHBOR_ENTRY_INTABLE_FLAG; } diff --git a/eigrpd/eigrp_update.c b/eigrpd/eigrp_update.c index e4b7883741..c59a010087 100644 --- a/eigrpd/eigrp_update.c +++ b/eigrpd/eigrp_update.c @@ -116,9 +116,10 @@ static void eigrp_update_receive_GR_ask(struct eigrp *eigrp, /* iterate over all prefixes which weren't advertised by neighbor */ for (ALL_LIST_ELEMENTS_RO(nbr_prefixes, node1, prefix)) { - zlog_debug("GR receive: Neighbor not advertised %s/%d", - inet_ntoa(prefix->destination_ipv4->prefix), - prefix->destination_ipv4->prefixlen); + char buffer[PREFIX_STRLEN]; + zlog_debug("GR receive: Neighbor not advertised %s", + prefix2str(prefix->destination, + buffer, PREFIX_STRLEN)); fsm_msg.metrics = prefix->reported_metric; /* set delay to MAX */ @@ -311,9 +312,8 @@ void eigrp_update_receive(struct eigrp *eigrp, struct ip *iph, /*Here comes topology information save*/ pe = eigrp_prefix_entry_new(); pe->serno = eigrp->serno; - pe->destination_ipv4 = prefix_ipv4_new(); - prefix_copy( - (struct prefix *)pe->destination_ipv4, + pe->destination = (struct prefix *)prefix_ipv4_new(); + prefix_copy(pe->destination, (struct prefix *)&dest_addr); pe->af = AF_INET; pe->state = EIGRP_FSM_STATE_PASSIVE; @@ -571,7 +571,7 @@ void eigrp_update_send_EOT(struct eigrp_neighbor *nbr) struct access_list *alist_i; struct prefix_list *plist_i; struct eigrp *e; - struct prefix_ipv4 *dest_addr; + struct prefix *dest_addr; u_int32_t seq_no = nbr->ei->eigrp->sequence_number; ep = eigrp_packet_new(nbr->ei->ifp->mtu, nbr); @@ -609,7 +609,7 @@ void eigrp_update_send_EOT(struct eigrp_neighbor *nbr) } } /* Get destination address from prefix */ - dest_addr = pe->destination_ipv4; + dest_addr = pe->destination; /* * Filtering @@ -656,7 +656,7 @@ void eigrp_update_send(struct eigrp_interface *ei) struct access_list *alist_i; struct prefix_list *plist_i; struct eigrp *e; - struct prefix_ipv4 *dest_addr; + struct prefix *dest_addr; u_int32_t seq_no = ei->eigrp->sequence_number; if (ei->nbrs->count == 0) @@ -714,7 +714,7 @@ void eigrp_update_send(struct eigrp_interface *ei) has_tlv = 0; } /* Get destination address from prefix */ - dest_addr = pe->destination_ipv4; + dest_addr = pe->destination; /* * Filtering @@ -824,7 +824,7 @@ static void eigrp_update_send_GR_part(struct eigrp_neighbor *nbr) u_int16_t length = EIGRP_HEADER_LEN; struct listnode *node, *nnode; struct eigrp_prefix_entry *pe; - struct prefix_ipv4 *dest_addr; + struct prefix *dest_addr; struct eigrp *e; struct access_list *alist, *alist_i; struct prefix_list *plist, *plist_i; @@ -887,7 +887,7 @@ static void eigrp_update_send_GR_part(struct eigrp_neighbor *nbr) /* * Filtering */ - dest_addr = pe->destination_ipv4; + dest_addr = pe->destination; /* get list from eigrp process */ e = eigrp_lookup(); /* Get access-lists and prefix-lists from process and interface @@ -899,22 +899,20 @@ static void eigrp_update_send_GR_part(struct eigrp_neighbor *nbr) /* Check if any list fits */ if ((alist - && access_list_apply(alist, (struct prefix *)dest_addr) + && access_list_apply(alist, dest_addr) == FILTER_DENY) || (plist - && prefix_list_apply(plist, (struct prefix *)dest_addr) + && prefix_list_apply(plist, dest_addr) == PREFIX_DENY) || (alist_i - && access_list_apply(alist_i, - (struct prefix *)dest_addr) + && access_list_apply(alist_i, dest_addr) == FILTER_DENY) || (plist_i - && prefix_list_apply(plist_i, - (struct prefix *)dest_addr) + && prefix_list_apply(plist_i, dest_addr) == PREFIX_DENY)) { /* do not send filtered route */ zlog_info("Filtered prefix %s won't be sent out.", - inet_ntoa(dest_addr->prefix)); + inet_ntoa(dest_addr->u.prefix4)); } else { /* sending route which wasn't filtered */ length += eigrp_add_internalTLV_to_stream(ep->s, pe); @@ -928,22 +926,20 @@ static void eigrp_update_send_GR_part(struct eigrp_neighbor *nbr) /* Check if any list fits */ if ((alist - && access_list_apply(alist, (struct prefix *)dest_addr) + && access_list_apply(alist, dest_addr) == FILTER_DENY) || (plist - && prefix_list_apply(plist, (struct prefix *)dest_addr) + && prefix_list_apply(plist, dest_addr) == PREFIX_DENY) || (alist_i - && access_list_apply(alist_i, - (struct prefix *)dest_addr) + && access_list_apply(alist_i, dest_addr) == FILTER_DENY) || (plist_i - && prefix_list_apply(plist_i, - (struct prefix *)dest_addr) + && prefix_list_apply(plist_i, dest_addr) == PREFIX_DENY)) { /* do not send filtered route */ zlog_info("Filtered prefix %s will be removed.", - inet_ntoa(dest_addr->prefix)); + inet_ntoa(dest_addr->u.prefix4)); /* prepare message for FSM */ struct eigrp_fsm_action_message fsm_msg; From 836aad7ee82af11cc4c014d0b2de687d43c46f46 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 23 Aug 2017 14:36:06 -0400 Subject: [PATCH 105/130] eigrpd: Refactor to use 'struct prefix' for eigrp_zebra.h Signed-off-by: Donald Sharp --- eigrpd/eigrp_topology.c | 15 +++++---------- eigrpd/eigrp_zebra.c | 21 +++++++++------------ eigrpd/eigrp_zebra.h | 4 ++-- 3 files changed, 16 insertions(+), 24 deletions(-) diff --git a/eigrpd/eigrp_topology.c b/eigrpd/eigrp_topology.c index e2f47ced31..0ae4788fd0 100644 --- a/eigrpd/eigrp_topology.c +++ b/eigrpd/eigrp_topology.c @@ -196,8 +196,7 @@ void eigrp_neighbor_entry_add(struct eigrp_prefix_entry *node, listnode_add_sort(node->entries, entry); entry->prefix = node; - eigrp_zebra_route_add((struct prefix_ipv4 *) - node->destination, l); + eigrp_zebra_route_add(node->destination, l); } list_delete(l); @@ -222,8 +221,7 @@ void eigrp_prefix_entry_delete(struct list *topology, list_free(node->entries); list_free(node->rij); listnode_delete(topology, node); - eigrp_zebra_route_delete((struct prefix_ipv4 *) - node->destination); + eigrp_zebra_route_delete(node->destination); XFREE(MTYPE_EIGRP_PREFIX_ENTRY, node); } } @@ -236,8 +234,7 @@ void eigrp_neighbor_entry_delete(struct eigrp_prefix_entry *node, { if (listnode_lookup(node->entries, entry) != NULL) { listnode_delete(node->entries, entry); - eigrp_zebra_route_delete((struct prefix_ipv4 *) - node->destination); + eigrp_zebra_route_delete(node->destination); XFREE(MTYPE_EIGRP_NEIGHBOR_ENTRY, entry); } } @@ -467,16 +464,14 @@ void eigrp_update_routing_table(struct eigrp_prefix_entry *prefix) struct eigrp_neighbor_entry *entry; if (successors) { - eigrp_zebra_route_add((struct prefix_ipv4 *) - prefix->destination, + eigrp_zebra_route_add(prefix->destination, successors); for (ALL_LIST_ELEMENTS_RO(successors, node, entry)) entry->flags |= EIGRP_NEIGHBOR_ENTRY_INTABLE_FLAG; list_delete(successors); } else { - eigrp_zebra_route_delete((struct prefix_ipv4 *) - prefix->destination); + eigrp_zebra_route_delete(prefix->destination); for (ALL_LIST_ELEMENTS_RO(prefix->entries, node, entry)) entry->flags &= ~EIGRP_NEIGHBOR_ENTRY_INTABLE_FLAG; } diff --git a/eigrpd/eigrp_zebra.c b/eigrpd/eigrp_zebra.c index 5aa7821e18..47871dfd3e 100644 --- a/eigrpd/eigrp_zebra.c +++ b/eigrpd/eigrp_zebra.c @@ -361,7 +361,7 @@ static struct interface *zebra_interface_if_lookup(struct stream *s) ifname_tmp, strnlen(ifname_tmp, INTERFACE_NAMSIZ), VRF_DEFAULT); } -void eigrp_zebra_route_add(struct prefix_ipv4 *p, struct list *successors) +void eigrp_zebra_route_add(struct prefix *p, struct list *successors) { struct zapi_route api; struct zapi_nexthop *api_nh; @@ -395,18 +395,16 @@ void eigrp_zebra_route_add(struct prefix_ipv4 *p, struct list *successors) } if (IS_DEBUG_EIGRP(zebra, ZEBRA_REDISTRIBUTE)) { - char buf[2][INET_ADDRSTRLEN]; - zlog_debug( - "Zebra: Route add %s/%d nexthop %s", - inet_ntop(AF_INET, &p->prefix, buf[0], sizeof(buf[0])), - p->prefixlen, inet_ntop(AF_INET, 0 /*&p->nexthop*/, - buf[1], sizeof(buf[1]))); + char buf[2][PREFIX_STRLEN]; + zlog_debug("Zebra: Route add %s nexthop %s", + prefix2str(p, buf[0], PREFIX_STRLEN), + inet_ntop(AF_INET, 0, buf[1], PREFIX_STRLEN)); } zclient_route_send(ZEBRA_ROUTE_ADD, zclient, &api); } -void eigrp_zebra_route_delete(struct prefix_ipv4 *p) +void eigrp_zebra_route_delete(struct prefix *p) { struct zapi_route api; @@ -421,10 +419,9 @@ void eigrp_zebra_route_delete(struct prefix_ipv4 *p) zclient_route_send(ZEBRA_ROUTE_DELETE, zclient, &api); if (IS_DEBUG_EIGRP(zebra, ZEBRA_REDISTRIBUTE)) { - char buf[INET_ADDRSTRLEN]; - zlog_debug("Zebra: Route del %s/%d", - inet_ntop(AF_INET, &p->prefix, buf, sizeof(buf)), - p->prefixlen); + char buf[PREFIX_STRLEN]; + zlog_debug("Zebra: Route del %s", + prefix2str(p, buf, PREFIX_STRLEN)); } return; diff --git a/eigrpd/eigrp_zebra.h b/eigrpd/eigrp_zebra.h index 3281c47018..1c418dddef 100644 --- a/eigrpd/eigrp_zebra.h +++ b/eigrpd/eigrp_zebra.h @@ -33,8 +33,8 @@ extern void eigrp_zebra_init(void); -extern void eigrp_zebra_route_add(struct prefix_ipv4 *, struct list *); -extern void eigrp_zebra_route_delete(struct prefix_ipv4 *); +extern void eigrp_zebra_route_add(struct prefix *, struct list *); +extern void eigrp_zebra_route_delete(struct prefix *); extern int eigrp_redistribute_set(struct eigrp *, int, struct eigrp_metrics); extern int eigrp_redistribute_unset(struct eigrp *, int); extern int eigrp_is_type_redistributed(int); From 476a146963c960a28c044d89840d9f0cbb41c62e Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 23 Aug 2017 15:31:02 -0400 Subject: [PATCH 106/130] eigrpd: Refactor eigrp_topoloy_table_lookup_ipv4 Allow eigrp_topology_table_lookup_ipv4 to use 'struct prefix' Signed-off-by: Donald Sharp --- eigrpd/eigrp_interface.c | 10 ++++------ eigrpd/eigrp_query.c | 4 ++-- eigrpd/eigrp_reply.c | 4 ++-- eigrpd/eigrp_siaquery.c | 4 ++-- eigrpd/eigrp_siareply.c | 4 ++-- eigrpd/eigrp_topology.c | 5 ++--- eigrpd/eigrp_topology.h | 2 +- eigrpd/eigrp_update.c | 42 ++++++++++++++++++---------------------- 8 files changed, 34 insertions(+), 41 deletions(-) diff --git a/eigrpd/eigrp_interface.c b/eigrpd/eigrp_interface.c index bc9172dee6..9f54b62353 100644 --- a/eigrpd/eigrp_interface.c +++ b/eigrpd/eigrp_interface.c @@ -296,7 +296,7 @@ int eigrp_if_up(struct eigrp_interface *ei) dest_addr.prefixlen = ei->connected->address->prefixlen; apply_mask(&dest_addr); pe = eigrp_topology_table_lookup_ipv4(eigrp->topology_table, - (struct prefix_ipv4 *)&dest_addr); + &dest_addr); if (pe == NULL) { pe = eigrp_prefix_entry_new(); @@ -430,7 +430,7 @@ u_char eigrp_default_iftype(struct interface *ifp) void eigrp_if_free(struct eigrp_interface *ei, int source) { - struct prefix_ipv4 dest_addr; + struct prefix dest_addr; struct eigrp_prefix_entry *pe; struct eigrp *eigrp = eigrp_lookup(); @@ -439,10 +439,8 @@ void eigrp_if_free(struct eigrp_interface *ei, int source) eigrp_hello_send(ei, EIGRP_HELLO_GRACEFUL_SHUTDOWN, NULL); } - dest_addr.family = AF_INET; - dest_addr.prefix = ei->connected->address->u.prefix4; - dest_addr.prefixlen = ei->connected->address->prefixlen; - apply_mask_ipv4(&dest_addr); + dest_addr = *ei->connected->address; + apply_mask(&dest_addr); pe = eigrp_topology_table_lookup_ipv4(eigrp->topology_table, &dest_addr); if (pe) diff --git a/eigrpd/eigrp_query.c b/eigrpd/eigrp_query.c index 4757097315..0167c8b3c2 100644 --- a/eigrpd/eigrp_query.c +++ b/eigrpd/eigrp_query.c @@ -91,7 +91,7 @@ void eigrp_query_receive(struct eigrp *eigrp, struct ip *iph, { struct eigrp_neighbor *nbr; struct TLV_IPv4_Internal_type *tlv; - struct prefix_ipv4 dest_addr; + struct prefix dest_addr; u_int16_t type; u_int16_t length; @@ -116,7 +116,7 @@ void eigrp_query_receive(struct eigrp *eigrp, struct ip *iph, tlv = eigrp_read_ipv4_tlv(s); dest_addr.family = AF_INET; - dest_addr.prefix = tlv->destination; + dest_addr.u.prefix4 = tlv->destination; dest_addr.prefixlen = tlv->prefix_length; struct eigrp_prefix_entry *dest = eigrp_topology_table_lookup_ipv4( diff --git a/eigrpd/eigrp_reply.c b/eigrpd/eigrp_reply.c index cc70d1cfee..2b5b0aa44b 100644 --- a/eigrpd/eigrp_reply.c +++ b/eigrpd/eigrp_reply.c @@ -179,14 +179,14 @@ void eigrp_reply_receive(struct eigrp *eigrp, struct ip *iph, while (s->endp > s->getp) { type = stream_getw(s); if (type == EIGRP_TLV_IPv4_INT) { - struct prefix_ipv4 dest_addr; + struct prefix dest_addr; stream_set_getp(s, s->getp - sizeof(u_int16_t)); tlv = eigrp_read_ipv4_tlv(s); dest_addr.family = AF_INET; - dest_addr.prefix = tlv->destination; + dest_addr.u.prefix4 = tlv->destination; dest_addr.prefixlen = tlv->prefix_length; struct eigrp_prefix_entry *dest = eigrp_topology_table_lookup_ipv4( diff --git a/eigrpd/eigrp_siaquery.c b/eigrpd/eigrp_siaquery.c index cd04f88595..7264e53b6b 100644 --- a/eigrpd/eigrp_siaquery.c +++ b/eigrpd/eigrp_siaquery.c @@ -78,14 +78,14 @@ void eigrp_siaquery_receive(struct eigrp *eigrp, struct ip *iph, while (s->endp > s->getp) { type = stream_getw(s); if (type == EIGRP_TLV_IPv4_INT) { - struct prefix_ipv4 dest_addr; + struct prefix dest_addr; stream_set_getp(s, s->getp - sizeof(u_int16_t)); tlv = eigrp_read_ipv4_tlv(s); dest_addr.family = AFI_IP; - dest_addr.prefix = tlv->destination; + dest_addr.u.prefix4 = tlv->destination; dest_addr.prefixlen = tlv->prefix_length; struct eigrp_prefix_entry *dest = eigrp_topology_table_lookup_ipv4( diff --git a/eigrpd/eigrp_siareply.c b/eigrpd/eigrp_siareply.c index 5e83549488..8496c05675 100644 --- a/eigrpd/eigrp_siareply.c +++ b/eigrpd/eigrp_siareply.c @@ -77,14 +77,14 @@ void eigrp_siareply_receive(struct eigrp *eigrp, struct ip *iph, while (s->endp > s->getp) { type = stream_getw(s); if (type == EIGRP_TLV_IPv4_INT) { - struct prefix_ipv4 dest_addr; + struct prefix dest_addr; stream_set_getp(s, s->getp - sizeof(u_int16_t)); tlv = eigrp_read_ipv4_tlv(s); dest_addr.family = AFI_IP; - dest_addr.prefix = tlv->destination; + dest_addr.u.prefix4 = tlv->destination; dest_addr.prefixlen = tlv->prefix_length; struct eigrp_prefix_entry *dest = eigrp_topology_table_lookup_ipv4( diff --git a/eigrpd/eigrp_topology.c b/eigrpd/eigrp_topology.c index 0ae4788fd0..6bc0987daa 100644 --- a/eigrpd/eigrp_topology.c +++ b/eigrpd/eigrp_topology.c @@ -261,13 +261,12 @@ unsigned int eigrp_topology_table_isempty(struct list *topology) struct eigrp_prefix_entry * eigrp_topology_table_lookup_ipv4(struct list *topology_table, - struct prefix_ipv4 *address) + struct prefix *address) { struct eigrp_prefix_entry *data; struct listnode *node; for (ALL_LIST_ELEMENTS_RO(topology_table, node, data)) { - if (prefix_same(data->destination, - (struct prefix *)address)) + if (prefix_same(data->destination, address)) return data; } diff --git a/eigrpd/eigrp_topology.h b/eigrpd/eigrp_topology.h index 0c9b5c60c6..8bff08b75a 100644 --- a/eigrpd/eigrp_topology.h +++ b/eigrpd/eigrp_topology.h @@ -49,7 +49,7 @@ extern void eigrp_neighbor_entry_delete(struct eigrp_prefix_entry *, extern void eigrp_topology_delete_all(struct list *); extern unsigned int eigrp_topology_table_isempty(struct list *); extern struct eigrp_prefix_entry * -eigrp_topology_table_lookup_ipv4(struct list *, struct prefix_ipv4 *); +eigrp_topology_table_lookup_ipv4(struct list *, struct prefix *); extern struct list *eigrp_topology_get_successor(struct eigrp_prefix_entry *); extern struct list * eigrp_topology_get_successor_max(struct eigrp_prefix_entry *pe, diff --git a/eigrpd/eigrp_update.c b/eigrpd/eigrp_update.c index c59a010087..d6a1134124 100644 --- a/eigrpd/eigrp_update.c +++ b/eigrpd/eigrp_update.c @@ -157,7 +157,7 @@ void eigrp_update_receive(struct eigrp *eigrp, struct ip *iph, u_char same; struct access_list *alist; struct prefix_list *plist; - struct prefix_ipv4 dest_addr; + struct prefix dest_addr; struct eigrp *e; u_char graceful_restart; u_char graceful_restart_final; @@ -281,7 +281,7 @@ void eigrp_update_receive(struct eigrp *eigrp, struct ip *iph, /*searching if destination exists */ dest_addr.family = AF_INET; - dest_addr.prefix = tlv->destination; + dest_addr.u.prefix4 = tlv->destination; dest_addr.prefixlen = tlv->prefix_length; struct eigrp_prefix_entry *dest = eigrp_topology_table_lookup_ipv4( @@ -314,7 +314,7 @@ void eigrp_update_receive(struct eigrp *eigrp, struct ip *iph, pe->serno = eigrp->serno; pe->destination = (struct prefix *)prefix_ipv4_new(); prefix_copy(pe->destination, - (struct prefix *)&dest_addr); + &dest_addr); pe->af = AF_INET; pe->state = EIGRP_FSM_STATE_PASSIVE; pe->nt = EIGRP_TOPOLOGY_TYPE_REMOTE; @@ -338,9 +338,8 @@ void eigrp_update_receive(struct eigrp *eigrp, struct ip *iph, /* Check if access-list fits */ if (alist - && access_list_apply( - alist, - (struct prefix *)&dest_addr) + && access_list_apply(alist, + &dest_addr) == FILTER_DENY) { /* If yes, set reported metric to Max */ ne->reported_metric.delay = @@ -355,9 +354,8 @@ void eigrp_update_receive(struct eigrp *eigrp, struct ip *iph, /* Check if prefix-list fits */ if (plist - && prefix_list_apply( - plist, - (struct prefix *)&dest_addr) + && prefix_list_apply(plist, + &dest_addr) == PREFIX_DENY) { /* If yes, set reported metric to Max */ ne->reported_metric.delay = @@ -369,9 +367,8 @@ void eigrp_update_receive(struct eigrp *eigrp, struct ip *iph, /* Check if access-list fits */ if (alist - && access_list_apply( - alist, - (struct prefix *)&dest_addr) + && access_list_apply(alist, + &dest_addr) == FILTER_DENY) { /* If yes, set reported metric to Max */ ne->reported_metric.delay = @@ -382,9 +379,8 @@ void eigrp_update_receive(struct eigrp *eigrp, struct ip *iph, /* Check if prefix-list fits */ if (plist - && prefix_list_apply( - plist, - (struct prefix *)&dest_addr) + && prefix_list_apply(plist, + &dest_addr) == PREFIX_DENY) { /* If yes, set reported metric to Max */ ne->reported_metric.delay = @@ -626,13 +622,13 @@ void eigrp_update_send_EOT(struct eigrp_neighbor *nbr) /* Check if any list fits */ if ((alist && access_list_apply (alist, - (struct prefix *) dest_addr) == FILTER_DENY)|| + dest_addr) == FILTER_DENY)|| (plist && prefix_list_apply (plist, - (struct prefix *) dest_addr) == PREFIX_DENY)|| + dest_addr) == PREFIX_DENY)|| (alist_i && access_list_apply (alist_i, - (struct prefix *) dest_addr) == FILTER_DENY)|| + dest_addr) == FILTER_DENY)|| (plist_i && prefix_list_apply (plist_i, - (struct prefix *) dest_addr) == PREFIX_DENY)) { + dest_addr) == PREFIX_DENY)) { //pe->reported_metric.delay = EIGRP_MAX_METRIC; continue; } else { @@ -730,19 +726,19 @@ void eigrp_update_send(struct eigrp_interface *ei) /* Check if any list fits */ if ((alist && access_list_apply(alist, - (struct prefix *)dest_addr) + dest_addr) == FILTER_DENY) || (plist && prefix_list_apply(plist, - (struct prefix *)dest_addr) + dest_addr) == PREFIX_DENY) || (alist_i && access_list_apply(alist_i, - (struct prefix *)dest_addr) + dest_addr) == FILTER_DENY) || (plist_i && prefix_list_apply(plist_i, - (struct prefix *)dest_addr) + dest_addr) == PREFIX_DENY)) { // pe->reported_metric.delay = EIGRP_MAX_METRIC; continue; From cd6c066eb3a62f7d68458a18df70a893b6f0db1d Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 23 Aug 2017 15:35:27 -0400 Subject: [PATCH 107/130] eigrpd: Refactor eigrp_network_[un]set to use prefix Signed-off-by: Donald Sharp --- eigrpd/eigrp_network.c | 8 ++++---- eigrpd/eigrp_network.h | 4 ++-- eigrpd/eigrp_vty.c | 8 ++++---- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/eigrpd/eigrp_network.c b/eigrpd/eigrp_network.c index ec8806750b..81597726e0 100644 --- a/eigrpd/eigrp_network.c +++ b/eigrpd/eigrp_network.c @@ -229,7 +229,7 @@ int eigrp_if_drop_allspfrouters(struct eigrp *top, struct prefix *p, return ret; } -int eigrp_network_set(struct eigrp *eigrp, struct prefix_ipv4 *p) +int eigrp_network_set(struct eigrp *eigrp, struct prefix *p) { struct route_node *rn; struct interface *ifp; @@ -334,21 +334,21 @@ void eigrp_if_update(struct interface *ifp) } } -int eigrp_network_unset(struct eigrp *eigrp, struct prefix_ipv4 *p) +int eigrp_network_unset(struct eigrp *eigrp, struct prefix *p) { struct route_node *rn; struct listnode *node, *nnode; struct eigrp_interface *ei; struct prefix *pref; - rn = route_node_lookup(eigrp->networks, (struct prefix *)p); + rn = route_node_lookup(eigrp->networks, p); if (rn == NULL) return 0; pref = rn->info; route_unlock_node(rn); - if (!IPV4_ADDR_SAME(&pref->u.prefix4, &p->prefix)) + if (!IPV4_ADDR_SAME(&pref->u.prefix4, &p->u.prefix4)) return 0; prefix_ipv4_free(rn->info); diff --git a/eigrpd/eigrp_network.h b/eigrpd/eigrp_network.h index e38f7ded40..6ddd57eee5 100644 --- a/eigrpd/eigrp_network.h +++ b/eigrpd/eigrp_network.h @@ -32,8 +32,8 @@ extern int eigrp_sock_init(void); extern int eigrp_if_ipmulticast(struct eigrp *, struct prefix *, unsigned int); -extern int eigrp_network_set(struct eigrp *, struct prefix_ipv4 *); -extern int eigrp_network_unset(struct eigrp *eigrp, struct prefix_ipv4 *p); +extern int eigrp_network_set(struct eigrp *eigrp, struct prefix *p); +extern int eigrp_network_unset(struct eigrp *eigrp, struct prefix *p); extern int eigrp_hello_timer(struct thread *); extern void eigrp_if_update(struct interface *); diff --git a/eigrpd/eigrp_vty.c b/eigrpd/eigrp_vty.c index 465007478d..4a8842f30e 100644 --- a/eigrpd/eigrp_vty.c +++ b/eigrpd/eigrp_vty.c @@ -391,10 +391,10 @@ DEFUN (eigrp_network, "EIGRP network prefix\n") { VTY_DECLVAR_CONTEXT(eigrp, eigrp); - struct prefix_ipv4 p; + struct prefix p; int ret; - str2prefix_ipv4(argv[1]->arg, &p); + str2prefix(argv[1]->arg, &p); ret = eigrp_network_set(eigrp, &p); @@ -414,10 +414,10 @@ DEFUN (no_eigrp_network, "EIGRP network prefix\n") { VTY_DECLVAR_CONTEXT(eigrp, eigrp); - struct prefix_ipv4 p; + struct prefix p; int ret; - str2prefix_ipv4(argv[2]->arg, &p); + str2prefix(argv[2]->arg, &p); ret = eigrp_network_unset(eigrp, &p); From 0ffa840756e10b6efb83e24aeaddf3e5f28c8ef3 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 23 Aug 2017 15:38:29 -0400 Subject: [PATCH 108/130] eigrpd: Remove 'struct prefix_ipv4' from eigrp_interface.c Signed-off-by: Donald Sharp --- eigrpd/eigrp_interface.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/eigrpd/eigrp_interface.c b/eigrpd/eigrp_interface.c index 9f54b62353..ae9ec293ce 100644 --- a/eigrpd/eigrp_interface.c +++ b/eigrpd/eigrp_interface.c @@ -225,14 +225,14 @@ void eigrp_del_if_params(struct eigrp_if_params *eip) struct eigrp_if_params *eigrp_lookup_if_params(struct interface *ifp, struct in_addr addr) { - struct prefix_ipv4 p; + struct prefix p; struct route_node *rn; p.family = AF_INET; p.prefixlen = IPV4_MAX_PREFIXLEN; - p.prefix = addr; + p.u.prefix4 = addr; - rn = route_node_lookup(IF_OIFS_PARAMS(ifp), (struct prefix *)&p); + rn = route_node_lookup(IF_OIFS_PARAMS(ifp), &p); if (rn) { route_unlock_node(rn); @@ -544,11 +544,11 @@ struct eigrp_interface *eigrp_if_lookup_recv_if(struct eigrp *eigrp, struct interface *ifp) { struct route_node *rn; - struct prefix_ipv4 addr; + struct prefix addr; struct eigrp_interface *ei, *match; addr.family = AF_INET; - addr.prefix = src; + addr.u.prefix4 = src; addr.prefixlen = IPV4_MAX_BITLEN; match = NULL; @@ -563,7 +563,7 @@ struct eigrp_interface *eigrp_if_lookup_recv_if(struct eigrp *eigrp, continue; if (prefix_match(CONNECTED_PREFIX(ei->connected), - (struct prefix *)&addr)) { + &addr)) { if ((match == NULL) || (match->address->prefixlen < ei->address->prefixlen)) match = ei; From a96029f8242521e0a905ae31a5ce21d57b91be67 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 23 Aug 2017 15:39:30 -0400 Subject: [PATCH 109/130] eigrpd: Remove 'struct prefix_ipv4' from eigrp_network.c Signed-off-by: Donald Sharp --- eigrpd/eigrp_network.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/eigrpd/eigrp_network.c b/eigrpd/eigrp_network.c index 81597726e0..0cf5bd9bad 100644 --- a/eigrpd/eigrp_network.c +++ b/eigrpd/eigrp_network.c @@ -242,7 +242,7 @@ int eigrp_network_set(struct eigrp *eigrp, struct prefix *p) return 0; } - struct prefix_ipv4 *pref = prefix_ipv4_new(); + struct prefix *pref = prefix_new(); PREFIX_COPY_IPV4(pref, p); rn->info = (void *)pref; @@ -253,7 +253,7 @@ int eigrp_network_set(struct eigrp *eigrp, struct prefix *p) /* Get target interface. */ for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) { zlog_debug("Setting up %s", ifp->name); - eigrp_network_run_interface(eigrp, (struct prefix *)p, ifp); + eigrp_network_run_interface(eigrp, p, ifp); } return 1; } From 4a64eed5773e6472985a7d42599853af553e4f05 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 23 Aug 2017 20:26:19 -0400 Subject: [PATCH 110/130] eigrpd: Fix compiler warning introduced Signed-off-by: Donald Sharp --- eigrpd/eigrp_topology.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/eigrpd/eigrp_topology.c b/eigrpd/eigrp_topology.c index 6bc0987daa..2e8128f474 100644 --- a/eigrpd/eigrp_topology.c +++ b/eigrpd/eigrp_topology.c @@ -402,10 +402,10 @@ enum metric_change eigrp_topology_update_distance(struct eigrp_fsm_action_messag if (eigrp_metrics_is_same(msg->metrics, entry->reported_metric)) return change; - } else + } else { change = METRIC_INCREASE; - - break; + } + break; default: zlog_err("%s: Please implement handler", __PRETTY_FUNCTION__); break; From 532e75e6ee1484d1940d9a918548227e920de9b5 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 24 Aug 2017 07:34:21 -0400 Subject: [PATCH 111/130] eigrpd: Fix distance comparison The distance comparison for when we received an internal and we already had an internal was overriding the metrics of the connected. Signed-off-by: Donald Sharp --- eigrpd/eigrp_topology.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/eigrpd/eigrp_topology.c b/eigrpd/eigrp_topology.c index 2e8128f474..64e65b694c 100644 --- a/eigrpd/eigrp_topology.c +++ b/eigrpd/eigrp_topology.c @@ -379,6 +379,10 @@ enum metric_change eigrp_topology_update_distance(struct eigrp_fsm_action_messag change = METRIC_DECREASE; break; case EIGRP_INT: + if (prefix->nt == EIGRP_TOPOLOGY_TYPE_CONNECTED) { + change = METRIC_INCREASE; + goto distance_done; + } if (eigrp_metrics_is_same(msg->metrics, entry->reported_metric)) { return change; // No change @@ -387,9 +391,10 @@ enum metric_change eigrp_topology_update_distance(struct eigrp_fsm_action_messag new_reported_distance = eigrp_calculate_metrics(eigrp, msg->metrics); - if (entry->reported_distance < new_reported_distance) + if (entry->reported_distance < new_reported_distance) { change = METRIC_INCREASE; - else + goto distance_done; + } else change = METRIC_DECREASE; entry->reported_metric = msg->metrics; @@ -404,12 +409,14 @@ enum metric_change eigrp_topology_update_distance(struct eigrp_fsm_action_messag return change; } else { change = METRIC_INCREASE; + goto distance_done; } break; default: zlog_err("%s: Please implement handler", __PRETTY_FUNCTION__); break; } + distance_done: /* * Move to correct position in list according to new distance */ From b5f7965155038d947f733d6aee92915c3c5d581c Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 24 Aug 2017 08:30:08 -0400 Subject: [PATCH 112/130] lib: Fix nexthop num If we assign MULTIPATH_NUM to be 256, this causes issues for us since 256 is bigger than a u_char. So let's make the api's multipath_num to be a u_int16_t and pass it around as a word. Signed-off-by: Donald Sharp --- lib/zclient.c | 4 ++-- lib/zclient.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/zclient.c b/lib/zclient.c index 75005d656b..72fa2679b3 100644 --- a/lib/zclient.c +++ b/lib/zclient.c @@ -940,7 +940,7 @@ int zapi_route_encode(u_char cmd, struct stream *s, struct zapi_route *api) api->nexthop_num = MULTIPATH_NUM; } - stream_putc(s, api->nexthop_num); + stream_putw(s, api->nexthop_num); for (i = 0; i < api->nexthop_num; i++) { api_nh = &api->nexthops[i]; @@ -1047,7 +1047,7 @@ int zapi_route_decode(struct stream *s, struct zapi_route *api) /* Nexthops. */ if (CHECK_FLAG(api->message, ZAPI_MESSAGE_NEXTHOP)) { - api->nexthop_num = stream_getc(s); + api->nexthop_num = stream_getw(s); if (api->nexthop_num > MULTIPATH_NUM) { zlog_warn("%s: invalid number of nexthops (%u)", __func__, api->nexthop_num); diff --git a/lib/zclient.h b/lib/zclient.h index bae52a441b..7c4780201e 100644 --- a/lib/zclient.h +++ b/lib/zclient.h @@ -242,7 +242,7 @@ struct zapi_route { struct prefix prefix; struct prefix_ipv6 src_prefix; - u_char nexthop_num; + u_int16_t nexthop_num; struct zapi_nexthop nexthops[MULTIPATH_NUM]; u_char distance; From 6c65db5f990f9e6a460d592fde1b1a9b86dd2f45 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 24 Aug 2017 09:53:05 -0400 Subject: [PATCH 113/130] pimd: Cleanup a debug for vrf Signed-off-by: Donald Sharp --- pimd/pim_upstream.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index 1fc952fdf8..96b9568c61 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -1624,8 +1624,9 @@ static void pim_upstream_sg_running(void *arg) // No packet can have arrived here if this is the case if (!up->channel_oil->installed) { if (PIM_DEBUG_TRACE) - zlog_debug("%s: %s is not installed in mroute", - __PRETTY_FUNCTION__, up->sg_str); + zlog_debug("%s: %s[%s] is not installed in mroute", + __PRETTY_FUNCTION__, + up->sg_str, pim->vrf->name); return; } From c206937b91fb1c50796e03ff3f35d1fd2ac81bc6 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 24 Aug 2017 09:55:19 -0400 Subject: [PATCH 114/130] pimd: Cleanup S,GRPt prune handling on Mroute Loss 1) Clean up display of S,GRPt prune state to be more meaningful 2) Upon receipt of a S,GRPt prune make sure we transition to the correct state 3) Upon loss of a S,GRPt prune make sure we transition to the correct state as well as immediately send a *,G join upstream to propagate the loss of the prune. 4) Removal of a weird S,G state being installed upon loss of a S,G RPt prune. Signed-off-by: Donald Sharp --- pimd/pim_cmd.c | 4 +- pimd/pim_ifchannel.c | 121 +++++++++++++++++++++++-------------------- pimd/pim_ifchannel.h | 3 +- pimd/pim_join.c | 9 +--- 4 files changed, 70 insertions(+), 67 deletions(-) diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index 9c79fd87e2..ae509f4a9b 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -1666,7 +1666,7 @@ static void pim_show_join_helper(struct vty *vty, json_row); } else { vty_out(vty, - "%-9s %-15s %-15s %-15s %-6s %8s %-6s %5s\n", + "%-9s %-15s %-15s %-15s %-10s %8s %-6s %5s\n", ch->interface->name, inet_ntoa(ifaddr), ch_src_str, ch_grp_str, pim_ifchannel_ifjoin_name(ch->ifjoin_state, @@ -1690,7 +1690,7 @@ static void pim_show_join(struct pim_instance *pim, struct vty *vty, u_char uj) json = json_object_new_object(); else vty_out(vty, - "Interface Address Source Group State Uptime Expire Prune\n"); + "Interface Address Source Group State Uptime Expire Prune\n"); for (ALL_LIST_ELEMENTS_RO(vrf_iflist(pim->vrf_id), if_node, ifp)) { pim_ifp = ifp->info; diff --git a/pimd/pim_ifchannel.c b/pimd/pim_ifchannel.c index 39f5f2cc4b..b5d6f04948 100644 --- a/pimd/pim_ifchannel.c +++ b/pimd/pim_ifchannel.c @@ -42,6 +42,7 @@ #include "pim_oil.h" #include "pim_upstream.h" #include "pim_ssm.h" +#include "pim_rp.h" RB_GENERATE(pim_ifchannel_rb, pim_ifchannel, pim_ifp_rb, pim_ifchannel_compare); @@ -348,7 +349,7 @@ const char *pim_ifchannel_ifjoin_name(enum pim_ifjoin_state ifjoin_state, switch (ifjoin_state) { case PIM_IFJOIN_NOINFO: if (PIM_IF_FLAG_TEST_S_G_RPT(flags)) - return "SGRpt"; + return "SGRpt(NI)"; else return "NOINFO"; break; @@ -356,16 +357,28 @@ const char *pim_ifchannel_ifjoin_name(enum pim_ifjoin_state ifjoin_state, return "JOIN"; break; case PIM_IFJOIN_PRUNE: - return "PRUNE"; + if (PIM_IF_FLAG_TEST_S_G_RPT(flags)) + return "SGRpt(P)"; + else + return "PRUNE"; break; case PIM_IFJOIN_PRUNE_PENDING: - return "PRUNEP"; + if (PIM_IF_FLAG_TEST_S_G_RPT(flags)) + return "SGRpt(PP)"; + else + return "PRUNEP"; break; case PIM_IFJOIN_PRUNE_TMP: - return "PRUNET"; + if (PIM_IF_FLAG_TEST_S_G_RPT(flags)) + return "SGRpt(P')"; + else + return "PRUNET"; break; case PIM_IFJOIN_PRUNE_PENDING_TMP: - return "PRUNEPT"; + if (PIM_IF_FLAG_TEST_S_G_RPT(flags)) + return "SGRpt(PP')"; + else + return "PRUNEPT"; break; } @@ -628,33 +641,34 @@ static int on_ifjoin_prune_pending_timer(struct thread *t) ch = THREAD_ARG(t); if (ch->ifjoin_state == PIM_IFJOIN_PRUNE_PENDING) { - /* Send PruneEcho(S,G) ? */ ifp = ch->interface; pim_ifp = ifp->info; - send_prune_echo = (listcount(pim_ifp->pim_neighbor_list) > 1); + if (!PIM_IF_FLAG_TEST_S_G_RPT(ch->flags)) { + /* Send PruneEcho(S,G) ? */ + send_prune_echo = + (listcount(pim_ifp->pim_neighbor_list) > 1); - if (send_prune_echo) { - struct pim_rpf rpf; + if (send_prune_echo) { + struct pim_rpf rpf; - rpf.source_nexthop.interface = ifp; - rpf.rpf_addr.u.prefix4 = pim_ifp->primary_address; - pim_jp_agg_single_upstream_send(&rpf, ch->upstream, 0); - } - /* If SGRpt flag is set on ifchannel, Trigger SGRpt - message on RP path upon prune timer expiry. - */ - if (PIM_IF_FLAG_TEST_S_G_RPT(ch->flags)) { + rpf.source_nexthop.interface = ifp; + rpf.rpf_addr.u.prefix4 = + pim_ifp->primary_address; + pim_jp_agg_single_upstream_send(&rpf, + ch->upstream, + 0); + } + + ifjoin_to_noinfo(ch, true); + } else { + /* If SGRpt flag is set on ifchannel, Trigger SGRpt + * message on RP path upon prune timer expiry. + */ + ch->ifjoin_state = PIM_IFJOIN_PRUNE; if (ch->upstream) pim_upstream_update_join_desired(pim_ifp->pim, ch->upstream); - /* - ch->ifjoin_state transition to NOINFO state - ch_del is set to 0 for not deleteing from here. - Holdtime expiry (ch_del set to 1) delete the entry. - */ - ifjoin_to_noinfo(ch, false); - } else - ifjoin_to_noinfo(ch, true); + } /* from here ch may have been deleted */ } else { zlog_warn( @@ -1104,7 +1118,6 @@ void pim_ifchannel_local_membership_del(struct interface *ifp, orig = ch = pim_ifchannel_find(ifp, sg); if (!ch) return; - ifmembership_set(ch, PIM_IFMEMBERSHIP_NOINFO); if (sg->src.s_addr == INADDR_ANY) { @@ -1311,11 +1324,12 @@ void pim_ifchannel_scan_forward_start(struct interface *new_ifp) * we get End of Message */ void pim_ifchannel_set_star_g_join_state(struct pim_ifchannel *ch, int eom, - uint8_t source_flags, uint8_t join, - uint8_t starg_alone) + uint8_t join) { struct pim_ifchannel *child; struct listnode *ch_node; + struct pim_instance *pim = + ((struct pim_interface *)ch->interface->info)->pim; if (PIM_DEBUG_PIM_TRACE) zlog_debug( @@ -1326,33 +1340,6 @@ void pim_ifchannel_set_star_g_join_state(struct pim_ifchannel *ch, int eom, return; for (ALL_LIST_ELEMENTS_RO(ch->sources, ch_node, child)) { - /* Only *,G Join received and no (SG-RPT) prune. - eom = 1, only (W,G) join_alone is true, WC and RPT are set. - Scan all S,G associated to G and if any SG-RPT - remove the SG-RPT flag. - */ - if (eom && starg_alone && (source_flags & PIM_RPT_BIT_MASK) - && (source_flags & PIM_WILDCARD_BIT_MASK)) { - if (PIM_IF_FLAG_TEST_S_G_RPT(child->flags)) { - struct pim_upstream *up = child->upstream; - - PIM_IF_FLAG_UNSET_S_G_RPT(child->flags); - if (up) { - if (PIM_DEBUG_TRACE) - zlog_debug( - "%s: SGRpt flag is cleared, add inherit oif to up %s", - __PRETTY_FUNCTION__, - up->sg_str); - pim_channel_add_oif( - up->channel_oil, ch->interface, - PIM_OIF_FLAG_PROTO_STAR); - pim_ifchannel_ifjoin_switch( - __PRETTY_FUNCTION__, child, - PIM_IFJOIN_JOIN); - } - } - } - if (!PIM_IF_FLAG_TEST_S_G_RPT(child->flags)) continue; @@ -1371,8 +1358,30 @@ void pim_ifchannel_set_star_g_join_state(struct pim_ifchannel *ch, int eom, break; case PIM_IFJOIN_PRUNE_TMP: case PIM_IFJOIN_PRUNE_PENDING_TMP: - if (eom) + if (eom) { + struct pim_upstream *parent = + child->upstream->parent; + + PIM_IF_FLAG_UNSET_S_G_RPT(child->flags); child->ifjoin_state = PIM_IFJOIN_NOINFO; + + if (I_am_RP(pim, child->sg.grp)) { + pim_channel_add_oif( + child->upstream->channel_oil, + ch->interface, + PIM_OIF_FLAG_PROTO_STAR); + pim_upstream_switch( + pim, child->upstream, + PIM_UPSTREAM_JOINED); + pim_jp_agg_single_upstream_send( + &child->upstream->rpf, + child->upstream, true); + } + if (parent) + pim_jp_agg_single_upstream_send( + &parent->rpf, + parent, true); + } break; } } diff --git a/pimd/pim_ifchannel.h b/pimd/pim_ifchannel.h index cef431c30d..0b1a8ea0e8 100644 --- a/pimd/pim_ifchannel.h +++ b/pimd/pim_ifchannel.h @@ -151,8 +151,7 @@ void pim_ifchannel_update_assert_tracking_desired(struct pim_ifchannel *ch); void pim_ifchannel_scan_forward_start(struct interface *new_ifp); void pim_ifchannel_set_star_g_join_state(struct pim_ifchannel *ch, int eom, - uint8_t source_flags, uint8_t join, - uint8_t starg_alone); + uint8_t join); int pim_ifchannel_compare(const struct pim_ifchannel *ch1, const struct pim_ifchannel *ch2); diff --git a/pimd/pim_join.c b/pimd/pim_join.c index c60e5a65aa..9d65330e5f 100644 --- a/pimd/pim_join.c +++ b/pimd/pim_join.c @@ -231,7 +231,6 @@ int pim_joinprune_recv(struct interface *ifp, struct pim_neighbor *neigh, uint16_t msg_num_pruned_sources; int source; struct pim_ifchannel *starg_ch = NULL, *sg_ch = NULL; - uint8_t starg_alone = 0; memset(&sg, 0, sizeof(struct prefix_sg)); addr_offset = pim_parse_addr_group(&sg, buf, pastend - buf); @@ -289,12 +288,10 @@ int pim_joinprune_recv(struct interface *ifp, struct pim_neighbor *neigh, msg_source_flags); if (sg.src.s_addr == INADDR_ANY) { - starg_alone = 1; starg_ch = pim_ifchannel_find(ifp, &sg); if (starg_ch) pim_ifchannel_set_star_g_join_state( - starg_ch, 0, msg_source_flags, - 1, starg_alone); + starg_ch, 0, 1); } } @@ -307,7 +304,6 @@ int pim_joinprune_recv(struct interface *ifp, struct pim_neighbor *neigh, } buf += addr_offset; - starg_alone = 0; recv_prune(ifp, neigh, msg_holdtime, msg_upstream_addr.u.prefix4, &sg, msg_source_flags); @@ -340,8 +336,7 @@ int pim_joinprune_recv(struct interface *ifp, struct pim_neighbor *neigh, } } if (starg_ch) - pim_ifchannel_set_star_g_join_state( - starg_ch, 1, msg_source_flags, 0, starg_alone); + pim_ifchannel_set_star_g_join_state(starg_ch, 1, 0); starg_ch = NULL; } /* scan groups */ From 0ee0892b6645c93d0e5f757b665ed40722487f96 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Fri, 25 Aug 2017 18:54:13 +0200 Subject: [PATCH 115/130] clippy: disable unneeded autogenerated code Coverity is generating a lot of warnings about unused stuff being around. Disabling these bits is most easily done by just putting a few preprocessor directives into the template. Signed-off-by: David Lamparter --- python/clidef.py | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/python/clidef.py b/python/clidef.py index aa6cd18b8b..6a69986323 100644 --- a/python/clidef.py +++ b/python/clidef.py @@ -36,12 +36,14 @@ class RenderHandler(object): deref = '' drop_str = False + canfail = True class StringHandler(RenderHandler): argtype = 'const char *' decl = Template('const char *$varname = NULL;') code = Template('$varname = argv[_i]->arg;') drop_str = True + canfail = False class LongHandler(RenderHandler): argtype = 'long' @@ -130,6 +132,10 @@ handlers = { } # core template invoked for each occurence of DEFPY. +# +# the "#if $..." bits are there to keep this template unified into one +# common form, without requiring a more advanced template engine (e.g. +# jinja2) templ = Template('''/* $fnname => "$cmddef" */ DEFUN_CMD_FUNC_DECL($fnname) #define funcdecl_$fnname static int ${fnname}_magic(\\ @@ -140,20 +146,31 @@ DEFUN_CMD_FUNC_DECL($fnname) funcdecl_$fnname; DEFUN_CMD_FUNC_TEXT($fnname) { +#if $nonempty /* anything to parse? */ int _i; +#if $canfail /* anything that can fail? */ unsigned _fail = 0, _failcnt = 0; +#endif $argdecls for (_i = 0; _i < argc; _i++) { if (!argv[_i]->varname) continue; - _fail = 0;$argblocks +#if $canfail /* anything that can fail? */ + _fail = 0; +#endif +$argblocks +#if $canfail /* anything that can fail? */ if (_fail) vty_out (vty, "%% invalid input for %s: %s\\n", argv[_i]->varname, argv[_i]->arg); _failcnt += _fail; +#endif } +#if $canfail /* anything that can fail? */ if (_failcnt) return CMD_WARNING; +#endif +#endif return ${fnname}_magic(self, vty, argc, argv$arglist); } @@ -196,6 +213,7 @@ def process_file(fn, ofd, dumpfd, all_defun): arglist = [] argblocks = [] doc = [] + canfail = 0 def do_add(handler, varname, attr = ''): argdefs.append(',\\\n\t%s %s%s' % (handler.argtype, varname, attr)) @@ -213,6 +231,8 @@ def process_file(fn, ofd, dumpfd, all_defun): if handler is None: continue do_add(handler, varname) code = handler.code.substitute({'varname': varname}).replace('\n', '\n\t\t\t') + if handler.canfail: + canfail = 1 strblock = '' if not handler.drop_str: do_add(StringHandler(None), '%s_str' % (varname), ' __attribute__ ((unused))') @@ -229,6 +249,8 @@ def process_file(fn, ofd, dumpfd, all_defun): params['argdecls'] = ''.join(argdecls) params['arglist'] = ''.join(arglist) params['argblocks'] = ''.join(argblocks) + params['canfail'] = canfail + params['nonempty'] = len(argblocks) ofd.write(templ.substitute(params)) if __name__ == '__main__': From 8295b504cbd6df715b779287ff9d2374ae306421 Mon Sep 17 00:00:00 2001 From: Quentin Young Date: Fri, 25 Aug 2017 13:39:13 -0400 Subject: [PATCH 116/130] lib: fix rare bug in ambiguous command resolution In certain situations, the CLI matcher would not handle ambiguous commands properly. If it found an ambiguous result in a lower subgraph, the ambiguous result would not correctly propagate up to previous frames in the resolution DFS as ambiguous; instead it would propagate up as a non-match, which could subsequently be overridden by a partial match. Example CLI space: show ip route summary show ip route supernet-only show ipv6 route summary Entering `show ip route su` would result in an ambiguous resolution for the `show ip route` subgraph but would propagate up to the `show ip` subgraph as a no-match, allowing `ip` to partial-match `ipv6` and execute that command. In this example entering `show ip route summary` would disambiguate the `show ip` subgraph. So this bug would only appear when entering input that caused ambiguities in at least two parallel subgraphs. Signed-off-by: Quentin Young --- lib/command_match.c | 130 ++++++++++++++++++++++++-------------------- 1 file changed, 72 insertions(+), 58 deletions(-) diff --git a/lib/command_match.c b/lib/command_match.c index f07448d716..5590fce6b1 100644 --- a/lib/command_match.c +++ b/lib/command_match.c @@ -46,8 +46,9 @@ DEFINE_MTYPE_STATIC(LIB, CMD_MATCHSTACK, "Command Match Stack") static int add_nexthops(struct list *, struct graph_node *, struct graph_node **, size_t); -static struct list *command_match_r(struct graph_node *, vector, unsigned int, - struct graph_node **); +static enum matcher_rv command_match_r(struct graph_node *, vector, + unsigned int, struct graph_node **, + struct list **); static int score_precedence(enum cmd_token_type); @@ -87,7 +88,8 @@ enum matcher_rv command_match(struct graph *cmdgraph, vector vline, struct list **argv, const struct cmd_element **el) { struct graph_node *stack[MAXDEPTH]; - matcher_rv = MATCHER_NO_MATCH; + enum matcher_rv status; + *argv = NULL; // prepend a dummy token to match that pesky start node vector vvline = vector_init(vline->alloced + 1); @@ -97,9 +99,8 @@ enum matcher_rv command_match(struct graph *cmdgraph, vector vline, vvline->active = vline->active + 1; struct graph_node *start = vector_slot(cmdgraph->nodes, 0); - if ((*argv = command_match_r(start, vvline, 0, - stack))) // successful match - { + status = command_match_r(start, vvline, 0, stack, argv); + if (status == MATCHER_OK) { // successful match struct listnode *head = listhead(*argv); struct listnode *tail = listtail(*argv); @@ -115,6 +116,9 @@ enum matcher_rv command_match(struct graph *cmdgraph, vector vline, // input, with each cmd_token->arg holding the corresponding // input assert(*el); + } else if (*argv) { + del_arglist(*argv); + *argv = NULL; } if (!*el) { @@ -129,7 +133,7 @@ enum matcher_rv command_match(struct graph *cmdgraph, vector vline, // free vector vector_free(vvline); - return matcher_rv; + return status; } /** @@ -183,11 +187,15 @@ enum matcher_rv command_match(struct graph *cmdgraph, vector vline, * * If no match was found, the return value is NULL. */ -static struct list *command_match_r(struct graph_node *start, vector vline, - unsigned int n, struct graph_node **stack) +static enum matcher_rv command_match_r(struct graph_node *start, vector vline, + unsigned int n, + struct graph_node **stack, + struct list **currbest) { assert(n < vector_active(vline)); + enum matcher_rv status = MATCHER_NO_MATCH; + // get the minimum match level that can count as a full match struct cmd_token *token = start->data; enum match_type minmatch = min_match_level(token->type); @@ -196,11 +204,11 @@ static struct list *command_match_r(struct graph_node *start, vector vline, * this disallows matching the same one more than once if there is a * circle in the graph (used for keyword arguments) */ if (n == MAXDEPTH) - return NULL; + return MATCHER_NO_MATCH; if (!token->allowrepeat) for (size_t s = 0; s < n; s++) if (stack[s] == start) - return NULL; + return MATCHER_NO_MATCH; // get the current operating input token char *input_token = vector_slot(vline, n); @@ -231,7 +239,7 @@ static struct list *command_match_r(struct graph_node *start, vector vline, // if we don't match this node, die if (match_token(token, input_token) < minmatch) - return NULL; + return MATCHER_NO_MATCH; stack[n] = start; @@ -244,86 +252,92 @@ static struct list *command_match_r(struct graph_node *start, vector vline, add_nexthops(next, start, NULL, 0); // determine the best match - int ambiguous = 0; - struct list *currbest = NULL; for (ALL_LIST_ELEMENTS_RO(next, ln, gn)) { // if we've matched all input we're looking for END_TKN if (n + 1 == vector_active(vline)) { struct cmd_token *tok = gn->data; if (tok->type == END_TKN) { - if (currbest) // there is more than one END_TKN - // in the follow set - { - ambiguous = 1; + // if more than one END_TKN in the follow set + if (*currbest) { + status = MATCHER_AMBIGUOUS; break; + } else { + status = MATCHER_OK; } - currbest = list_new(); + *currbest = list_new(); // node should have one child node with the // element struct graph_node *leaf = vector_slot(gn->to, 0); // last node in the list will hold the - // cmd_element; - // this is important because list_delete() - // expects - // that all nodes have the same data type, so - // when - // deleting this list the last node must be - // manually deleted + // cmd_element; this is important because + // list_delete() expects that all nodes have + // the same data type, so when deleting this + // list the last node must be manually deleted struct cmd_element *el = leaf->data; - listnode_add(currbest, el); - currbest->del = + listnode_add(*currbest, el); + (*currbest)->del = (void (*)(void *)) & cmd_token_del; // do not break immediately; continue walking - // through the follow set - // to ensure that there is exactly one END_TKN + // through the follow set to ensure that there + // is exactly one END_TKN } continue; } // else recurse on candidate child node - struct list *result = command_match_r(gn, vline, n + 1, stack); + struct list *result = NULL; + enum matcher_rv rstat = + command_match_r(gn, vline, n + 1, stack, &result); // save the best match - if (result && currbest) { + if (result && *currbest) { // pick the best of two matches struct list *newbest = - disambiguate(currbest, result, vline, n + 1); - // set ambiguity flag - ambiguous = - !newbest || (ambiguous && newbest == currbest); + disambiguate(*currbest, result, vline, n + 1); + + // current best and result are ambiguous + if (!newbest) + status = MATCHER_AMBIGUOUS; + // current best is still the best, but ambiguous + else if (newbest == *currbest + && status == MATCHER_AMBIGUOUS) + status = MATCHER_AMBIGUOUS; + // result is better, but also ambiguous + else if (newbest == result + && rstat == MATCHER_AMBIGUOUS) + status = MATCHER_AMBIGUOUS; + // one or the other is superior and not ambiguous + else + status = MATCHER_OK; + // delete the unnecessary result struct list *todelete = - ((newbest && newbest == result) ? currbest + ((newbest && newbest == result) ? *currbest : result); del_arglist(todelete); - currbest = newbest ? newbest : currbest; - } else if (result) - currbest = result; - } - - if (currbest) { - if (ambiguous) { - del_arglist(currbest); - currbest = NULL; - matcher_rv = MATCHER_AMBIGUOUS; - } else { - // copy token, set arg and prepend to currbest - struct cmd_token *token = start->data; - struct cmd_token *copy = cmd_token_dup(token); - copy->arg = XSTRDUP(MTYPE_CMD_ARG, input_token); - listnode_add_before(currbest, currbest->head, copy); - matcher_rv = MATCHER_OK; + *currbest = newbest ? newbest : *currbest; + } else if (result) { + status = rstat; + *currbest = result; + } else if (!*currbest) { + status = MAX(rstat, status); } - } else if (n + 1 == vector_active(vline) - && matcher_rv == MATCHER_NO_MATCH) - matcher_rv = MATCHER_INCOMPLETE; + } + if (*currbest) { + // copy token, set arg and prepend to currbest + struct cmd_token *token = start->data; + struct cmd_token *copy = cmd_token_dup(token); + copy->arg = XSTRDUP(MTYPE_CMD_ARG, input_token); + listnode_add_before(*currbest, (*currbest)->head, copy); + } else if (n + 1 == vector_active(vline) && status == MATCHER_NO_MATCH) + status = MATCHER_INCOMPLETE; // cleanup list_delete(next); - return currbest; + return status; } static void stack_del(void *val) From 935cee3f9b84903b821c8abc17b70cbda08cb145 Mon Sep 17 00:00:00 2001 From: Quentin Young Date: Fri, 25 Aug 2017 14:08:16 -0400 Subject: [PATCH 117/130] lib: remove static variable from cli matcher Signed-off-by: Quentin Young --- lib/command_match.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/lib/command_match.c b/lib/command_match.c index 5590fce6b1..ad3ec2492e 100644 --- a/lib/command_match.c +++ b/lib/command_match.c @@ -81,9 +81,6 @@ static enum match_type match_variable(struct cmd_token *, const char *); static enum match_type match_mac(const char *, bool); -/* matching functions */ -static enum matcher_rv matcher_rv; - enum matcher_rv command_match(struct graph *cmdgraph, vector vline, struct list **argv, const struct cmd_element **el) { @@ -446,12 +443,12 @@ enum matcher_rv command_complete(struct graph *graph, vector vline, * next = set of all nodes reachable from all nodes in `matched` */ - matcher_rv = idx == vector_active(vline) && next->count - ? MATCHER_OK - : MATCHER_NO_MATCH; + enum matcher_rv mrv = idx == vector_active(vline) && next->count + ? MATCHER_OK + : MATCHER_NO_MATCH; *completions = NULL; - if (!MATCHER_ERROR(matcher_rv)) { + if (!MATCHER_ERROR(mrv)) { // extract cmd_token into list *completions = list_new(); for (ALL_LIST_ELEMENTS_RO(next, node, gstack)) { @@ -462,7 +459,7 @@ enum matcher_rv command_complete(struct graph *graph, vector vline, list_delete(current); list_delete(next); - return matcher_rv; + return mrv; } /** From a97986ffba560458b2b1e88b09b31822f78d8542 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Sat, 26 Aug 2017 01:14:25 +0200 Subject: [PATCH 118/130] *: fix compiler warnings Specifically, gcc 4.2.1 on OpenBSD 6.0 warns about these; they're bogus (gcc 4.2, being rather old, isn't quite as "intelligent" as newer versions; the newer ones apply more logic and less warnings.) Signed-off-by: David Lamparter --- babeld/babeld.c | 4 +-- babeld/message.c | 2 +- isisd/isisd.c | 4 +-- lib/module.c | 6 ++-- lib/spf_backoff.c | 10 +++--- lib/termtable.c | 88 +++++++++++++++++++++++++++-------------------- pimd/pim_join.c | 2 +- zebra/zserv.c | 2 +- 8 files changed, 67 insertions(+), 51 deletions(-) diff --git a/babeld/babeld.c b/babeld/babeld.c index f995745e41..207c37d9b1 100644 --- a/babeld/babeld.c +++ b/babeld/babeld.c @@ -331,8 +331,8 @@ babel_main_loop(struct thread *thread) /* if there is no timeout, we must wait. */ if(timeval_compare(&tv, &babel_now) > 0) { timeval_minus(&tv, &tv, &babel_now); - debugf(BABEL_DEBUG_TIMEOUT, "babel main loop : timeout: %ld msecs", - tv.tv_sec * 1000 + tv.tv_usec / 1000); + debugf(BABEL_DEBUG_TIMEOUT, "babel main loop : timeout: %lld msecs", + (long long)tv.tv_sec * 1000 + tv.tv_usec / 1000); /* it happens often to have less than 1 ms, it's bad. */ timeval_add_msec(&tv, &tv, 300); babel_set_timer(&tv); diff --git a/babeld/message.c b/babeld/message.c index 5990373b69..e31d5de5df 100644 --- a/babeld/message.c +++ b/babeld/message.c @@ -391,7 +391,7 @@ parse_packet(const unsigned char *from, struct interface *ifp, } else if(type == MESSAGE_HELLO) { unsigned short seqno, interval; int changed; - unsigned int timestamp; + unsigned int timestamp = 0; DO_NTOHS(seqno, message + 4); DO_NTOHS(interval, message + 6); debugf(BABEL_DEBUG_COMMON,"Received hello %d (%d) from %s on %s.", diff --git a/isisd/isisd.c b/isisd/isisd.c index f8a9df45c7..3d39a1ed52 100644 --- a/isisd/isisd.c +++ b/isisd/isisd.c @@ -1260,8 +1260,8 @@ DEFUN (show_isis_spf_ietf, if (area->spf_timer[level - 1]) { struct timeval remain = thread_timer_remain( area->spf_timer[level - 1]); - vty_out(vty, "Pending, due in %ld msec\n", - remain.tv_sec * 1000 + vty_out(vty, "Pending, due in %lld msec\n", + (long long)remain.tv_sec * 1000 + remain.tv_usec / 1000); } else { vty_out(vty, "Not scheduled\n"); diff --git a/lib/module.c b/lib/module.c index beef791093..b3ab91c4ea 100644 --- a/lib/module.c +++ b/lib/module.c @@ -42,8 +42,10 @@ static struct frrmod_info frrmod_default_info = { .description = "libfrr core module", }; union _frrmod_runtime_u frrmod_default = { - .r.info = &frrmod_default_info, - .r.finished_loading = 1, + .r = { + .info = &frrmod_default_info, + .finished_loading = 1, + }, }; // if defined(HAVE_SYS_WEAK_ALIAS_ATTRIBUTE) diff --git a/lib/spf_backoff.c b/lib/spf_backoff.c index d075e70d4e..92b7620eda 100644 --- a/lib/spf_backoff.c +++ b/lib/spf_backoff.c @@ -226,8 +226,9 @@ void spf_backoff_show(struct spf_backoff *backoff, struct vty *vty, if (backoff->t_holddown) { struct timeval remain = thread_timer_remain(backoff->t_holddown); - vty_out(vty, "%s Still runs for %ld msec\n", - prefix, remain.tv_sec * 1000 + remain.tv_usec / 1000); + vty_out(vty, "%s Still runs for %lld msec\n", + prefix, (long long)remain.tv_sec * 1000 + + remain.tv_usec / 1000); } else { vty_out(vty, "%s Inactive\n", prefix); } @@ -237,8 +238,9 @@ void spf_backoff_show(struct spf_backoff *backoff, struct vty *vty, if (backoff->t_timetolearn) { struct timeval remain = thread_timer_remain(backoff->t_timetolearn); - vty_out(vty, "%s Still runs for %ld msec\n", - prefix, remain.tv_sec * 1000 + remain.tv_usec / 1000); + vty_out(vty, "%s Still runs for %lld msec\n", + prefix, (long long)remain.tv_sec * 1000 + + remain.tv_usec / 1000); } else { vty_out(vty, "%s Inactive\n", prefix); } diff --git a/lib/termtable.c b/lib/termtable.c index f7aec43118..ba85962cc9 100644 --- a/lib/termtable.c +++ b/lib/termtable.c @@ -31,48 +31,60 @@ struct ttable_style ttable_styles[] = { .corner = '+', .rownums_on = false, .indent = 1, - .border.top = '-', - .border.bottom = '-', - .border.left = '|', - .border.right = '|', - .border.top_on = true, - .border.bottom_on = true, - .border.left_on = true, - .border.right_on = true, - .cell.lpad = 1, - .cell.rpad = 1, - .cell.align = LEFT, - .cell.border.bottom = '-', - .cell.border.bottom_on = true, - .cell.border.top = '-', - .cell.border.top_on = false, - .cell.border.right = '|', - .cell.border.right_on = true, - .cell.border.left = '|', - .cell.border.left_on = false, + .border = { + .top = '-', + .bottom = '-', + .left = '|', + .right = '|', + .top_on = true, + .bottom_on = true, + .left_on = true, + .right_on = true, + }, + .cell = { + .lpad = 1, + .rpad = 1, + .align = LEFT, + .border = { + .bottom = '-', + .bottom_on = true, + .top = '-', + .top_on = false, + .right = '|', + .right_on = true, + .left = '|', + .left_on = false, + }, + }, }, { // blank, suitable for plaintext alignment .corner = ' ', .rownums_on = false, .indent = 1, - .border.top = ' ', - .border.bottom = ' ', - .border.left = ' ', - .border.right = ' ', - .border.top_on = false, - .border.bottom_on = false, - .border.left_on = false, - .border.right_on = false, - .cell.lpad = 0, - .cell.rpad = 3, - .cell.align = LEFT, - .cell.border.bottom = ' ', - .cell.border.bottom_on = false, - .cell.border.top = ' ', - .cell.border.top_on = false, - .cell.border.right = ' ', - .cell.border.right_on = false, - .cell.border.left = ' ', - .cell.border.left_on = false, + .border = { + .top = ' ', + .bottom = ' ', + .left = ' ', + .right = ' ', + .top_on = false, + .bottom_on = false, + .left_on = false, + .right_on = false, + }, + .cell = { + .lpad = 0, + .rpad = 3, + .align = LEFT, + .border = { + .bottom = ' ', + .bottom_on = false, + .top = ' ', + .top_on = false, + .right = ' ', + .right_on = false, + .left = ' ', + .left_on = false, + }, + } } }; /* clang-format on */ diff --git a/pimd/pim_join.c b/pimd/pim_join.c index 9d65330e5f..4f5e534010 100644 --- a/pimd/pim_join.c +++ b/pimd/pim_join.c @@ -414,7 +414,7 @@ int pim_joinprune_send(struct pim_rpf *rpf, struct list *groups) struct pim_jp_agg_group *group; struct pim_interface *pim_ifp = NULL; struct pim_jp_groups *grp = NULL; - struct pim_jp *msg; + struct pim_jp *msg = NULL; struct listnode *node, *nnode; uint8_t pim_msg[10000]; uint8_t *curr_ptr = pim_msg; diff --git a/zebra/zserv.c b/zebra/zserv.c index 7899a8375c..0e0cc78bbe 100644 --- a/zebra/zserv.c +++ b/zebra/zserv.c @@ -1198,7 +1198,7 @@ static int zread_ipv4_add(struct zserv *client, u_short length, ifindex_t ifindex; safi_t safi; int ret; - enum lsp_types_t label_type; + enum lsp_types_t label_type = ZEBRA_LSP_NONE; mpls_label_t label; struct nexthop *nexthop; From 8c9cc7bbf657e3440d9bc758fe45aef5f43c989f Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Sat, 26 Aug 2017 01:27:22 +0200 Subject: [PATCH 119/130] bgpd: encap: fix extension sizing Variably-sized struct tails are done as [0], not [1]. The latter triggers compiler warnings and mis-sizes "sizeof(struct) + n" expressions. Signed-off-by: David Lamparter --- bgpd/bgp_attr.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bgpd/bgp_attr.h b/bgpd/bgp_attr.h index 324813c085..4dd38459f8 100644 --- a/bgpd/bgp_attr.h +++ b/bgpd/bgp_attr.h @@ -72,7 +72,7 @@ struct bgp_attr_encap_subtlv { unsigned long refcnt; uint16_t type; uint16_t length; - uint8_t value[1]; /* will be extended */ + uint8_t value[0]; /* will be extended */ }; #if ENABLE_BGP_VNC From d440e3dbf0180e63e461a5c2ec908d1c71327cad Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Sat, 26 Aug 2017 01:38:10 +0200 Subject: [PATCH 120/130] lib: prefix: fix char value size There are 16 bytes here, not 8. Signed-off-by: David Lamparter --- lib/prefix.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/prefix.h b/lib/prefix.h index eab4ac2bb7..a27f46ba0a 100644 --- a/lib/prefix.h +++ b/lib/prefix.h @@ -125,7 +125,7 @@ struct prefix { struct in_addr adv_router; } lp; struct ethaddr prefix_eth; /* AF_ETHERNET */ - u_char val[8]; + u_char val[16]; uintptr_t ptr; struct evpn_addr prefix_evpn; /* AF_EVPN */ } u __attribute__((aligned(8))); From adf580f72af5885ce25cb0df44d9e5676dfc0214 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Sat, 26 Aug 2017 01:41:07 +0200 Subject: [PATCH 121/130] zebra: remove RT_ROUNDUP warning This warning is at odds with how the world works. Also, the code is correct on all platforms we care about. Signed-off-by: David Lamparter --- zebra/kernel_socket.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/zebra/kernel_socket.c b/zebra/kernel_socket.c index 84d01bca6f..e2a1deb9ac 100644 --- a/zebra/kernel_socket.c +++ b/zebra/kernel_socket.c @@ -88,13 +88,10 @@ extern struct zebra_privs_t zserv_privs; #if !defined(ROUNDUP) /* - * It's a bug for a platform not to define rounding/alignment for - * sockaddrs on the routing socket. This warning really is - * intentional, to provoke filing bug reports with operating systems - * that don't define RT_ROUNDUP or equivalent. + * If you're porting to a platform that changed RT_ROUNDUP but doesn't + * have it in its headers, this will break rather obviously and you'll + * have to fix it here. */ -#warning \ - "net/route.h does not define RT_ROUNDUP; making unwarranted assumptions!" /* OS X (Xcode as of 2014-12) is known not to define RT_ROUNDUP */ #ifdef __APPLE__ From d9e5b009554f99230be1eee62daf098403c3cadf Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Sat, 26 Aug 2017 01:52:12 +0200 Subject: [PATCH 122/130] isisd: bpf: ETHER_HDR_LEN -> ETH_ALEN Signed-off-by: David Lamparter --- isisd/isis_bpf.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/isisd/isis_bpf.c b/isisd/isis_bpf.c index 98f612f827..2c8b126088 100644 --- a/isisd/isis_bpf.c +++ b/isisd/isis_bpf.c @@ -48,14 +48,15 @@ extern struct zebra_privs_t isisd_privs; struct bpf_insn llcfilter[] = { - BPF_STMT(BPF_LD + BPF_B + BPF_ABS, - ETHER_HDR_LEN), /* check first byte */ + /* check first byte */ + BPF_STMT(BPF_LD + BPF_B + BPF_ABS, ETH_ALEN), BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ISO_SAP, 0, 5), - BPF_STMT(BPF_LD + BPF_B + BPF_ABS, ETHER_HDR_LEN + 1), - BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ISO_SAP, 0, - 3), /* check second byte */ - BPF_STMT(BPF_LD + BPF_B + BPF_ABS, ETHER_HDR_LEN + 2), - BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0x03, 0, 1), /* check third byte */ + /* check second byte */ + BPF_STMT(BPF_LD + BPF_B + BPF_ABS, ETH_ALEN + 1), + BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ISO_SAP, 0, 3), + /* check third byte */ + BPF_STMT(BPF_LD + BPF_B + BPF_ABS, ETH_ALEN + 2), + BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0x03, 0, 1), BPF_STMT(BPF_RET + BPF_K, (u_int)-1), BPF_STMT(BPF_RET + BPF_K, 0)}; u_int readblen = 0; @@ -243,15 +244,14 @@ int isis_recv_pdu_bcast(struct isis_circuit *circuit, u_char *ssnpa) assert(bpf_hdr->bh_caplen == bpf_hdr->bh_datalen); - offset = bpf_hdr->bh_hdrlen + LLC_LEN + ETHER_HDR_LEN; + offset = bpf_hdr->bh_hdrlen + LLC_LEN + ETH_ALEN; /* then we lose the BPF, LLC and ethernet headers */ stream_write(circuit->rcv_stream, readbuff + offset, - bpf_hdr->bh_caplen - LLC_LEN - ETHER_HDR_LEN); + bpf_hdr->bh_caplen - LLC_LEN - ETH_ALEN); stream_set_getp(circuit->rcv_stream, 0); - memcpy(ssnpa, readbuff + bpf_hdr->bh_hdrlen + ETH_ALEN, - ETH_ALEN); + memcpy(ssnpa, readbuff + bpf_hdr->bh_hdrlen + ETH_ALEN, ETH_ALEN); if (ioctl(circuit->fd, BIOCFLUSH, &one) < 0) zlog_warn("Flushing failed: %s", safe_strerror(errno)); @@ -265,7 +265,7 @@ int isis_send_pdu_bcast(struct isis_circuit *circuit, int level) ssize_t written; size_t buflen; - buflen = stream_get_endp(circuit->snd_stream) + LLC_LEN + ETHER_HDR_LEN; + buflen = stream_get_endp(circuit->snd_stream) + LLC_LEN + ETH_ALEN; if (buflen > sizeof(sock_buff)) { zlog_warn( "isis_send_pdu_bcast: sock_buff size %zu is less than " @@ -291,12 +291,12 @@ int isis_send_pdu_bcast(struct isis_circuit *circuit, int level) /* * Then the LLC */ - sock_buff[ETHER_HDR_LEN] = ISO_SAP; - sock_buff[ETHER_HDR_LEN + 1] = ISO_SAP; - sock_buff[ETHER_HDR_LEN + 2] = 0x03; + sock_buff[ETH_ALEN] = ISO_SAP; + sock_buff[ETH_ALEN + 1] = ISO_SAP; + sock_buff[ETH_ALEN + 2] = 0x03; /* then we copy the data */ - memcpy(sock_buff + (LLC_LEN + ETHER_HDR_LEN), circuit->snd_stream->data, + memcpy(sock_buff + (LLC_LEN + ETH_ALEN), circuit->snd_stream->data, stream_get_endp(circuit->snd_stream)); /* now we can send this */ From cd6c573c697897dd73fb4bffeb176940af4582c2 Mon Sep 17 00:00:00 2001 From: Don Slice Date: Sat, 26 Aug 2017 15:51:43 -0400 Subject: [PATCH 123/130] eigrpd: add correct interface metrics when interface comes up Problem noticed where we were not sending the correct metric values to our peers for connected interfaces. Found that we were not storing these values on the structure used to send the update packets. Signed-off-by: Don Slice --- eigrpd/eigrp_interface.c | 1 + 1 file changed, 1 insertion(+) diff --git a/eigrpd/eigrp_interface.c b/eigrpd/eigrp_interface.c index ae9ec293ce..aa59516002 100644 --- a/eigrpd/eigrp_interface.c +++ b/eigrpd/eigrp_interface.c @@ -307,6 +307,7 @@ int eigrp_if_up(struct eigrp_interface *ei) pe->nt = EIGRP_TOPOLOGY_TYPE_CONNECTED; ne->prefix = pe; + pe->reported_metric = metric; pe->state = EIGRP_FSM_STATE_PASSIVE; pe->fdistance = eigrp_calculate_metrics(eigrp, metric); pe->req_action |= EIGRP_FSM_NEED_UPDATE; From b6116506ec81735afa647af112c6aaa1ed35e9df Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Wed, 17 May 2017 18:27:54 +0200 Subject: [PATCH 124/130] lib: ZeroMQ read handler, v2 This uses zmq_getsockopt(ZMQ_FD) to create a libfrr read event, which then wraps zmq_poll and calls an user-specified ZeroMQ read handler. It's wrapped in a separate library in order to make ZeroMQ support an installation-time option instead of build-time. Extended to support per-message and per-fragment callbacks as discussed with Bingen in PR #566. Signed-off-by: David Lamparter --- configure.ac | 17 +++++ lib/frr_zmq.c | 191 ++++++++++++++++++++++++++++++++++++++++++++++++++ lib/frr_zmq.h | 50 +++++++++++++ lib/subdir.am | 15 ++++ 4 files changed, 273 insertions(+) create mode 100644 lib/frr_zmq.c create mode 100644 lib/frr_zmq.h diff --git a/configure.ac b/configure.ac index bf66e00f9f..ec04190485 100755 --- a/configure.ac +++ b/configure.ac @@ -320,6 +320,8 @@ AC_ARG_WITH(rfp-path, AS_HELP_STRING([--with-rfp-path[=DIR]],[path to replaced stub RFP used with BGP VNC])) AC_ARG_ENABLE(snmp, AS_HELP_STRING([--enable-snmp=ARG], [enable SNMP support (smux or agentx)])) +AC_ARG_ENABLE(zeromq, + AS_HELP_STRING([--enable-zeromq], [enable ZeroMQ handler (libfrrzmq)])) AC_ARG_WITH(libpam, AS_HELP_STRING([--with-libpam], [use libpam for PAM support in vtysh])) AC_ARG_ENABLE(ospfapi, @@ -1714,6 +1716,21 @@ AC_CHECK_HEADER([malloc.h], ) ], [], FRR_INCLUDES) +dnl ------ +dnl ZeroMQ +dnl ------ +if test "x$enable_zeromq" != "xno"; then + PKG_CHECK_MODULES(ZEROMQ, [libzmq >= 4.0.0], [ + AC_DEFINE(HAVE_ZEROMQ, 1, [Enable ZeroMQ support]) + ZEROMQ=true + ], [ + if test "x$enable_zeromq" = "xyes"; then + AC_MSG_ERROR([configuration specifies --enable-zeromq but libzmq was not found]) + fi + ]) +fi +AM_CONDITIONAL([ZEROMQ], test "x$ZEROMQ" = "xtrue") + dnl ---------- dnl configure date dnl ---------- diff --git a/lib/frr_zmq.c b/lib/frr_zmq.c new file mode 100644 index 0000000000..861f7a5f0c --- /dev/null +++ b/lib/frr_zmq.c @@ -0,0 +1,191 @@ +/* + * libzebra ZeroMQ bindings + * Copyright (C) 2015 David Lamparter + * + * 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. + * + * 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; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include + +#include "thread.h" +#include "memory.h" +#include "frr_zmq.h" +#include "log.h" + +DEFINE_MTYPE_STATIC(LIB, ZEROMQ_CB, "ZeroMQ callback") + +/* libzmq's context */ +void *frrzmq_context = NULL; +static unsigned frrzmq_initcount = 0; + +void frrzmq_init(void) +{ + if (frrzmq_initcount++ == 0) { + frrzmq_context = zmq_ctx_new(); + zmq_ctx_set(frrzmq_context, ZMQ_IPV6, 1); + } +} + +void frrzmq_finish(void) +{ + if (--frrzmq_initcount == 0) { + zmq_ctx_term(frrzmq_context); + frrzmq_context = NULL; + } +} + +/* read callback integration */ +struct frrzmq_cb { + struct thread *thread; + void *zmqsock; + void *arg; + int fd; + + bool cancelled; + + void (*cb_msg)(void *arg, void *zmqsock); + void (*cb_part)(void *arg, void *zmqsock, + zmq_msg_t *msg, unsigned partnum); +}; + + +static int frrzmq_read_msg(struct thread *t) +{ + struct frrzmq_cb *cb = THREAD_ARG(t); + zmq_msg_t msg; + unsigned partno; + int ret, more; + size_t moresz; + + while (1) { + zmq_pollitem_t polli = { + .socket = cb->zmqsock, + .events = ZMQ_POLLIN + }; + ret = zmq_poll(&polli, 1, 0); + + if (ret < 0) + goto out_err; + if (!(polli.revents & ZMQ_POLLIN)) + break; + + if (cb->cb_msg) { + cb->cb_msg(cb->arg, cb->zmqsock); + + if (cb->cancelled) { + XFREE(MTYPE_ZEROMQ_CB, cb); + return 0; + } + continue; + } + + partno = 0; + if (zmq_msg_init(&msg)) + goto out_err; + do { + ret = zmq_msg_recv(&msg, cb->zmqsock, ZMQ_NOBLOCK); + if (ret < 0) { + if (errno == EAGAIN) + break; + + zmq_msg_close(&msg); + goto out_err; + } + + cb->cb_part(cb->arg, cb->zmqsock, &msg, partno); + if (cb->cancelled) { + zmq_msg_close(&msg); + XFREE(MTYPE_ZEROMQ_CB, cb); + return 0; + } + + /* cb_part may have read additional parts of the + * message; don't use zmq_msg_more here */ + moresz = sizeof(more); + more = 0; + ret = zmq_getsockopt(cb->zmqsock, ZMQ_RCVMORE, + &more, &moresz); + if (ret < 0) { + zmq_msg_close(&msg); + goto out_err; + } + + partno++; + } while (more); + zmq_msg_close(&msg); + } + + funcname_thread_add_read_write(THREAD_READ, t->master, frrzmq_read_msg, + cb, cb->fd, &cb->thread, t->funcname, t->schedfrom, + t->schedfrom_line); + return 0; + +out_err: + zlog_err("ZeroMQ error: %s(%d)", strerror (errno), errno); + return 0; +} + +struct frrzmq_cb *funcname_frrzmq_thread_add_read( + struct thread_master *master, + void (*msgfunc)(void *arg, void *zmqsock), + void (*partfunc)(void *arg, void *zmqsock, + zmq_msg_t *msg, unsigned partnum), + void *arg, void *zmqsock, debugargdef) +{ + int fd, events; + size_t len; + struct frrzmq_cb *cb; + + if (!(msgfunc || partfunc) || (msgfunc && partfunc)) + return NULL; + len = sizeof(fd); + if (zmq_getsockopt(zmqsock, ZMQ_FD, &fd, &len)) + return NULL; + len = sizeof(events); + if (zmq_getsockopt(zmqsock, ZMQ_EVENTS, &events, &len)) + return NULL; + + cb = XCALLOC(MTYPE_ZEROMQ_CB, sizeof(struct frrzmq_cb)); + if (!cb) + return NULL; + + cb->arg = arg; + cb->zmqsock = zmqsock; + cb->cb_msg = msgfunc; + cb->cb_part = partfunc; + cb->fd = fd; + + if (events & ZMQ_POLLIN) + funcname_thread_add_event(master, + frrzmq_read_msg, cb, fd, &cb->thread, + funcname, schedfrom, fromln); + else + funcname_thread_add_read_write(THREAD_READ, master, + frrzmq_read_msg, cb, fd, &cb->thread, + funcname, schedfrom, fromln); + return cb; +} + +void frrzmq_thread_cancel(struct frrzmq_cb *cb) +{ + if (!cb->thread) { + /* canceling from within callback */ + cb->cancelled = 1; + return; + } + thread_cancel(cb->thread); + XFREE(MTYPE_ZEROMQ_CB, cb); +} diff --git a/lib/frr_zmq.h b/lib/frr_zmq.h new file mode 100644 index 0000000000..d37824522b --- /dev/null +++ b/lib/frr_zmq.h @@ -0,0 +1,50 @@ +/* + * libzebra ZeroMQ bindings + * Copyright (C) 2015 David Lamparter + * + * 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. + * + * 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; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _FRRZMQ_H +#define _FRRZMQ_H + +#include "thread.h" +#include + +/* libzmq's context */ +extern void *frrzmq_context; + +extern void frrzmq_init (void); +extern void frrzmq_finish (void); + +#define debugargdef const char *funcname, const char *schedfrom, int fromln + +#define frrzmq_thread_add_read_msg(m,f,a,z) funcname_frrzmq_thread_add_read( \ + m,f,NULL,a,z,#f,__FILE__,__LINE__) +#define frrzmq_thread_add_read_part(m,f,a,z) funcname_frrzmq_thread_add_read( \ + m,NULL,f,a,z,#f,__FILE__,__LINE__) + +struct frrzmq_cb; + +extern struct frrzmq_cb *funcname_frrzmq_thread_add_read( + struct thread_master *master, + void (*msgfunc)(void *arg, void *zmqsock), + void (*partfunc)(void *arg, void *zmqsock, + zmq_msg_t *msg, unsigned partnum), + void *arg, void *zmqsock, debugargdef); + +extern void frrzmq_thread_cancel(struct frrzmq_cb *cb); + +#endif /* _FRRZMQ_H */ diff --git a/lib/subdir.am b/lib/subdir.am index d6349ba22d..5f38cc7a14 100644 --- a/lib/subdir.am +++ b/lib/subdir.am @@ -183,6 +183,21 @@ lib_libfrrsnmp_la_SOURCES = \ lib/snmp.c \ # end +# +# ZeroMQ support +# +if ZEROMQ +lib_LTLIBRARIES += lib/libfrrzmq.la +pkginclude_HEADERS += lib/frr_zmq.h +endif + +lib_libfrrzmq_la_CFLAGS = $(WERROR) $(ZEROMQ_CFLAGS) +lib_libfrrzmq_la_LDFLAGS = -version-info 0:0:0 +lib_libfrrzmq_la_LIBADD = lib/libfrr.la $(ZEROMQ_LIBS) +lib_libfrrzmq_la_SOURCES = \ + lib/frr_zmq.c \ + #end + # # CLI utilities # From a0b974def7e6c76d4e4c31ee93bc33f67c57c611 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Thu, 24 Aug 2017 18:13:31 +0200 Subject: [PATCH 125/130] tests: add ZeroMQ test Signed-off-by: David Lamparter --- tests/.gitignore | 1 + tests/Makefile.am | 8 ++ tests/lib/test_zmq.c | 212 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 221 insertions(+) create mode 100644 tests/lib/test_zmq.c diff --git a/tests/.gitignore b/tests/.gitignore index 604ffaa8b6..41349cce24 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -45,4 +45,5 @@ __pycache__ /lib/test_timer_correctness /lib/test_timer_performance /lib/test_ttable +/lib/test_zmq /ospf6d/test_lsdb diff --git a/tests/Makefile.am b/tests/Makefile.am index 59ea3c4c69..0fd84570a3 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -72,6 +72,12 @@ check_PROGRAMS = \ $(TESTS_OSPF6D) \ # end +if ZEROMQ +check_PROGRAMS += \ + lib/test_zmq \ + # end +endif + ../vtysh/vtysh_cmd.c: $(MAKE) -C ../vtysh vtysh_cmd.c @@ -112,6 +118,7 @@ lib_test_timer_correctness_SOURCES = lib/test_timer_correctness.c \ lib_test_timer_performance_SOURCES = lib/test_timer_performance.c \ helpers/c/prng.c lib_test_ttable_SOURCES = lib/test_ttable.c +lib_test_zmq_SOURCES = lib/test_zmq.c lib_cli_test_cli_SOURCES = lib/cli/test_cli.c lib/cli/common_cli.c lib_cli_test_commands_SOURCES = lib/cli/test_commands_defun.c \ lib/cli/test_commands.c \ @@ -147,6 +154,7 @@ lib_test_table_LDADD = $(ALL_TESTS_LDADD) -lm lib_test_timer_correctness_LDADD = $(ALL_TESTS_LDADD) lib_test_timer_performance_LDADD = $(ALL_TESTS_LDADD) lib_test_ttable_LDADD = $(ALL_TESTS_LDADD) +lib_test_zmq_LDADD = $(ALL_TESTS_LDADD) ../lib/libfrrzmq.la lib_cli_test_cli_LDADD = $(ALL_TESTS_LDADD) lib_cli_test_commands_LDADD = $(ALL_TESTS_LDADD) bgpd_test_aspath_LDADD = $(BGP_TEST_LDADD) diff --git a/tests/lib/test_zmq.c b/tests/lib/test_zmq.c new file mode 100644 index 0000000000..c270ec3d18 --- /dev/null +++ b/tests/lib/test_zmq.c @@ -0,0 +1,212 @@ +/* + * ZeroMQ event test + * Copyright (C) 2017 David Lamparter, for NetDEF, Inc. + * + * 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. + * + * 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; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include "memory.h" +#include "sigevent.h" +#include "frr_zmq.h" + +DEFINE_MTYPE_STATIC(LIB, TESTBUF, "zmq test buffer") + +static struct thread_master *master; + +static void msg_buf_free(void *data, void *hint) +{ + XFREE(MTYPE_TESTBUF, data); +} + +static void run_client(int syncfd) +{ + int i, j; + char buf[32]; + char dummy; + void *zmqctx = NULL; + void *zmqsock; + + read(syncfd, &dummy, 1); + + zmqctx = zmq_ctx_new(); + zmq_ctx_set(zmqctx, ZMQ_IPV6, 1); + + zmqsock = zmq_socket(zmqctx, ZMQ_REQ); + if (zmq_connect(zmqsock, "tcp://127.0.0.1:17171")) { + perror("zmq_connect"); + exit(1); + } + + /* single-part */ + for (i = 0; i < 8; i++) { + snprintf(buf, sizeof(buf), "msg #%d %c%c%c", + i, 'a' + i, 'b' + i, 'c' + i); + printf("client send: %s\n", buf); + fflush(stdout); + zmq_send(zmqsock, buf, strlen(buf) + 1, 0); + zmq_recv(zmqsock, buf, sizeof(buf), 0); + printf("client recv: %s\n", buf); + } + + /* multipart */ + for (i = 2; i < 5; i++) { + int more; + + printf("---\n"); + for (j = 1; j <= i; j++) { + zmq_msg_t part; + char *dyn = XMALLOC(MTYPE_TESTBUF, 32); + + snprintf(dyn, 32, "part %d/%d", j, i); + printf("client send: %s\n", dyn); + fflush(stdout); + + zmq_msg_init_data(&part, dyn, strlen(dyn) + 1, + msg_buf_free, NULL); + zmq_msg_send(&part, zmqsock, j < i ? ZMQ_SNDMORE : 0); + } + + zmq_msg_t part; + do { + char *data; + + zmq_msg_recv(&part, zmqsock, 0); + data = zmq_msg_data(&part); + more = zmq_msg_more(&part); + printf("client recv (more: %d): %s\n", more, data); + } while (more); + zmq_msg_close(&part); + } + zmq_close(zmqsock); + zmq_ctx_term(zmqctx); +} + +static struct frrzmq_cb *cb; + +static void serverpartfn(void *arg, void *zmqsock, zmq_msg_t *msg, + unsigned partnum) +{ + int more = zmq_msg_more(msg); + char *in = zmq_msg_data(msg); + size_t i; + zmq_msg_t reply; + char *out; + + printf("server recv part %u (more: %d): %s\n", partnum, more, in); + fflush(stdout); + /* REQ-REP doesn't allow sending a reply here */ + if (more) + return; + + out = XMALLOC(MTYPE_TESTBUF, strlen(in) + 1); + for (i = 0; i < strlen(in); i++) + out[i] = toupper(in[i]); + out[i] = '\0'; + zmq_msg_init_data(&reply, out, strlen(out) + 1, msg_buf_free, NULL); + zmq_msg_send(&reply, zmqsock, ZMQ_SNDMORE); + + out = XMALLOC(MTYPE_TESTBUF, 32); + snprintf(out, 32, "msg# was %u", partnum); + zmq_msg_init_data(&reply, out, strlen(out) + 1, msg_buf_free, NULL); + zmq_msg_send(&reply, zmqsock, 0); +} + +static void serverfn(void *arg, void *zmqsock) +{ + static int num = 0; + + char buf[32]; + size_t i; + zmq_recv(zmqsock, buf, sizeof(buf), 0); + + printf("server recv: %s\n", buf); + fflush(stdout); + for (i = 0; i < strlen(buf); i++) + buf[i] = toupper(buf[i]); + zmq_send(zmqsock, buf, strlen(buf) + 1, 0); + + if (++num < 4) + return; + + /* change to multipart callback */ + frrzmq_thread_cancel(cb); + + cb = frrzmq_thread_add_read_part(master, serverpartfn, NULL, zmqsock); +} + +static void sigchld(void) +{ + printf("child exited.\n"); + frrzmq_thread_cancel(cb); +} + +static struct quagga_signal_t sigs[] = { + { + .signal = SIGCHLD, + .handler = sigchld, + }, +}; + +static void run_server(int syncfd) +{ + void *zmqsock; + char dummy = 0; + struct thread t; + + master = thread_master_create(NULL); + signal_init(master, array_size(sigs), sigs); + frrzmq_init(); + + zmqsock = zmq_socket(frrzmq_context, ZMQ_REP); + if (zmq_bind(zmqsock, "tcp://*:17171")) { + perror("zmq_bind"); + exit(1); + } + + cb = frrzmq_thread_add_read_msg(master, serverfn, NULL, zmqsock); + + write(syncfd, &dummy, sizeof(dummy)); + while (thread_fetch(master, &t)) + thread_call(&t); + + zmq_close(zmqsock); + frrzmq_finish(); + thread_master_free(master); + log_memstats_stderr("test"); +} + +int main(void) +{ + int syncpipe[2]; + pid_t child; + + if (pipe(syncpipe)) { + perror("pipe"); + exit(1); + } + + child = fork(); + if (child < 0) { + perror("fork"); + exit(1); + } else if (child == 0) { + run_client(syncpipe[0]); + exit(0); + } + + run_server(syncpipe[1]); + exit(0); +} From 35b416fde2cedf75da4d27665fd6d063c6cf5b8e Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Mon, 28 Aug 2017 17:20:38 +0200 Subject: [PATCH 126/130] tests: fix & run ZeroMQ test add reference output & run the test with proper libs and such. Signed-off-by: David Lamparter --- tests/Makefile.am | 3 +- tests/lib/cli/test_commands.py | 2 +- tests/lib/test_zmq.py | 11 ++++++++ tests/lib/test_zmq.refout | 50 ++++++++++++++++++++++++++++++++++ 4 files changed, 64 insertions(+), 2 deletions(-) create mode 100644 tests/lib/test_zmq.py create mode 100644 tests/lib/test_zmq.refout diff --git a/tests/Makefile.am b/tests/Makefile.am index 0fd84570a3..8a8918dcb4 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -119,6 +119,7 @@ lib_test_timer_performance_SOURCES = lib/test_timer_performance.c \ helpers/c/prng.c lib_test_ttable_SOURCES = lib/test_ttable.c lib_test_zmq_SOURCES = lib/test_zmq.c +lib_test_zmq_CFLAGS = $(AM_CFLAGS) $(ZEROMQ_CFLAGS) lib_cli_test_cli_SOURCES = lib/cli/test_cli.c lib/cli/common_cli.c lib_cli_test_commands_SOURCES = lib/cli/test_commands_defun.c \ lib/cli/test_commands.c \ @@ -154,7 +155,7 @@ lib_test_table_LDADD = $(ALL_TESTS_LDADD) -lm lib_test_timer_correctness_LDADD = $(ALL_TESTS_LDADD) lib_test_timer_performance_LDADD = $(ALL_TESTS_LDADD) lib_test_ttable_LDADD = $(ALL_TESTS_LDADD) -lib_test_zmq_LDADD = $(ALL_TESTS_LDADD) ../lib/libfrrzmq.la +lib_test_zmq_LDADD = ../lib/libfrrzmq.la $(ALL_TESTS_LDADD) $(ZEROMQ_LIBS) lib_cli_test_cli_LDADD = $(ALL_TESTS_LDADD) lib_cli_test_commands_LDADD = $(ALL_TESTS_LDADD) bgpd_test_aspath_LDADD = $(BGP_TEST_LDADD) diff --git a/tests/lib/cli/test_commands.py b/tests/lib/cli/test_commands.py index bda0bbac44..d55345186a 100644 --- a/tests/lib/cli/test_commands.py +++ b/tests/lib/cli/test_commands.py @@ -8,4 +8,4 @@ class TestCommands(frrtest.TestRefOut): @pytest.mark.skipif('QUAGGA_TEST_COMMANDS' not in os.environ, reason='QUAGGA_TEST_COMMANDS not set') def test_refout(self): - return super(TestCommands, self).test_refout(self) + return super(TestCommands, self).test_refout() diff --git a/tests/lib/test_zmq.py b/tests/lib/test_zmq.py new file mode 100644 index 0000000000..1f8ee54169 --- /dev/null +++ b/tests/lib/test_zmq.py @@ -0,0 +1,11 @@ +import frrtest +import pytest +import os + +class TestZMQ(frrtest.TestRefOut): + program = './test_zmq' + + @pytest.mark.skipif('S["ZEROMQ_TRUE"]=""\n' not in open('../config.status').readlines(), + reason='ZEROMQ not enabled') + def test_refout(self): + return super(TestZMQ, self).test_refout() diff --git a/tests/lib/test_zmq.refout b/tests/lib/test_zmq.refout new file mode 100644 index 0000000000..61f45f02b1 --- /dev/null +++ b/tests/lib/test_zmq.refout @@ -0,0 +1,50 @@ +client send: msg #0 abc +server recv: msg #0 abc +client recv: MSG #0 ABC +client send: msg #1 bcd +server recv: msg #1 bcd +client recv: MSG #1 BCD +client send: msg #2 cde +server recv: msg #2 cde +client recv: MSG #2 CDE +client send: msg #3 def +server recv: msg #3 def +client recv: MSG #3 DEF +client send: msg #4 efg +server recv part 0 (more: 0): msg #4 efg +client recv: MSG #4 EFG +client send: msg #5 fgh +client recv: msg# was 0 +client send: msg #6 ghi +server recv part 0 (more: 0): msg #6 ghi +client recv: MSG #6 GHI +client send: msg #7 hij +client recv: msg# was 0 +--- +client send: part 1/2 +client send: part 2/2 +server recv part 0 (more: 1): part 1/2 +server recv part 1 (more: 0): part 2/2 +client recv (more: 1): PART 2/2 +client recv (more: 0): msg# was 1 +--- +client send: part 1/3 +client send: part 2/3 +client send: part 3/3 +server recv part 0 (more: 1): part 1/3 +server recv part 1 (more: 1): part 2/3 +server recv part 2 (more: 0): part 3/3 +client recv (more: 1): PART 3/3 +client recv (more: 0): msg# was 2 +--- +client send: part 1/4 +client send: part 2/4 +client send: part 3/4 +client send: part 4/4 +server recv part 0 (more: 1): part 1/4 +server recv part 1 (more: 1): part 2/4 +server recv part 2 (more: 1): part 3/4 +server recv part 3 (more: 0): part 4/4 +client recv (more: 1): PART 4/4 +client recv (more: 0): msg# was 3 +child exited. From f3cd305f1b3adab0be9aee509f8575bc7826e52c Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Mon, 28 Aug 2017 17:59:54 +0200 Subject: [PATCH 127/130] lib: document frrzmq in its header file Signed-off-by: David Lamparter --- lib/frr_zmq.h | 40 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/lib/frr_zmq.h b/lib/frr_zmq.h index d37824522b..69c6f8580d 100644 --- a/lib/frr_zmq.h +++ b/lib/frr_zmq.h @@ -23,7 +23,21 @@ #include "thread.h" #include -/* libzmq's context */ +/* linking/packaging note: this is a separate library that needs to be + * linked into any daemon/library/module that wishes to use its + * functionality. The purpose of this is to encapsulate the libzmq + * dependency and not make libfrr/FRR itself depend on libzmq. + * + * libfrrzmq should be put in LDFLAGS/LIBADD *before* either libfrr or + * libzmq, and both of these should always be listed, e.g. + * foo_LDFLAGS = libfrrzmq.la libfrr.la $(ZEROMQ_LIBS) + */ + +/* libzmq's context + * + * this is mostly here as a convenience, it has IPv6 enabled but nothing + * else is tied to it; you can use a separate context without problems + */ extern void *frrzmq_context; extern void frrzmq_init (void); @@ -31,6 +45,7 @@ extern void frrzmq_finish (void); #define debugargdef const char *funcname, const char *schedfrom, int fromln +/* core event registration, one of these 2 macros should be used */ #define frrzmq_thread_add_read_msg(m,f,a,z) funcname_frrzmq_thread_add_read( \ m,f,NULL,a,z,#f,__FILE__,__LINE__) #define frrzmq_thread_add_read_part(m,f,a,z) funcname_frrzmq_thread_add_read( \ @@ -38,6 +53,29 @@ extern void frrzmq_finish (void); struct frrzmq_cb; +/* Set up a POLLIN notification to be called from the libfrr main loop. + * This has the following properties: + * + * - since ZeroMQ works with edge triggered notifications, it will loop and + * dispatch as many events as ZeroMQ has pending at the time libfrr calls + * into this code + * - due to this looping (which means it non-single-issue), the callback is + * also persistent. Do _NOT_ re-register the event inside of your + * callback function. + * - either msgfunc or partfunc will be called (only one can be specified) + * - msgfunc is called once for each incoming message + * - if partfunc is specified, the message is read and partfunc is called + * for each ZeroMQ multi-part subpart. Note that you can't send replies + * before all parts have been read because that violates the ZeroMQ FSM. + * - you can safely cancel the callback from within itself + * - installing a callback will check for pending events (ZMQ_EVENTS) and + * may schedule the event to run as soon as libfrr is back in its main + * loop. + * + * TODO #1: add ZMQ_POLLERR / error callback + * TODO #2: add frrzmq_check_events() function to check for edge triggered + * things that may have happened after a zmq_send() call or so + */ extern struct frrzmq_cb *funcname_frrzmq_thread_add_read( struct thread_master *master, void (*msgfunc)(void *arg, void *zmqsock), From 5d1a2ee87bf0bd343a9f90ff3c37267137be83a4 Mon Sep 17 00:00:00 2001 From: Quentin Young Date: Mon, 28 Aug 2017 13:38:42 -0400 Subject: [PATCH 128/130] ospf6d, ospfd: add `no ospf6 router-id ...` * Deprecate `router-id A.B.C.D` for ospf6d * Add `ospf6 router-id A.B.C.D` * Add `no ospf6 router-id [A.B.C.D]` * Add deprecation notices for previously deprecated ospf commands Signed-off-by: Quentin Young --- ospf6d/ospf6_top.c | 54 ++++++++++++++++++++++++++++++++++++++++------ ospfd/ospf_vty.c | 8 +++++-- 2 files changed, 54 insertions(+), 8 deletions(-) diff --git a/ospf6d/ospf6_top.c b/ospf6d/ospf6_top.c index 387690bc8a..dc5792aa17 100644 --- a/ospf6d/ospf6_top.c +++ b/ospf6d/ospf6_top.c @@ -308,19 +308,24 @@ DEFUN (no_router_ospf6, /* change Router_ID commands. */ DEFUN (ospf6_router_id, ospf6_router_id_cmd, - "router-id A.B.C.D", - "Configure OSPF Router-ID\n" + "ospf6 router-id A.B.C.D", + OSPF6_STR + "Configure OSPF6 Router-ID\n" V4NOTATION_STR) { VTY_DECLVAR_CONTEXT(ospf6, o); - int idx_ipv4 = 1; + int idx = 0; int ret; + const char *router_id_str; u_int32_t router_id; - ret = inet_pton(AF_INET, argv[idx_ipv4]->arg, &router_id); + argv_find(argv, argc, "A.B.C.D", &idx); + router_id_str = argv[idx]->arg; + + ret = inet_pton(AF_INET, router_id_str, &router_id); if (ret == 0) { vty_out(vty, "malformed OSPF Router-ID: %s\n", - argv[idx_ipv4]->arg); + router_id_str); return CMD_SUCCESS; } @@ -331,6 +336,40 @@ DEFUN (ospf6_router_id, return CMD_SUCCESS; } +DEFUN (no_ospf6_router_id, + no_ospf6_router_id_cmd, + "no ospf6 router-id [A.B.C.D]", + NO_STR + OSPF6_STR + "Configure OSPF6 Router-ID\n" + V4NOTATION_STR) +{ + VTY_DECLVAR_CONTEXT(ospf6, o); + o->router_id_static = 0; + o->router_id = 0; + + return CMD_SUCCESS; +} + +#if CONFDATE > 20180828 +CPP_NOTICE("ospf6: `router-id A.B.C.D` deprecated 2017/08/28") +#endif +ALIAS_HIDDEN(ospf6_router_id, + ospf6_router_id_hdn_cmd, + "router-id A.B.C.D", + "Configure OSPF6 Router-ID\n" + V4NOTATION_STR) + +#if CONFDATE > 20180828 +CPP_NOTICE("ospf6: `no router-id A.B.C.D` deprecated 2017/08/28") +#endif +ALIAS_HIDDEN(no_ospf6_router_id, + no_ospf6_router_id_hdn_cmd, + "no router-id [A.B.C.D]", + NO_STR + "Configure OSPF6 Router-ID\n" + V4NOTATION_STR) + DEFUN (ospf6_log_adjacency_changes, ospf6_log_adjacency_changes_cmd, "log-adjacency-changes", @@ -974,7 +1013,7 @@ static int config_write_ospf6(struct vty *vty) sizeof(router_id)); vty_out(vty, "router ospf6\n"); if (ospf6->router_id_static != 0) - vty_out(vty, " router-id %s\n", router_id); + vty_out(vty, " ospf6 router-id %s\n", router_id); /* log-adjacency-changes flag print. */ if (CHECK_FLAG(ospf6->config_flags, OSPF6_LOG_ADJACENCY_CHANGES)) { @@ -1032,6 +1071,9 @@ void ospf6_top_init(void) install_default(OSPF6_NODE); install_element(OSPF6_NODE, &ospf6_router_id_cmd); + install_element(OSPF6_NODE, &no_ospf6_router_id_cmd); + install_element(OSPF6_NODE, &ospf6_router_id_hdn_cmd); + install_element(OSPF6_NODE, &no_ospf6_router_id_hdn_cmd); install_element(OSPF6_NODE, &ospf6_log_adjacency_changes_cmd); install_element(OSPF6_NODE, &ospf6_log_adjacency_changes_detail_cmd); install_element(OSPF6_NODE, &no_ospf6_log_adjacency_changes_cmd); diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c index 87aef1ea97..c52790a839 100644 --- a/ospfd/ospf_vty.c +++ b/ospfd/ospf_vty.c @@ -2268,7 +2268,9 @@ DEFUN (no_ospf_timers_lsa_min_arrival, return CMD_SUCCESS; } -/* Deprecated: 08/07/2017 */ +#if CONFDATE > 20180708 +CPP_NOTICE("ospf: `timers lsa arrival (0-1000)` deprecated 2017/07/08") +#endif ALIAS_HIDDEN (ospf_timers_lsa_min_arrival, ospf_timers_lsa_arrival_cmd, "timers lsa arrival (0-1000)", @@ -2277,7 +2279,9 @@ ALIAS_HIDDEN (ospf_timers_lsa_min_arrival, "ospf minimum arrival interval delay\n" "delay (msec) between accepted lsas\n"); -/* Deprecated: 08/07/2017 */ +#if CONFDATE > 20180708 +CPP_NOTICE("ospf: `no timers lsa arrival (0-1000)` deprecated 2017/07/08") +#endif ALIAS_HIDDEN (no_ospf_timers_lsa_min_arrival, no_ospf_timers_lsa_arrival_cmd, "no timers lsa arrival (0-1000)", From 344d9016be4051bedd0b87240edf7d8d70c7cd7e Mon Sep 17 00:00:00 2001 From: Nigel Kukard Date: Mon, 28 Aug 2017 18:35:15 +0000 Subject: [PATCH 129/130] vtysh: Fix for the ordering of large-community lists in config output Signed-off-by: Nigel Kukard --- vtysh/vtysh_config.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/vtysh/vtysh_config.c b/vtysh/vtysh_config.c index c561b5222f..58772ec549 100644 --- a/vtysh/vtysh_config.c +++ b/vtysh/vtysh_config.c @@ -245,7 +245,10 @@ void vtysh_config_parse_line(void *arg, const char *line) == 0 || strncmp(line, "ip extcommunity-list", strlen("ip extcommunity-list")) - == 0) + == 0 + || strncmp(line, "ip large-community-list", + strlen("ip large-community-list")) + == 0) config = config_get(COMMUNITY_LIST_NODE, line); else if (strncmp(line, "ip route", strlen("ip route")) == 0) config = config_get(IP_NODE, line); From c594d99ffbda5f74ec3ecfc4589bf5dd3c6726d6 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 24 Aug 2017 12:16:24 -0400 Subject: [PATCH 130/130] configure: Add `-funwind-tables` Certain platforms( ARM comes to mind ) in order to get a proper stack trace on crash you need to compile with this value. Since it only slightly increases the size of the binary for other platforms, I would consider it worthwhile to include this directive. Signed-off-by: Donald Sharp --- configure.ac | 1 + 1 file changed, 1 insertion(+) diff --git a/configure.ac b/configure.ac index ec04190485..f6f38b47cf 100755 --- a/configure.ac +++ b/configure.ac @@ -195,6 +195,7 @@ fi dnl always want these CFLAGS AC_C_FLAG([-fno-omit-frame-pointer]) +AC_C_FLAG([-funwind-tables]) AC_C_FLAG([-Wall]) AC_C_FLAG([-Wextra]) AC_C_FLAG([-Wmissing-prototypes])