From 92e5026146483d8483e79400967b73ddabe361bf Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Wed, 14 Jun 2017 10:26:07 +0200 Subject: [PATCH 01/12] build: fix some cross-compilation issues Signed-off-by: David Lamparter --- configure.ac | 31 +++++++++++++++++++++++++++---- lib/command_parse.y | 2 ++ zebra/Makefile.am | 2 +- 3 files changed, 30 insertions(+), 5 deletions(-) diff --git a/configure.ac b/configure.ac index 65ba26d5f8..29bff56a5e 100755 --- a/configure.ac +++ b/configure.ac @@ -123,6 +123,28 @@ AC_DEFUN([AC_C_FLAG], [{ AC_LANG_POP(C) }]) +AC_DEFUN([AC_LINK_IFELSE_FLAGS], [{ + AC_LANG_PUSH(C) + ac_cflags_save="$CFLAGS" + ac_libs_save="$LIBS" + CFLAGS="$CFLAGS $1" + LIBS="$LIBS $2" + AC_LINK_IFELSE( + [$3], + [ + AC_MSG_RESULT([yes]) + CFLAGS="$ac_cflags_save" + LIBS="$ac_libs_save" + $5 + ], [ + AC_MSG_RESULT([no]) + CFLAGS="$ac_cflags_save" + LIBS="$ac_libs_save" + $4 + ]) + AC_LANG_POP(C) + }]) + dnl ICC won't bail on unknown options without -diag-error 10006 dnl need to do this first so we get useful results for the other options AC_C_FLAG([-diag-error 10006]) @@ -1430,7 +1452,9 @@ dnl ------------------ dnl check C-Ares library dnl ------------------ if test "${NHRPD}" != ""; then - PKG_CHECK_MODULES([CARES], [libcares]) + PKG_CHECK_MODULES([CARES], [libcares], , [ + AC_MSG_ERROR([trying to build nhrpd, but libcares not found. install c-ares and its -dev headers.]) + ]) fi @@ -1445,15 +1469,14 @@ if test "${enable_snmp}" != ""; then SNMP_LIBS="`${NETSNMP_CONFIG} --agent-libs`" SNMP_CFLAGS="`${NETSNMP_CONFIG} --base-cflags`" AC_MSG_CHECKING([whether we can link to Net-SNMP]) - AC_LINK_IFELSE([AC_LANG_PROGRAM([ + AC_LINK_IFELSE_FLAGS([$SNMP_CFLAGS], [$SNMP_LIBS], [AC_LANG_PROGRAM([ int main(void); ], [ { return 0; } -])],[AC_MSG_RESULT(yes)],[ - AC_MSG_RESULT(no) +])], [ AC_MSG_ERROR([--enable-snmp given but not usable])]) case "${enable_snmp}" in yes) diff --git a/lib/command_parse.y b/lib/command_parse.y index 466e3d3f1f..77e4e543aa 100644 --- a/lib/command_parse.y +++ b/lib/command_parse.y @@ -44,6 +44,8 @@ * struct parser_ctx is needed for the bison forward decls. */ %code requires { + #include "config.h" + #include #include #include diff --git a/zebra/Makefile.am b/zebra/Makefile.am index 3e0de3b463..45fc2680dc 100644 --- a/zebra/Makefile.am +++ b/zebra/Makefile.am @@ -76,10 +76,10 @@ zebra_fpm_la_SOURCES += zebra_fpm_netlink.c endif if HAVE_PROTOBUF zebra_fpm_la_SOURCES += zebra_fpm_protobuf.c -endif if DEV_BUILD zebra_fpm_la_SOURCES += zebra_fpm_dt.c endif +endif EXTRA_DIST = if_ioctl.c if_ioctl_solaris.c if_netlink.c \ From 29ad6f6882de5a871d6d81c609e8b20d825d6138 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Fri, 11 Nov 2016 17:10:02 +0100 Subject: [PATCH 02/12] lib: clippy the assistant Wraps the command parsing code for Python, so we can use it to do fancy preprocessing and replace extract.pl. Signed-off-by: David Lamparter --- configure.ac | 102 +++++++++++++- lib/Makefile.am | 24 +++- lib/clippy.c | 137 +++++++++++++++++++ lib/clippy.h | 28 ++++ lib/command_py.c | 336 +++++++++++++++++++++++++++++++++++++++++++++++ lib/defun_lex.l | 265 +++++++++++++++++++++++++++++++++++++ 6 files changed, 890 insertions(+), 2 deletions(-) create mode 100644 lib/clippy.c create mode 100644 lib/clippy.h create mode 100644 lib/command_py.c create mode 100644 lib/defun_lex.l diff --git a/configure.ac b/configure.ac index 29bff56a5e..ca8eae9057 100755 --- a/configure.ac +++ b/configure.ac @@ -23,7 +23,36 @@ dnl Get hostname and other information. dnl ----------------------------------- AC_CANONICAL_BUILD() AC_CANONICAL_HOST() -AC_CANONICAL_TARGET() + +AS_IF([test "$host" != "$build"], [ + if test "$srcdir" = "."; then + AC_MSG_ERROR([cross-compilation is only possible with builddir separate from srcdir. create a separate directory and run as .../path-to-frr/configure.]) + fi + test -d hosttools || mkdir hosttools + abssrc="`cd \"${srcdir}\"; pwd`" + + AC_MSG_NOTICE([...]) + AC_MSG_NOTICE([... cross-compilation: creating hosttools directory and self-configuring for build platform tools]) + AC_MSG_NOTICE([... use HOST_CPPFLAGS / HOST_CFLAGS / HOST_LDFLAGS if neccessary]) + AC_MSG_NOTICE([...]) + + ( CPPFLAGS="$HOST_CPPFLAGS"; \ + CFLAGS="$HOST_CFLAGS"; \ + LDFLAGS="$HOST_LDFLAGS"; \ + cd hosttools; "${abssrc}/configure" "--host=$build" "--build=$build"; ) + + AC_MSG_NOTICE([...]) + AC_MSG_NOTICE([... cross-compilation: finished self-configuring for build platform tools]) + AC_MSG_NOTICE([...]) + + build_clippy="false" + CLIPPYDIR="hosttools/lib" +], [ + build_clippy="true" + CLIPPYDIR="lib" +]) +AC_SUBST(CLIPPYDIR) +AM_CONDITIONAL([BUILD_CLIPPY], [$build_clippy]) # Disable portability warnings -- our automake code (in particular # common.am) uses some constructs specific to gmake. @@ -431,6 +460,77 @@ if test "x${enable_dev_build}" = "xyes"; then fi AM_CONDITIONAL([DEV_BUILD], [test "x$enable_dev_build" = "xyes"]) +# +# Python for clippy +# +AS_IF([test "$host" = "$build"], [ + PYTHONCONFIG="" + + # ordering: + # 1. try python3, but respect the user's preference on which minor ver + # 2. try python, which might be py3 or py2 again on the user's preference + # 3. try python2 (can really only be 2.7 but eh) + # 4. try 3.5 > 3.4 > 3.3 > 3.2 > 2.7 through pkg-config (no user pref) + # + # (AX_PYTHON_DEVEL has no clue about py3 vs py2) + # (AX_PYTHON does not do what we need) + + AC_CHECK_TOOLS([PYTHONCONFIG], [python3-config python-config python2-config]) + if test -n "$PYTHONCONFIG"; then + PYTHON_CFLAGS="`\"${PYTHONCONFIG}\" --includes`" + PYTHON_LIBS="`\"${PYTHONCONFIG}\" --libs`" + + AC_MSG_CHECKING([whether we found a working Python version]) + AC_LINK_IFELSE_FLAGS([$PYTHON_CFLAGS], [$PYTHON_LIBS], [AC_LANG_PROGRAM([ +#include +#if PY_VERSION_HEX < 0x02070000 +#error python too old +#endif +int main(void); +], +[ +{ + Py_Initialize(); + return 0; +} +])], [ + PYTHONCONFIG="" + unset PYTHON_LIBS + unset PYTHON_CFLAGS + ]) + fi + + if test -z "$PYTHONCONFIG"; then + PKG_CHECK_MODULES([PYTHON], python-3.5, [], [ + PKG_CHECK_MODULES([PYTHON], python-3.4, [], [ + PKG_CHECK_MODULES([PYTHON], python-3.3, [], [ + PKG_CHECK_MODULES([PYTHON], python-3.2, [], [ + PKG_CHECK_MODULES([PYTHON], python-2.7, [], [ + AC_MSG_FAILURE([could not find python-config or pkg-config python, please install Python development files from libpython-dev or similar]) + ])])])])]) + + + AC_MSG_CHECKING([whether we found a working Python version]) + AC_LINK_IFELSE_FLAGS([$PYTHON_CFLAGS], [$PYTHON_LIBS], [AC_LANG_PROGRAM([ +#include +#if PY_VERSION_HEX < 0x02070000 +#error python too old +#endif +int main(void); +], +[ +{ + Py_Initialize(); + return 0; +} +])], [ + AC_MSG_FAILURE([could not find python-config or pkg-config python, please install Python development files from libpython-dev or similar]) + ]) + fi +]) +AC_SUBST(PYTHON_CFLAGS) +AC_SUBST(PYTHON_LIBS) + # # Logic for protobuf support. # diff --git a/lib/Makefile.am b/lib/Makefile.am index a1b78d3c4d..25d7d6d950 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -9,6 +9,7 @@ command_lex.h: command_lex.c @if test ! -f $@; then rm -f command_lex.c; else :; fi @if test ! -f $@; then $(MAKE) $(AM_MAKEFLAGS) command_lex.c; else :; fi command_parse.lo: command_lex.h +clippy-command_parse.$(OBJEXT): command_lex.h lib_LTLIBRARIES = libfrr.la libfrr_la_LDFLAGS = -version-info 0:0:0 @@ -85,13 +86,34 @@ pkginclude_HEADERS = \ noinst_HEADERS = \ plist_int.h \ - log_int.h + log_int.h \ + clippy.h \ + # end noinst_PROGRAMS = grammar_sandbox +if BUILD_CLIPPY +noinst_PROGRAMS += clippy +endif grammar_sandbox_SOURCES = grammar_sandbox_main.c grammar_sandbox_LDADD = libfrr.la +clippy_SOURCES = \ + defun_lex.l \ + command_parse.y \ + command_lex.l \ + command_graph.c \ + command_py.c \ + memory.c \ + graph.c \ + vector.c \ + clippy.c \ + # end +clippy_CPPFLAGS = -D_GNU_SOURCE +clippy_CFLAGS = $(PYTHON_CFLAGS) +clippy_LDADD = $(PYTHON_LIBS) +clippy-command_graph.$(OBJEXT): route_types.h + EXTRA_DIST = \ queue.h \ command_lex.h \ diff --git a/lib/clippy.c b/lib/clippy.c new file mode 100644 index 0000000000..26ef246573 --- /dev/null +++ b/lib/clippy.c @@ -0,0 +1,137 @@ +/* + * clippy (CLI preparator in python) main executable + * Copyright (C) 2016-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 "config.h" +#include +#include +#include +#include +#include "getopt.h" + +#include "command_graph.h" +#include "clippy.h" + +#if PY_MAJOR_VERSION >= 3 +#define pychar wchar_t +static wchar_t *wconv(const char *s) +{ + size_t outlen = mbstowcs(NULL, s, 0); + wchar_t *out = malloc((outlen + 1) * sizeof(wchar_t)); + mbstowcs(out, s, outlen + 1); + out[outlen] = 0; + return out; +} +#else +#define pychar char +#define wconv(x) x +#endif + +int main(int argc, char **argv) +{ + pychar **wargv; + +#if PY_VERSION_HEX >= 0x03040000 /* 3.4 */ + Py_SetStandardStreamEncoding("UTF-8", NULL); +#endif + Py_SetProgramName(wconv(argv[0])); + PyImport_AppendInittab("_clippy", command_py_init); + + Py_Initialize(); + + wargv = malloc(argc * sizeof(pychar *)); + for (int i = 1; i < argc; i++) + wargv[i - 1] = wconv(argv[i]); + PySys_SetArgv(argc - 1, wargv); + + const char *pyfile = argc > 1 ? argv[1] : NULL; + FILE *fp; + if (pyfile) { + fp = fopen(pyfile, "r"); + if (!fp) { + fprintf(stderr, "%s: %s\n", pyfile, strerror(errno)); + return 1; + } + } else { + fp = stdin; + char *ver = strdup(Py_GetVersion()); + char *cr = strchr(ver, '\n'); + if (cr) + *cr = ' '; + fprintf(stderr, "clippy interactive shell\n(Python %s)\n", ver); + free(ver); + PyRun_SimpleString("import rlcompleter, readline\n" + "readline.parse_and_bind('tab: complete')"); + } + + if (PyRun_AnyFile(fp, pyfile)) { + if (PyErr_Occurred()) + PyErr_Print(); + else + printf("unknown python failure (?)\n"); + return 1; + } + Py_Finalize(); + +#if PY_MAJOR_VERSION >= 3 + for (int i = 1; i < argc; i++) + free(wargv[i - 1]); +#endif + free(wargv); + return 0; +} + +/* and now for the ugly part... provide simplified logging functions so we + * don't need to link libzebra (which would be a circular build dep) */ + +#ifdef __ASSERT_FUNCTION +#undef __ASSERT_FUNCTION +#endif + +#include "log.h" +#include "zassert.h" + +#define ZLOG_FUNC(FUNCNAME) \ +void FUNCNAME(const char *format, ...) \ +{ \ + va_list args; \ + va_start(args, format); \ + vfprintf (stderr, format, args); \ + fputs ("\n", stderr); \ + va_end(args); \ +} + +ZLOG_FUNC(zlog_err) +ZLOG_FUNC(zlog_warn) +ZLOG_FUNC(zlog_info) +ZLOG_FUNC(zlog_notice) +ZLOG_FUNC(zlog_debug) + +void +_zlog_assert_failed (const char *assertion, const char *file, + unsigned int line, const char *function) +{ + fprintf(stderr, "Assertion `%s' failed in file %s, line %u, function %s", + assertion, file, line, (function ? function : "?")); + abort(); +} + +void memory_oom (size_t size, const char *name) +{ + abort(); +} diff --git a/lib/clippy.h b/lib/clippy.h new file mode 100644 index 0000000000..8df98cbb8e --- /dev/null +++ b/lib/clippy.h @@ -0,0 +1,28 @@ +/* + * clippy (CLI preparator in python) + * Copyright (C) 2016-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 + */ + +#ifndef _FRR_CLIPPY_H +#define _FRR_CLIPPY_H + +#include + +extern PyObject *clippy_parse(PyObject *self, PyObject *args); +extern PyMODINIT_FUNC command_py_init(void); + +#endif /* _FRR_CLIPPY_H */ diff --git a/lib/command_py.c b/lib/command_py.c new file mode 100644 index 0000000000..6621b0fa72 --- /dev/null +++ b/lib/command_py.c @@ -0,0 +1,336 @@ +/* + * clippy (CLI preparator in python) wrapper for FRR command_graph + * Copyright (C) 2016-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 + */ + +/* note: this wrapper is intended to be used as build-time helper. while + * it should be generally correct and proper, there may be the occasional + * memory leak or SEGV for things that haven't been well-tested. + */ + +#include +#include "structmember.h" +#include +#include + +#include "command_graph.h" +#include "clippy.h" + +struct wrap_graph; +static PyObject *graph_to_pyobj(struct wrap_graph *graph, struct graph_node *gn); + +/* + * nodes are wrapped as follows: + * - instances can only be acquired from a graph + * - the same node will return the same wrapper object (they're buffered + * through "idx") + * - a reference is held onto the graph + * - fields are copied for easy access with PyMemberDef + */ +struct wrap_graph_node { + PyObject_HEAD + + bool allowrepeat; + const char *type; + + bool deprecated; + bool hidden; + const char *text; + const char *desc; + const char *varname; + long long min, max; + + struct graph_node *node; + struct wrap_graph *wgraph; + size_t idx; +}; + +/* + * graphs are wrapped as follows: + * - they can only be created by parsing a definition string + * - there's a table here for the wrapped nodes (nodewrappers), indexed + * by "idx" (corresponds to node's position in graph's table of nodes) + * - graphs do NOT hold references to nodes (would be circular) + */ +struct wrap_graph { + PyObject_HEAD + + char *definition; + struct graph *graph; + struct wrap_graph_node **nodewrappers; +}; + +static PyObject *refuse_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + PyErr_SetString(PyExc_ValueError, "cannot create instances of this type"); + return NULL; +} + +#define member(name, type) {(char *)#name, type, offsetof(struct wrap_graph_node, name), READONLY, \ + (char *)#name " (" #type ")"} +static PyMemberDef members_graph_node[] = { + member(allowrepeat, T_BOOL), + member(type, T_STRING), + member(deprecated, T_BOOL), + member(hidden, T_BOOL), + member(text, T_STRING), + member(desc, T_STRING), + member(min, T_LONGLONG), + member(max, T_LONGLONG), + member(varname, T_STRING), + {}, +}; +#undef member + +/* + * node.next() -- returns list of all "next" nodes. + * this will include circles if the graph has them. + */ +static PyObject *graph_node_next(PyObject *self, PyObject *args) +{ + struct wrap_graph_node *wrap = (struct wrap_graph_node *)self; + PyObject *pylist; + + if (wrap->node->data + && ((struct cmd_token *)wrap->node->data)->type == END_TKN) + return PyList_New(0); + pylist = PyList_New(vector_active(wrap->node->to)); + for (size_t i = 0; i < vector_active(wrap->node->to); i++) { + struct graph_node *gn = vector_slot(wrap->node->to, i); + PyList_SetItem(pylist, i, graph_to_pyobj(wrap->wgraph, gn)); + } + return pylist; +}; + +/* + * node.join() -- return FORK's JOIN node or None + */ +static PyObject *graph_node_join(PyObject *self, PyObject *args) +{ + struct wrap_graph_node *wrap = (struct wrap_graph_node *)self; + + if (!wrap->node->data + || ((struct cmd_token *)wrap->node->data)->type == END_TKN) + Py_RETURN_NONE; + + struct cmd_token *tok = wrap->node->data; + if (tok->type != FORK_TKN) + Py_RETURN_NONE; + + return graph_to_pyobj(wrap->wgraph, tok->forkjoin); +}; + +static PyMethodDef methods_graph_node[] = { + {"next", graph_node_next, METH_NOARGS, "outbound graph edge list"}, + {"join", graph_node_join, METH_NOARGS, "outbound join node"}, + {} +}; + +static void graph_node_wrap_free(void *arg) +{ + struct wrap_graph_node *wrap = arg; + wrap->wgraph->nodewrappers[wrap->idx] = NULL; + Py_DECREF(wrap->wgraph); +} + +static PyTypeObject typeobj_graph_node = { + PyVarObject_HEAD_INIT(NULL, 0) + .tp_name = "_clippy.GraphNode", + .tp_basicsize = sizeof(struct wrap_graph_node), + .tp_flags = Py_TPFLAGS_DEFAULT, + .tp_doc = "struct graph_node *", + .tp_new = refuse_new, + .tp_free = graph_node_wrap_free, + .tp_members = members_graph_node, + .tp_methods = methods_graph_node, +}; + +static PyObject *graph_to_pyobj(struct wrap_graph *wgraph, struct graph_node *gn) +{ + struct wrap_graph_node *wrap; + size_t i; + + for (i = 0; i < vector_active(wgraph->graph->nodes); i++) + if (vector_slot(wgraph->graph->nodes, i) == gn) + break; + if (i == vector_active(wgraph->graph->nodes)) { + PyErr_SetString(PyExc_ValueError, "cannot find node in graph"); + return NULL; + } + if (wgraph->nodewrappers[i]) { + PyObject *obj = (PyObject *)wgraph->nodewrappers[i]; + Py_INCREF(obj); + return obj; + } + + wrap = (struct wrap_graph_node *)typeobj_graph_node.tp_alloc(&typeobj_graph_node, 0); + if (!wrap) + return NULL; + wgraph->nodewrappers[i] = wrap; + Py_INCREF(wgraph); + + wrap->idx = i; + wrap->wgraph = wgraph; + wrap->node = gn; + wrap->type = "NULL"; + wrap->allowrepeat = false; + if (gn->data) { + struct cmd_token *tok = gn->data; + switch (tok->type) { +#define item(x) case x: wrap->type = #x; break; + item(WORD_TKN) // words + item(VARIABLE_TKN) // almost anything + item(RANGE_TKN) // integer range + item(IPV4_TKN) // IPV4 addresses + item(IPV4_PREFIX_TKN) // IPV4 network prefixes + item(IPV6_TKN) // IPV6 prefixes + item(IPV6_PREFIX_TKN) // IPV6 network prefixes + + /* plumbing types */ + item(FORK_TKN) + item(JOIN_TKN) + item(START_TKN) + item(END_TKN) + default: + wrap->type = "???"; + } + + wrap->deprecated = (tok->attr == CMD_ATTR_DEPRECATED); + wrap->hidden = (tok->attr == CMD_ATTR_HIDDEN); + wrap->text = tok->text; + wrap->desc = tok->desc; + wrap->varname = tok->varname; + wrap->min = tok->min; + wrap->max = tok->max; + wrap->allowrepeat = tok->allowrepeat; + } + + return (PyObject *)wrap; +} + +#define member(name, type) {(char *)#name, type, offsetof(struct wrap_graph, name), READONLY, \ + (char *)#name " (" #type ")"} +static PyMemberDef members_graph[] = { + member(definition, T_STRING), + {}, +}; +#undef member + +/* graph.first() - root node */ +static PyObject *graph_first(PyObject *self, PyObject *args) +{ + struct wrap_graph *gwrap = (struct wrap_graph *)self; + struct graph_node *gn = vector_slot(gwrap->graph->nodes, 0); + return graph_to_pyobj(gwrap, gn); +}; + +static PyMethodDef methods_graph[] = { + {"first", graph_first, METH_NOARGS, "first graph node"}, + {} +}; + +static PyObject *graph_parse(PyTypeObject *type, PyObject *args, PyObject *kwds); + +static void graph_wrap_free(void *arg) +{ + struct wrap_graph *wgraph = arg; + free(wgraph->nodewrappers); + free(wgraph->definition); +} + +static PyTypeObject typeobj_graph = { + PyVarObject_HEAD_INIT(NULL, 0) + .tp_name = "_clippy.Graph", + .tp_basicsize = sizeof(struct wrap_graph), + .tp_flags = Py_TPFLAGS_DEFAULT, + .tp_doc = "struct graph *", + .tp_new = graph_parse, + .tp_free = graph_wrap_free, + .tp_members = members_graph, + .tp_methods = methods_graph, +}; + +/* top call / entrypoint for python code */ +static PyObject *graph_parse(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + const char *def, *doc = NULL; + struct wrap_graph *gwrap; + static const char *kwnames[] = { "cmddef", "doc", NULL }; + + gwrap = (struct wrap_graph *)typeobj_graph.tp_alloc(&typeobj_graph, 0); + if (!gwrap) + return NULL; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|s", (char **)kwnames, &def, &doc)) + return NULL; + + struct graph *graph = graph_new (); + struct cmd_token *token = cmd_token_new (START_TKN, 0, NULL, NULL); + graph_new_node (graph, token, (void (*)(void *)) &cmd_token_del); + + struct cmd_element cmd = { .string = def, .doc = doc }; + cmd_graph_parse (graph, &cmd); + cmd_graph_names (graph); + + gwrap->graph = graph; + gwrap->definition = strdup(def); + gwrap->nodewrappers = calloc(vector_active(graph->nodes), + sizeof (gwrap->nodewrappers[0])); + return (PyObject *)gwrap; +} + +static PyMethodDef clippy_methods[] = { + {"parse", clippy_parse, METH_VARARGS, "Parse a C file"}, + {NULL, NULL, 0, NULL} +}; + +#if PY_MAJOR_VERSION >= 3 +static struct PyModuleDef pymoddef_clippy = { + PyModuleDef_HEAD_INIT, + "_clippy", + NULL, /* docstring */ + -1, + clippy_methods, +}; +#define modcreate() PyModule_Create(&pymoddef_clippy) +#define initret(val) return val; +#else +#define modcreate() Py_InitModule("_clippy", clippy_methods) +#define initret(val) do { \ + if (!val) Py_FatalError("initialization failure"); \ + return; } while (0) +#endif + +PyMODINIT_FUNC command_py_init(void) +{ + PyObject* pymod; + + if (PyType_Ready(&typeobj_graph_node) < 0) + initret(NULL); + if (PyType_Ready(&typeobj_graph) < 0) + initret(NULL); + + pymod = modcreate(); + if (!pymod) + initret(NULL); + + Py_INCREF(&typeobj_graph_node); + PyModule_AddObject(pymod, "GraphNode", (PyObject *)&typeobj_graph_node); + Py_INCREF(&typeobj_graph); + PyModule_AddObject(pymod, "Graph", (PyObject *)&typeobj_graph); + initret(pymod); +} diff --git a/lib/defun_lex.l b/lib/defun_lex.l new file mode 100644 index 0000000000..8aa37a62a2 --- /dev/null +++ b/lib/defun_lex.l @@ -0,0 +1,265 @@ +%{ +/* + * clippy (CLI preparator in python) C pseudo-lexer + * Copyright (C) 2016-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 + */ + +/* This is just enough of a lexer to make rough sense of a C source file. + * It handles C preprocessor directives, strings, and looks for FRR-specific + * idioms (aka DEFUN). + * + * There is some preliminary support for documentation comments for DEFUNs. + * They would look like this (note the ~): (replace \ by /) + * + * \*~ documentation for foobar_cmd + * * parameter does xyz + * *\ + * DEFUN(foobar_cmd, ...) + * + * This is intended for user documentation / command reference. Don't put + * code documentation in it. + */ + +/* ignore harmless bug in old versions of flex */ +#pragma GCC diagnostic ignored "-Wsign-compare" + +#include "config.h" +#include +#include +#include + +#include "command_graph.h" +#include "clippy.h" + +#define ID 258 +#define PREPROC 259 +#define OPERATOR 260 +#define STRING 261 +#define COMMENT 262 +#define SPECIAL 263 + +#define DEFUNNY 270 +#define INSTALL 271 +#define AUXILIARY 272 + +int comment_link; +char string_end; + +char *value; + +static void extendbuf(char **what, const char *arg) +{ + if (!*what) + *what = strdup(arg); + else { + size_t vall = strlen(*what), argl = strlen(arg); + *what = realloc(*what, vall + argl + 1); + memcpy(*what + vall, arg, argl); + (*what)[vall + argl] = '\0'; + } +} +#define extend(x) extendbuf(&value, x) + +%} + +ID [A-Za-z0-9_]+ +OPERATOR [!%&/\[\]{}=?:^|\*.;><~'\\+-] +SPECIAL [(),] + +%pointer +%option yylineno +%option noyywrap +%option noinput +%option nounput +%option outfile="defun_lex.c" +%option prefix="def_yy" +%option 8bit + +%s linestart +%x comment +%x linecomment +%x preproc +%x rstring +%% + BEGIN(linestart); + +\n BEGIN(linestart); + +"/*" comment_link = YY_START; extend(yytext); BEGIN(comment); +[^*\n]* extend(yytext); +"*"+[^*/\n]* extend(yytext); +\n extend(yytext); +"*"+"/" extend(yytext); BEGIN(comment_link); return COMMENT; + +"//" comment_link = YY_START; extend(yytext); BEGIN(linecomment); +[^\n]* extend(yytext); +\n BEGIN((comment_link == INITIAL) ? linestart : comment_link); return COMMENT; + +# BEGIN(preproc); +\n BEGIN(INITIAL); return PREPROC; +[^\n\\]+ extend(yytext); +\\\n extend(yytext); +\\+[^\n] extend(yytext); + +[\"\'] string_end = yytext[0]; extend(yytext); BEGIN(rstring); +[\"\'] { + extend(yytext); + if (yytext[0] == string_end) { + BEGIN(INITIAL); + return STRING; + } + } +\\\n /* ignore */ +\\. extend(yytext); +[^\\\"\']+ extend(yytext); + +"DEFUN" value = strdup(yytext); return DEFUNNY; +"DEFUN_NOSH" value = strdup(yytext); return DEFUNNY; +"DEFUN_HIDDEN" value = strdup(yytext); return DEFUNNY; +"DEFPY" value = strdup(yytext); return DEFUNNY; +"ALIAS" value = strdup(yytext); return DEFUNNY; +"ALIAS_HIDDEN" value = strdup(yytext); return DEFUNNY; +"install_element" value = strdup(yytext); return INSTALL; +"VTYSH_TARGETS" value = strdup(yytext); return AUXILIARY; +"VTYSH_NODESWITCH" value = strdup(yytext); return AUXILIARY; + +[ \t\n]+ /* ignore */ +\\ /* ignore */ +{ID} BEGIN(INITIAL); value = strdup(yytext); return ID; +{OPERATOR} BEGIN(INITIAL); value = strdup(yytext); return OPERATOR; +{SPECIAL} BEGIN(INITIAL); value = strdup(yytext); return SPECIAL; +. /* printf("-- '%s' in init\n", yytext); */ BEGIN(INITIAL); return yytext[0]; + +%% + +static int yylex_clr(char **retbuf) +{ + int rv = def_yylex(); + *retbuf = value; + value = NULL; + return rv; +} + +static PyObject *get_args(void) +{ + PyObject *pyObj = PyList_New(0); + PyObject *pyArg = NULL; + + char *tval; + int depth = 1; + int token; + + while ((token = yylex_clr(&tval)) != YY_NULL) { + if (token == SPECIAL && tval[0] == '(') { + free(tval); + break; + } + if (token == COMMENT) { + free(tval); + continue; + } + fprintf(stderr, "invalid input!\n"); + exit(1); + } + + while ((token = yylex_clr(&tval)) != YY_NULL) { + if (token == COMMENT) { + free(tval); + continue; + } + if (token == SPECIAL) { + if (depth == 1 && (tval[0] == ',' || tval[0] == ')')) { + if (pyArg) + PyList_Append(pyObj, pyArg); + pyArg = NULL; + if (tval[0] == ')') { + free(tval); + break; + } + free(tval); + continue; + } + if (tval[0] == '(') + depth++; + if (tval[0] == ')') + depth--; + } + if (!pyArg) + pyArg = PyList_New(0); + PyList_Append(pyArg, PyUnicode_FromString(tval)); + free(tval); + } + return pyObj; +} + +/* _clippy.parse() -- read a C file, returning a list of interesting bits. + * note this ditches most of the actual C code. */ +PyObject *clippy_parse(PyObject *self, PyObject *args) +{ + const char *filename; + if (!PyArg_ParseTuple(args, "s", &filename)) + return NULL; + + FILE *fd = fopen(filename, "r"); + if (!fd) + return PyErr_SetFromErrnoWithFilename(PyExc_IOError, filename); + + char *tval; + int token; + yyin = fd; + value = NULL; + + PyObject *pyCont = PyDict_New(); + PyObject *pyObj = PyList_New(0); + PyDict_SetItemString(pyCont, "filename", PyUnicode_FromString(filename)); + PyDict_SetItemString(pyCont, "data", pyObj); + + while ((token = yylex_clr(&tval)) != YY_NULL) { + int lineno = yylineno; + PyObject *pyItem = NULL, *pyArgs; + switch (token) { + case DEFUNNY: + case INSTALL: + case AUXILIARY: + pyArgs = get_args(); + pyItem = PyDict_New(); + PyDict_SetItemString(pyItem, "type", PyUnicode_FromString(tval)); + PyDict_SetItemString(pyItem, "args", pyArgs); + break; + case COMMENT: + if (strncmp(tval, "//~", 3) && strncmp(tval, "/*~", 3)) + break; + pyItem = PyDict_New(); + PyDict_SetItemString(pyItem, "type", PyUnicode_FromString("COMMENT")); + PyDict_SetItemString(pyItem, "line", PyUnicode_FromString(tval)); + break; + case PREPROC: + pyItem = PyDict_New(); + PyDict_SetItemString(pyItem, "type", PyUnicode_FromString("PREPROC")); + PyDict_SetItemString(pyItem, "line", PyUnicode_FromString(tval)); + break; + } + if (pyItem) { + PyDict_SetItemString(pyItem, "lineno", PyLong_FromLong(lineno)); + PyList_Append(pyObj, pyItem); + } + free(tval); + } + def_yylex_destroy(); + fclose(fd); + return pyCont; +} From 5578a14d949d89e25ec3e6136158603049e5a2dd Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Thu, 11 May 2017 15:36:04 +0200 Subject: [PATCH 03/12] python: clidef.py Adds "DEFPY()" which invokes an additional layer of preprocessing, so that we get pre-parsed and named function arguments for the CLI. Signed-off-by: David Lamparter --- .gitignore | 1 + Makefile.am | 4 +- common.am | 11 ++ configure.ac | 1 + lib/command.h | 7 ++ python/Makefile.am | 3 + python/clidef.py | 254 ++++++++++++++++++++++++++++++++++++++ python/clippy/__init__.py | 64 ++++++++++ 8 files changed, 344 insertions(+), 1 deletion(-) create mode 100644 python/Makefile.am create mode 100644 python/clidef.py create mode 100644 python/clippy/__init__.py diff --git a/.gitignore b/.gitignore index 5b88cf25af..62aa48e22f 100644 --- a/.gitignore +++ b/.gitignore @@ -61,6 +61,7 @@ debian/quagga.prerm.debhelper debian/quagga.substvars debian/quagga/ debian/tmp/ +*.pyc *.swp cscope.* *.pb.h diff --git a/Makefile.am b/Makefile.am index 6d787e3c6e..d18837c083 100644 --- a/Makefile.am +++ b/Makefile.am @@ -9,7 +9,9 @@ SUBDIRS = lib qpb fpm @ZEBRA@ @LIBRFP@ @RFPTEST@ \ DIST_SUBDIRS = lib qpb fpm zebra bgpd ripd ripngd ospfd ospf6d ldpd \ isisd watchfrr vtysh ospfclient doc m4 pkgsrc redhat tests \ solaris pimd nhrpd eigrpd @LIBRFP@ @RFPTEST@ tools snapcraft \ - babeld + babeld \ + python \ + # end EXTRA_DIST = aclocal.m4 SERVICES REPORTING-BUGS \ update-autotools \ diff --git a/common.am b/common.am index d01d673ae6..0ccc4c9fd1 100644 --- a/common.am +++ b/common.am @@ -3,6 +3,17 @@ # tree. # +AM_V_CLIPPY = $(am__v_CLIPPY_$(V)) +am__v_CLIPPY_ = $(am__v_CLIPPY_$(AM_DEFAULT_VERBOSITY)) +am__v_CLIPPY_0 = @echo " CLIPPY " $@; +am__v_CLIPPY_1 = + +SUFFIXES = _clippy.c +.c_clippy.c: + $(AM_V_at)$(MAKE) -C $(top_builddir)/$(CLIPPYDIR) clippy + $(AM_V_CLIPPY)$(top_builddir)/$(CLIPPYDIR)/clippy $(top_srcdir)/python/clidef.py $< > $@.tmp + @{ test -f $@ && diff $@.tmp $@ >/dev/null 2>/dev/null; } && rm $@.tmp || mv $@.tmp $@ + if HAVE_PROTOBUF # Uncomment to use an non-system version of libprotobuf-c. diff --git a/configure.ac b/configure.ac index ca8eae9057..1dd570fcee 100755 --- a/configure.ac +++ b/configure.ac @@ -1983,6 +1983,7 @@ AC_CONFIG_FILES([Makefile lib/Makefile qpb/Makefile zebra/Makefile ripd/Makefile redhat/Makefile tools/Makefile pkgsrc/Makefile + python/Makefile fpm/Makefile redhat/frr.spec snapcraft/Makefile diff --git a/lib/command.h b/lib/command.h index ada9003cc9..927c04006c 100644 --- a/lib/command.h +++ b/lib/command.h @@ -207,6 +207,10 @@ struct cmd_node int argc __attribute__ ((unused)), \ struct cmd_token *argv[] __attribute__ ((unused)) ) +#define DEFPY(funcname, cmdname, cmdstr, helpstr) \ + DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, 0, 0) \ + funcdecl_##funcname + #define DEFUN(funcname, cmdname, cmdstr, helpstr) \ DEFUN_CMD_FUNC_DECL(funcname) \ DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, 0, 0) \ @@ -274,6 +278,9 @@ struct cmd_node #define ALIAS_SH_DEPRECATED(daemon, funcname, cmdname, cmdstr, helpstr) \ DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, CMD_ATTR_DEPRECATED, daemon) +#else /* VTYSH_EXTRACT_PL */ +#define DEFPY(funcname, cmdname, cmdstr, helpstr) \ + DEFUN(funcname, cmdname, cmdstr, helpstr) #endif /* VTYSH_EXTRACT_PL */ /* Some macroes */ diff --git a/python/Makefile.am b/python/Makefile.am new file mode 100644 index 0000000000..4ad1e36b59 --- /dev/null +++ b/python/Makefile.am @@ -0,0 +1,3 @@ +EXTRA_DIST = \ + clidef.py \ + clippy/__init__.py diff --git a/python/clidef.py b/python/clidef.py new file mode 100644 index 0000000000..de3a764a0b --- /dev/null +++ b/python/clidef.py @@ -0,0 +1,254 @@ +# FRR CLI preprocessor (DEFPY) +# +# 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 + +import clippy, traceback, sys, os +from collections import OrderedDict +from functools import reduce +from pprint import pprint +from string import Template +from io import StringIO + +# the various handlers generate output C code for a particular type of +# CLI token, choosing the most useful output C type. + +class RenderHandler(object): + def __init__(self, token): + pass + def combine(self, other): + if type(self) == type(other): + return other + return StringHandler(None) + + deref = '' + drop_str = False + +class StringHandler(RenderHandler): + argtype = 'const char *' + decl = Template('const char *$varname = NULL;') + code = Template('$varname = argv[_i]->arg;') + drop_str = True + +class LongHandler(RenderHandler): + argtype = 'long' + decl = Template('long $varname = 0;') + code = Template('''\ +char *_end; +$varname = strtol(argv[_i]->arg, &_end, 10); +_fail = (_end == argv[_i]->arg) || (*_end != '\\0');''') + +# A.B.C.D/M (prefix_ipv4) and +# X:X::X:X/M (prefix_ipv6) are "compatible" and can merge into a +# struct prefix: + +class PrefixBase(RenderHandler): + def combine(self, other): + if type(self) == type(other): + return other + if type(other) in [Prefix4Handler, Prefix6Handler, PrefixGenHandler]: + return PrefixGenHandler(None) + return StringHandler(None) + deref = '&' +class Prefix4Handler(PrefixBase): + argtype = 'const struct prefix_ipv4 *' + decl = Template('struct prefix_ipv4 $varname = { };') + code = Template('_fail = !str2prefix_ipv4(argv[_i]->arg, &$varname);') +class Prefix6Handler(PrefixBase): + argtype = 'const struct prefix_ipv6 *' + decl = Template('struct prefix_ipv6 $varname = { };') + code = Template('_fail = !str2prefix_ipv6(argv[_i]->arg, &$varname);') +class PrefixGenHandler(PrefixBase): + argtype = 'const struct prefix *' + decl = Template('struct prefix $varname = { };') + code = Template('_fail = !str2prefix(argv[_i]->arg, &$varname);') + +# same for IP addresses. result is union sockunion. +class IPBase(RenderHandler): + def combine(self, other): + if type(self) == type(other): + return other + if type(other) in [IP4Handler, IP6Handler, IPGenHandler]: + return IPGenHandler(None) + return StringHandler(None) +class IP4Handler(IPBase): + argtype = 'struct in_addr' + decl = Template('struct in_addr $varname = { INADDR_ANY };') + code = Template('_fail = !inet_aton(argv[_i]->arg, &$varname);') +class IP6Handler(IPBase): + argtype = 'struct in6_addr' + decl = Template('struct in6_addr $varname = IN6ADDR_ANY_INIT;') + code = Template('_fail = !inet_pton(AF_INET6, argv[_i]->arg, &$varname);') +class IPGenHandler(IPBase): + argtype = 'const union sockunion *' + decl = Template('''union sockunion s__$varname = { .sa.sa_family = AF_UNSPEC }, *$varname = NULL;''') + code = Template('''\ +if (argv[_i]->text[0] == 'X') { + s__$varname.sa.sa_family = AF_INET6; + _fail = !inet_pton(AF_INET6, argv[_i]->arg, &s__$varname.sin6.sin6_addr); + $varname = &s__$varname; +} else { + s__$varname.sa.sa_family = AF_INET; + _fail = !inet_aton(argv[_i]->arg, &s__$varname.sin.sin_addr); + $varname = &s__$varname; +}''') + +def mix_handlers(handlers): + def combine(a, b): + if a is None: + return b + return a.combine(b) + return reduce(combine, handlers, None) + +handlers = { + 'WORD_TKN': StringHandler, + 'VARIABLE_TKN': StringHandler, + 'RANGE_TKN': LongHandler, + 'IPV4_TKN': IP4Handler, + 'IPV4_PREFIX_TKN': Prefix4Handler, + 'IPV6_TKN': IP6Handler, + 'IPV6_PREFIX_TKN': Prefix6Handler, +} + +# core template invoked for each occurence of DEFPY. +templ = Template('''/* $fnname => "$cmddef" */ +DEFUN_CMD_FUNC_DECL($fnname) +#define funcdecl_$fnname static int ${fnname}_magic(\\ + const struct cmd_element *self __attribute__ ((unused)),\\ + struct vty *vty __attribute__ ((unused)),\\ + int argc __attribute__ ((unused)),\\ + struct cmd_token *argv[] __attribute__ ((unused))$argdefs) +funcdecl_$fnname; +DEFUN_CMD_FUNC_TEXT($fnname) +{ + int _i; + unsigned _fail = 0, _failcnt = 0; +$argdecls + for (_i = 0; _i < argc; _i++) { + if (!argv[_i]->varname) + continue; + _fail = 0;$argblocks + if (_fail) + vty_out (vty, "%% invalid input for %s: %s%s", + argv[_i]->varname, argv[_i]->arg, VTY_NEWLINE); + _failcnt += _fail; + } + if (_failcnt) + return CMD_WARNING; + return ${fnname}_magic(self, vty, argc, argv$arglist); +} + +''') + +# invoked for each named parameter +argblock = Template(''' + if (!strcmp(argv[_i]->varname, \"$varname\")) {$strblock + $code + }''') + +def process_file(fn, ofd, dumpfd, all_defun): + filedata = clippy.parse(fn) + + for entry in filedata['data']: + if entry['type'] == 'DEFPY' or (all_defun and entry['type'].startswith('DEFUN')): + cmddef = entry['args'][2] + for i in cmddef: + assert i.startswith('"') and i.endswith('"') + cmddef = ''.join([i[1:-1] for i in cmddef]) + + graph = clippy.Graph(cmddef) + args = OrderedDict() + for token, depth in clippy.graph_iterate(graph): + if token.type not in handlers: + continue + if token.varname is None: + continue + arg = args.setdefault(token.varname, []) + arg.append(handlers[token.type](token)) + + #print('-' * 76) + #pprint(entry) + #clippy.dump(graph) + #pprint(args) + + params = { 'cmddef': cmddef, 'fnname': entry['args'][0][0] } + argdefs = [] + argdecls = [] + arglist = [] + argblocks = [] + doc = [] + + def do_add(handler, varname, attr = ''): + argdefs.append(',\\\n\t%s %s%s' % (handler.argtype, varname, attr)) + argdecls.append('\t%s\n' % (handler.decl.substitute({'varname': varname}).replace('\n', '\n\t'))) + arglist.append(', %s%s' % (handler.deref, varname)) + if attr == '': + at = handler.argtype + if not at.startswith('const '): + at = '. . . ' + at + doc.append('\t%-26s %s' % (at, varname)) + + for varname in args.keys(): + handler = mix_handlers(args[varname]) + #print(varname, handler) + if handler is None: continue + do_add(handler, varname) + code = handler.code.substitute({'varname': varname}).replace('\n', '\n\t\t\t') + strblock = '' + if not handler.drop_str: + do_add(StringHandler(None), '%s_str' % (varname), ' __attribute__ ((unused))') + strblock = '\n\t\t\t%s_str = argv[_i]->arg;' % (varname) + argblocks.append(argblock.substitute({'varname': varname, 'strblock': strblock, 'code': code})) + + if dumpfd is not None: + if len(arglist) > 0: + dumpfd.write('"%s":\n%s\n\n' % (cmddef, '\n'.join(doc))) + else: + dumpfd.write('"%s":\n\t---- no magic arguments ----\n\n' % (cmddef)) + + params['argdefs'] = ''.join(argdefs) + params['argdecls'] = ''.join(argdecls) + params['arglist'] = ''.join(arglist) + params['argblocks'] = ''.join(argblocks) + ofd.write(templ.substitute(params)) + +if __name__ == '__main__': + import argparse + + argp = argparse.ArgumentParser(description = 'FRR CLI preprocessor in Python') + argp.add_argument('--all-defun', action = 'store_const', const = True, + help = 'process DEFUN() statements in addition to DEFPY()') + argp.add_argument('--show', action = 'store_const', const = True, + help = 'print out list of arguments and types for each definition') + argp.add_argument('-o', type = str, metavar = 'OUTFILE', + help = 'output C file name') + argp.add_argument('cfile', type = str) + args = argp.parse_args() + + dumpfd = None + if args.o is not None: + ofd = StringIO() + if args.show: + dumpfd = sys.stdout + else: + ofd = sys.stdout + if args.show: + dumpfd = sys.stderr + + process_file(args.cfile, ofd, dumpfd, args.all_defun) + + if args.o is not None: + clippy.wrdiff(args.o, ofd) diff --git a/python/clippy/__init__.py b/python/clippy/__init__.py new file mode 100644 index 0000000000..82aa9495d4 --- /dev/null +++ b/python/clippy/__init__.py @@ -0,0 +1,64 @@ +# FRR CLI preprocessor +# +# 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 + +import _clippy +from _clippy import parse, Graph, GraphNode + +def graph_iterate(graph): + '''iterator yielding all nodes of a graph + + nodes arrive in input/definition order, graph circles are avoided. + ''' + + queue = [(graph.first(), frozenset(), 0)] + while len(queue) > 0: + node, stop, depth = queue.pop(0) + yield node, depth + + join = node.join() + if join is not None: + queue.insert(0, (join, stop.union(frozenset([node])), depth)) + join = frozenset([join]) + + stop = join or stop + nnext = node.next() + for n in reversed(nnext): + if n not in stop and n is not node: + queue.insert(0, (n, stop, depth + 1)) + +def dump(graph): + '''print out clippy.Graph''' + + for i, depth in graph_iterate(graph): + print('\t%s%s %r' % (' ' * (depth * 2), i.type, i.text)) + +def wrdiff(filename, buf): + '''write buffer to file if contents changed''' + + expl = '' + if hasattr(buf, 'getvalue'): + buf = buf.getvalue() + old = None + try: old = open(filename, 'r').read() + except: pass + if old == buf: + # sys.stderr.write('%s unchanged, not written\n' % (filename)) + return + with open('.new.' + filename, 'w') as out: + out.write(buf) + os.rename('.new.' + filename, filename) From 169e541c28e21eee3bbb12e06dfeac5b276794c5 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Fri, 18 Nov 2016 14:05:49 +0100 Subject: [PATCH 04/12] tests: cli: unit test DEFPY() + clidef.py Signed-off-by: David Lamparter --- tests/Makefile.am | 4 + tests/lib/cli/common_cli.c | 2 +- tests/lib/cli/test_cli.c | 24 +++- tests/lib/cli/test_cli.refout.in | 195 ++++++++++++++++--------------- 4 files changed, 125 insertions(+), 100 deletions(-) diff --git a/tests/Makefile.am b/tests/Makefile.am index f48abac47a..800796eb65 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -1,3 +1,5 @@ +include ../common.am + PYTHON ?= python AUTOMAKE_OPTIONS = subdir-objects @@ -28,6 +30,8 @@ else BGP_VNC_RFP_LIB = endif +lib/cli/test_cli.o: lib/cli/test_cli_clippy.c + check_PROGRAMS = \ lib/test_buffer \ lib/test_checksum \ diff --git a/tests/lib/cli/common_cli.c b/tests/lib/cli/common_cli.c index 7825564e54..cfe1e3cc3b 100644 --- a/tests/lib/cli/common_cli.c +++ b/tests/lib/cli/common_cli.c @@ -39,7 +39,7 @@ int dump_args(struct vty *vty, const char *descr, vty_out (vty, "%s with %d args.%s", descr, argc, VTY_NEWLINE); for (i = 0; i < argc; i++) { - vty_out (vty, "[%02d]: %s%s", i, argv[i]->arg, VTY_NEWLINE); + vty_out (vty, "[%02d] %s@%s: %s%s", i, argv[i]->text, argv[i]->varname, argv[i]->arg, VTY_NEWLINE); } return CMD_SUCCESS; diff --git a/tests/lib/cli/test_cli.c b/tests/lib/cli/test_cli.c index ba1218120c..2a68ba3826 100644 --- a/tests/lib/cli/test_cli.c +++ b/tests/lib/cli/test_cli.c @@ -21,21 +21,38 @@ #include +#include "prefix.h" #include "common_cli.h" DUMMY_DEFUN(cmd0, "arg ipv4 A.B.C.D"); DUMMY_DEFUN(cmd1, "arg ipv4m A.B.C.D/M"); -DUMMY_DEFUN(cmd2, "arg ipv6 X:X::X:X"); +DUMMY_DEFUN(cmd2, "arg ipv6 X:X::X:X$foo"); DUMMY_DEFUN(cmd3, "arg ipv6m X:X::X:X/M"); DUMMY_DEFUN(cmd4, "arg range (5-15)"); DUMMY_DEFUN(cmd5, "pat a < a|b>"); +DUMMY_DEFUN(cmd6, "pat b "); DUMMY_DEFUN(cmd7, "pat c A.B.C.D"); -DUMMY_DEFUN(cmd8, "pat d { foo A.B.C.D|bar X:X::X:X| baz }"); +DUMMY_DEFUN(cmd8, "pat d { foo A.B.C.D$foo|bar X:X::X:X$bar| baz } [final]"); DUMMY_DEFUN(cmd9, "pat e [ WORD ]"); DUMMY_DEFUN(cmd10, "pat f [key]"); DUMMY_DEFUN(cmd11, "alt a WORD"); DUMMY_DEFUN(cmd12, "alt a A.B.C.D"); DUMMY_DEFUN(cmd13, "alt a X:X::X:X"); +DUMMY_DEFUN(cmd14, "pat g { foo A.B.C.D$foo|foo|bar X:X::X:X$bar| baz } [final]"); + +#include "tests/lib/cli/test_cli_clippy.c" + +DEFPY(magic_test, magic_test_cmd, + "magic (0-100) {ipv4net A.B.C.D/M|X:X::X:X$ipv6}", + "1\n2\n3\n4\n5\n") +{ + char buf[256]; + vty_out(vty, "def: %s%s", self->string, VTY_NEWLINE); + vty_out(vty, "num: %ld%s", magic, VTY_NEWLINE); + vty_out(vty, "ipv4: %s%s", prefix2str(ipv4net, buf, sizeof(buf)), VTY_NEWLINE); + vty_out(vty, "ipv6: %s%s", inet_ntop(AF_INET6, &ipv6, buf, sizeof(buf)), VTY_NEWLINE); + return CMD_SUCCESS; +} void test_init(int argc, char **argv) { @@ -47,6 +64,7 @@ void test_init(int argc, char **argv) install_element (ENABLE_NODE, &cmd3_cmd); install_element (ENABLE_NODE, &cmd4_cmd); install_element (ENABLE_NODE, &cmd5_cmd); + install_element (ENABLE_NODE, &cmd6_cmd); install_element (ENABLE_NODE, &cmd7_cmd); install_element (ENABLE_NODE, &cmd8_cmd); install_element (ENABLE_NODE, &cmd9_cmd); @@ -62,4 +80,6 @@ void test_init(int argc, char **argv) uninstall_element (ENABLE_NODE, &cmd13_cmd); install_element (ENABLE_NODE, &cmd13_cmd); } + install_element (ENABLE_NODE, &cmd14_cmd); + install_element (ENABLE_NODE, &magic_test_cmd); } diff --git a/tests/lib/cli/test_cli.refout.in b/tests/lib/cli/test_cli.refout.in index db9da429ab..ba789de81c 100644 --- a/tests/lib/cli/test_cli.refout.in +++ b/tests/lib/cli/test_cli.refout.in @@ -9,16 +9,16 @@ test# echo test# test# arg ipv4 1.2.3.4 cmd0 with 3 args. -[00]: arg -[01]: ipv4 -[02]: 1.2.3.4 +[00] arg@(null): arg +[01] ipv4@(null): ipv4 +[02] A.B.C.D@ipv4: 1.2.3.4 test# arg ipv4 1.2. A.B.C.D 02 test# arg ipv4 1.2.3.4 cmd0 with 3 args. -[00]: arg -[01]: ipv4 -[02]: 1.2.3.4 +[00] arg@(null): arg +[01] ipv4@(null): ipv4 +[02] A.B.C.D@ipv4: 1.2.3.4 test# arg ipv4 1.2.3 % [NONE] Unknown command: arg ipv4 1.2.3 test# arg ipv4 1.2.3.4.5 @@ -30,16 +30,16 @@ test# arg ipv4 blah test# test# arg ipv4m 1.2.3.0/24 cmd1 with 3 args. -[00]: arg -[01]: ipv4m -[02]: 1.2.3.0/24 +[00] arg@(null): arg +[01] ipv4m@(null): ipv4m +[02] A.B.C.D/M@ipv4m: 1.2.3.0/24 test# arg ipv4m 1.2. A.B.C.D/M 02 test# arg ipv4m 1.2.3.0/24 cmd1 with 3 args. -[00]: arg -[01]: ipv4m -[02]: 1.2.3.0/24 +[00] arg@(null): arg +[01] ipv4m@(null): ipv4m +[02] A.B.C.D/M@ipv4m: 1.2.3.0/24 test# arg ipv4m 1.2.3/9 % [NONE] Unknown command: arg ipv4m 1.2.3/9 test# arg ipv4m 1.2.3.4.5/6 @@ -57,35 +57,35 @@ test# arg ipv4m 1.2.3.0/9a test# test# arg ipv6 de4d:b33f::cafe cmd2 with 3 args. -[00]: arg -[01]: ipv6 -[02]: de4d:b33f::cafe +[00] arg@(null): arg +[01] ipv6@(null): ipv6 +[02] X:X::X:X@foo: de4d:b33f::cafe test# arg ipv6 de4d:b3 X:X::X:X 02 test# arg ipv6 de4d:b33f::caf X:X::X:X 02 test# arg ipv6 de4d:b33f::cafe cmd2 with 3 args. -[00]: arg -[01]: ipv6 -[02]: de4d:b33f::cafe +[00] arg@(null): arg +[01] ipv6@(null): ipv6 +[02] X:X::X:X@foo: de4d:b33f::cafe test# arg ipv6 de4d:b3 test# arg ipv6 de4d:b33f::caf X:X::X:X 02 test# arg ipv6 de4d:b33f::cafe cmd2 with 3 args. -[00]: arg -[01]: ipv6 -[02]: de4d:b33f::cafe +[00] arg@(null): arg +[01] ipv6@(null): ipv6 +[02] X:X::X:X@foo: de4d:b33f::cafe test# arg ipv6 de4d:b33f:z::cafe % [NONE] Unknown command: arg ipv6 de4d:b33f:z::cafe test# arg ipv6 de4d:b33f:cafe: % [NONE] Unknown command: arg ipv6 de4d:b33f:cafe: test# arg ipv6 :: cmd2 with 3 args. -[00]: arg -[01]: ipv6 -[02]: :: +[00] arg@(null): arg +[01] ipv6@(null): ipv6 +[02] X:X::X:X@foo: :: test# arg ipv6 ::/ % [NONE] Unknown command: arg ipv6 ::/ test# arg ipv6 1:2:3:4:5:6:7:8:9:0:1:2:3:4:5:6:7:8:9:0:1:2:3:4:5:6:7:8:9:0 @@ -94,38 +94,38 @@ test# arg ipv6 12::34::56 % [NONE] Unknown command: arg ipv6 12::34::56 test# arg ipv6m dead:beef:cafe::/64 cmd3 with 3 args. -[00]: arg -[01]: ipv6m -[02]: dead:beef:cafe::/64 +[00] arg@(null): arg +[01] ipv6m@(null): ipv6m +[02] X:X::X:X/M@ipv6m: dead:beef:cafe::/64 test# arg ipv6m dead:be X:X::X:X/M 02 test# arg ipv6m dead:beef:cafe: X:X::X:X/M 02 test# arg ipv6m dead:beef:cafe::/64 cmd3 with 3 args. -[00]: arg -[01]: ipv6m -[02]: dead:beef:cafe::/64 +[00] arg@(null): arg +[01] ipv6m@(null): ipv6m +[02] X:X::X:X/M@ipv6m: dead:beef:cafe::/64 test# test# arg range 4 % [NONE] Unknown command: arg range 4 test# arg range 5 cmd4 with 3 args. -[00]: arg -[01]: range -[02]: 5 +[00] arg@(null): arg +[01] range@(null): range +[02] (5-15)@range: 5 test# arg range 9 (5-15) 02 test# arg range 9 cmd4 with 3 args. -[00]: arg -[01]: range -[02]: 9 +[00] arg@(null): arg +[01] range@(null): range +[02] (5-15)@range: 9 test# arg range 15 cmd4 with 3 args. -[00]: arg -[01]: range -[02]: 15 +[00] arg@(null): arg +[01] range@(null): range +[02] (5-15)@range: 15 test# arg range 16 % [NONE] Unknown command: arg range 16 test# arg range -1 @@ -146,7 +146,8 @@ test# pa test# papat % Command incomplete. test# pat -a c d e f +a b c d e f +g test# pat % Command incomplete. test# @@ -154,17 +155,17 @@ test# pat a % Command incomplete. test# pat a a cmd5 with 3 args. -[00]: pat -[01]: a -[02]: a +[00] pat@(null): pat +[01] a@(null): a +[02] a@(null): a test# pat a a 02 b 03 test# pat a b cmd5 with 3 args. -[00]: pat -[01]: a -[02]: b +[00] pat@(null): pat +[01] a@(null): a +[02] b@(null): b test# pat a c % There is no matched command. test# pat a c @@ -176,10 +177,10 @@ test# pat c a % Command incomplete. test# pat c a 1.2.3.4 cmd7 with 4 args. -[00]: pat -[01]: c -[02]: a -[03]: 1.2.3.4 +[00] pat@(null): pat +[01] c@(null): c +[02] a@(null): a +[03] A.B.C.D@(null): 1.2.3.4 test# pat c b 2.3.4 % [NONE] Unknown command: pat c b 2.3.4 test# pat c c @@ -195,72 +196,72 @@ test# pat d % Command incomplete. test# pat d foo 1.2.3.4 cmd8 with 4 args. -[00]: pat -[01]: d -[02]: foo -[03]: 1.2.3.4 +[00] pat@(null): pat +[01] d@(null): d +[02] foo@(null): foo +[03] A.B.C.D@foo: 1.2.3.4 test# pat d foo % Command incomplete. test# pat d noooo % [NONE] Unknown command: pat d noooo test# pat d bar 1::2 cmd8 with 4 args. -[00]: pat -[01]: d -[02]: bar -[03]: 1::2 +[00] pat@(null): pat +[01] d@(null): d +[02] bar@(null): bar +[03] X:X::X:X@bar: 1::2 test# pat d bar 1::2 foo 3.4.5.6 cmd8 with 6 args. -[00]: pat -[01]: d -[02]: bar -[03]: 1::2 -[04]: foo -[05]: 3.4.5.6 +[00] pat@(null): pat +[01] d@(null): d +[02] bar@(null): bar +[03] X:X::X:X@bar: 1::2 +[04] foo@(null): foo +[05] A.B.C.D@foo: 3.4.5.6 test# pat d ba bar 04 baz 06 test# pat d baz cmd8 with 3 args. -[00]: pat -[01]: d -[02]: baz +[00] pat@(null): pat +[01] d@(null): d +[02] baz@(null): baz test# pat d foo 3.4.5.6 baz cmd8 with 5 args. -[00]: pat -[01]: d -[02]: foo -[03]: 3.4.5.6 -[04]: baz +[00] pat@(null): pat +[01] d@(null): d +[02] foo@(null): foo +[03] A.B.C.D@foo: 3.4.5.6 +[04] baz@(null): baz test# test# pat e cmd9 with 2 args. -[00]: pat -[01]: e +[00] pat@(null): pat +[01] e@(null): e test# pat e f cmd9 with 3 args. -[00]: pat -[01]: e -[02]: f +[00] pat@(null): pat +[01] e@(null): e +[02] WORD@e: f test# pat e f g % [NONE] Unknown command: pat e f g test# pat e 1.2.3.4 cmd9 with 3 args. -[00]: pat -[01]: e -[02]: 1.2.3.4 +[00] pat@(null): pat +[01] e@(null): e +[02] WORD@e: 1.2.3.4 test# test# pat f cmd10 with 2 args. -[00]: pat -[01]: f +[00] pat@(null): pat +[01] f@(null): f test# pat f foo % [NONE] Unknown command: pat f foo test# pat f key cmd10 with 3 args. -[00]: pat -[01]: f -[02]: key +[00] pat@(null): pat +[01] f@(null): f +[02] key@(null): key test# test# alt a test# alt a a @@ -268,18 +269,18 @@ test# alt a a X:X::X:X 02 test# alt a ab cmd11 with 3 args. -[00]: alt -[01]: a -[02]: ab +[00] alt@(null): alt +[01] a@(null): a +[02] WORD@a: ab test# alt a 1 test# alt a 1.2 A.B.C.D 02 WORD 02 test# alt a 1.2.3.4 cmd12 with 3 args. -[00]: alt -[01]: a -[02]: 1.2.3.4 +[00] alt@(null): alt +[01] a@(null): a +[02] A.B.C.D@a: 1.2.3.4 test# alt a 1 test# alt a 1:2 WORD 02 @@ -290,16 +291,16 @@ test# alt a 1:2:: X:X::X:X 02 test# alt a 1:2::3 cmd13 with 3 args. -[00]: alt -[01]: a -[02]: 1:2::3 +[00] alt@(null): alt +[01] a@(null): a +[02] X:X::X:X@a: 1:2::3 test# test# conf t test(config)# do pat d baz cmd8 with 3 args. -[00]: pat -[01]: d -[02]: baz +[00] pat@(null): pat +[01] d@(null): d +[02] baz@(null): baz test(config)# exit test# test# show run From ae56903ca77693829e0380dc54db6548465053c9 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Wed, 14 Jun 2017 14:52:12 +0200 Subject: [PATCH 05/12] doc: CLI: document DEFPY() usage Signed-off-by: David Lamparter --- doc/cli.md | 121 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 121 insertions(+) diff --git a/doc/cli.md b/doc/cli.md index ffd34dd302..cfb4d629f9 100644 --- a/doc/cli.md +++ b/doc/cli.md @@ -107,6 +107,127 @@ Automatic assignment of variable names works by applying the following rules: These rules should make it possible to avoid manual varname assignment in 90% of the cases. +DEFPY +----- + +`DEFPY(...)` is an enhanced version of `DEFUN()` which is preprocessed by +` python/clidef.py`. The python script parses the command definition string, +extracts variable names and types, and generates a C wrapper function that +parses the variables and passes them on. This means that in the CLI function +body, you will receive additional parameters with appropriate types. + +This is best explained by an example: + +``` +DEFPY(func, func_cmd, "[no] foo bar A.B.C.D (0-99)$num", "...help...") + +=> + +func(self, vty, argc, argv, /* standard CLI arguments */ + + const char *no, /* unparsed "no" */ + struct in_addr bar, /* parsed IP address */ + const char *bar_str, /* unparsed IP address */ + long num, /* parsed num */ + const char *num_str) /* unparsed num */ +``` + +Note that as documented in the previous section, "bar" is automatically +applied as variable name for "A.B.C.D". The python code then detects this +is an IP address argument and generates code to parse it into a +`struct in_addr`, passing it in `bar`. The raw value is passed in `bar_str`. +The range/number argument works in the same way with the explicitly given +variable name. + +### Type rules + +| Token(s) | Type | Value if omitted by user | +|--------------------------|-------------|--------------------------| +| `A.B.C.D` | `struct in_addr` | 0.0.0.0 | +| `X:X::X:X` | `struct in6_addr` | :: | +| `A.B.C.D + X:X::X:X` | `const union sockunion *` | NULL | +| `A.B.C.D/M` | `const struct prefix_ipv4 *` | NULL | +| `X:X::X:X/M` | `const struct prefix_ipv6 *` | NULL | +| `A.B.C.D/M + X:X::X:X/M` | `const struct prefix *` | NULL | +| `(0-9)` | `long` | 0 | +| `VARIABLE` | `const char *` | NULL | +| `word` | `const char *` | NULL | +| _all other_ | `const char *` | NULL | + +Note the following details: + +* not all parameters are pointers, some are passed as values. +* when the type is not `const char *`, there will be an extra `_str` argument + with type `const char *`. +* you can give a variable name not only to `VARIABLE` tokens but also to + `word` tokens (e.g. constant words). This is useful if some parts of a + command are optional. The type will be `const char *`. +* `[no]` will be passed as `const char *no`. +* pointers will be NULL when the argument is optional and the user did not + use it. +* if a parameter is not a pointer, but is optional and the user didn't use it, + the default value will be passed. Check the `_str` argument if you need to + determine whether the parameter was omitted. +* if the definition contains multiple parameters with the same variable name, + they will be collapsed into a single function parameter. The python code + will detect if the types are compatible (i.e. IPv4 + IPv6 variantes) and + choose a corresponding C type. +* the standard DEFUN parameters (self, vty, argc, argv) are still present and + can be used. A DEFUN can simply be **edited into a DEFPY without further + changes and it will still work**; this allows easy forward migration. +* a file may contain both DEFUN and DEFPY statements. + +### Getting a parameter dump + +The clidef.py script can be called to get a list of DEFUNs/DEFPYs with +the parameter name/type list: + +``` +lib/clippy python/clidef.py --all-defun --show lib/plist.c > /dev/null +``` + +The generated code is printed to stdout, the info dump to stderr. The +`--all-defun` argument will make it process DEFUN blocks as well as DEFPYs, +which is useful prior to converting some DEFUNs. **The dump does not list +the `_str` arguments** to keep the output shorter. + +Note that the clidef.py script cannot be run with python directly, it needs +to be run with _clippy_ since the latter makes the CLI parser available. + +### Include & Makefile requirements + +A source file that uses DEFPY needs to include the `_clippy.c` file **before +all DEFPY statements**: + +``` +/* GPL header */ +#include ... + +... + +#include "filename_clippy.c" + +DEFPY(...) +DEFPY(...) + +install_element(...) +``` + +This dependency needs to be marked in Makefile.am: (there is no ordering +requirement) + +``` +include ../common.am + +# ... + +# if linked into a LTLIBRARY (.la/.so): +filename.lo: filename_clippy.c + +# if linked into an executable or static library (.a): +filename.o: filename_clippy.c +``` + Doc Strings ----------- Each token in a command definition should be documented with a brief doc From 6cdff321965cf8cee48370406feedefd6c41c58e Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Fri, 18 Nov 2016 14:05:49 +0100 Subject: [PATCH 06/12] lib: use DEFPY() for plist.c Shorten lib/plist.c by combining the various command variants... Signed-off-by: David Lamparter --- lib/Makefile.am | 4 + lib/plist.c | 1352 +++++------------------------------------------ 2 files changed, 137 insertions(+), 1219 deletions(-) diff --git a/lib/Makefile.am b/lib/Makefile.am index 25d7d6d950..f1356d2be4 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -1,5 +1,7 @@ ## Process this file with automake to produce Makefile.in. +include ../common.am + AM_CPPFLAGS = -I.. -I$(top_srcdir) -I$(top_srcdir)/lib -I$(top_builddir)/lib AM_CFLAGS = $(WERROR) DEFS = @DEFS@ -DSYSCONFDIR=\"$(sysconfdir)/\" @@ -114,6 +116,8 @@ clippy_CFLAGS = $(PYTHON_CFLAGS) clippy_LDADD = $(PYTHON_LIBS) clippy-command_graph.$(OBJEXT): route_types.h +plist.lo: plist_clippy.c + EXTRA_DIST = \ queue.h \ command_lex.h \ diff --git a/lib/plist.c b/lib/plist.c index d9bdeab6b6..7be56d4320 100644 --- a/lib/plist.c +++ b/lib/plist.c @@ -1413,495 +1413,74 @@ vty_clear_prefix_list (struct vty *vty, afi_t afi, const char *name, return CMD_SUCCESS; } -DEFUN (ip_prefix_list, +#ifndef VTYSH_EXTRACT_PL +#include "plist_clippy.c" +#endif + +DEFPY (ip_prefix_list, ip_prefix_list_cmd, - "ip prefix-list WORD ", - IP_STR - PREFIX_LIST_STR - "Name of a prefix list\n" - "Specify packets to reject\n" - "Specify packets to forward\n" - "IP prefix /, e.g., 35.0.0.0/8\n" - "Any prefix match. Same as \"0.0.0.0/0 le 32\"\n") -{ - int idx_word = 2; - int idx_permit_deny = 3; - int idx_ipv4_any = 4; - return vty_prefix_list_install (vty, AFI_IP, argv[idx_word]->arg, NULL, - argv[idx_permit_deny]->arg, argv[idx_ipv4_any]->arg, NULL, NULL); -} - -DEFUN (ip_prefix_list_ge, - ip_prefix_list_ge_cmd, - "ip prefix-list WORD A.B.C.D/M ge (0-32)", - IP_STR - PREFIX_LIST_STR - "Name of a prefix list\n" - "Specify packets to reject\n" - "Specify packets to forward\n" - "IP prefix /, e.g., 35.0.0.0/8\n" - "Minimum prefix length to be matched\n" - "Minimum prefix length\n") -{ - int idx_word = 2; - int idx_permit_deny = 3; - int idx_ipv4_prefixlen = 4; - int idx_number = 6; - return vty_prefix_list_install (vty, AFI_IP, argv[idx_word]->arg, NULL, argv[idx_permit_deny]->arg, - argv[idx_ipv4_prefixlen]->arg, argv[idx_number]->arg, NULL); -} - -DEFUN (ip_prefix_list_ge_le, - ip_prefix_list_ge_le_cmd, - "ip prefix-list WORD A.B.C.D/M ge (0-32) le (0-32)", + "ip prefix-list WORD [seq (1-4294967295)] $action ", IP_STR PREFIX_LIST_STR "Name of a prefix list\n" + "sequence number of an entry\n" + "Sequence number\n" "Specify packets to reject\n" "Specify packets to forward\n" + "Any prefix match. Same as \"0.0.0.0/0 le 32\"\n" "IP prefix /, e.g., 35.0.0.0/8\n" "Minimum prefix length to be matched\n" "Minimum prefix length\n" "Maximum prefix length to be matched\n" "Maximum prefix length\n") { - int idx_word = 2; - int idx_permit_deny = 3; - int idx_ipv4_prefixlen = 4; - int idx_number = 6; - int idx_number_2 = 8; - return vty_prefix_list_install (vty, AFI_IP, argv[idx_word]->arg, NULL, argv[idx_permit_deny]->arg, - argv[idx_ipv4_prefixlen]->arg, argv[idx_number]->arg, argv[idx_number_2]->arg); + return vty_prefix_list_install (vty, AFI_IP, prefix_list, seq_str, action, + dest, ge_str, le_str); } -DEFUN (ip_prefix_list_le, - ip_prefix_list_le_cmd, - "ip prefix-list WORD A.B.C.D/M le (0-32)", - IP_STR - PREFIX_LIST_STR - "Name of a prefix list\n" - "Specify packets to reject\n" - "Specify packets to forward\n" - "IP prefix /, e.g., 35.0.0.0/8\n" - "Maximum prefix length to be matched\n" - "Maximum prefix length\n") -{ - int idx_word = 2; - int idx_permit_deny = 3; - int idx_ipv4_prefixlen = 4; - int idx_number = 6; - return vty_prefix_list_install (vty, AFI_IP, argv[idx_word]->arg, NULL, argv[idx_permit_deny]->arg, - argv[idx_ipv4_prefixlen]->arg, NULL, argv[idx_number]->arg); -} - -DEFUN (ip_prefix_list_le_ge, - ip_prefix_list_le_ge_cmd, - "ip prefix-list WORD A.B.C.D/M le (0-32) ge (0-32)", - IP_STR - PREFIX_LIST_STR - "Name of a prefix list\n" - "Specify packets to reject\n" - "Specify packets to forward\n" - "IP prefix /, e.g., 35.0.0.0/8\n" - "Maximum prefix length to be matched\n" - "Maximum prefix length\n" - "Minimum prefix length to be matched\n" - "Minimum prefix length\n") -{ - int idx_word = 2; - int idx_permit_deny = 3; - int idx_ipv4_prefixlen = 4; - int idx_number = 6; - int idx_number_2 = 8; - return vty_prefix_list_install (vty, AFI_IP, argv[idx_word]->arg, NULL, argv[idx_permit_deny]->arg, - argv[idx_ipv4_prefixlen]->arg, argv[idx_number_2]->arg, argv[idx_number]->arg); -} - -DEFUN (ip_prefix_list_seq, - ip_prefix_list_seq_cmd, - "ip prefix-list WORD seq (1-4294967295) ", - IP_STR - PREFIX_LIST_STR - "Name of a prefix list\n" - "sequence number of an entry\n" - "Sequence number\n" - "Specify packets to reject\n" - "Specify packets to forward\n" - "IP prefix /, e.g., 35.0.0.0/8\n" - "Any prefix match. Same as \"0.0.0.0/0 le 32\"\n") -{ - int idx_word = 2; - int idx_number = 4; - int idx_permit_deny = 5; - int idx_ipv4_any = 6; - return vty_prefix_list_install (vty, AFI_IP, argv[idx_word]->arg, argv[idx_number]->arg, argv[idx_permit_deny]->arg, - argv[idx_ipv4_any]->arg, NULL, NULL); -} - -DEFUN (ip_prefix_list_seq_ge, - ip_prefix_list_seq_ge_cmd, - "ip prefix-list WORD seq (1-4294967295) A.B.C.D/M ge (0-32)", - IP_STR - PREFIX_LIST_STR - "Name of a prefix list\n" - "sequence number of an entry\n" - "Sequence number\n" - "Specify packets to reject\n" - "Specify packets to forward\n" - "IP prefix /, e.g., 35.0.0.0/8\n" - "Minimum prefix length to be matched\n" - "Minimum prefix length\n") -{ - int idx_word = 2; - int idx_number = 4; - int idx_permit_deny = 5; - int idx_ipv4_prefixlen = 6; - int idx_number_2 = 8; - return vty_prefix_list_install (vty, AFI_IP, argv[idx_word]->arg, argv[idx_number]->arg, argv[idx_permit_deny]->arg, - argv[idx_ipv4_prefixlen]->arg, argv[idx_number_2]->arg, NULL); -} - -DEFUN (ip_prefix_list_seq_ge_le, - ip_prefix_list_seq_ge_le_cmd, - "ip prefix-list WORD seq (1-4294967295) A.B.C.D/M ge (0-32) le (0-32)", - IP_STR - PREFIX_LIST_STR - "Name of a prefix list\n" - "sequence number of an entry\n" - "Sequence number\n" - "Specify packets to reject\n" - "Specify packets to forward\n" - "IP prefix /, e.g., 35.0.0.0/8\n" - "Minimum prefix length to be matched\n" - "Minimum prefix length\n" - "Maximum prefix length to be matched\n" - "Maximum prefix length\n") -{ - int idx_word = 2; - int idx_number = 4; - int idx_permit_deny = 5; - int idx_ipv4_prefixlen = 6; - int idx_number_2 = 8; - int idx_number_3 = 10; - return vty_prefix_list_install (vty, AFI_IP, argv[idx_word]->arg, argv[idx_number]->arg, argv[idx_permit_deny]->arg, - argv[idx_ipv4_prefixlen]->arg, argv[idx_number_2]->arg, argv[idx_number_3]->arg); -} - -DEFUN (ip_prefix_list_seq_le, - ip_prefix_list_seq_le_cmd, - "ip prefix-list WORD seq (1-4294967295) A.B.C.D/M le (0-32)", - IP_STR - PREFIX_LIST_STR - "Name of a prefix list\n" - "sequence number of an entry\n" - "Sequence number\n" - "Specify packets to reject\n" - "Specify packets to forward\n" - "IP prefix /, e.g., 35.0.0.0/8\n" - "Maximum prefix length to be matched\n" - "Maximum prefix length\n") -{ - int idx_word = 2; - int idx_number = 4; - int idx_permit_deny = 5; - int idx_ipv4_prefixlen = 6; - int idx_number_2 = 8; - return vty_prefix_list_install (vty, AFI_IP, argv[idx_word]->arg, argv[idx_number]->arg, argv[idx_permit_deny]->arg, - argv[idx_ipv4_prefixlen]->arg, NULL, argv[idx_number_2]->arg); -} - -DEFUN (ip_prefix_list_seq_le_ge, - ip_prefix_list_seq_le_ge_cmd, - "ip prefix-list WORD seq (1-4294967295) A.B.C.D/M le (0-32) ge (0-32)", - IP_STR - PREFIX_LIST_STR - "Name of a prefix list\n" - "sequence number of an entry\n" - "Sequence number\n" - "Specify packets to reject\n" - "Specify packets to forward\n" - "IP prefix /, e.g., 35.0.0.0/8\n" - "Maximum prefix length to be matched\n" - "Maximum prefix length\n" - "Minimum prefix length to be matched\n" - "Minimum prefix length\n") -{ - int idx_word = 2; - int idx_number = 4; - int idx_permit_deny = 5; - int idx_ipv4_prefixlen = 6; - int idx_number_2 = 8; - int idx_number_3 = 10; - return vty_prefix_list_install (vty, AFI_IP, argv[idx_word]->arg, argv[idx_number]->arg, argv[idx_permit_deny]->arg, - argv[idx_ipv4_prefixlen]->arg, argv[idx_number_3]->arg, argv[idx_number_2]->arg); -} - -DEFUN (no_ip_prefix_list, +DEFPY (no_ip_prefix_list, no_ip_prefix_list_cmd, + "no ip prefix-list WORD [seq (1-4294967295)] $action ", + NO_STR + IP_STR + PREFIX_LIST_STR + "Name of a prefix list\n" + "sequence number of an entry\n" + "Sequence number\n" + "Specify packets to reject\n" + "Specify packets to forward\n" + "Any prefix match. Same as \"0.0.0.0/0 le 32\"\n" + "IP prefix /, e.g., 35.0.0.0/8\n" + "Minimum prefix length to be matched\n" + "Minimum prefix length\n" + "Maximum prefix length to be matched\n" + "Maximum prefix length\n") +{ + return vty_prefix_list_uninstall (vty, AFI_IP, prefix_list, seq_str, action, + dest, ge_str, le_str); +} + +DEFPY (no_ip_prefix_list_all, + no_ip_prefix_list_all_cmd, "no ip prefix-list WORD", NO_STR IP_STR PREFIX_LIST_STR "Name of a prefix list\n") { - int idx_word = 3; - return vty_prefix_list_uninstall (vty, AFI_IP, argv[idx_word]->arg, NULL, NULL, + return vty_prefix_list_uninstall (vty, AFI_IP, prefix_list, NULL, NULL, NULL, NULL, NULL); } -DEFUN (no_ip_prefix_list_prefix, - no_ip_prefix_list_prefix_cmd, - "no ip prefix-list WORD ", - NO_STR - IP_STR - PREFIX_LIST_STR - "Name of a prefix list\n" - "Specify packets to reject\n" - "Specify packets to forward\n" - "IP prefix /, e.g., 35.0.0.0/8\n" - "Any prefix match. Same as \"0.0.0.0/0 le 32\"\n") -{ - int idx_word = 3; - int idx_permit_deny = 4; - int idx_ipv4_any = 5; - return vty_prefix_list_uninstall (vty, AFI_IP, argv[idx_word]->arg, NULL, argv[idx_permit_deny]->arg, - argv[idx_ipv4_any]->arg, NULL, NULL); -} - -DEFUN (no_ip_prefix_list_ge, - no_ip_prefix_list_ge_cmd, - "no ip prefix-list WORD A.B.C.D/M ge (0-32)", - NO_STR - IP_STR - PREFIX_LIST_STR - "Name of a prefix list\n" - "Specify packets to reject\n" - "Specify packets to forward\n" - "IP prefix /, e.g., 35.0.0.0/8\n" - "Minimum prefix length to be matched\n" - "Minimum prefix length\n") -{ - int idx_word = 3; - int idx_permit_deny = 4; - int idx_ipv4_prefixlen = 5; - int idx_number = 7; - return vty_prefix_list_uninstall (vty, AFI_IP, argv[idx_word]->arg, NULL, argv[idx_permit_deny]->arg, - argv[idx_ipv4_prefixlen]->arg, argv[idx_number]->arg, NULL); -} - -DEFUN (no_ip_prefix_list_ge_le, - no_ip_prefix_list_ge_le_cmd, - "no ip prefix-list WORD A.B.C.D/M ge (0-32) le (0-32)", - NO_STR - IP_STR - PREFIX_LIST_STR - "Name of a prefix list\n" - "Specify packets to reject\n" - "Specify packets to forward\n" - "IP prefix /, e.g., 35.0.0.0/8\n" - "Minimum prefix length to be matched\n" - "Minimum prefix length\n" - "Maximum prefix length to be matched\n" - "Maximum prefix length\n") -{ - int idx_word = 3; - int idx_permit_deny = 4; - int idx_ipv4_prefixlen = 5; - int idx_number = 7; - int idx_number_2 = 9; - return vty_prefix_list_uninstall (vty, AFI_IP, argv[idx_word]->arg, NULL, argv[idx_permit_deny]->arg, - argv[idx_ipv4_prefixlen]->arg, argv[idx_number]->arg, argv[idx_number_2]->arg); -} - -DEFUN (no_ip_prefix_list_le, - no_ip_prefix_list_le_cmd, - "no ip prefix-list WORD A.B.C.D/M le (0-32)", - NO_STR - IP_STR - PREFIX_LIST_STR - "Name of a prefix list\n" - "Specify packets to reject\n" - "Specify packets to forward\n" - "IP prefix /, e.g., 35.0.0.0/8\n" - "Maximum prefix length to be matched\n" - "Maximum prefix length\n") -{ - int idx_word = 3; - int idx_permit_deny = 4; - int idx_ipv4_prefixlen = 5; - int idx_number = 7; - return vty_prefix_list_uninstall (vty, AFI_IP, argv[idx_word]->arg, NULL, argv[idx_permit_deny]->arg, - argv[idx_ipv4_prefixlen]->arg, NULL, argv[idx_number]->arg); -} - -DEFUN (no_ip_prefix_list_le_ge, - no_ip_prefix_list_le_ge_cmd, - "no ip prefix-list WORD A.B.C.D/M le (0-32) ge (0-32)", - NO_STR - IP_STR - PREFIX_LIST_STR - "Name of a prefix list\n" - "Specify packets to reject\n" - "Specify packets to forward\n" - "IP prefix /, e.g., 35.0.0.0/8\n" - "Maximum prefix length to be matched\n" - "Maximum prefix length\n" - "Minimum prefix length to be matched\n" - "Minimum prefix length\n") -{ - int idx_word = 3; - int idx_permit_deny = 4; - int idx_ipv4_prefixlen = 5; - int idx_number = 7; - int idx_number_2 = 9; - return vty_prefix_list_uninstall (vty, AFI_IP, argv[idx_word]->arg, NULL, argv[idx_permit_deny]->arg, - argv[idx_ipv4_prefixlen]->arg, argv[idx_number_2]->arg, argv[idx_number]->arg); -} - -DEFUN (no_ip_prefix_list_seq, - no_ip_prefix_list_seq_cmd, - "no ip prefix-list WORD seq (1-4294967295) ", - NO_STR - IP_STR - PREFIX_LIST_STR - "Name of a prefix list\n" - "sequence number of an entry\n" - "Sequence number\n" - "Specify packets to reject\n" - "Specify packets to forward\n" - "IP prefix /, e.g., 35.0.0.0/8\n" - "Any prefix match. Same as \"0.0.0.0/0 le 32\"\n") -{ - int idx_word = 3; - int idx_number = 5; - int idx_permit_deny = 6; - int idx_ipv4_any = 7; - return vty_prefix_list_uninstall (vty, AFI_IP, argv[idx_word]->arg, argv[idx_number]->arg, argv[idx_permit_deny]->arg, - argv[idx_ipv4_any]->arg, NULL, NULL); -} - -DEFUN (no_ip_prefix_list_seq_ge, - no_ip_prefix_list_seq_ge_cmd, - "no ip prefix-list WORD seq (1-4294967295) A.B.C.D/M ge (0-32)", - NO_STR - IP_STR - PREFIX_LIST_STR - "Name of a prefix list\n" - "sequence number of an entry\n" - "Sequence number\n" - "Specify packets to reject\n" - "Specify packets to forward\n" - "IP prefix /, e.g., 35.0.0.0/8\n" - "Minimum prefix length to be matched\n" - "Minimum prefix length\n") -{ - int idx_word = 3; - int idx_number = 5; - int idx_permit_deny = 6; - int idx_ipv4_prefixlen = 7; - int idx_number_2 = 9; - return vty_prefix_list_uninstall (vty, AFI_IP, argv[idx_word]->arg, argv[idx_number]->arg, argv[idx_permit_deny]->arg, - argv[idx_ipv4_prefixlen]->arg, argv[idx_number_2]->arg, NULL); -} - -DEFUN (no_ip_prefix_list_seq_ge_le, - no_ip_prefix_list_seq_ge_le_cmd, - "no ip prefix-list WORD seq (1-4294967295) A.B.C.D/M ge (0-32) le (0-32)", - NO_STR - IP_STR - PREFIX_LIST_STR - "Name of a prefix list\n" - "sequence number of an entry\n" - "Sequence number\n" - "Specify packets to reject\n" - "Specify packets to forward\n" - "IP prefix /, e.g., 35.0.0.0/8\n" - "Minimum prefix length to be matched\n" - "Minimum prefix length\n" - "Maximum prefix length to be matched\n" - "Maximum prefix length\n") -{ - int idx_word = 3; - int idx_number = 5; - int idx_permit_deny = 6; - int idx_ipv4_prefixlen = 7; - int idx_number_2 = 9; - int idx_number_3 = 11; - return vty_prefix_list_uninstall (vty, AFI_IP, argv[idx_word]->arg, argv[idx_number]->arg, argv[idx_permit_deny]->arg, - argv[idx_ipv4_prefixlen]->arg, argv[idx_number_2]->arg, argv[idx_number_3]->arg); -} - -DEFUN (no_ip_prefix_list_seq_le, - no_ip_prefix_list_seq_le_cmd, - "no ip prefix-list WORD seq (1-4294967295) A.B.C.D/M le (0-32)", - NO_STR - IP_STR - PREFIX_LIST_STR - "Name of a prefix list\n" - "sequence number of an entry\n" - "Sequence number\n" - "Specify packets to reject\n" - "Specify packets to forward\n" - "IP prefix /, e.g., 35.0.0.0/8\n" - "Maximum prefix length to be matched\n" - "Maximum prefix length\n") -{ - int idx_word = 3; - int idx_number = 5; - int idx_permit_deny = 6; - int idx_ipv4_prefixlen = 7; - int idx_number_2 = 9; - return vty_prefix_list_uninstall (vty, AFI_IP, argv[idx_word]->arg, argv[idx_number]->arg, argv[idx_permit_deny]->arg, - argv[idx_ipv4_prefixlen]->arg, NULL, argv[idx_number_2]->arg); -} - -DEFUN (no_ip_prefix_list_seq_le_ge, - no_ip_prefix_list_seq_le_ge_cmd, - "no ip prefix-list WORD seq (1-4294967295) A.B.C.D/M le (0-32) ge (0-32)", - NO_STR - IP_STR - PREFIX_LIST_STR - "Name of a prefix list\n" - "sequence number of an entry\n" - "Sequence number\n" - "Specify packets to reject\n" - "Specify packets to forward\n" - "IP prefix /, e.g., 35.0.0.0/8\n" - "Maximum prefix length to be matched\n" - "Maximum prefix length\n" - "Minimum prefix length to be matched\n" - "Minimum prefix length\n") -{ - int idx_word = 3; - int idx_number = 5; - int idx_permit_deny = 6; - int idx_ipv4_prefixlen = 7; - int idx_number_2 = 9; - int idx_number_3 = 11; - return vty_prefix_list_uninstall (vty, AFI_IP, argv[idx_word]->arg, argv[idx_number]->arg, argv[idx_permit_deny]->arg, - argv[idx_ipv4_prefixlen]->arg, argv[idx_number_3]->arg, argv[idx_number_2]->arg); -} - -DEFUN (ip_prefix_list_sequence_number, +DEFPY (ip_prefix_list_sequence_number, ip_prefix_list_sequence_number_cmd, - "ip prefix-list sequence-number", - IP_STR - PREFIX_LIST_STR - "Include/exclude sequence numbers in NVGEN\n") -{ - prefix_master_ipv4.seqnum = 1; - return CMD_SUCCESS; -} - -DEFUN (no_ip_prefix_list_sequence_number, - no_ip_prefix_list_sequence_number_cmd, - "no ip prefix-list sequence-number", + "[no] ip prefix-list sequence-number", NO_STR IP_STR PREFIX_LIST_STR "Include/exclude sequence numbers in NVGEN\n") { - prefix_master_ipv4.seqnum = 0; + prefix_master_ipv4.seqnum = no ? 0 : 1; return CMD_SUCCESS; } @@ -1957,31 +1536,9 @@ DEFUN (no_ip_prefix_list_description_comment, return no_ip_prefix_list_description (self, vty, argc, argv); } -DEFUN (show_ip_prefix_list, +DEFPY (show_ip_prefix_list, show_ip_prefix_list_cmd, - "show ip prefix-list", - SHOW_STR - IP_STR - PREFIX_LIST_STR) -{ - return vty_show_prefix_list (vty, AFI_IP, NULL, NULL, normal_display); -} - -DEFUN (show_ip_prefix_list_name, - show_ip_prefix_list_name_cmd, - "show ip prefix-list WORD", - SHOW_STR - IP_STR - PREFIX_LIST_STR - "Name of a prefix list\n") -{ - int idx_word = 3; - return vty_show_prefix_list (vty, AFI_IP, argv[idx_word]->arg, NULL, normal_display); -} - -DEFUN (show_ip_prefix_list_name_seq, - show_ip_prefix_list_name_seq_cmd, - "show ip prefix-list WORD seq (1-4294967295)", + "show ip prefix-list [WORD [seq$dseq (1-4294967295)$arg]]", SHOW_STR IP_STR PREFIX_LIST_STR @@ -1989,630 +1546,133 @@ DEFUN (show_ip_prefix_list_name_seq, "sequence number of an entry\n" "Sequence number\n") { - int idx_word = 3; - int idx_number = 5; - return vty_show_prefix_list (vty, AFI_IP, argv[idx_word]->arg, argv[idx_number]->arg, sequential_display); + enum display_type dtype = normal_display; + if (dseq) + dtype = sequential_display; + + return vty_show_prefix_list (vty, AFI_IP, prefix_list, arg_str, dtype); } -DEFUN (show_ip_prefix_list_prefix, +DEFPY (show_ip_prefix_list_prefix, show_ip_prefix_list_prefix_cmd, - "show ip prefix-list WORD A.B.C.D/M", - SHOW_STR - IP_STR - PREFIX_LIST_STR - "Name of a prefix list\n" - "IP prefix /, e.g., 35.0.0.0/8\n") -{ - int idx_word = 3; - int idx_ipv4_prefixlen = 4; - return vty_show_prefix_list_prefix (vty, AFI_IP, argv[idx_word]->arg, argv[idx_ipv4_prefixlen]->arg, normal_display); -} - -DEFUN (show_ip_prefix_list_prefix_longer, - show_ip_prefix_list_prefix_longer_cmd, - "show ip prefix-list WORD A.B.C.D/M longer", - SHOW_STR - IP_STR - PREFIX_LIST_STR - "Name of a prefix list\n" - "IP prefix /, e.g., 35.0.0.0/8\n" - "Lookup longer prefix\n") -{ - int idx_word = 3; - int idx_ipv4_prefixlen = 4; - return vty_show_prefix_list_prefix (vty, AFI_IP, argv[idx_word]->arg, argv[idx_ipv4_prefixlen]->arg, longer_display); -} - -DEFUN (show_ip_prefix_list_prefix_first_match, - show_ip_prefix_list_prefix_first_match_cmd, - "show ip prefix-list WORD A.B.C.D/M first-match", + "show ip prefix-list WORD A.B.C.D/M$prefix [longer$dl|first-match$dfm]", SHOW_STR IP_STR PREFIX_LIST_STR "Name of a prefix list\n" "IP prefix /, e.g., 35.0.0.0/8\n" + "Lookup longer prefix\n" "First matched prefix\n") { - int idx_word = 3; - int idx_ipv4_prefixlen = 4; - return vty_show_prefix_list_prefix (vty, AFI_IP, argv[idx_word]->arg, argv[idx_ipv4_prefixlen]->arg, first_match_display); + enum display_type dtype = normal_display; + if (dl) + dtype = longer_display; + else if (dfm) + dtype = first_match_display; + + return vty_show_prefix_list_prefix (vty, AFI_IP, prefix_list, prefix_str, dtype); } -DEFUN (show_ip_prefix_list_summary, +DEFPY (show_ip_prefix_list_summary, show_ip_prefix_list_summary_cmd, - "show ip prefix-list summary", - SHOW_STR - IP_STR - PREFIX_LIST_STR - "Summary of prefix lists\n") -{ - return vty_show_prefix_list (vty, AFI_IP, NULL, NULL, summary_display); -} - -DEFUN (show_ip_prefix_list_summary_name, - show_ip_prefix_list_summary_name_cmd, - "show ip prefix-list summary WORD", + "show ip prefix-list summary [WORD$prefix_list]", SHOW_STR IP_STR PREFIX_LIST_STR "Summary of prefix lists\n" "Name of a prefix list\n") { - int idx_word = 4; - return vty_show_prefix_list (vty, AFI_IP, argv[idx_word]->arg, NULL, summary_display); + return vty_show_prefix_list (vty, AFI_IP, prefix_list, NULL, summary_display); } - -DEFUN (show_ip_prefix_list_detail, +DEFPY (show_ip_prefix_list_detail, show_ip_prefix_list_detail_cmd, - "show ip prefix-list detail", - SHOW_STR - IP_STR - PREFIX_LIST_STR - "Detail of prefix lists\n") -{ - return vty_show_prefix_list (vty, AFI_IP, NULL, NULL, detail_display); -} - -DEFUN (show_ip_prefix_list_detail_name, - show_ip_prefix_list_detail_name_cmd, - "show ip prefix-list detail WORD", + "show ip prefix-list detail [WORD$prefix_list]", SHOW_STR IP_STR PREFIX_LIST_STR "Detail of prefix lists\n" "Name of a prefix list\n") { - int idx_word = 4; - return vty_show_prefix_list (vty, AFI_IP, argv[idx_word]->arg, NULL, detail_display); + return vty_show_prefix_list (vty, AFI_IP, prefix_list, NULL, detail_display); } -DEFUN (clear_ip_prefix_list, +DEFPY (clear_ip_prefix_list, clear_ip_prefix_list_cmd, - "clear ip prefix-list", - CLEAR_STR - IP_STR - PREFIX_LIST_STR) -{ - return vty_clear_prefix_list (vty, AFI_IP, NULL, NULL); -} - -DEFUN (clear_ip_prefix_list_name, - clear_ip_prefix_list_name_cmd, - "clear ip prefix-list WORD", - CLEAR_STR - IP_STR - PREFIX_LIST_STR - "Name of a prefix list\n") -{ - int idx_word = 3; - return vty_clear_prefix_list (vty, AFI_IP, argv[idx_word]->arg, NULL); -} - -DEFUN (clear_ip_prefix_list_name_prefix, - clear_ip_prefix_list_name_prefix_cmd, - "clear ip prefix-list WORD A.B.C.D/M", + "clear ip prefix-list [WORD [A.B.C.D/M$prefix]]", CLEAR_STR IP_STR PREFIX_LIST_STR "Name of a prefix list\n" "IP prefix /, e.g., 35.0.0.0/8\n") { - int idx_word = 3; - int idx_ipv4_prefixlen = 4; - return vty_clear_prefix_list (vty, AFI_IP, argv[idx_word]->arg, argv[idx_ipv4_prefixlen]->arg); + return vty_clear_prefix_list (vty, AFI_IP, prefix_list, prefix_str); } -DEFUN (ipv6_prefix_list, +DEFPY (ipv6_prefix_list, ipv6_prefix_list_cmd, - "ipv6 prefix-list WORD ", - IPV6_STR - PREFIX_LIST_STR - "Name of a prefix list\n" - "Specify packets to reject\n" - "Specify packets to forward\n" - "IPv6 prefix /, e.g., 3ffe::/16\n" - "Any prefix match. Same as \"::0/0 le 128\"\n") -{ - int idx_word = 2; - int idx_permit_deny = 3; - int idx_ipv6_any = 4; - return vty_prefix_list_install (vty, AFI_IP6, argv[idx_word]->arg, NULL, - argv[idx_permit_deny]->arg, argv[idx_ipv6_any]->arg, NULL, NULL); -} - -DEFUN (ipv6_prefix_list_ge, - ipv6_prefix_list_ge_cmd, - "ipv6 prefix-list WORD X:X::X:X/M ge (0-128)", - IPV6_STR - PREFIX_LIST_STR - "Name of a prefix list\n" - "Specify packets to reject\n" - "Specify packets to forward\n" - "IPv6 prefix /, e.g., 3ffe::/16\n" - "Minimum prefix length to be matched\n" - "Minimum prefix length\n") -{ - int idx_word = 2; - int idx_permit_deny = 3; - int idx_ipv6_prefixlen = 4; - int idx_number = 6; - return vty_prefix_list_install (vty, AFI_IP6, argv[idx_word]->arg, NULL, argv[idx_permit_deny]->arg, - argv[idx_ipv6_prefixlen]->arg, argv[idx_number]->arg, NULL); -} - -DEFUN (ipv6_prefix_list_ge_le, - ipv6_prefix_list_ge_le_cmd, - "ipv6 prefix-list WORD X:X::X:X/M ge (0-128) le (0-128)", - IPV6_STR - PREFIX_LIST_STR - "Name of a prefix list\n" - "Specify packets to reject\n" - "Specify packets to forward\n" - "IPv6 prefix /, e.g., 3ffe::/16\n" - "Minimum prefix length to be matched\n" - "Minimum prefix length\n" - "Maximum prefix length to be matched\n" - "Maximum prefix length\n") - -{ - int idx_word = 2; - int idx_permit_deny = 3; - int idx_ipv6_prefixlen = 4; - int idx_number = 6; - int idx_number_2 = 8; - return vty_prefix_list_install (vty, AFI_IP6, argv[idx_word]->arg, NULL, argv[idx_permit_deny]->arg, - argv[idx_ipv6_prefixlen]->arg, argv[idx_number]->arg, argv[idx_number_2]->arg); -} - -DEFUN (ipv6_prefix_list_le, - ipv6_prefix_list_le_cmd, - "ipv6 prefix-list WORD X:X::X:X/M le (0-128)", - IPV6_STR - PREFIX_LIST_STR - "Name of a prefix list\n" - "Specify packets to reject\n" - "Specify packets to forward\n" - "IPv6 prefix /, e.g., 3ffe::/16\n" - "Maximum prefix length to be matched\n" - "Maximum prefix length\n") -{ - int idx_word = 2; - int idx_permit_deny = 3; - int idx_ipv6_prefixlen = 4; - int idx_number = 6; - return vty_prefix_list_install (vty, AFI_IP6, argv[idx_word]->arg, NULL, argv[idx_permit_deny]->arg, - argv[idx_ipv6_prefixlen]->arg, NULL, argv[idx_number]->arg); -} - -DEFUN (ipv6_prefix_list_le_ge, - ipv6_prefix_list_le_ge_cmd, - "ipv6 prefix-list WORD X:X::X:X/M le (0-128) ge (0-128)", + "ipv6 prefix-list WORD [seq (1-4294967295)] $action ", IPV6_STR PREFIX_LIST_STR "Name of a prefix list\n" + "sequence number of an entry\n" + "Sequence number\n" "Specify packets to reject\n" "Specify packets to forward\n" + "Any prefix match. Same as \"::0/0 le 128\"\n" "IPv6 prefix /, e.g., 3ffe::/16\n" "Maximum prefix length to be matched\n" "Maximum prefix length\n" "Minimum prefix length to be matched\n" "Minimum prefix length\n") { - int idx_word = 2; - int idx_permit_deny = 3; - int idx_ipv6_prefixlen = 4; - int idx_number = 6; - int idx_number_2 = 8; - return vty_prefix_list_install (vty, AFI_IP6, argv[idx_word]->arg, NULL, argv[idx_permit_deny]->arg, - argv[idx_ipv6_prefixlen]->arg, argv[idx_number_2]->arg, argv[idx_number]->arg); + return vty_prefix_list_install (vty, AFI_IP6, prefix_list, seq_str, action, + dest, ge_str, le_str); } -DEFUN (ipv6_prefix_list_seq, - ipv6_prefix_list_seq_cmd, - "ipv6 prefix-list WORD seq (1-4294967295) ", - IPV6_STR - PREFIX_LIST_STR - "Name of a prefix list\n" - "sequence number of an entry\n" - "Sequence number\n" - "Specify packets to reject\n" - "Specify packets to forward\n" - "IPv6 prefix /, e.g., 3ffe::/16\n" - "Any prefix match. Same as \"::0/0 le 128\"\n") -{ - int idx_word = 2; - int idx_number = 4; - int idx_permit_deny = 5; - int idx_ipv6_any = 6; - return vty_prefix_list_install (vty, AFI_IP6, argv[idx_word]->arg, argv[idx_number]->arg, argv[idx_permit_deny]->arg, - argv[idx_ipv6_any]->arg, NULL, NULL); -} - -DEFUN (ipv6_prefix_list_seq_ge, - ipv6_prefix_list_seq_ge_cmd, - "ipv6 prefix-list WORD seq (1-4294967295) X:X::X:X/M ge (0-128)", - IPV6_STR - PREFIX_LIST_STR - "Name of a prefix list\n" - "sequence number of an entry\n" - "Sequence number\n" - "Specify packets to reject\n" - "Specify packets to forward\n" - "IPv6 prefix /, e.g., 3ffe::/16\n" - "Minimum prefix length to be matched\n" - "Minimum prefix length\n") -{ - int idx_word = 2; - int idx_number = 4; - int idx_permit_deny = 5; - int idx_ipv6_prefixlen = 6; - int idx_number_2 = 8; - return vty_prefix_list_install (vty, AFI_IP6, argv[idx_word]->arg, argv[idx_number]->arg, argv[idx_permit_deny]->arg, - argv[idx_ipv6_prefixlen]->arg, argv[idx_number_2]->arg, NULL); -} - -DEFUN (ipv6_prefix_list_seq_ge_le, - ipv6_prefix_list_seq_ge_le_cmd, - "ipv6 prefix-list WORD seq (1-4294967295) X:X::X:X/M ge (0-128) le (0-128)", - IPV6_STR - PREFIX_LIST_STR - "Name of a prefix list\n" - "sequence number of an entry\n" - "Sequence number\n" - "Specify packets to reject\n" - "Specify packets to forward\n" - "IPv6 prefix /, e.g., 3ffe::/16\n" - "Minimum prefix length to be matched\n" - "Minimum prefix length\n" - "Maximum prefix length to be matched\n" - "Maximum prefix length\n") -{ - int idx_word = 2; - int idx_number = 4; - int idx_permit_deny = 5; - int idx_ipv6_prefixlen = 6; - int idx_number_2 = 8; - int idx_number_3 = 10; - return vty_prefix_list_install (vty, AFI_IP6, argv[idx_word]->arg, argv[idx_number]->arg, argv[idx_permit_deny]->arg, - argv[idx_ipv6_prefixlen]->arg, argv[idx_number_2]->arg, argv[idx_number_3]->arg); -} - -DEFUN (ipv6_prefix_list_seq_le, - ipv6_prefix_list_seq_le_cmd, - "ipv6 prefix-list WORD seq (1-4294967295) X:X::X:X/M le (0-128)", - IPV6_STR - PREFIX_LIST_STR - "Name of a prefix list\n" - "sequence number of an entry\n" - "Sequence number\n" - "Specify packets to reject\n" - "Specify packets to forward\n" - "IPv6 prefix /, e.g., 3ffe::/16\n" - "Maximum prefix length to be matched\n" - "Maximum prefix length\n") -{ - int idx_word = 2; - int idx_number = 4; - int idx_permit_deny = 5; - int idx_ipv6_prefixlen = 6; - int idx_number_2 = 8; - return vty_prefix_list_install (vty, AFI_IP6, argv[idx_word]->arg, argv[idx_number]->arg, argv[idx_permit_deny]->arg, - argv[idx_ipv6_prefixlen]->arg, NULL, argv[idx_number_2]->arg); -} - -DEFUN (ipv6_prefix_list_seq_le_ge, - ipv6_prefix_list_seq_le_ge_cmd, - "ipv6 prefix-list WORD seq (1-4294967295) X:X::X:X/M le (0-128) ge (0-128)", - IPV6_STR - PREFIX_LIST_STR - "Name of a prefix list\n" - "sequence number of an entry\n" - "Sequence number\n" - "Specify packets to reject\n" - "Specify packets to forward\n" - "IPv6 prefix /, e.g., 3ffe::/16\n" - "Maximum prefix length to be matched\n" - "Maximum prefix length\n" - "Minimum prefix length to be matched\n" - "Minimum prefix length\n") -{ - int idx_word = 2; - int idx_number = 4; - int idx_permit_deny = 5; - int idx_ipv6_prefixlen = 6; - int idx_number_2 = 8; - int idx_number_3 = 10; - return vty_prefix_list_install (vty, AFI_IP6, argv[idx_word]->arg, argv[idx_number]->arg, argv[idx_permit_deny]->arg, - argv[idx_ipv6_prefixlen]->arg, argv[idx_number_3]->arg, argv[idx_number_2]->arg); -} - -DEFUN (no_ipv6_prefix_list, +DEFPY (no_ipv6_prefix_list, no_ipv6_prefix_list_cmd, + "no ipv6 prefix-list WORD [seq (1-4294967295)] $action ", + NO_STR + IPV6_STR + PREFIX_LIST_STR + "Name of a prefix list\n" + "sequence number of an entry\n" + "Sequence number\n" + "Specify packets to reject\n" + "Specify packets to forward\n" + "Any prefix match. Same as \"::0/0 le 128\"\n" + "IPv6 prefix /, e.g., 3ffe::/16\n" + "Maximum prefix length to be matched\n" + "Maximum prefix length\n" + "Minimum prefix length to be matched\n" + "Minimum prefix length\n") +{ + return vty_prefix_list_uninstall (vty, AFI_IP6, prefix_list, seq_str, action, + dest, ge_str, le_str); +} + +DEFPY (no_ipv6_prefix_list_all, + no_ipv6_prefix_list_all_cmd, "no ipv6 prefix-list WORD", NO_STR IPV6_STR PREFIX_LIST_STR "Name of a prefix list\n") { - int idx_word = 3; - return vty_prefix_list_uninstall (vty, AFI_IP6, argv[idx_word]->arg, NULL, NULL, + return vty_prefix_list_uninstall (vty, AFI_IP6, prefix_list, NULL, NULL, NULL, NULL, NULL); } -DEFUN (no_ipv6_prefix_list_prefix, - no_ipv6_prefix_list_prefix_cmd, - "no ipv6 prefix-list WORD ", - NO_STR - IPV6_STR - PREFIX_LIST_STR - "Name of a prefix list\n" - "Specify packets to reject\n" - "Specify packets to forward\n" - "IPv6 prefix /, e.g., 3ffe::/16\n" - "Any prefix match. Same as \"::0/0 le 128\"\n") -{ - int idx_word = 3; - int idx_permit_deny = 4; - int idx_ipv6_any = 5; - return vty_prefix_list_uninstall (vty, AFI_IP6, argv[idx_word]->arg, NULL, argv[idx_permit_deny]->arg, - argv[idx_ipv6_any]->arg, NULL, NULL); -} - -DEFUN (no_ipv6_prefix_list_ge, - no_ipv6_prefix_list_ge_cmd, - "no ipv6 prefix-list WORD X:X::X:X/M ge (0-128)", - NO_STR - IPV6_STR - PREFIX_LIST_STR - "Name of a prefix list\n" - "Specify packets to reject\n" - "Specify packets to forward\n" - "IPv6 prefix /, e.g., 3ffe::/16\n" - "Minimum prefix length to be matched\n" - "Minimum prefix length\n") -{ - int idx_word = 3; - int idx_permit_deny = 4; - int idx_ipv6_prefixlen = 5; - int idx_number = 7; - return vty_prefix_list_uninstall (vty, AFI_IP6, argv[idx_word]->arg, NULL, argv[idx_permit_deny]->arg, - argv[idx_ipv6_prefixlen]->arg, argv[idx_number]->arg, NULL); -} - -DEFUN (no_ipv6_prefix_list_ge_le, - no_ipv6_prefix_list_ge_le_cmd, - "no ipv6 prefix-list WORD X:X::X:X/M ge (0-128) le (0-128)", - NO_STR - IPV6_STR - PREFIX_LIST_STR - "Name of a prefix list\n" - "Specify packets to reject\n" - "Specify packets to forward\n" - "IPv6 prefix /, e.g., 3ffe::/16\n" - "Minimum prefix length to be matched\n" - "Minimum prefix length\n" - "Maximum prefix length to be matched\n" - "Maximum prefix length\n") -{ - int idx_word = 3; - int idx_permit_deny = 4; - int idx_ipv6_prefixlen = 5; - int idx_number = 7; - int idx_number_2 = 9; - return vty_prefix_list_uninstall (vty, AFI_IP6, argv[idx_word]->arg, NULL, argv[idx_permit_deny]->arg, - argv[idx_ipv6_prefixlen]->arg, argv[idx_number]->arg, argv[idx_number_2]->arg); -} - -DEFUN (no_ipv6_prefix_list_le, - no_ipv6_prefix_list_le_cmd, - "no ipv6 prefix-list WORD X:X::X:X/M le (0-128)", - NO_STR - IPV6_STR - PREFIX_LIST_STR - "Name of a prefix list\n" - "Specify packets to reject\n" - "Specify packets to forward\n" - "IPv6 prefix /, e.g., 3ffe::/16\n" - "Maximum prefix length to be matched\n" - "Maximum prefix length\n") -{ - int idx_word = 3; - int idx_permit_deny = 4; - int idx_ipv6_prefixlen = 5; - int idx_number = 7; - return vty_prefix_list_uninstall (vty, AFI_IP6, argv[idx_word]->arg, NULL, argv[idx_permit_deny]->arg, - argv[idx_ipv6_prefixlen]->arg, NULL, argv[idx_number]->arg); -} - -DEFUN (no_ipv6_prefix_list_le_ge, - no_ipv6_prefix_list_le_ge_cmd, - "no ipv6 prefix-list WORD X:X::X:X/M le (0-128) ge (0-128)", - NO_STR - IPV6_STR - PREFIX_LIST_STR - "Name of a prefix list\n" - "Specify packets to reject\n" - "Specify packets to forward\n" - "IPv6 prefix /, e.g., 3ffe::/16\n" - "Maximum prefix length to be matched\n" - "Maximum prefix length\n" - "Minimum prefix length to be matched\n" - "Minimum prefix length\n") -{ - int idx_word = 3; - int idx_permit_deny = 4; - int idx_ipv6_prefixlen = 5; - int idx_number = 7; - int idx_number_2 = 9; - return vty_prefix_list_uninstall (vty, AFI_IP6, argv[idx_word]->arg, NULL, argv[idx_permit_deny]->arg, - argv[idx_ipv6_prefixlen]->arg, argv[idx_number_2]->arg, argv[idx_number]->arg); -} - -DEFUN (no_ipv6_prefix_list_seq, - no_ipv6_prefix_list_seq_cmd, - "no ipv6 prefix-list WORD seq (1-4294967295) ", - NO_STR - IPV6_STR - PREFIX_LIST_STR - "Name of a prefix list\n" - "sequence number of an entry\n" - "Sequence number\n" - "Specify packets to reject\n" - "Specify packets to forward\n" - "IPv6 prefix /, e.g., 3ffe::/16\n" - "Any prefix match. Same as \"::0/0 le 128\"\n") -{ - int idx_word = 3; - int idx_number = 5; - int idx_permit_deny = 6; - int idx_ipv6_any = 7; - return vty_prefix_list_uninstall (vty, AFI_IP6, argv[idx_word]->arg, argv[idx_number]->arg, argv[idx_permit_deny]->arg, - argv[idx_ipv6_any]->arg, NULL, NULL); -} - -DEFUN (no_ipv6_prefix_list_seq_ge, - no_ipv6_prefix_list_seq_ge_cmd, - "no ipv6 prefix-list WORD seq (1-4294967295) X:X::X:X/M ge (0-128)", - NO_STR - IPV6_STR - PREFIX_LIST_STR - "Name of a prefix list\n" - "sequence number of an entry\n" - "Sequence number\n" - "Specify packets to reject\n" - "Specify packets to forward\n" - "IPv6 prefix /, e.g., 3ffe::/16\n" - "Minimum prefix length to be matched\n" - "Minimum prefix length\n") -{ - int idx_word = 3; - int idx_number = 5; - int idx_permit_deny = 6; - int idx_ipv6_prefixlen = 7; - int idx_number_2 = 9; - return vty_prefix_list_uninstall (vty, AFI_IP6, argv[idx_word]->arg, argv[idx_number]->arg, argv[idx_permit_deny]->arg, - argv[idx_ipv6_prefixlen]->arg, argv[idx_number_2]->arg, NULL); -} - -DEFUN (no_ipv6_prefix_list_seq_ge_le, - no_ipv6_prefix_list_seq_ge_le_cmd, - "no ipv6 prefix-list WORD seq (1-4294967295) X:X::X:X/M ge (0-128) le (0-128)", - NO_STR - IPV6_STR - PREFIX_LIST_STR - "Name of a prefix list\n" - "sequence number of an entry\n" - "Sequence number\n" - "Specify packets to reject\n" - "Specify packets to forward\n" - "IPv6 prefix /, e.g., 3ffe::/16\n" - "Minimum prefix length to be matched\n" - "Minimum prefix length\n" - "Maximum prefix length to be matched\n" - "Maximum prefix length\n") -{ - int idx_word = 3; - int idx_number = 5; - int idx_permit_deny = 6; - int idx_ipv6_prefixlen = 7; - int idx_number_2 = 9; - int idx_number_3 = 11; - return vty_prefix_list_uninstall (vty, AFI_IP6, argv[idx_word]->arg, argv[idx_number]->arg, argv[idx_permit_deny]->arg, - argv[idx_ipv6_prefixlen]->arg, argv[idx_number_2]->arg, argv[idx_number_3]->arg); -} - -DEFUN (no_ipv6_prefix_list_seq_le, - no_ipv6_prefix_list_seq_le_cmd, - "no ipv6 prefix-list WORD seq (1-4294967295) X:X::X:X/M le (0-128)", - NO_STR - IPV6_STR - PREFIX_LIST_STR - "Name of a prefix list\n" - "sequence number of an entry\n" - "Sequence number\n" - "Specify packets to reject\n" - "Specify packets to forward\n" - "IPv6 prefix /, e.g., 3ffe::/16\n" - "Maximum prefix length to be matched\n" - "Maximum prefix length\n") -{ - int idx_word = 3; - int idx_number = 5; - int idx_permit_deny = 6; - int idx_ipv6_prefixlen = 7; - int idx_number_2 = 9; - return vty_prefix_list_uninstall (vty, AFI_IP6, argv[idx_word]->arg, argv[idx_number]->arg, argv[idx_permit_deny]->arg, - argv[idx_ipv6_prefixlen]->arg, NULL, argv[idx_number_2]->arg); -} - -DEFUN (no_ipv6_prefix_list_seq_le_ge, - no_ipv6_prefix_list_seq_le_ge_cmd, - "no ipv6 prefix-list WORD seq (1-4294967295) X:X::X:X/M le (0-128) ge (0-128)", - NO_STR - IPV6_STR - PREFIX_LIST_STR - "Name of a prefix list\n" - "sequence number of an entry\n" - "Sequence number\n" - "Specify packets to reject\n" - "Specify packets to forward\n" - "IPv6 prefix /, e.g., 3ffe::/16\n" - "Maximum prefix length to be matched\n" - "Maximum prefix length\n" - "Minimum prefix length to be matched\n" - "Minimum prefix length\n") -{ - int idx_word = 3; - int idx_number = 5; - int idx_permit_deny = 6; - int idx_ipv6_prefixlen = 7; - int idx_number_2 = 9; - int idx_number_3 = 11; - return vty_prefix_list_uninstall (vty, AFI_IP6, argv[idx_word]->arg, argv[idx_number]->arg, argv[idx_permit_deny]->arg, - argv[idx_ipv6_prefixlen]->arg, argv[idx_number_3]->arg, argv[idx_number_2]->arg); -} - -DEFUN (ipv6_prefix_list_sequence_number, +DEFPY (ipv6_prefix_list_sequence_number, ipv6_prefix_list_sequence_number_cmd, - "ipv6 prefix-list sequence-number", - IPV6_STR - PREFIX_LIST_STR - "Include/exclude sequence numbers in NVGEN\n") -{ - prefix_master_ipv6.seqnum = 1; - return CMD_SUCCESS; -} - -DEFUN (no_ipv6_prefix_list_sequence_number, - no_ipv6_prefix_list_sequence_number_cmd, - "no ipv6 prefix-list sequence-number", + "[no] ipv6 prefix-list sequence-number", NO_STR IPV6_STR PREFIX_LIST_STR "Include/exclude sequence numbers in NVGEN\n") { - prefix_master_ipv6.seqnum = 0; + prefix_master_ipv6.seqnum = no ? 0 : 1; return CMD_SUCCESS; } @@ -2669,169 +1729,79 @@ DEFUN (no_ipv6_prefix_list_description_comment, } -DEFUN (show_ipv6_prefix_list, +DEFPY (show_ipv6_prefix_list, show_ipv6_prefix_list_cmd, - "show ipv6 prefix-list", - SHOW_STR - IPV6_STR - PREFIX_LIST_STR) -{ - return vty_show_prefix_list (vty, AFI_IP6, NULL, NULL, normal_display); -} - -DEFUN (show_ipv6_prefix_list_name, - show_ipv6_prefix_list_name_cmd, - "show ipv6 prefix-list WORD", - SHOW_STR - IPV6_STR - PREFIX_LIST_STR - "Name of a prefix list\n") -{ - int idx_word = 3; - return vty_show_prefix_list (vty, AFI_IP6, argv[idx_word]->arg, NULL, normal_display); -} - -DEFUN (show_ipv6_prefix_list_name_seq, - show_ipv6_prefix_list_name_seq_cmd, - "show ipv6 prefix-list WORD seq (1-4294967295)", + "show ipv6 prefix-list [WORD [seq$dseq (1-4294967295)$arg]]", SHOW_STR IPV6_STR PREFIX_LIST_STR "Name of a prefix list\n" "sequence number of an entry\n" - "Sequence number\n") -{ - int idx_word = 3; - int idx_number = 5; - return vty_show_prefix_list (vty, AFI_IP6, argv[idx_word]->arg, argv[idx_number]->arg, sequential_display); -} - -DEFUN (show_ipv6_prefix_list_prefix, - show_ipv6_prefix_list_prefix_cmd, - "show ipv6 prefix-list WORD X:X::X:X/M", - SHOW_STR - IPV6_STR - PREFIX_LIST_STR - "Name of a prefix list\n" - "IPv6 prefix /, e.g., 3ffe::/16\n") -{ - int idx_word = 3; - int idx_ipv6_prefixlen = 4; - return vty_show_prefix_list_prefix (vty, AFI_IP6, argv[idx_word]->arg, argv[idx_ipv6_prefixlen]->arg, normal_display); -} - -DEFUN (show_ipv6_prefix_list_prefix_longer, - show_ipv6_prefix_list_prefix_longer_cmd, - "show ipv6 prefix-list WORD X:X::X:X/M longer", - SHOW_STR - IPV6_STR - PREFIX_LIST_STR - "Name of a prefix list\n" - "IPv6 prefix /, e.g., 3ffe::/16\n" - "Lookup longer prefix\n") -{ - int idx_word = 3; - int idx_ipv6_prefixlen = 4; - return vty_show_prefix_list_prefix (vty, AFI_IP6, argv[idx_word]->arg, argv[idx_ipv6_prefixlen]->arg, longer_display); -} - -DEFUN (show_ipv6_prefix_list_prefix_first_match, - show_ipv6_prefix_list_prefix_first_match_cmd, - "show ipv6 prefix-list WORD X:X::X:X/M first-match", - SHOW_STR - IPV6_STR - PREFIX_LIST_STR - "Name of a prefix list\n" - "IPv6 prefix /, e.g., 3ffe::/16\n" + "Sequence number\n" + "Lookup longer prefix\n" "First matched prefix\n") { - int idx_word = 3; - int idx_ipv6_prefixlen = 4; - return vty_show_prefix_list_prefix (vty, AFI_IP6, argv[idx_word]->arg, argv[idx_ipv6_prefixlen]->arg, first_match_display); + enum display_type dtype = normal_display; + if (dseq) + dtype = sequential_display; + + return vty_show_prefix_list (vty, AFI_IP6, prefix_list, arg_str, dtype); } -DEFUN (show_ipv6_prefix_list_summary, - show_ipv6_prefix_list_summary_cmd, - "show ipv6 prefix-list summary", +DEFPY (show_ipv6_prefix_list_prefix, + show_ipv6_prefix_list_prefix_cmd, + "show ipv6 prefix-list WORD X:X::X:X/M$prefix [longer$dl|first-match$dfm]", SHOW_STR IPV6_STR PREFIX_LIST_STR - "Summary of prefix lists\n") + "Name of a prefix list\n" + "IPv6 prefix /, e.g., 3ffe::/16\n" + "Lookup longer prefix\n" + "First matched prefix\n") { - return vty_show_prefix_list (vty, AFI_IP6, NULL, NULL, summary_display); + enum display_type dtype = normal_display; + if (dl) + dtype = longer_display; + else if (dfm) + dtype = first_match_display; + + return vty_show_prefix_list_prefix (vty, AFI_IP6, prefix_list, prefix_str, dtype); } -DEFUN (show_ipv6_prefix_list_summary_name, - show_ipv6_prefix_list_summary_name_cmd, - "show ipv6 prefix-list summary WORD", +DEFPY (show_ipv6_prefix_list_summary, + show_ipv6_prefix_list_summary_cmd, + "show ipv6 prefix-list summary [WORD$prefix-list]", SHOW_STR IPV6_STR PREFIX_LIST_STR "Summary of prefix lists\n" "Name of a prefix list\n") { - int idx_word = 4; - return vty_show_prefix_list (vty, AFI_IP6, argv[idx_word]->arg, NULL, summary_display); + return vty_show_prefix_list (vty, AFI_IP6, prefix_list, NULL, summary_display); } -DEFUN (show_ipv6_prefix_list_detail, +DEFPY (show_ipv6_prefix_list_detail, show_ipv6_prefix_list_detail_cmd, - "show ipv6 prefix-list detail", - SHOW_STR - IPV6_STR - PREFIX_LIST_STR - "Detail of prefix lists\n") -{ - return vty_show_prefix_list (vty, AFI_IP6, NULL, NULL, detail_display); -} - -DEFUN (show_ipv6_prefix_list_detail_name, - show_ipv6_prefix_list_detail_name_cmd, - "show ipv6 prefix-list detail WORD", + "show ipv6 prefix-list detail [WORD$prefix-list]", SHOW_STR IPV6_STR PREFIX_LIST_STR "Detail of prefix lists\n" "Name of a prefix list\n") { - int idx_word = 4; - return vty_show_prefix_list (vty, AFI_IP6, argv[idx_word]->arg, NULL, detail_display); + return vty_show_prefix_list (vty, AFI_IP6, prefix_list, NULL, detail_display); } -DEFUN (clear_ipv6_prefix_list, +DEFPY (clear_ipv6_prefix_list, clear_ipv6_prefix_list_cmd, - "clear ipv6 prefix-list", - CLEAR_STR - IPV6_STR - PREFIX_LIST_STR) -{ - return vty_clear_prefix_list (vty, AFI_IP6, NULL, NULL); -} - -DEFUN (clear_ipv6_prefix_list_name, - clear_ipv6_prefix_list_name_cmd, - "clear ipv6 prefix-list WORD", - CLEAR_STR - IPV6_STR - PREFIX_LIST_STR - "Name of a prefix list\n") -{ - int idx_word = 3; - return vty_clear_prefix_list (vty, AFI_IP6, argv[idx_word]->arg, NULL); -} - -DEFUN (clear_ipv6_prefix_list_name_prefix, - clear_ipv6_prefix_list_name_prefix_cmd, - "clear ipv6 prefix-list WORD X:X::X:X/M", + "clear ipv6 prefix-list [WORD [X:X::X:X/M$prefix]]", CLEAR_STR IPV6_STR PREFIX_LIST_STR "Name of a prefix list\n" "IPv6 prefix /, e.g., 3ffe::/16\n") { - int idx_word = 3; - int idx_ipv6_prefixlen = 4; - return vty_clear_prefix_list (vty, AFI_IP6, argv[idx_word]->arg, argv[idx_ipv6_prefixlen]->arg); + return vty_clear_prefix_list (vty, AFI_IP6, prefix_list, prefix_str); } /* Configuration write function. */ @@ -3196,49 +2166,21 @@ prefix_list_init_ipv4 (void) install_node (&prefix_node, config_write_prefix_ipv4); install_element (CONFIG_NODE, &ip_prefix_list_cmd); - install_element (CONFIG_NODE, &ip_prefix_list_ge_cmd); - install_element (CONFIG_NODE, &ip_prefix_list_ge_le_cmd); - install_element (CONFIG_NODE, &ip_prefix_list_le_cmd); - install_element (CONFIG_NODE, &ip_prefix_list_le_ge_cmd); - install_element (CONFIG_NODE, &ip_prefix_list_seq_cmd); - install_element (CONFIG_NODE, &ip_prefix_list_seq_ge_cmd); - install_element (CONFIG_NODE, &ip_prefix_list_seq_ge_le_cmd); - install_element (CONFIG_NODE, &ip_prefix_list_seq_le_cmd); - install_element (CONFIG_NODE, &ip_prefix_list_seq_le_ge_cmd); - install_element (CONFIG_NODE, &no_ip_prefix_list_cmd); - install_element (CONFIG_NODE, &no_ip_prefix_list_prefix_cmd); - install_element (CONFIG_NODE, &no_ip_prefix_list_ge_cmd); - install_element (CONFIG_NODE, &no_ip_prefix_list_ge_le_cmd); - install_element (CONFIG_NODE, &no_ip_prefix_list_le_cmd); - install_element (CONFIG_NODE, &no_ip_prefix_list_le_ge_cmd); - install_element (CONFIG_NODE, &no_ip_prefix_list_seq_cmd); - install_element (CONFIG_NODE, &no_ip_prefix_list_seq_ge_cmd); - install_element (CONFIG_NODE, &no_ip_prefix_list_seq_ge_le_cmd); - install_element (CONFIG_NODE, &no_ip_prefix_list_seq_le_cmd); - install_element (CONFIG_NODE, &no_ip_prefix_list_seq_le_ge_cmd); + install_element (CONFIG_NODE, &no_ip_prefix_list_all_cmd); install_element (CONFIG_NODE, &ip_prefix_list_description_cmd); install_element (CONFIG_NODE, &no_ip_prefix_list_description_cmd); install_element (CONFIG_NODE, &no_ip_prefix_list_description_comment_cmd); install_element (CONFIG_NODE, &ip_prefix_list_sequence_number_cmd); - install_element (CONFIG_NODE, &no_ip_prefix_list_sequence_number_cmd); install_element (VIEW_NODE, &show_ip_prefix_list_cmd); - install_element (VIEW_NODE, &show_ip_prefix_list_name_cmd); - install_element (VIEW_NODE, &show_ip_prefix_list_name_seq_cmd); install_element (VIEW_NODE, &show_ip_prefix_list_prefix_cmd); - install_element (VIEW_NODE, &show_ip_prefix_list_prefix_longer_cmd); - install_element (VIEW_NODE, &show_ip_prefix_list_prefix_first_match_cmd); install_element (VIEW_NODE, &show_ip_prefix_list_summary_cmd); - install_element (VIEW_NODE, &show_ip_prefix_list_summary_name_cmd); install_element (VIEW_NODE, &show_ip_prefix_list_detail_cmd); - install_element (VIEW_NODE, &show_ip_prefix_list_detail_name_cmd); install_element (ENABLE_NODE, &clear_ip_prefix_list_cmd); - install_element (ENABLE_NODE, &clear_ip_prefix_list_name_cmd); - install_element (ENABLE_NODE, &clear_ip_prefix_list_name_prefix_cmd); } /* Prefix-list node. */ @@ -3261,49 +2203,21 @@ prefix_list_init_ipv6 (void) install_node (&prefix_ipv6_node, config_write_prefix_ipv6); install_element (CONFIG_NODE, &ipv6_prefix_list_cmd); - install_element (CONFIG_NODE, &ipv6_prefix_list_ge_cmd); - install_element (CONFIG_NODE, &ipv6_prefix_list_ge_le_cmd); - install_element (CONFIG_NODE, &ipv6_prefix_list_le_cmd); - install_element (CONFIG_NODE, &ipv6_prefix_list_le_ge_cmd); - install_element (CONFIG_NODE, &ipv6_prefix_list_seq_cmd); - install_element (CONFIG_NODE, &ipv6_prefix_list_seq_ge_cmd); - install_element (CONFIG_NODE, &ipv6_prefix_list_seq_ge_le_cmd); - install_element (CONFIG_NODE, &ipv6_prefix_list_seq_le_cmd); - install_element (CONFIG_NODE, &ipv6_prefix_list_seq_le_ge_cmd); - install_element (CONFIG_NODE, &no_ipv6_prefix_list_cmd); - install_element (CONFIG_NODE, &no_ipv6_prefix_list_prefix_cmd); - install_element (CONFIG_NODE, &no_ipv6_prefix_list_ge_cmd); - install_element (CONFIG_NODE, &no_ipv6_prefix_list_ge_le_cmd); - install_element (CONFIG_NODE, &no_ipv6_prefix_list_le_cmd); - install_element (CONFIG_NODE, &no_ipv6_prefix_list_le_ge_cmd); - install_element (CONFIG_NODE, &no_ipv6_prefix_list_seq_cmd); - install_element (CONFIG_NODE, &no_ipv6_prefix_list_seq_ge_cmd); - install_element (CONFIG_NODE, &no_ipv6_prefix_list_seq_ge_le_cmd); - install_element (CONFIG_NODE, &no_ipv6_prefix_list_seq_le_cmd); - install_element (CONFIG_NODE, &no_ipv6_prefix_list_seq_le_ge_cmd); + install_element (CONFIG_NODE, &no_ipv6_prefix_list_all_cmd); install_element (CONFIG_NODE, &ipv6_prefix_list_description_cmd); install_element (CONFIG_NODE, &no_ipv6_prefix_list_description_cmd); install_element (CONFIG_NODE, &no_ipv6_prefix_list_description_comment_cmd); install_element (CONFIG_NODE, &ipv6_prefix_list_sequence_number_cmd); - install_element (CONFIG_NODE, &no_ipv6_prefix_list_sequence_number_cmd); install_element (VIEW_NODE, &show_ipv6_prefix_list_cmd); - install_element (VIEW_NODE, &show_ipv6_prefix_list_name_cmd); - install_element (VIEW_NODE, &show_ipv6_prefix_list_name_seq_cmd); install_element (VIEW_NODE, &show_ipv6_prefix_list_prefix_cmd); - install_element (VIEW_NODE, &show_ipv6_prefix_list_prefix_longer_cmd); - install_element (VIEW_NODE, &show_ipv6_prefix_list_prefix_first_match_cmd); install_element (VIEW_NODE, &show_ipv6_prefix_list_summary_cmd); - install_element (VIEW_NODE, &show_ipv6_prefix_list_summary_name_cmd); install_element (VIEW_NODE, &show_ipv6_prefix_list_detail_cmd); - install_element (VIEW_NODE, &show_ipv6_prefix_list_detail_name_cmd); install_element (ENABLE_NODE, &clear_ipv6_prefix_list_cmd); - install_element (ENABLE_NODE, &clear_ipv6_prefix_list_name_cmd); - install_element (ENABLE_NODE, &clear_ipv6_prefix_list_name_prefix_cmd); } void From f787d7a0b3f84c9dd7f858f73c8f920bed111098 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Fri, 18 Nov 2016 14:05:49 +0100 Subject: [PATCH 07/12] bgpd: (demo) apply some DEFPY() (This was intended as further demonstration of the DEFPY code, but it might as well go into the tree.) Signed-off-by: David Lamparter --- bgpd/Makefile.am | 5 +++++ bgpd/bgp_debug.c | 37 ++++++++++++++----------------------- bgpd/bgp_vty.c | 40 +++++++++++----------------------------- 3 files changed, 30 insertions(+), 52 deletions(-) diff --git a/bgpd/Makefile.am b/bgpd/Makefile.am index a57a66488f..f096f0ff11 100644 --- a/bgpd/Makefile.am +++ b/bgpd/Makefile.am @@ -1,6 +1,8 @@ ## Process this file with automake to produce Makefile.in. AUTOMAKE_OPTIONS = subdir-objects +include ../common.am + if ENABLE_BGP_VNC #o file to keep linker happy BGP_VNC_RFP_LIB=rfapi/rfapi_descriptor_rfp_utils.o @top_builddir@/$(LIBRFP)/librfp.a @@ -116,5 +118,8 @@ examplesdir = $(exampledir) dist_examples_DATA = bgpd.conf.sample bgpd.conf.sample2 \ bgpd.conf.vnc.sample +bgp_vty.o: bgp_vty_clippy.c +bgp_debug.o: bgp_debug_clippy.c + EXTRA_DIST = BGP4-MIB.txt diff --git a/bgpd/bgp_debug.c b/bgpd/bgp_debug.c index a39ec90cc6..710a8b6a32 100644 --- a/bgpd/bgp_debug.c +++ b/bgpd/bgp_debug.c @@ -299,7 +299,7 @@ bgp_debug_list_conf_print (struct vty *vty, const char *desc, struct list *list) } static void -bgp_debug_list_add_entry(struct list *list, const char *host, struct prefix *p) +bgp_debug_list_add_entry(struct list *list, const char *host, const struct prefix *p) { struct bgp_debug_filter *filter; @@ -313,7 +313,8 @@ bgp_debug_list_add_entry(struct list *list, const char *host, struct prefix *p) else if (p) { filter->host = NULL; - filter->p = p; + filter->p = prefix_new(); + prefix_copy (filter->p, p); } listnode_add(list, filter); @@ -347,7 +348,7 @@ bgp_debug_list_remove_entry(struct list *list, const char *host, struct prefix * } static int -bgp_debug_list_has_entry(struct list *list, const char *host, struct prefix *p) +bgp_debug_list_has_entry(struct list *list, const char *host, const struct prefix *p) { struct bgp_debug_filter *filter; struct listnode *node, *nnode; @@ -898,10 +899,14 @@ DEFUN (no_debug_bgp_keepalive_peer, return CMD_SUCCESS; } +#ifndef VTYSH_EXTRACT_PL +#include "bgp_debug_clippy.c" +#endif + /* debug bgp bestpath */ -DEFUN (debug_bgp_bestpath_prefix, +DEFPY (debug_bgp_bestpath_prefix, debug_bgp_bestpath_prefix_cmd, - "debug bgp bestpath ", + "debug bgp bestpath $bestpath", DEBUG_STR BGP_STR "BGP bestpath\n" @@ -909,30 +914,16 @@ DEFUN (debug_bgp_bestpath_prefix, "IPv6 prefix\n") { - int idx_ipv4_ipv6_prefixlen = 3; - struct prefix *argv_p; - int ret; - - argv_p = prefix_new(); - ret = str2prefix (argv[idx_ipv4_ipv6_prefixlen]->arg, argv_p); - if (!ret) - { - prefix_free(argv_p); - vty_out (vty, "%% Malformed Prefix%s", VTY_NEWLINE); - return CMD_WARNING; - } - - if (!bgp_debug_bestpath_prefixes) bgp_debug_bestpath_prefixes = list_new (); - if (bgp_debug_list_has_entry(bgp_debug_bestpath_prefixes, NULL, argv_p)) + if (bgp_debug_list_has_entry(bgp_debug_bestpath_prefixes, NULL, bestpath)) { - vty_out (vty, "BGP bestptah debugging is already enabled for %s%s", argv[idx_ipv4_ipv6_prefixlen]->arg, VTY_NEWLINE); + vty_out (vty, "BGP bestpath debugging is already enabled for %s%s", bestpath_str, VTY_NEWLINE); return CMD_SUCCESS; } - bgp_debug_list_add_entry(bgp_debug_bestpath_prefixes, NULL, argv_p); + bgp_debug_list_add_entry(bgp_debug_bestpath_prefixes, NULL, bestpath); if (vty->node == CONFIG_NODE) { @@ -941,7 +932,7 @@ DEFUN (debug_bgp_bestpath_prefix, else { TERM_DEBUG_ON (bestpath, BESTPATH); - vty_out (vty, "BGP bestpath debugging is on for %s%s", argv[idx_ipv4_ipv6_prefixlen]->arg, VTY_NEWLINE); + vty_out (vty, "BGP bestpath debugging is on for %s%s", bestpath_str, VTY_NEWLINE); } return CMD_SUCCESS; diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index f5f538de95..86b8025d2e 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -777,6 +777,10 @@ bgp_clear_star_soft_out (struct vty *vty, const char *name) } +#ifndef VTYSH_EXTRACT_PL +#include "bgp_vty_clippy.c" +#endif + /* BGP global configuration. */ DEFUN (bgp_multiple_instance_func, @@ -993,7 +997,7 @@ DEFUN (no_router_bgp, /* BGP router-id. */ -DEFUN (bgp_router_id, +DEFPY (bgp_router_id, bgp_router_id_cmd, "bgp router-id A.B.C.D", BGP_STR @@ -1001,23 +1005,11 @@ DEFUN (bgp_router_id, "Manually configured router identifier\n") { VTY_DECLVAR_CONTEXT(bgp, bgp); - int idx_ipv4 = 2; - int ret; - struct in_addr id; - - ret = inet_aton (argv[idx_ipv4]->arg, &id); - if (! ret) - { - vty_out (vty, "%% Malformed bgp router identifier%s", VTY_NEWLINE); - return CMD_WARNING; - } - - bgp_router_id_static_set (bgp, id); - + bgp_router_id_static_set (bgp, router_id); return CMD_SUCCESS; } -DEFUN (no_bgp_router_id, +DEFPY (no_bgp_router_id, no_bgp_router_id_cmd, "no bgp router-id [A.B.C.D]", NO_STR @@ -1026,28 +1018,18 @@ DEFUN (no_bgp_router_id, "Manually configured router identifier\n") { VTY_DECLVAR_CONTEXT(bgp, bgp); - int idx_router_id = 3; - int ret; - struct in_addr id; - if (argc > idx_router_id) + if (router_id_str) { - ret = inet_aton (argv[idx_router_id]->arg, &id); - if (! ret) - { - vty_out (vty, "%% Malformed BGP router identifier%s", VTY_NEWLINE); - return CMD_WARNING; - } - - if (! IPV4_ADDR_SAME (&bgp->router_id_static, &id)) + if (! IPV4_ADDR_SAME (&bgp->router_id_static, &router_id)) { vty_out (vty, "%% BGP router-id doesn't match%s", VTY_NEWLINE); return CMD_WARNING; } } - id.s_addr = 0; - bgp_router_id_static_set (bgp, id); + router_id.s_addr = 0; + bgp_router_id_static_set (bgp, router_id); return CMD_SUCCESS; } From 4d85f868a515679b983b95e5793df988a048a545 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Wed, 14 Jun 2017 17:34:57 +0200 Subject: [PATCH 08/12] lib: fix CLI parser memleak Signed-off-by: David Lamparter --- lib/command_parse.y | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/command_parse.y b/lib/command_parse.y index 77e4e543aa..3337481094 100644 --- a/lib/command_parse.y +++ b/lib/command_parse.y @@ -191,7 +191,7 @@ start: varname_token: '$' WORD { - $$ = XSTRDUP (MTYPE_LEX, $2); + $$ = $2; } | /* empty */ { From 8400033687339f21952c58f503aa30de0e4f31e3 Mon Sep 17 00:00:00 2001 From: Martin Winter Date: Tue, 27 Jun 2017 18:08:55 -0700 Subject: [PATCH 09/12] doc: Update to reflect Python Development Library dependency for all builds Signed-off-by: Martin Winter --- doc/Building_FRR_on_CentOS6.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/doc/Building_FRR_on_CentOS6.md b/doc/Building_FRR_on_CentOS6.md index 9f40418fff..d88f8144ae 100644 --- a/doc/Building_FRR_on_CentOS6.md +++ b/doc/Building_FRR_on_CentOS6.md @@ -46,8 +46,7 @@ Install newer version of autoconf and automake (Package versions are too old) sudo make install cd .. -Install `Python 2.7` in parallel to default 2.6 (needed for `make check` to -run unittests). +Install `Python 2.7` in parallel to default 2.6 Make sure you've install EPEL (`epel-release` as above). Then install current `python2.7` and `pytest` From 4448b4daec8657dafe8b8f8167127f31d6928ff1 Mon Sep 17 00:00:00 2001 From: Martin Winter Date: Tue, 27 Jun 2017 18:09:38 -0700 Subject: [PATCH 10/12] debian: python3-dev is now a build requirement for main package Signed-off-by: Martin Winter --- debian/control | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debian/control b/debian/control index 3982aa41be..d2b2e7cea6 100644 --- a/debian/control +++ b/debian/control @@ -3,7 +3,7 @@ Section: net Priority: optional Maintainer: Christian Hammers Uploaders: Florian Weimer -Build-Depends: debhelper (>= 7.0.50~), libncurses5-dev, libreadline-dev, texlive-latex-base, texlive-generic-recommended, libpam0g-dev | libpam-dev, libcap-dev, texinfo (>= 4.7), imagemagick, ghostscript, groff, po-debconf, autotools-dev, hardening-wrapper, libpcre3-dev, gawk, chrpath, libsnmp-dev, git, dh-autoreconf, libjson0, libjson0-dev, dh-systemd, libsystemd-dev, python-ipaddr, bison, flex, libc-ares-dev +Build-Depends: debhelper (>= 7.0.50~), libncurses5-dev, libreadline-dev, texlive-latex-base, texlive-generic-recommended, libpam0g-dev | libpam-dev, libcap-dev, texinfo (>= 4.7), imagemagick, ghostscript, groff, po-debconf, autotools-dev, hardening-wrapper, libpcre3-dev, gawk, chrpath, libsnmp-dev, git, dh-autoreconf, libjson0, libjson0-dev, dh-systemd, libsystemd-dev, python-ipaddr, bison, flex, libc-ares-dev, python3-dev Standards-Version: 3.9.6 Homepage: http://www.frr.net/ XS-Testsuite: autopkgtest From 6f59986bd41a3611595ff2b0b5b85527e41aabac Mon Sep 17 00:00:00 2001 From: Martin Winter Date: Tue, 27 Jun 2017 18:10:29 -0700 Subject: [PATCH 11/12] redhat: python-devel is now a build requirement for main package Signed-off-by: Martin Winter --- redhat/frr.spec.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/redhat/frr.spec.in b/redhat/frr.spec.in index 71ee307c96..6bf4c37967 100644 --- a/redhat/frr.spec.in +++ b/redhat/frr.spec.in @@ -142,7 +142,7 @@ Requires(preun): /sbin/install-info Requires(post): /sbin/install-info BuildRequires: gcc texi2html texinfo patch libcap-devel groff BuildRequires: readline readline-devel ncurses ncurses-devel -BuildRequires: json-c-devel bison >= 2.7 flex make +BuildRequires: json-c-devel bison >= 2.7 flex make python-devel >= 2.7 Requires: ncurses json-c initscripts %if %{with_pam} BuildRequires: pam-devel From 01aff72e26c51a36d34636b96434589bc621336c Mon Sep 17 00:00:00 2001 From: Martin Winter Date: Tue, 27 Jun 2017 19:49:38 -0700 Subject: [PATCH 12/12] redhat: On CentOS/RedHat 6, use python27-devel from iuscommunity.org FRR requires now Python 2.7 development libraries, but CentOS 6 does not provide this (not in main and not in EPEL library) This is only a build limitation. Signed-off-by: Martin Winter --- redhat/frr.spec.in | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/redhat/frr.spec.in b/redhat/frr.spec.in index 6bf4c37967..bf4a362972 100644 --- a/redhat/frr.spec.in +++ b/redhat/frr.spec.in @@ -142,7 +142,13 @@ Requires(preun): /sbin/install-info Requires(post): /sbin/install-info BuildRequires: gcc texi2html texinfo patch libcap-devel groff BuildRequires: readline readline-devel ncurses ncurses-devel -BuildRequires: json-c-devel bison >= 2.7 flex make python-devel >= 2.7 +BuildRequires: json-c-devel bison >= 2.7 flex make +%if 0%{?rhel} && 0%{?rhel} < 7 +#python27-devel is available from ius community repo for RedHat/CentOS 6 +BuildRequires: python27-devel +%else +BuildRequires: python-devel >= 2.7 +%endif Requires: ncurses json-c initscripts %if %{with_pam} BuildRequires: pam-devel