summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bgpd/bgp_vty.c8
-rwxr-xr-xconfigure.ac129
-rw-r--r--doc/developer/building-frr-for-centos6.rst5
-rw-r--r--doc/developer/building-frr-for-debian8.rst4
-rw-r--r--doc/developer/building-frr-for-debian9.rst4
-rw-r--r--doc/developer/building-frr-for-fedora.rst4
-rw-r--r--doc/developer/building-frr-for-freebsd10.rst2
-rw-r--r--doc/developer/building-frr-for-freebsd11.rst2
-rw-r--r--doc/developer/building-frr-for-freebsd9.rst4
-rw-r--r--doc/developer/building-frr-for-netbsd6.rst9
-rw-r--r--doc/developer/building-frr-for-netbsd7.rst9
-rw-r--r--doc/developer/building-frr-for-ubuntu1404.rst2
-rw-r--r--doc/developer/building-frr-for-ubuntu1604.rst2
-rw-r--r--doc/developer/building-frr-for-ubuntu1804.rst2
-rw-r--r--doc/developer/packaging-redhat.rst2
-rw-r--r--doc/subdir.am11
-rw-r--r--doc/user/installation.rst21
-rw-r--r--eigrpd/eigrp_routemap.c24
-rw-r--r--eigrpd/eigrp_vty.c4
-rw-r--r--lib/compiler.h22
-rw-r--r--lib/log.h19
-rw-r--r--lib/nexthop_group.c19
-rw-r--r--lib/ntop.c174
-rw-r--r--lib/plist.c2
-rw-r--r--lib/printf/printf-pos.c1
-rw-r--r--lib/sockopt.c6
-rw-r--r--lib/subdir.am1
-rw-r--r--lib/thread.c2
-rw-r--r--lib/zclient.h44
-rw-r--r--lib/zebra.h73
-rw-r--r--m4/.gitignore1
-rw-r--r--m4/ax_python.m4284
-rw-r--r--pbrd/pbr_nht.c29
-rw-r--r--pbrd/pbr_vty.c27
-rw-r--r--pimd/mtracebis.c4
-rw-r--r--pimd/pim_cmd.c12
-rw-r--r--pimd/pim_mroute.c12
-rw-r--r--pimd/pim_nht.c2
-rw-r--r--pimd/pim_rp.c2
-rw-r--r--pimd/pim_rpf.c11
-rw-r--r--pimd/pim_rpf.h4
-rw-r--r--pimd/pim_upstream.c4
-rw-r--r--pimd/pim_vxlan.c2
-rw-r--r--pimd/pim_zlookup.c19
-rw-r--r--redhat/frr.spec.in8
-rw-r--r--sharpd/sharp_vty.c4
-rw-r--r--sharpd/sharp_zebra.c4
-rw-r--r--tests/.gitignore1
-rw-r--r--tests/lib/test_ntop.c87
-rw-r--r--tests/lib/test_ntop.py6
-rw-r--r--tests/subdir.am8
-rw-r--r--vtysh/vtysh.c8
-rw-r--r--zebra/zebra_rnh.c50
53 files changed, 871 insertions, 329 deletions
diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c
index 7dc3f02b0d..43d0d93520 100644
--- a/bgpd/bgp_vty.c
+++ b/bgpd/bgp_vty.c
@@ -217,6 +217,10 @@ int argv_find_and_parse_afi(struct cmd_token **argv, int argc, int *index,
ret = 1;
if (afi)
*afi = AFI_IP6;
+ } else if (argv_find(argv, argc, "l2vpn", index)) {
+ ret = 1;
+ if (afi)
+ *afi = AFI_L2VPN;
}
return ret;
}
@@ -260,6 +264,10 @@ int argv_find_and_parse_safi(struct cmd_token **argv, int argc, int *index,
ret = 1;
if (safi)
*safi = SAFI_MPLS_VPN;
+ } else if (argv_find(argv, argc, "evpn", index)) {
+ ret = 1;
+ if (safi)
+ *safi = SAFI_EVPN;
} else if (argv_find(argv, argc, "flowspec", index)) {
ret = 1;
if (safi)
diff --git a/configure.ac b/configure.ac
index e94cb541ec..77d5ee1555 100755
--- a/configure.ac
+++ b/configure.ac
@@ -183,15 +183,17 @@ AC_DEFUN([AC_LINK_IFELSE_FLAGS], [{
AC_LINK_IFELSE(
[$3],
[
- AC_MSG_RESULT([yes])
CFLAGS="$ac_cflags_save"
LIBS="$ac_libs_save"
- $5
+ m4_default([$5], [
+ AC_MSG_RESULT([yes])
+ ])
], [
- AC_MSG_RESULT([no])
CFLAGS="$ac_cflags_save"
LIBS="$ac_libs_save"
- $4
+ m4_default([$4], [
+ AC_MSG_RESULT([no])
+ ])
])
AC_LANG_POP([C])
}])
@@ -609,92 +611,30 @@ AM_CONDITIONAL([FPM], [test "x$enable_fpm" = "xyes"])
# Python for clippy
#
-AC_DEFUN([FRR_PYTHON_CHECK_WORKING], [
- AC_MSG_CHECKING([whether we found a working Python version])
- AC_LINK_IFELSE_FLAGS([$PYTHON_CFLAGS], [$PYTHON_LIBS], [AC_LANG_PROGRAM([
-#include <Python.h>
-#if PY_VERSION_HEX < 0x02070000
-#error python too old
-#endif
-int main(void);
-],
-[
-{
- Py_Initialize();
- return 0;
-}
-])], [
- # some python installs are missing the zlib dependency...
- PYTHON_LIBS="${PYTHON_LIBS} -lz"
- AC_LINK_IFELSE_FLAGS([$PYTHON_CFLAGS], [$PYTHON_LIBS], [AC_LANG_PROGRAM([
-#include <Python.h>
-#if PY_VERSION_HEX < 0x02070000
-#error python too old
-#endif
-int main(void);
-],
-[
-{
- Py_Initialize();
- return 0;
-}
-])], [
- m4_if([$1], [], [
- PYTHONCONFIG=""
- unset PYTHON_LIBS
- unset PYTHON_CFLAGS
- ], [$1])
- ])
- ])
-])
-
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.6 > 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 \
- python3.6-config \
- python3.5-config \
- python3.4-config \
- python3.3-config \
- python3.2-config \
- python2.7-config ])
- if test -n "$PYTHONCONFIG"; then
- PYTHON_CFLAGS="`\"${PYTHONCONFIG}\" --includes`"
- PYTHON_LIBS="`\"${PYTHONCONFIG}\" --ldflags`"
-
- FRR_PYTHON_CHECK_WORKING([])
- fi
+ FRR_PYTHON_DEV
+], [
+ FRR_PYTHON
+])
- if test -z "$PYTHONCONFIG"; then
- PKG_CHECK_MODULES([PYTHON], [python-3.6], [], [
- 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])
- ])])])])])])
+FRR_PYTHON_MODULES([pytest])
+if test "${enable_doc}" != "no"; then
+ FRR_PYTHON_MODULES([sphinx], , [
+ if test "${enable_doc}" = "yes"; then
+ AC_MSG_ERROR([Documentation was explicitly requested with --enable-doc but sphinx is not available for $PYTHON. Please disable docs or install sphinx.])
+ fi
+ ])
+fi
+AM_CONDITIONAL([DOC], [test "${enable_doc}" != "no" -a "$frr_py_mod_sphinx" != "false"])
+AM_CONDITIONAL([DOC_HTML], [test "${enable_doc_html}" = "yes"])
- FRR_PYTHON_CHECK_WORKING([
- AC_MSG_FAILURE([could not find python-config or pkg-config python, please install Python development files from libpython-dev or similar])
- ])
- fi
+FRR_PYTHON_MOD_EXEC([sphinx], [--version], [
+ PYSPHINX="-m sphinx"
+], [
+ PYSPHINX="-c 'import sys; from sphinx import main; sys.exit(main(sys.argv))'"
])
-AC_SUBST([PYTHON_CFLAGS])
-AC_SUBST([PYTHON_LIBS])
+AC_SUBST([PYSPHINX])
#
# Logic for protobuf support.
@@ -1507,16 +1447,6 @@ FRR_INCLUDES
#endif
])dnl
-dnl disable doc check
-AC_CHECK_PROGS([SPHINXBUILD], [sphinx-build sphinx-build3 sphinx-build2], [/bin/false])
-if test "$SPHINXBUILD" = "/bin/false"; then
- if test "${enable_doc}" = "yes"; then
- AC_MSG_ERROR([Documentation was explicitly requested with --enable-doc but sphinx-build is not available. Please disable docs or install sphinx.])
- fi
-fi
-AM_CONDITIONAL([DOC], [test "${enable_doc}" != "no" -a "$SPHINXBUILD" != "/bin/false"])
-AM_CONDITIONAL([DOC_HTML], [test "${enable_doc_html}" = "yes"])
-
dnl --------------------
dnl Daemon disable check
dnl --------------------
@@ -1666,6 +1596,7 @@ int main(void);
return 0;
}
])], [
+ AC_MSG_RESULT([no])
AC_MSG_ERROR([--enable-snmp given but not usable])])
case "${enable_snmp}" in
yes)
@@ -2356,7 +2287,9 @@ zebra protobuf enabled : ${enable_protobuf:-no}
The above user and group must have read/write access to the state file
directory and to the config files in the config file directory."
-if test "${enable_doc}" != "no";then
- AS_IF([test "$SPHINXBUILD" = /bin/false],
- AC_MSG_WARN([sphinx-build is missing but required to build documentation]))
+if test "${enable_doc}" != "no" -a "$frr_py_mod_sphinx" = false; then
+ AC_MSG_WARN([sphinx is missing but required to build documentation])
+fi
+if test "$frr_py_mod_pytest" = false; then
+ AC_MSG_WARN([pytest is missing, unit tests cannot be performed])
fi
diff --git a/doc/developer/building-frr-for-centos6.rst b/doc/developer/building-frr-for-centos6.rst
index f1ec2ad3ea..ee0ffc2bf7 100644
--- a/doc/developer/building-frr-for-centos6.rst
+++ b/doc/developer/building-frr-for-centos6.rst
@@ -163,10 +163,9 @@ an example.)
--disable-ldpd \
--enable-fpm \
--with-pkg-git-version \
- --with-pkg-extra-version=-MyOwnFRRVersion \
- SPHINXBUILD=sphinx-build2.7
+ --with-pkg-extra-version=-MyOwnFRRVersion
make
- make check PYTHON=/usr/bin/python2.7
+ make check
sudo make install
Create empty FRR configuration files
diff --git a/doc/developer/building-frr-for-debian8.rst b/doc/developer/building-frr-for-debian8.rst
index a26d055bc2..76f927853d 100644
--- a/doc/developer/building-frr-for-debian8.rst
+++ b/doc/developer/building-frr-for-debian8.rst
@@ -16,7 +16,7 @@ Add packages:
::
sudo apt-get install git autoconf automake libtool make \
- libreadline-dev texinfo libjson-c-dev pkg-config bison flex python-pip \
+ libreadline-dev texinfo libjson-c-dev pkg-config bison flex python3-pip \
libc-ares-dev python3-dev python3-sphinx build-essential libsystemd-dev \
libsnmp-dev
@@ -24,7 +24,7 @@ Install newer pytest (>3.0) from pip
::
- sudo pip install pytest
+ sudo pip3 install pytest
.. include:: building-libyang.rst
diff --git a/doc/developer/building-frr-for-debian9.rst b/doc/developer/building-frr-for-debian9.rst
index 2c5a9681af..e58c59f451 100644
--- a/doc/developer/building-frr-for-debian9.rst
+++ b/doc/developer/building-frr-for-debian9.rst
@@ -9,8 +9,8 @@ Add packages:
::
sudo apt-get install git autoconf automake libtool make \
- libreadline-dev texinfo libjson-c-dev pkg-config bison flex python-pip \
- libc-ares-dev python3-dev python-pytest python3-sphinx build-essential \
+ libreadline-dev texinfo libjson-c-dev pkg-config bison flex \
+ libc-ares-dev python3-dev python3-pytest python3-sphinx build-essential \
libsnmp-dev libsystemd-dev
.. include:: building-libyang.rst
diff --git a/doc/developer/building-frr-for-fedora.rst b/doc/developer/building-frr-for-fedora.rst
index 204c185f56..d11da2d647 100644
--- a/doc/developer/building-frr-for-fedora.rst
+++ b/doc/developer/building-frr-for-fedora.rst
@@ -13,8 +13,8 @@ Installing Dependencies
sudo dnf install git autoconf automake libtool make \
readline-devel texinfo net-snmp-devel groff pkgconfig json-c-devel \
- pam-devel pytest bison flex c-ares-devel python3-devel python2-sphinx \
- perl-core patch
+ pam-devel python3-pytest bison flex c-ares-devel python3-devel \
+ python3-sphinx perl-core patch
.. include:: building-libyang.rst
diff --git a/doc/developer/building-frr-for-freebsd10.rst b/doc/developer/building-frr-for-freebsd10.rst
index 86c44f4d90..e85cb80053 100644
--- a/doc/developer/building-frr-for-freebsd10.rst
+++ b/doc/developer/building-frr-for-freebsd10.rst
@@ -17,7 +17,7 @@ is first package install and asked)
::
pkg install git autoconf automake libtool gmake json-c pkgconf \
- bison flex py27-pytest c-ares python3 py-sphinx
+ bison flex py36-pytest c-ares python3.6 py36-sphinx
Make sure there is no /usr/bin/flex preinstalled (and use the newly
installed in /usr/local/bin): (FreeBSD frequently provides a older flex
diff --git a/doc/developer/building-frr-for-freebsd11.rst b/doc/developer/building-frr-for-freebsd11.rst
index 5e56c8cd7a..b97538b763 100644
--- a/doc/developer/building-frr-for-freebsd11.rst
+++ b/doc/developer/building-frr-for-freebsd11.rst
@@ -17,7 +17,7 @@ is first package install and asked)
.. code-block:: shell
pkg install git autoconf automake libtool gmake json-c pkgconf \
- bison flex py27-pytest c-ares python3 py36-sphinx texinfo
+ bison flex py36-pytest c-ares python3.6 py36-sphinx texinfo
Make sure there is no /usr/bin/flex preinstalled (and use the newly
installed in /usr/local/bin): (FreeBSD frequently provides a older flex
diff --git a/doc/developer/building-frr-for-freebsd9.rst b/doc/developer/building-frr-for-freebsd9.rst
index 59241d1d13..1e97749795 100644
--- a/doc/developer/building-frr-for-freebsd9.rst
+++ b/doc/developer/building-frr-for-freebsd9.rst
@@ -17,8 +17,8 @@ is first package install and asked)
::
pkg install -y git autoconf automake libtool gmake \
- pkgconf texinfo json-c bison flex py27-pytest c-ares \
- python3 py-sphinx libexecinfo
+ pkgconf texinfo json-c bison flex py36-pytest c-ares \
+ python3 py36-sphinx libexecinfo
Make sure there is no /usr/bin/flex preinstalled (and use the newly
installed in /usr/local/bin): (FreeBSD frequently provides a older flex
diff --git a/doc/developer/building-frr-for-netbsd6.rst b/doc/developer/building-frr-for-netbsd6.rst
index 49091c49b4..e50d11130a 100644
--- a/doc/developer/building-frr-for-netbsd6.rst
+++ b/doc/developer/building-frr-for-netbsd6.rst
@@ -23,7 +23,7 @@ Add packages:
::
sudo pkg_add git autoconf automake libtool gmake openssl \
- pkg-config json-c python27 py27-test python35 py-sphinx
+ pkg-config json-c py36-test python36 py36-sphinx
Install SSL Root Certificates (for git https access):
@@ -33,13 +33,6 @@ Install SSL Root Certificates (for git https access):
sudo touch /etc/openssl/openssl.cnf
sudo mozilla-rootcerts install
-Select default Python and py.test
-
-::
-
- sudo ln -s /usr/pkg/bin/python2.7 /usr/bin/python
- sudo ln -s /usr/pkg/bin/py.test-2.7 /usr/bin/py.test
-
.. include:: building-libyang.rst
Get FRR, compile it and install it (from Git)
diff --git a/doc/developer/building-frr-for-netbsd7.rst b/doc/developer/building-frr-for-netbsd7.rst
index 64c462a5c8..32d1145edc 100644
--- a/doc/developer/building-frr-for-netbsd7.rst
+++ b/doc/developer/building-frr-for-netbsd7.rst
@@ -14,7 +14,7 @@ Install required packages
::
sudo pkgin install git autoconf automake libtool gmake openssl \
- pkg-config json-c python27 py27-test python35 py-sphinx
+ pkg-config json-c python36 py36-test py36-sphinx
Install SSL Root Certificates (for git https access):
@@ -24,13 +24,6 @@ Install SSL Root Certificates (for git https access):
sudo touch /etc/openssl/openssl.cnf
sudo mozilla-rootcerts install
-Select default Python and py.test
-
-::
-
- sudo ln -s /usr/pkg/bin/python2.7 /usr/bin/python
- sudo ln -s /usr/pkg/bin/py.test-2.7 /usr/bin/py.test
-
.. include:: building-libyang.rst
Get FRR, compile it and install it (from Git)
diff --git a/doc/developer/building-frr-for-ubuntu1404.rst b/doc/developer/building-frr-for-ubuntu1404.rst
index 6e2765c1c8..569b3bded1 100644
--- a/doc/developer/building-frr-for-ubuntu1404.rst
+++ b/doc/developer/building-frr-for-ubuntu1404.rst
@@ -12,7 +12,7 @@ Installing Dependencies
apt-get update
apt-get install \
git autoconf automake libtool make libreadline-dev texinfo \
- pkg-config libpam0g-dev libjson-c-dev bison flex python-pytest \
+ pkg-config libpam0g-dev libjson-c-dev bison flex python3-pytest \
libc-ares-dev python3-dev python3-sphinx install-info build-essential \
libsnmp-dev perl
diff --git a/doc/developer/building-frr-for-ubuntu1604.rst b/doc/developer/building-frr-for-ubuntu1604.rst
index a9a0a2f733..03852a62aa 100644
--- a/doc/developer/building-frr-for-ubuntu1604.rst
+++ b/doc/developer/building-frr-for-ubuntu1604.rst
@@ -12,7 +12,7 @@ Installing Dependencies
apt-get update
apt-get install \
git autoconf automake libtool make libreadline-dev texinfo \
- pkg-config libpam0g-dev libjson-c-dev bison flex python-pytest \
+ pkg-config libpam0g-dev libjson-c-dev bison flex python3-pytest \
libc-ares-dev python3-dev libsystemd-dev python-ipaddress python3-sphinx \
install-info build-essential libsystemd-dev libsnmp-dev perl
diff --git a/doc/developer/building-frr-for-ubuntu1804.rst b/doc/developer/building-frr-for-ubuntu1804.rst
index 8bdc2b9c76..96c0efe02a 100644
--- a/doc/developer/building-frr-for-ubuntu1804.rst
+++ b/doc/developer/building-frr-for-ubuntu1804.rst
@@ -12,7 +12,7 @@ Installing Dependencies
sudo apt update
sudo apt-get install \
git autoconf automake libtool make libreadline-dev texinfo \
- pkg-config libpam0g-dev libjson-c-dev bison flex python-pytest \
+ pkg-config libpam0g-dev libjson-c-dev bison flex python3-pytest \
libc-ares-dev python3-dev libsystemd-dev python-ipaddress python3-sphinx \
install-info build-essential libsystemd-dev libsnmp-dev perl
diff --git a/doc/developer/packaging-redhat.rst b/doc/developer/packaging-redhat.rst
index f6b9931156..d344046148 100644
--- a/doc/developer/packaging-redhat.rst
+++ b/doc/developer/packaging-redhat.rst
@@ -32,7 +32,7 @@ Tested on CentOS 6, CentOS 7 and Fedora 24.
cd frr
./bootstrap.sh
- ./configure --with-pkg-extra-version=-MyRPMVersion SPHINXBUILD=sphinx-build2.7
+ ./configure --with-pkg-extra-version=-MyRPMVersion
make dist
.. note::
diff --git a/doc/subdir.am b/doc/subdir.am
index 7d3792bf2b..a1297a4f81 100644
--- a/doc/subdir.am
+++ b/doc/subdir.am
@@ -4,7 +4,6 @@
# You can set these variables from the command line.
SPHINXOPTS ?=
-SPHINXBUILD ?= sphinx-build
PAPER ?=
# Internal variables.
@@ -32,20 +31,20 @@ am__v_MAKEINFO_1 =
doc/%/_build/.doctrees/environment.pickle:
$(AM_V_SPHINX) ( \
subdoc="$@"; subdoc="$${subdoc#doc/}"; subdoc="doc/$${subdoc%%/*}"; \
- $(SPHINXBUILD) -a -q -b text -d "$${subdoc}/_build/.doctrees" \
+ $(PYTHON) $(PYSPHINX) -a -q -b text -d "$${subdoc}/_build/.doctrees" \
$(ALLSPHINXOPTS) "$(top_srcdir)/$${subdoc}" "$${subdoc}/_build/text" \
)
doc/%/_build/html/.buildinfo: doc/%/_build/.doctrees/environment.pickle
$(AM_V_SPHINX) ( \
subdoc="$@"; subdoc="$${subdoc#doc/}"; subdoc="doc/$${subdoc%%/*}"; \
- $(SPHINXBUILD) -q -b html -d "$${subdoc}/_build/.doctrees" \
+ $(PYTHON) $(PYSPHINX) -q -b html -d "$${subdoc}/_build/.doctrees" \
$(ALLSPHINXOPTS) "$(top_srcdir)/$${subdoc}" "$${subdoc}/_build/html" \
)
.PRECIOUS: doc/%/_build/texinfo/frr.texi
doc/%/_build/texinfo/frr.texi: doc/%/_build/.doctrees/environment.pickle
$(AM_V_SPHINX) ( \
subdoc="$@"; subdoc="$${subdoc#doc/}"; subdoc="doc/$${subdoc%%/*}"; \
- $(SPHINXBUILD) -q -b texinfo -d "$${subdoc}/_build/.doctrees" \
+ $(PYTHON) $(PYSPHINX) -q -b texinfo -d "$${subdoc}/_build/.doctrees" \
$(ALLSPHINXOPTS) "$(top_srcdir)/$${subdoc}" "$${subdoc}/_build/texinfo" \
)
doc/%/_build/texinfo/frr.info: doc/%/_build/texinfo/frr.texi
@@ -54,7 +53,7 @@ doc/%/_build/man/man.stamp: doc/%/_build/.doctrees/environment.pickle
$(AM_V_SPHINX) ( \
subdoc="$@"; subdoc="$${subdoc#doc/}"; subdoc="doc/$${subdoc%%/*}"; \
$(MKDIR_P) "$${subdoc}/_build/man"; touch $@.tmp; \
- $(SPHINXBUILD) -a -q -b man -d "$${subdoc}/_build/.doctrees" \
+ $(PYTHON) $(PYSPHINX) -a -q -b man -d "$${subdoc}/_build/.doctrees" \
$(ALLSPHINXOPTS) "$(top_srcdir)/$${subdoc}" "$${subdoc}/_build/man" && \
mv -f $@.tmp $@ \
)
@@ -80,7 +79,7 @@ $(M_SPHINXTARGETS): doc/%/_build/.doctrees/environment.pickle
builder="$${target##*/}"; \
subdoc="$${target#doc/}"; subdoc="doc/$${subdoc%%/*}"; \
rm -rf "$@"; \
- $(SPHINXBUILD) -q -b $${builder} -d $${subdoc}/_build/.doctrees \
+ $(PYTHON) $(PYSPHINX) -q -b $${builder} -d $${subdoc}/_build/.doctrees \
$(ALLSPHINXOPTS) $(top_srcdir)/$${subdoc} $@ \
)
diff --git a/doc/user/installation.rst b/doc/user/installation.rst
index 964297292f..6438c11413 100644
--- a/doc/user/installation.rst
+++ b/doc/user/installation.rst
@@ -347,6 +347,27 @@ compile directory:
./configure --with-libyang-pluginsdir="`pwd`/yang/libyang_plugins/.libs" \
--with-yangmodelsdir="`pwd`/yang"
+Python dependency, documentation and tests
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+FRR's documentation and basic unit tests heavily use code written in Python.
+Additionally, FRR ships Python extensions written in C which are used during
+its build process.
+
+To this extent, FRR needs the following:
+
+* an installation of CPython, preferably version 3.2 or newer (2.7 works but
+ is end of life and will stop working at some point.)
+* development files (mostly headers) for that version of CPython
+* an installation of `sphinx` for that version of CPython, to build the
+ documentation
+* an installation of `pytest` for that version of CPython, to run the unit
+ tests
+
+The `sphinx` and `pytest` dependencies can be avoided by not building
+documentation / not running ``make check``, but the CPython dependency is a
+hard dependency of the FRR build process (for the `clippy` tool.)
+
.. _least-privilege-support:
Least-Privilege Support
diff --git a/eigrpd/eigrp_routemap.c b/eigrpd/eigrp_routemap.c
index 0a00497d5a..f080ba4876 100644
--- a/eigrpd/eigrp_routemap.c
+++ b/eigrpd/eigrp_routemap.c
@@ -764,7 +764,7 @@ static struct route_map_rule_cmd route_set_tag_cmd = {
DEFUN (match_metric,
match_metric_cmd,
- "match metric <0-4294967295>",
+ "match metric (0-4294967295)",
MATCH_STR
"Match metric of route\n"
"Metric value\n")
@@ -787,7 +787,7 @@ DEFUN (no_match_metric,
}
ALIAS(no_match_metric, no_match_metric_val_cmd,
- "no match metric <0-4294967295>", NO_STR MATCH_STR
+ "no match metric (0-4294967295)", NO_STR MATCH_STR
"Match metric of route\n"
"Metric value\n")
@@ -822,7 +822,7 @@ ALIAS(no_match_interface, no_match_interface_val_cmd, "no match interface WORD",
DEFUN (match_ip_next_hop,
match_ip_next_hop_cmd,
- "match ip next-hop (<1-199>|<1300-2699>|WORD)",
+ "match ip next-hop ((1-199)|(1300-2699)|WORD)",
MATCH_STR
IP_STR
"Match next-hop address of route\n"
@@ -850,7 +850,7 @@ DEFUN (no_match_ip_next_hop,
}
ALIAS(no_match_ip_next_hop, no_match_ip_next_hop_val_cmd,
- "no match ip next-hop (<1-199>|<1300-2699>|WORD)", NO_STR MATCH_STR IP_STR
+ "no match ip next-hop ((1-199)|(1300-2699)|WORD)", NO_STR MATCH_STR IP_STR
"Match next-hop address of route\n"
"IP access-list number\n"
"IP access-list number (expanded range)\n"
@@ -895,7 +895,7 @@ ALIAS(no_match_ip_next_hop_prefix_list,
DEFUN (match_ip_address,
match_ip_address_cmd,
- "match ip address (<1-199>|<1300-2699>|WORD)",
+ "match ip address ((1-199)|(1300-2699)|WORD)",
MATCH_STR
IP_STR
"Match address of route\n"
@@ -922,7 +922,7 @@ DEFUN (no_match_ip_address,
}
ALIAS(no_match_ip_address, no_match_ip_address_val_cmd,
- "no match ip address (<1-199>|<1300-2699>|WORD)", NO_STR MATCH_STR IP_STR
+ "no match ip address ((1-199)|(1300-2699)|WORD)", NO_STR MATCH_STR IP_STR
"Match address of route\n"
"IP access-list number\n"
"IP access-list number (expanded range)\n"
@@ -966,7 +966,7 @@ ALIAS(no_match_ip_address_prefix_list, no_match_ip_address_prefix_list_val_cmd,
DEFUN (match_tag,
match_tag_cmd,
- "match tag <0-65535>",
+ "match tag (0-65535)",
MATCH_STR
"Match tag of route\n"
"Metric value\n")
@@ -987,7 +987,7 @@ DEFUN (no_match_tag,
return eigrp_route_match_delete(vty, vty->index, "tag", argv[0]);
}
-ALIAS(no_match_tag, no_match_tag_val_cmd, "no match tag <0-65535>",
+ALIAS(no_match_tag, no_match_tag_val_cmd, "no match tag (0-65535)",
NO_STR MATCH_STR
"Match tag of route\n"
"Metric value\n")
@@ -996,7 +996,7 @@ ALIAS(no_match_tag, no_match_tag_val_cmd, "no match tag <0-65535>",
DEFUN (set_metric,
set_metric_cmd,
- "set metric <0-4294967295>",
+ "set metric (0-4294967295)",
SET_STR
"Metric value for destination routing protocol\n"
"Metric value\n")
@@ -1022,7 +1022,7 @@ DEFUN (no_set_metric,
}
ALIAS(no_set_metric, no_set_metric_val_cmd,
- "no set metric (<0-4294967295>|<+/-metric>)", NO_STR SET_STR
+ "no set metric ((0-4294967295)|<+/-metric>)", NO_STR SET_STR
"Metric value for destination routing protocol\n"
"Metric value\n"
"Add or subtract metric\n")
@@ -1069,7 +1069,7 @@ ALIAS(no_set_ip_nexthop, no_set_ip_nexthop_val_cmd,
DEFUN (set_tag,
set_tag_cmd,
- "set tag <0-65535>",
+ "set tag (0-65535)",
SET_STR
"Tag value for routing protocol\n"
"Tag value\n")
@@ -1090,7 +1090,7 @@ DEFUN (no_set_tag,
return eigrp_route_set_delete(vty, vty->index, "tag", argv[0]);
}
-ALIAS(no_set_tag, no_set_tag_val_cmd, "no set tag <0-65535>", NO_STR SET_STR
+ALIAS(no_set_tag, no_set_tag_val_cmd, "no set tag (0-65535)", NO_STR SET_STR
"Tag value for routing protocol\n"
"Tag value\n")
diff --git a/eigrpd/eigrp_vty.c b/eigrpd/eigrp_vty.c
index fc5bdbdbc5..1a1634ca91 100644
--- a/eigrpd/eigrp_vty.c
+++ b/eigrpd/eigrp_vty.c
@@ -370,7 +370,7 @@ DEFUN (eigrp_metric_weights,
DEFUN (no_eigrp_metric_weights,
no_eigrp_metric_weights_cmd,
- "no metric weights <0-255> <0-255> <0-255> <0-255> <0-255>",
+ "no metric weights (0-255) (0-255) (0-255) (0-255) (0-255)",
NO_STR
"Modify metrics and parameters for advertisement\n"
"Modify metric coefficients\n"
@@ -1209,7 +1209,7 @@ DEFUN (eigrp_maximum_paths,
DEFUN (no_eigrp_maximum_paths,
no_eigrp_maximum_paths_cmd,
- "no maximum-paths <1-32>",
+ "no maximum-paths (1-32)",
NO_STR
"Forward packets over multiple paths\n"
"Number of paths\n")
diff --git a/lib/compiler.h b/lib/compiler.h
index 7509428220..9ce91e3361 100644
--- a/lib/compiler.h
+++ b/lib/compiler.h
@@ -33,6 +33,9 @@ extern "C" {
#endif
# define _CONSTRUCTOR(x) constructor(x)
# define _DEPRECATED(x) deprecated(x)
+# if __has_builtin(assume)
+# define assume(x) __builtin_assume(x)
+# endif
#elif defined(__GNUC__)
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9)
# define _RET_NONNULL , returns_nonnull
@@ -44,12 +47,28 @@ extern "C" {
#endif
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)
# define _DEPRECATED(x) deprecated(x)
+# define assume(x) do { if (!(x)) __builtin_unreachable(); } while (0)
+#endif
+#if __GNUC__ < 5
+# define __has_attribute(x) 0
#endif
#if __GNUC__ >= 7
# define _FALLTHROUGH __attribute__((fallthrough));
#endif
#endif
+#if __has_attribute(hot)
+# define _OPTIMIZE_HOT __attribute__((hot))
+#else
+# define _OPTIMIZE_HOT
+#endif
+#if __has_attribute(optimize)
+# define _OPTIMIZE_O3 __attribute__((optimize("3")))
+#else
+# define _OPTIMIZE_O3
+#endif
+#define OPTIMIZE _OPTIMIZE_O3 _OPTIMIZE_HOT
+
#if !defined(__GNUC__)
#error module code needs GCC visibility extensions
#elif __GNUC__ < 4
@@ -85,6 +104,9 @@ extern "C" {
#ifndef _DEPRECATED
#define _DEPRECATED(x) deprecated
#endif
+#ifndef assume
+#define assume(x)
+#endif
/* pure = function does not modify memory & return value is the same if
* memory hasn't changed (=> allows compiler to optimize)
diff --git a/lib/log.h b/lib/log.h
index e41a472e0d..3ef4d2f379 100644
--- a/lib/log.h
+++ b/lib/log.h
@@ -154,6 +154,25 @@ extern void zlog_hexdump(const void *mem, unsigned int len);
extern const char *zlog_sanitize(char *buf, size_t bufsz, const void *in,
size_t inlen);
+/* Note: whenever a new route-type or zserv-command is added the
+ * corresponding {command,route}_types[] table in lib/log.c MUST be
+ * updated! */
+
+/* Map a route type to a string. For example, ZEBRA_ROUTE_RIPNG -> "ripng". */
+extern const char *zebra_route_string(unsigned int route_type);
+/* Map a route type to a char. For example, ZEBRA_ROUTE_RIPNG -> 'R'. */
+extern char zebra_route_char(unsigned int route_type);
+/* Map a zserv command type to the same string,
+ * e.g. ZEBRA_INTERFACE_ADD -> "ZEBRA_INTERFACE_ADD" */
+/* Map a protocol name to its number. e.g. ZEBRA_ROUTE_BGP->9*/
+extern int proto_name2num(const char *s);
+/* Map redistribute X argument to protocol number.
+ * unlike proto_name2num, this accepts shorthands and takes
+ * an AFI value to restrict input */
+extern int proto_redistnum(int afi, const char *s);
+
+extern const char *zserv_command_string(unsigned int command);
+
extern int vzlog_test(int priority);
diff --git a/lib/nexthop_group.c b/lib/nexthop_group.c
index ed22f64494..10f610db37 100644
--- a/lib/nexthop_group.c
+++ b/lib/nexthop_group.c
@@ -308,7 +308,7 @@ static void nhgc_delete(struct nexthop_group_cmd *nhgc)
DEFINE_QOBJ_TYPE(nexthop_group_cmd)
-DEFUN_NOSH(nexthop_group, nexthop_group_cmd, "nexthop-group NAME",
+DEFUN_NOSH(nexthop_group, nexthop_group_cmd, "nexthop-group NHGNAME",
"Enter into the nexthop-group submode\n"
"Specify the NAME of the nexthop-group\n")
{
@@ -321,7 +321,7 @@ DEFUN_NOSH(nexthop_group, nexthop_group_cmd, "nexthop-group NAME",
return CMD_SUCCESS;
}
-DEFUN_NOSH(no_nexthop_group, no_nexthop_group_cmd, "no nexthop-group NAME",
+DEFUN_NOSH(no_nexthop_group, no_nexthop_group_cmd, "no nexthop-group NHGNAME",
NO_STR
"Delete the nexthop-group\n"
"Specify the NAME of the nexthop-group\n")
@@ -714,6 +714,19 @@ void nexthop_group_interface_state_change(struct interface *ifp,
}
}
+static void nhg_name_autocomplete(vector comps, struct cmd_token *token)
+{
+ struct nexthop_group_cmd *nhgc;
+
+ RB_FOREACH (nhgc, nhgc_entry_head, &nhgc_entries) {
+ vector_set(comps, XSTRDUP(MTYPE_COMPLETION, nhgc->name));
+ }
+}
+
+static const struct cmd_variable_handler nhg_name_handlers[] = {
+ {.tokenname = "NHGNAME", .completions = nhg_name_autocomplete},
+ {.completions = NULL}};
+
void nexthop_group_init(void (*new)(const char *name),
void (*add_nexthop)(const struct nexthop_group_cmd *nhg,
const struct nexthop *nhop),
@@ -723,6 +736,8 @@ void nexthop_group_init(void (*new)(const char *name),
{
RB_INIT(nhgc_entry_head, &nhgc_entries);
+ cmd_variable_handler_register(nhg_name_handlers);
+
install_node(&nexthop_group_node, nexthop_group_write);
install_element(CONFIG_NODE, &nexthop_group_cmd);
install_element(CONFIG_NODE, &no_nexthop_group_cmd);
diff --git a/lib/ntop.c b/lib/ntop.c
new file mode 100644
index 0000000000..d47a0b697a
--- /dev/null
+++ b/lib/ntop.c
@@ -0,0 +1,174 @@
+/*
+ * optimized ntop, about 10x faster than libc versions [as of 2019]
+ *
+ * Copyright (c) 2019 David Lamparter, for NetDEF, Inc.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include "compiler.h"
+
+#define pos (*posx)
+
+static inline void putbyte(uint8_t bytex, char **posx)
+ __attribute__((always_inline)) OPTIMIZE;
+
+static inline void putbyte(uint8_t bytex, char **posx)
+{
+ bool zero = false;
+ int byte = bytex, tmp, a, b;
+
+ if ((tmp = byte - 200) >= 0) {
+ *pos++ = '2';
+ zero = true;
+ byte = tmp;
+ } else if ((tmp = byte - 100) >= 0) {
+ *pos++ = '1';
+ zero = true;
+ byte = tmp;
+ }
+
+ /* make sure the compiler knows the value range of "byte" */
+ assume(byte < 100 && byte >= 0);
+
+ b = byte % 10;
+ a = byte / 10;
+ if (a || zero) {
+ *pos++ = '0' + a;
+ *pos++ = '0' + b;
+ } else
+ *pos++ = '0' + b;
+}
+
+static inline void puthex(uint16_t word, char **posx)
+ __attribute__((always_inline)) OPTIMIZE;
+
+static inline void puthex(uint16_t word, char **posx)
+{
+ const char *digits = "0123456789abcdef";
+ if (word >= 0x1000)
+ *pos++ = digits[(word >> 12) & 0xf];
+ if (word >= 0x100)
+ *pos++ = digits[(word >> 8) & 0xf];
+ if (word >= 0x10)
+ *pos++ = digits[(word >> 4) & 0xf];
+ *pos++ = digits[word & 0xf];
+}
+
+#undef pos
+
+const char *frr_inet_ntop(int af, const void * restrict src,
+ char * restrict dst, socklen_t size)
+ __attribute__((flatten)) DSO_SELF OPTIMIZE;
+
+const char *frr_inet_ntop(int af, const void * restrict src,
+ char * restrict dst, socklen_t size)
+{
+ const uint8_t *b = src;
+ /* 8 * "abcd:" for IPv6
+ * note: the IPv4-embedded IPv6 syntax is only used for ::A.B.C.D,
+ * which isn't longer than 40 chars either. even with ::ffff:A.B.C.D
+ * it's shorter.
+ */
+ char buf[8 * 5], *o = buf;
+ size_t best = 0, bestlen = 0, curlen = 0, i;
+
+ switch (af) {
+ case AF_INET:
+inet4:
+ putbyte(b[0], &o);
+ *o++ = '.';
+ putbyte(b[1], &o);
+ *o++ = '.';
+ putbyte(b[2], &o);
+ *o++ = '.';
+ putbyte(b[3], &o);
+ *o++ = '\0';
+ break;
+ case AF_INET6:
+ for (i = 0; i < 8; i++) {
+ if (b[i * 2] || b[i * 2 + 1]) {
+ if (curlen && curlen > bestlen) {
+ best = i - curlen;
+ bestlen = curlen;
+ }
+ curlen = 0;
+ continue;
+ }
+ curlen++;
+ }
+ if (curlen && curlen > bestlen) {
+ best = i - curlen;
+ bestlen = curlen;
+ }
+ /* do we want ::ffff:A.B.C.D? */
+ if (best == 0 && bestlen == 6) {
+ *o++ = ':';
+ *o++ = ':';
+ b += 12;
+ goto inet4;
+ }
+ if (bestlen == 1)
+ bestlen = 0;
+
+ for (i = 0; i < 8; i++) {
+ if (bestlen && i == best) {
+ if (i == 0)
+ *o++ = ':';
+ *o++ = ':';
+ continue;
+ }
+ if (i > best && i < best + bestlen) {
+ continue;
+ }
+ puthex((b[i * 2] << 8) | b[i * 2 + 1], &o);
+
+ if (i < 7)
+ *o++ = ':';
+ }
+ *o++ = '\0';
+ break;
+ default:
+ return NULL;
+ }
+
+ i = o - buf;
+ if (i > size)
+ return NULL;
+ /* compiler might inline memcpy if it knows the length is short,
+ * although neither gcc nor clang actually do this currently [2019]
+ */
+ assume(i <= 8 * 5);
+ memcpy(dst, buf, i);
+ return dst;
+}
+
+#ifndef INET_NTOP_NO_OVERRIDE
+/* we want to override libc inet_ntop, but make sure it shows up in backtraces
+ * as frr_inet_ntop (to avoid confusion while debugging)
+ */
+const char *inet_ntop(int af, const void *src, char *dst, socklen_t size)
+ __attribute__((alias ("frr_inet_ntop"))) DSO_SELF;
+#endif
diff --git a/lib/plist.c b/lib/plist.c
index 9957ff1f51..54ea742c66 100644
--- a/lib/plist.c
+++ b/lib/plist.c
@@ -1009,7 +1009,7 @@ static int vty_prefix_list_uninstall(struct vty *vty, afi_t afi,
if (pentry == NULL) {
vty_out(vty,
- "%% Can't find prefix-list %s with sequence number %lu\n",
+ "%% Can't find prefix-list %s with sequence number %" PRIu64 "\n",
name, seqnum);
return CMD_WARNING_CONFIG_FAILED;
}
diff --git a/lib/printf/printf-pos.c b/lib/printf/printf-pos.c
index 399573e6c1..1f5f283e82 100644
--- a/lib/printf/printf-pos.c
+++ b/lib/printf/printf-pos.c
@@ -54,6 +54,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <strings.h>
#include <wchar.h>
#include "printflocal.h"
diff --git a/lib/sockopt.c b/lib/sockopt.c
index 89f3d5b594..8e38a29278 100644
--- a/lib/sockopt.c
+++ b/lib/sockopt.c
@@ -701,6 +701,12 @@ int sockopt_tcp_signature_ext(int sock, union sockunion *su, uint16_t prefixlen,
}
return ret;
#endif /* HAVE_TCP_MD5SIG */
+
+ /*
+ * Making compiler happy. If we get to this point we probably
+ * have done something really really wrong.
+ */
+ return -2;
}
int sockopt_tcp_signature(int sock, union sockunion *su, const char *password)
diff --git a/lib/subdir.am b/lib/subdir.am
index 50ff1feecc..4e6adced74 100644
--- a/lib/subdir.am
+++ b/lib/subdir.am
@@ -56,6 +56,7 @@ lib_libfrr_la_SOURCES = \
lib/northbound.c \
lib/northbound_cli.c \
lib/northbound_db.c \
+ lib/ntop.c \
lib/openbsd-tree.c \
lib/pid_output.c \
lib/plist.c \
diff --git a/lib/thread.c b/lib/thread.c
index d3fb2cdf36..3879e936a1 100644
--- a/lib/thread.c
+++ b/lib/thread.c
@@ -95,7 +95,7 @@ static void cpu_record_hash_free(void *a)
static void vty_out_cpu_thread_history(struct vty *vty,
struct cpu_thread_history *a)
{
- vty_out(vty, "%5zu %10zu.%03lu %9zu %8zu %9zu %8lu %9lu",
+ vty_out(vty, "%5zu %10zu.%03zu %9zu %8zu %9zu %8zu %9zu",
a->total_active, a->cpu.total / 1000, a->cpu.total % 1000,
a->total_calls, a->cpu.total / a->total_calls, a->cpu.max,
a->real.total / a->total_calls, a->real.max);
diff --git a/lib/zclient.h b/lib/zclient.h
index c61c8d4226..d651738687 100644
--- a/lib/zclient.h
+++ b/lib/zclient.h
@@ -38,6 +38,15 @@
#include "mlag.h"
+/* Zebra types. Used in Zserv message header. */
+typedef uint16_t zebra_size_t;
+
+/* Marker value used in new Zserv, in the byte location corresponding
+ * the command value in the old zserv header. To allow old and new
+ * Zserv headers to be distinguished from each other.
+ */
+#define ZEBRA_HEADER_MARKER 254
+
/* For input/output buffer to zebra. */
#define ZEBRA_MAX_PACKET_SIZ 16384U
@@ -322,6 +331,41 @@ struct zapi_route {
unsigned short instance;
uint32_t flags;
+/*
+ * Cause Zebra to consider this routes nexthops recursively
+ */
+#define ZEBRA_FLAG_ALLOW_RECURSION 0x01
+/*
+ * This is a route that is read in on startup that was left around
+ * from a previous run of FRR
+ */
+#define ZEBRA_FLAG_SELFROUTE 0x02
+/*
+ * This flag is used to tell Zebra that the BGP route being passed
+ * down is a IBGP route
+ */
+#define ZEBRA_FLAG_IBGP 0x04
+/*
+ * This is a route that has been selected for FIB installation.
+ * This flag is set in zebra and can be passed up to routing daemons
+ */
+#define ZEBRA_FLAG_SELECTED 0x08
+/*
+ * This is a route that we are telling Zebra that this route *must*
+ * win and will be installed even over ZEBRA_FLAG_SELECTED
+ */
+#define ZEBRA_FLAG_FIB_OVERRIDE 0x10
+/*
+ * This flag tells Zebra that the route is a EVPN route and should
+ * be treated specially
+ */
+#define ZEBRA_FLAG_EVPN_ROUTE 0x20
+/*
+ * This flag tells Zebra that it should treat the distance passed
+ * down as an additional discriminator for route selection of the
+ * route entry. This mainly is used for backup static routes.
+ */
+#define ZEBRA_FLAG_RR_USE_DISTANCE 0x40
uint8_t message;
diff --git a/lib/zebra.h b/lib/zebra.h
index 3e1eefdb2e..2f9ada09be 100644
--- a/lib/zebra.h
+++ b/lib/zebra.h
@@ -202,18 +202,12 @@ typedef unsigned char uint8_t;
/* Some systems do not define UINT32_MAX, etc.. from inttypes.h
* e.g. this makes life easier for FBSD 4.11 users.
*/
-#ifndef INT8_MAX
-#define INT8_MAX (127)
-#endif
#ifndef INT16_MAX
#define INT16_MAX (32767)
#endif
#ifndef INT32_MAX
#define INT32_MAX (2147483647)
#endif
-#ifndef UINT8_MAX
-#define UINT8_MAX (255U)
-#endif
#ifndef UINT16_MAX
#define UINT16_MAX (65535U)
#endif
@@ -343,12 +337,6 @@ struct in_pktinfo {
/* default zebra TCP port for zclient */
#define ZEBRA_PORT 2600
-/* Marker value used in new Zserv, in the byte location corresponding
- * the command value in the old zserv header. To allow old and new
- * Zserv headers to be distinguished from each other.
- */
-#define ZEBRA_HEADER_MARKER 254
-
/*
* The compiler.h header is used for anyone using the CPP_NOTICE
* since this is universally needed, let's add it to zebra.h
@@ -358,65 +346,8 @@ struct in_pktinfo {
/* Zebra route's types are defined in route_types.h */
#include "route_types.h"
-/* Note: whenever a new route-type or zserv-command is added the
- * corresponding {command,route}_types[] table in lib/log.c MUST be
- * updated! */
-
-/* Map a route type to a string. For example, ZEBRA_ROUTE_RIPNG -> "ripng". */
-extern const char *zebra_route_string(unsigned int route_type);
-/* Map a route type to a char. For example, ZEBRA_ROUTE_RIPNG -> 'R'. */
-extern char zebra_route_char(unsigned int route_type);
-/* Map a zserv command type to the same string,
- * e.g. ZEBRA_INTERFACE_ADD -> "ZEBRA_INTERFACE_ADD" */
-/* Map a protocol name to its number. e.g. ZEBRA_ROUTE_BGP->9*/
-extern int proto_name2num(const char *s);
-/* Map redistribute X argument to protocol number.
- * unlike proto_name2num, this accepts shorthands and takes
- * an AFI value to restrict input */
-extern int proto_redistnum(int afi, const char *s);
-
-extern const char *zserv_command_string(unsigned int command);
-
#define strmatch(a,b) (!strcmp((a), (b)))
-/* Zebra message flags */
-
-/*
- * Cause Zebra to consider this routes nexthops recursively
- */
-#define ZEBRA_FLAG_ALLOW_RECURSION 0x01
-/*
- * This is a route that is read in on startup that was left around
- * from a previous run of FRR
- */
-#define ZEBRA_FLAG_SELFROUTE 0x02
-/*
- * This flag is used to tell Zebra that the BGP route being passed
- * down is a IBGP route
- */
-#define ZEBRA_FLAG_IBGP 0x04
-/*
- * This is a route that has been selected for FIB installation.
- * This flag is set in zebra and can be passed up to routing daemons
- */
-#define ZEBRA_FLAG_SELECTED 0x08
-/*
- * This is a route that we are telling Zebra that this route *must*
- * win and will be installed even over ZEBRA_FLAG_SELECTED
- */
-#define ZEBRA_FLAG_FIB_OVERRIDE 0x10
-/*
- * This flag tells Zebra that the route is a EVPN route and should
- * be treated specially
- */
-#define ZEBRA_FLAG_EVPN_ROUTE 0x20
-/*
- * This flag tells Zebra that it should treat the distance passed
- * down as an additional discriminator for route selection of the
- * route entry. This mainly is used for backup static routes.
- */
-#define ZEBRA_FLAG_RR_USE_DISTANCE 0x40
-
#ifndef INADDR_LOOPBACK
#define INADDR_LOOPBACK 0x7f000001 /* Internet address 127.0.0.1. */
#endif
@@ -501,10 +432,6 @@ typedef enum {
#define RESET_FLAG_ATOMIC(PV) \
((atomic_store_explicit(PV, 0, memory_order_seq_cst)))
-/* Zebra types. Used in Zserv message header. */
-typedef uint16_t zebra_size_t;
-typedef uint16_t zebra_command_t;
-
/* VRF ID type. */
typedef uint32_t vrf_id_t;
diff --git a/m4/.gitignore b/m4/.gitignore
index 2c04163659..cc778b9e99 100644
--- a/m4/.gitignore
+++ b/m4/.gitignore
@@ -4,6 +4,7 @@
!ax_compare_version.m4
!ax_prog_perl_modules.m4
!ax_pthread.m4
+!ax_python.m4
!ax_sys_weak_alias.m4
!ax_sys_weak_alias.m4
!pkg.m4
diff --git a/m4/ax_python.m4 b/m4/ax_python.m4
new file mode 100644
index 0000000000..32043c81ae
--- /dev/null
+++ b/m4/ax_python.m4
@@ -0,0 +1,284 @@
+dnl FRR Python autoconf magic
+dnl 2019 David Lamparter for NetDEF, Inc.
+dnl SPDX-License-Identifier: GPL-2.0-or-later
+
+dnl the _ at the beginning will be cut off (to support the empty version string)
+m4_define_default([_FRR_PY_VERS], [_3 _ _2 _3.7 _3.6 _3.5 _3.4 _3.3 _3.2 _2.7])
+
+dnl check basic interpreter properties (py2/py3)
+dnl doubles as simple check whether the interpreter actually works
+dnl also swaps in the full path to the interpreter
+dnl arg1: if-true, arg2: if-false
+AC_DEFUN([_FRR_PYTHON_INTERP], [dnl
+AC_ARG_VAR([PYTHON], [Python interpreter to use])dnl
+ AC_MSG_CHECKING([python interpreter $PYTHON])
+ AC_RUN_LOG(["$PYTHON" -c 'import sys; open("conftest.pyver", "w").write(sys.executable or ""); sys.exit(not (sys.version_info.major == 2 and sys.version_info.minor >= 7))'])
+ py2=$ac_status
+ _py2_full="`cat conftest.pyver 2>/dev/null`"
+ rm -f "conftest.pyver" >/dev/null 2>/dev/null
+
+ AC_RUN_LOG(["$PYTHON" -c 'import sys; open("conftest.pyver", "w").write(sys.executable or ""); sys.exit(not ((sys.version_info.major == 3 and sys.version_info.minor >= 2) or sys.version_info.major > 3))'])
+ py3=$ac_status
+ _py3_full="`cat conftest.pyver 2>/dev/null`"
+ rm -f "conftest.pyver" >/dev/null 2>/dev/null
+
+ case "p${py2}p${py3}" in
+ p0p1) frr_cv_python=python2
+ _python_full="$_py2_full" ;;
+ p1p0) frr_cv_python=python3
+ _python_full="$_py3_full" ;;
+ *) frr_cv_python=none ;;
+ esac
+
+ if test "$frr_cv_python" = none; then
+ AC_MSG_RESULT([not working])
+ $2
+ else
+ test -n "$_python_full" -a -x "$_python_full" && PYTHON="$_python_full"
+ AC_MSG_RESULT([$PYTHON ($frr_cv_python)])
+ $1
+ fi
+
+ dnl return value
+ test "$frr_cv_python" != none
+])
+
+dnl check whether $PYTHON has modules available
+dnl arg1: list of modules (space separated)
+dnl arg2: if all true, arg3: if any missing
+dnl also sets frr_py_mod_<name> to "true" or "false"
+AC_DEFUN([FRR_PYTHON_MODULES], [
+ result=true
+ for pymod in $1; do
+ AC_MSG_CHECKING([whether $PYTHON module $pymod is available])
+ AC_RUN_LOG(["$PYTHON" -c "import $pymod"])
+ sane="`echo \"$pymod\" | tr -c '[a-zA-Z0-9\n]' '_'`"
+ if test "$ac_status" -eq 0; then
+ AC_MSG_RESULT([yes])
+ eval frr_py_mod_$sane=true
+ else
+ AC_MSG_RESULT([no])
+ eval frr_py_mod_$sane=false
+ result=false
+ fi
+ done
+ if $result; then
+ m4_default([$2], [:])
+ else
+ m4_default([$3], [:])
+ fi
+ $result
+])
+
+dnl check whether $PYTHON has modules available
+dnl arg1: list of modules (space separated)
+dnl arg2: command line parameters for executing
+dnl arg3: if all true, arg4: if any missing
+dnl also sets frr_py_modexec_<name> to "true" or "false"
+AC_DEFUN([FRR_PYTHON_MOD_EXEC], [
+ result=true
+ for pymod in $1; do
+ AC_MSG_CHECKING([whether $PYTHON module $pymod is executable])
+ AC_RUN_LOG(["$PYTHON" -m "$pymod" $2 > /dev/null])
+ sane="`echo \"$pymod\" | tr -c '[a-zA-Z0-9\n]' '_'`"
+ if test "$ac_status" -eq 0; then
+ AC_MSG_RESULT([yes])
+ eval frr_py_modexec_$sane=true
+ else
+ AC_MSG_RESULT([no])
+ eval frr_py_modexec_$sane=false
+ result=false
+ fi
+ done
+ if $result; then
+ m4_default([$3], [:])
+ else
+ m4_default([$4], [:])
+ fi
+ $result
+])
+
+dnl check whether we can build & link python bits
+dnl input: PYTHON_CFLAGS and PYTHON_LIBS
+AC_DEFUN([_FRR_PYTHON_DEVENV], [
+ result=true
+ AC_LINK_IFELSE_FLAGS([$PYTHON_CFLAGS], [$PYTHON_LIBS], [AC_LANG_PROGRAM([
+#include <Python.h>
+#if PY_VERSION_HEX < 0x02070000
+#error python too old
+#endif
+int main(void);
+],
+[
+{
+ Py_Initialize();
+ return 0;
+}
+])], [
+ # some python installs are missing the zlib dependency...
+ PYTHON_LIBS="${PYTHON_LIBS} -lz"
+ AC_LINK_IFELSE_FLAGS([$PYTHON_CFLAGS], [$PYTHON_LIBS], [AC_LANG_PROGRAM([
+#include <Python.h>
+#if PY_VERSION_HEX < 0x02070000
+#error python too old
+#endif
+int main(void);
+],
+[
+{
+ Py_Initialize();
+ return 0;
+}
+])], [
+ result=false
+ AC_MSG_RESULT([no])
+ ], [:])
+ ], [:])
+
+ if $result; then
+ AC_LINK_IFELSE_FLAGS([$PYTHON_CFLAGS], [$PYTHON_LIBS], [AC_LANG_PROGRAM([
+#include <Python.h>
+#if PY_VERSION_HEX != $1
+#error python version mismatch
+#endif
+int main(void);
+],
+[
+{
+ Py_Initialize();
+ return 0;
+}
+])], [
+ result=false
+ AC_MSG_RESULT([version mismatch])
+ ], [
+ AC_MSG_RESULT([yes])
+ ])
+ fi
+
+ if $result; then
+ m4_default([$2], [:])
+ else
+ m4_default([$3], [
+ unset PYTHON_LIBS
+ unset PYTHON_CFLAGS
+ ])
+ fi
+])
+
+AC_DEFUN([_FRR_PYTHON_GETDEV], [dnl
+AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
+
+ py_abi="` \"$1\" -c \"import sys; print(getattr(sys, 'abiflags', ''))\"`"
+ py_hex="` \"$1\" -c \"import sys; print(hex(sys.hexversion))\"`"
+ py_ldver="` \"$1\" -c \"import sysconfig; print(sysconfig.get_config_var('LDVERSION') or '')\"`"
+ py_ver="` \"$1\" -c \"import sysconfig; print(sysconfig.get_config_var('VERSION') or '')\"`"
+ py_bindir="`\"$1\" -c \"import sysconfig; print(sysconfig.get_config_var('BINDIR') or '')\"`"
+ test -z "$py_bindir" || py_bindir="$py_bindir/"
+ echo "py_abi=${py_abi} py_ldver=${py_ldver} py_ver=${py_ver} py_bindir=${py_bindir}" >&AS_MESSAGE_LOG_FD
+
+ py_found=false
+
+ for tryver in "${py_ldver}" "${py_ver}"; do
+ pycfg="${py_bindir}python${tryver}-config"
+ AC_MSG_CHECKING([whether ${pycfg} is available])
+ if "$pycfg" --configdir >/dev/null 2>/dev/null; then
+ AC_MSG_RESULT([yes])
+
+ PYTHON_CFLAGS="`\"$pycfg\" --includes`"
+ PYTHON_LIBS="`\"$pycfg\" --ldflags`"
+
+ AC_MSG_CHECKING([whether ${pycfg} provides a working build environment])
+ _FRR_PYTHON_DEVENV([$py_hex], [
+ py_found=true
+ break
+ ])
+ else
+ AC_MSG_RESULT([no])
+ fi
+
+ pkg_failed=no
+ AC_MSG_CHECKING([whether pkg-config python-${tryver} is available])
+ unset PYTHON_CFLAGS
+ unset PYTHON_LIBS
+ pkg="python-${tryver}"
+ pkg="${pkg%-}"
+ _PKG_CONFIG([PYTHON_CFLAGS], [cflags], [${pkg}])
+ _PKG_CONFIG([PYTHON_LIBS], [libs], [${pkg}])
+ if test $pkg_failed = no; then
+ AC_MSG_RESULT([yes])
+
+ PYTHON_CFLAGS=$pkg_cv_PYTHON_CFLAGS
+ PYTHON_LIBS=$pkg_cv_PYTHON_LIBS
+
+ AC_MSG_CHECKING([whether pkg-config python-${tryver} provides a working build environment])
+ _FRR_PYTHON_DEVENV([$py_hex], [
+ py_found=true
+ break
+ ])
+ else
+ AC_MSG_RESULT([no])
+ fi
+ done
+
+ if $py_found; then
+ m4_default([$2], [:])
+ else
+ unset PYTHON_CFLAGS
+ unset PYTHON_LIBS
+ m4_default([$3], [:])
+ fi
+])
+
+dnl just find python without checking headers/libs
+AC_DEFUN([FRR_PYTHON], [
+ dnl user override
+ if test "x$PYTHON" != "x"; then
+ _FRR_PYTHON_INTERP([], [
+ AC_MSG_ERROR([PYTHON ($PYTHON) explicitly specified but not working])
+ ])
+ else
+ for frr_pyver in _FRR_PY_VERS; do
+ PYTHON="python${frr_pyver#_}"
+ _FRR_PYTHON_INTERP([break])
+ PYTHON=":"
+ done
+ if test "$PYTHON" = ":"; then
+ AC_MSG_ERROR([no working python version found])
+ fi
+ fi
+ AC_SUBST([PYTHON])
+])
+
+dnl find python with checking headers/libs
+AC_DEFUN([FRR_PYTHON_DEV], [dnl
+AC_ARG_VAR([PYTHON_CFLAGS], [C compiler flags for Python])dnl
+AC_ARG_VAR([PYTHON_LIBS], [linker flags for Python])dnl
+
+ dnl user override
+ if test "x$PYTHON" != "x"; then
+ _FRR_PYTHON_INTERP([], [
+ AC_MSG_ERROR([PYTHON ($PYTHON) explicitly specified but not working])
+ ])
+ _FRR_PYTHON_GETDEV([$PYTHON], [], [
+ AC_MSG_ERROR([PYTHON ($PYTHON) explicitly specified but development environment not working])
+ ])
+ else
+ for frr_pyver in _FRR_PY_VERS; do
+ PYTHON="python${frr_pyver#_}"
+ _FRR_PYTHON_INTERP([
+ _FRR_PYTHON_GETDEV([$PYTHON], [
+ break
+ ])
+ ])
+ PYTHON=":"
+ done
+ if test "$PYTHON" = ":"; then
+ AC_MSG_ERROR([no working python version found])
+ fi
+ fi
+
+ AC_SUBST([PYTHON_CFLAGS])
+ AC_SUBST([PYTHON_LIBS])
+ AC_SUBST([PYTHON])
+])
diff --git a/pbrd/pbr_nht.c b/pbrd/pbr_nht.c
index fc78b8ed1f..22dd6f1a38 100644
--- a/pbrd/pbr_nht.c
+++ b/pbrd/pbr_nht.c
@@ -66,6 +66,8 @@ static void *pbr_nhrc_hash_alloc(void *p)
{
struct nhrc *nhrc = XCALLOC(MTYPE_PBR_NHG, sizeof(struct nhrc));
nhrc->nexthop = *(struct nexthop *)p;
+ nhrc->nexthop.next = NULL;
+ nhrc->nexthop.prev = NULL;
return nhrc;
}
@@ -712,10 +714,30 @@ static void pbr_nht_individual_nexthop_update_lookup(struct hash_bucket *b,
pnhi->valid += 1;
}
+static void pbr_nexthop_group_cache_iterate_to_group(struct hash_bucket *b,
+ void *data)
+{
+ struct pbr_nexthop_cache *pnhc = b->data;
+ struct nexthop_group *nhg = data;
+ struct nexthop *nh = NULL;
+
+ copy_nexthops(&nh, pnhc->nexthop, NULL);
+
+ nexthop_add(&nhg->nexthop, nh);
+}
+
+static void
+pbr_nexthop_group_cache_to_nexthop_group(struct nexthop_group *nhg,
+ struct pbr_nexthop_group_cache *pnhgc)
+{
+ hash_iterate(pnhgc->nhh, pbr_nexthop_group_cache_iterate_to_group, nhg);
+}
+
static void pbr_nht_nexthop_update_lookup(struct hash_bucket *b, void *data)
{
struct pbr_nexthop_group_cache *pnhgc = b->data;
struct pbr_nht_individual pnhi;
+ struct nexthop_group nhg = {};
bool old_valid;
old_valid = pnhgc->valid;
@@ -730,6 +752,13 @@ static void pbr_nht_nexthop_update_lookup(struct hash_bucket *b, void *data)
*/
pnhgc->valid = !!pnhi.valid;
+ if (pnhgc->valid) {
+ pbr_nexthop_group_cache_to_nexthop_group(&nhg, pnhgc);
+ pbr_nht_install_nexthop_group(pnhgc, nhg);
+ /* Don't need copied nexthops anymore */
+ nexthops_free(nhg.nexthop);
+ }
+
if (old_valid != pnhgc->valid)
pbr_map_check_nh_group_change(pnhgc->name);
}
diff --git a/pbrd/pbr_vty.c b/pbrd/pbr_vty.c
index 067d5c01fd..a71c712ea7 100644
--- a/pbrd/pbr_vty.c
+++ b/pbrd/pbr_vty.c
@@ -38,7 +38,7 @@
#include "pbrd/pbr_vty_clippy.c"
#endif
-DEFUN_NOSH(pbr_map, pbr_map_cmd, "pbr-map WORD seq (1-700)",
+DEFUN_NOSH(pbr_map, pbr_map_cmd, "pbr-map PBRMAP seq (1-700)",
"Create pbr-map or enter pbr-map command mode\n"
"The name of the PBR MAP\n"
"Sequence to insert in existing pbr-map entry\n"
@@ -54,7 +54,7 @@ DEFUN_NOSH(pbr_map, pbr_map_cmd, "pbr-map WORD seq (1-700)",
return CMD_SUCCESS;
}
-DEFUN_NOSH(no_pbr_map, no_pbr_map_cmd, "no pbr-map WORD [seq (1-700)]",
+DEFUN_NOSH(no_pbr_map, no_pbr_map_cmd, "no pbr-map PBRMAP [seq (1-700)]",
NO_STR
"Delete pbr-map\n"
"The name of the PBR MAP\n"
@@ -172,7 +172,7 @@ DEFPY(pbr_map_match_dst, pbr_map_match_dst_cmd,
}
DEFPY(pbr_map_nexthop_group, pbr_map_nexthop_group_cmd,
- "[no] set nexthop-group NAME$name",
+ "[no] set nexthop-group NHGNAME$name",
NO_STR
"Set for the PBR-MAP\n"
"nexthop-group to use\n"
@@ -348,7 +348,7 @@ DEFPY(pbr_map_nexthop, pbr_map_nexthop_cmd,
DEFPY (pbr_policy,
pbr_policy_cmd,
- "[no] pbr-policy NAME$mapname",
+ "[no] pbr-policy PBRMAP$mapname",
NO_STR
"Policy to use\n"
"Name of the pbr-map to apply\n")
@@ -661,8 +661,27 @@ static int pbr_vty_map_config_write(struct vty *vty)
return 1;
}
+static void pbr_map_completer(vector comps, struct cmd_token *token)
+{
+ struct pbr_map *pbrm;
+
+ RB_FOREACH (pbrm, pbr_map_entry_head, &pbr_maps)
+ vector_set(comps, XSTRDUP(MTYPE_COMPLETION, pbrm->name));
+}
+
+static const struct cmd_variable_handler pbr_map_name[] = {
+ {
+ .tokenname = "PBRMAP", .completions = pbr_map_completer,
+ },
+ {
+ .completions = NULL
+ }
+};
+
void pbr_vty_init(void)
{
+ cmd_variable_handler_register(pbr_map_name);
+
install_node(&interface_node,
pbr_interface_config_write);
if_cmd_init();
diff --git a/pimd/mtracebis.c b/pimd/mtracebis.c
index 65c495eff0..dd95762754 100644
--- a/pimd/mtracebis.c
+++ b/pimd/mtracebis.c
@@ -17,9 +17,7 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
+#include <zebra.h>
#ifdef __linux__
diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c
index 7788191454..6591bdc32e 100644
--- a/pimd/pim_cmd.c
+++ b/pimd/pim_cmd.c
@@ -1536,7 +1536,7 @@ static void pim_show_interface_traffic(struct pim_instance *pim,
json_object_object_add(json, ifp->name, json_row);
} else {
vty_out(vty,
- "%-16s %8u/%-8u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u %7lu/%-7lu \n",
+ "%-16s %8u/%-8u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u %7" PRIu64 "/%-7" PRIu64 "\n",
ifp->name, pim_ifp->pim_ifstat_hello_recv,
pim_ifp->pim_ifstat_hello_sent,
pim_ifp->pim_ifstat_join_recv,
@@ -1629,7 +1629,7 @@ static void pim_show_interface_traffic_single(struct pim_instance *pim,
json_object_object_add(json, ifp->name, json_row);
} else {
vty_out(vty,
- "%-16s %8u/%-8u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u %7lu/%-7lu \n",
+ "%-16s %8u/%-8u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u %7" PRIu64 "/%-7" PRIu64 "\n",
ifp->name, pim_ifp->pim_ifstat_hello_recv,
pim_ifp->pim_ifstat_hello_sent,
pim_ifp->pim_ifstat_join_recv,
@@ -3238,9 +3238,11 @@ static void pim_show_statistics(struct pim_instance *pim, struct vty *vty,
} else {
vty_out(vty, "BSM Statistics :\n");
vty_out(vty, "----------------\n");
- vty_out(vty, "Number of Received BSMs : %ld\n", pim->bsm_rcvd);
- vty_out(vty, "Number of Forwared BSMs : %ld\n", pim->bsm_sent);
- vty_out(vty, "Number of Dropped BSMs : %ld\n",
+ vty_out(vty, "Number of Received BSMs : %" PRIu64 "\n",
+ pim->bsm_rcvd);
+ vty_out(vty, "Number of Forwared BSMs : %" PRIu64 "\n",
+ pim->bsm_sent);
+ vty_out(vty, "Number of Dropped BSMs : %" PRIu64 "\n",
pim->bsm_dropped);
}
diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c
index 866a19fc98..ca05824347 100644
--- a/pimd/pim_mroute.c
+++ b/pimd/pim_mroute.c
@@ -897,11 +897,11 @@ int pim_mroute_add(struct channel_oil *c_oil, const char *name)
int err;
int orig = 0;
int orig_iif_vif = 0;
- struct pim_interface *pim_reg_ifp;
- int orig_pimreg_ttl;
+ struct pim_interface *pim_reg_ifp = NULL;
+ int orig_pimreg_ttl = 0;
bool pimreg_ttl_reset = false;
- struct pim_interface *vxlan_ifp;
- int orig_term_ttl;
+ struct pim_interface *vxlan_ifp = NULL;
+ int orig_term_ttl = 0;
bool orig_term_ttl_reset = false;
pim->mroute_add_last = pim_time_monotonic_sec();
@@ -985,9 +985,11 @@ int pim_mroute_add(struct channel_oil *c_oil, const char *name)
if (c_oil->oil.mfcc_origin.s_addr == INADDR_ANY)
c_oil->oil.mfcc_ttls[c_oil->oil.mfcc_parent] = orig;
- if (pimreg_ttl_reset)
+ if (pimreg_ttl_reset) {
+ assert(pim_reg_ifp);
c_oil->oil.mfcc_ttls[pim_reg_ifp->mroute_vif_index] =
orig_pimreg_ttl;
+ }
if (orig_term_ttl_reset)
c_oil->oil.mfcc_ttls[vxlan_ifp->mroute_vif_index] =
diff --git a/pimd/pim_nht.c b/pimd/pim_nht.c
index 1a2f451524..65ea858cb6 100644
--- a/pimd/pim_nht.c
+++ b/pimd/pim_nht.c
@@ -447,7 +447,7 @@ static int pim_update_upstream_nh_helper(struct hash_bucket *bucket, void *arg)
struct pim_rpf old;
old.source_nexthop.interface = up->rpf.source_nexthop.interface;
- rpf_result = pim_rpf_update(pim, up, &old, 0);
+ rpf_result = pim_rpf_update(pim, up, &old);
if (rpf_result == PIM_RPF_FAILURE) {
pim_upstream_rpf_clear(pim, up);
return HASHWALK_CONTINUE;
diff --git a/pimd/pim_rp.c b/pimd/pim_rp.c
index ca865d28c3..35c040c64c 100644
--- a/pimd/pim_rp.c
+++ b/pimd/pim_rp.c
@@ -381,7 +381,7 @@ void pim_upstream_update(struct pim_instance *pim, struct pim_upstream *up)
old_rpf.source_nexthop.interface = up->rpf.source_nexthop.interface;
- rpf_result = pim_rpf_update(pim, up, &old_rpf, 1);
+ rpf_result = pim_rpf_update(pim, up, &old_rpf);
if (rpf_result == PIM_RPF_FAILURE)
pim_mroute_del(up->channel_oil, __PRETTY_FUNCTION__);
diff --git a/pimd/pim_rpf.c b/pimd/pim_rpf.c
index d388802454..b1a2e717d6 100644
--- a/pimd/pim_rpf.c
+++ b/pimd/pim_rpf.c
@@ -195,8 +195,7 @@ static int nexthop_mismatch(const struct pim_nexthop *nh1,
}
enum pim_rpf_result pim_rpf_update(struct pim_instance *pim,
- struct pim_upstream *up, struct pim_rpf *old,
- uint8_t is_new)
+ struct pim_upstream *up, struct pim_rpf *old)
{
struct pim_rpf *rpf = &up->rpf;
struct pim_rpf saved;
@@ -216,14 +215,6 @@ enum pim_rpf_result pim_rpf_update(struct pim_instance *pim,
saved.source_nexthop = rpf->source_nexthop;
saved.rpf_addr = rpf->rpf_addr;
- if (is_new && PIM_DEBUG_ZEBRA) {
- char source_str[INET_ADDRSTRLEN];
- pim_inet4_dump("<source?>", up->upstream_addr, source_str,
- sizeof(source_str));
- zlog_debug("%s: NHT Register upstream %s addr %s with Zebra.",
- __PRETTY_FUNCTION__, up->sg_str, source_str);
- }
- /* Register addr with Zebra NHT */
nht_p.family = AF_INET;
nht_p.prefixlen = IPV4_MAX_BITLEN;
nht_p.u.prefix4.s_addr = up->upstream_addr.s_addr;
diff --git a/pimd/pim_rpf.h b/pimd/pim_rpf.h
index 1172acb4b2..df7b249289 100644
--- a/pimd/pim_rpf.h
+++ b/pimd/pim_rpf.h
@@ -62,8 +62,8 @@ bool pim_rpf_equal(const void *arg1, const void *arg2);
bool pim_nexthop_lookup(struct pim_instance *pim, struct pim_nexthop *nexthop,
struct in_addr addr, int neighbor_needed);
enum pim_rpf_result pim_rpf_update(struct pim_instance *pim,
- struct pim_upstream *up, struct pim_rpf *old,
- uint8_t is_new);
+ struct pim_upstream *up,
+ struct pim_rpf *old);
void pim_upstream_rpf_clear(struct pim_instance *pim,
struct pim_upstream *up);
int pim_rpf_addr_is_inaddr_none(struct pim_rpf *rpf);
diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c
index 44b8ecbfea..50c68c66bd 100644
--- a/pimd/pim_upstream.c
+++ b/pimd/pim_upstream.c
@@ -749,7 +749,7 @@ static struct pim_upstream *pim_upstream_new(struct pim_instance *pim,
up->channel_oil = pim_channel_oil_add(pim, &up->sg, MAXVIFS);
} else {
- rpf_result = pim_rpf_update(pim, up, NULL, 1);
+ rpf_result = pim_rpf_update(pim, up, NULL);
if (rpf_result == PIM_RPF_FAILURE) {
if (PIM_DEBUG_TRACE)
zlog_debug(
@@ -1625,7 +1625,7 @@ void pim_upstream_find_new_rpf(struct pim_instance *pim)
zlog_debug(
"%s: Upstream %s without a path to send join, checking",
__PRETTY_FUNCTION__, up->sg_str);
- pim_rpf_update(pim, up, NULL, 1);
+ pim_rpf_update(pim, up, NULL);
}
}
}
diff --git a/pimd/pim_vxlan.c b/pimd/pim_vxlan.c
index 09669e206e..d2648fad50 100644
--- a/pimd/pim_vxlan.c
+++ b/pimd/pim_vxlan.c
@@ -245,7 +245,7 @@ static void pim_vxlan_orig_mr_up_del(struct pim_vxlan_sg *vxlan_sg)
* for nht
*/
if (up)
- pim_rpf_update(vxlan_sg->pim, up, NULL, 1 /* is_new */);
+ pim_rpf_update(vxlan_sg->pim, up, NULL);
}
}
diff --git a/pimd/pim_zlookup.c b/pimd/pim_zlookup.c
index 6d93a40b91..77526281d1 100644
--- a/pimd/pim_zlookup.c
+++ b/pimd/pim_zlookup.c
@@ -37,8 +37,10 @@
#include "pim_zlookup.h"
static struct zclient *zlookup = NULL;
+struct thread *zlookup_read;
static void zclient_lookup_sched(struct zclient *zlookup, int delay);
+static int zclient_lookup_read_pipe(struct thread *thread);
/* Connect to zebra for nexthop lookup. */
static int zclient_lookup_connect(struct thread *t)
@@ -65,6 +67,8 @@ static int zclient_lookup_connect(struct thread *t)
return -1;
}
+ thread_add_timer(router->master, zclient_lookup_read_pipe, zlookup, 60,
+ &zlookup_read);
return 0;
}
@@ -113,6 +117,7 @@ static void zclient_lookup_failed(struct zclient *zlookup)
void zclient_lookup_free(void)
{
+ thread_cancel(zlookup_read);
zclient_stop(zlookup);
zclient_free(zlookup);
zlookup = NULL;
@@ -357,6 +362,20 @@ static int zclient_lookup_nexthop_once(struct pim_instance *pim,
return zclient_read_nexthop(pim, zlookup, nexthop_tab, tab_size, addr);
}
+int zclient_lookup_read_pipe(struct thread *thread)
+{
+ struct zclient *zlookup = THREAD_ARG(thread);
+ struct pim_instance *pim = pim_get_pim_instance(VRF_DEFAULT);
+ struct pim_zlookup_nexthop nexthop_tab[10];
+ struct in_addr l = {.s_addr = INADDR_ANY};
+
+ zclient_lookup_nexthop_once(pim, nexthop_tab, 10, l);
+ thread_add_timer(router->master, zclient_lookup_read_pipe, zlookup, 60,
+ &zlookup_read);
+
+ return 1;
+}
+
int zclient_lookup_nexthop(struct pim_instance *pim,
struct pim_zlookup_nexthop nexthop_tab[],
const int tab_size, struct in_addr addr,
diff --git a/redhat/frr.spec.in b/redhat/frr.spec.in
index ebd9ac3f47..27042e197c 100644
--- a/redhat/frr.spec.in
+++ b/redhat/frr.spec.in
@@ -44,12 +44,6 @@
# defines for configure
%define rundir %{_localstatedir}/run/%{name}
-# define for sphinx-build binary
-%if 0%{?rhel} && 0%{?rhel} < 7
- %define sphinx sphinx-build2.7
-%else
- %define sphinx sphinx-build
-%endif
############################################################################
#### Version String tweak
@@ -360,7 +354,7 @@ developing OSPF-API and frr applications.
%else
--disable-bfdd \
%endif
- SPHINXBUILD=%{sphinx}
+ # end
make %{?_smp_mflags} MAKEINFO="makeinfo --no-split"
diff --git a/sharpd/sharp_vty.c b/sharpd/sharp_vty.c
index fbcbbe3fdc..dad09dd992 100644
--- a/sharpd/sharp_vty.c
+++ b/sharpd/sharp_vty.c
@@ -150,14 +150,14 @@ DEFPY (install_routes_data_dump,
sg.r.total_routes,
sg.r.installed_routes,
sg.r.removed_routes,
- r.tv_sec, r.tv_usec);
+ r.tv_sec, (long int)r.tv_usec);
return CMD_SUCCESS;
}
DEFPY (install_routes,
install_routes_cmd,
- "sharp install routes [vrf NAME$name] <A.B.C.D$start4|X:X::X:X$start6> <nexthop <A.B.C.D$nexthop4|X:X::X:X$nexthop6>|nexthop-group NAME$nexthop_group> (1-1000000)$routes [instance (0-255)$instance] [repeat (2-1000)$rpt]",
+ "sharp install routes [vrf NAME$name] <A.B.C.D$start4|X:X::X:X$start6> <nexthop <A.B.C.D$nexthop4|X:X::X:X$nexthop6>|nexthop-group NHGNAME$nexthop_group> (1-1000000)$routes [instance (0-255)$instance] [repeat (2-1000)$rpt]",
"Sharp routing Protocol\n"
"install some routes\n"
"Routes to install\n"
diff --git a/sharpd/sharp_zebra.c b/sharpd/sharp_zebra.c
index 19c7e556ca..7447076993 100644
--- a/sharpd/sharp_zebra.c
+++ b/sharpd/sharp_zebra.c
@@ -213,7 +213,7 @@ static int route_notify_owner(ZAPI_CALLBACK_ARGS)
monotime(&sg.r.t_end);
timersub(&sg.r.t_end, &sg.r.t_start, &r);
zlog_debug("Installed All Items %ld.%ld", r.tv_sec,
- r.tv_usec);
+ (long int)r.tv_usec);
handle_repeated(true);
}
break;
@@ -229,7 +229,7 @@ static int route_notify_owner(ZAPI_CALLBACK_ARGS)
monotime(&sg.r.t_end);
timersub(&sg.r.t_end, &sg.r.t_start, &r);
zlog_debug("Removed all Items %ld.%ld", r.tv_sec,
- r.tv_usec);
+ (long int)r.tv_usec);
handle_repeated(false);
}
break;
diff --git a/tests/.gitignore b/tests/.gitignore
index 7177165e4a..4c6a51d475 100644
--- a/tests/.gitignore
+++ b/tests/.gitignore
@@ -30,6 +30,7 @@
/lib/test_idalloc
/lib/test_memory
/lib/test_nexthop_iter
+/lib/test_ntop
/lib/test_printfrr
/lib/test_privs
/lib/test_ringbuf
diff --git a/tests/lib/test_ntop.c b/tests/lib/test_ntop.c
new file mode 100644
index 0000000000..1806059963
--- /dev/null
+++ b/tests/lib/test_ntop.c
@@ -0,0 +1,87 @@
+/*
+ * frr_inet_ntop() unit test
+ * Copyright (C) 2019 David Lamparter
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <assert.h>
+
+#include "tests/helpers/c/prng.h"
+
+/* NB: libfrr is NOT linked for this unit test! */
+
+#define INET_NTOP_NO_OVERRIDE
+#include "lib/ntop.c"
+
+int main(int argc, char **argv)
+{
+ size_t i, j, k, l;
+ struct in_addr i4;
+ struct in6_addr i6, i6check;
+ char buf1[64], buf2[64];
+ const char *rv;
+ struct prng *prng;
+
+ prng = prng_new(0);
+ /* IPv4 */
+ for (i = 0; i < 1000; i++) {
+ i4.s_addr = prng_rand(prng);
+ assert(frr_inet_ntop(AF_INET, &i4, buf1, sizeof(buf1)));
+ assert(inet_ntop(AF_INET, &i4, buf2, sizeof(buf2)));
+ assert(!strcmp(buf1, buf2));
+ }
+
+ /* check size limit */
+ for (i = 0; i < sizeof(buf1); i++) {
+ memset(buf2, 0xcc, sizeof(buf2));
+ rv = frr_inet_ntop(AF_INET, &i4, buf2, i);
+ if (i < strlen(buf1) + 1)
+ assert(!rv);
+ else
+ assert(rv && !strcmp(buf1, buf2));
+ }
+
+ /* IPv6 */
+ for (i = 0; i < 10000; i++) {
+ uint16_t *i6w = (uint16_t *)&i6;
+ for (j = 0; j < 8; j++)
+ i6w[j] = prng_rand(prng);
+
+ /* clear some words */
+ l = prng_rand(prng) & 7;
+ for (j = 0; j < l; j++) {
+ uint32_t num = __builtin_ctz(prng_rand(prng));
+ uint32_t where = prng_rand(prng) & 7;
+
+ for (k = where; k < where + num && k < 8; k++)
+ i6w[k] = 0;
+ }
+
+ assert(frr_inet_ntop(AF_INET6, &i6, buf1, sizeof(buf1)));
+ assert(inet_ntop(AF_INET6, &i6, buf2, sizeof(buf2)));
+ if (strcmp(buf1, buf2))
+ printf("%-40s (FRR) != (SYS) %-40s\n", buf1, buf2);
+
+ assert(inet_pton(AF_INET6, buf1, &i6check));
+ assert(!memcmp(&i6, &i6check, sizeof(i6)));
+ assert(strlen(buf1) <= strlen(buf2));
+ }
+ return 0;
+}
diff --git a/tests/lib/test_ntop.py b/tests/lib/test_ntop.py
new file mode 100644
index 0000000000..2526f53db5
--- /dev/null
+++ b/tests/lib/test_ntop.py
@@ -0,0 +1,6 @@
+import frrtest
+
+class TestNtop(frrtest.TestMultiOut):
+ program = './test_ntop'
+
+TestNtop.exit_cleanly()
diff --git a/tests/subdir.am b/tests/subdir.am
index bbab8cd86a..41f1a4873b 100644
--- a/tests/subdir.am
+++ b/tests/subdir.am
@@ -2,8 +2,6 @@
# tests
#
-PYTHON ?= python
-
if BGPD
TESTS_BGPD = \
tests/bgpd/test_aspath \
@@ -56,6 +54,7 @@ check_PROGRAMS = \
tests/lib/test_idalloc \
tests/lib/test_memory \
tests/lib/test_nexthop_iter \
+ tests/lib/test_ntop \
tests/lib/test_printfrr \
tests/lib/test_privs \
tests/lib/test_ringbuf \
@@ -233,6 +232,10 @@ tests_lib_test_nexthop_iter_CFLAGS = $(TESTS_CFLAGS)
tests_lib_test_nexthop_iter_CPPFLAGS = $(TESTS_CPPFLAGS)
tests_lib_test_nexthop_iter_LDADD = $(ALL_TESTS_LDADD)
tests_lib_test_nexthop_iter_SOURCES = tests/lib/test_nexthop_iter.c tests/helpers/c/prng.c
+tests_lib_test_ntop_CFLAGS = $(TESTS_CFLAGS)
+tests_lib_test_ntop_CPPFLAGS = $(TESTS_CPPFLAGS)
+tests_lib_test_ntop_LDADD = # none
+tests_lib_test_ntop_SOURCES = tests/lib/test_ntop.c tests/helpers/c/prng.c
tests_lib_test_printfrr_CFLAGS = $(TESTS_CFLAGS)
tests_lib_test_printfrr_CPPFLAGS = $(TESTS_CPPFLAGS)
tests_lib_test_printfrr_LDADD = $(ALL_TESTS_LDADD)
@@ -324,6 +327,7 @@ EXTRA_DIST += \
tests/lib/northbound/test_oper_data.refout \
tests/lib/test_atomlist.py \
tests/lib/test_nexthop_iter.py \
+ tests/lib/test_ntop.py \
tests/lib/test_printfrr.py \
tests/lib/test_ringbuf.py \
tests/lib/test_srcdest_table.py \
diff --git a/vtysh/vtysh.c b/vtysh/vtysh.c
index baf77d1cb7..c3aeb27eb9 100644
--- a/vtysh/vtysh.c
+++ b/vtysh/vtysh.c
@@ -1678,7 +1678,7 @@ DEFUNSH(VTYSH_RMAP, vtysh_route_map, vtysh_route_map_cmd,
}
DEFUNSH(VTYSH_PBRD, vtysh_pbr_map, vtysh_pbr_map_cmd,
- "pbr-map NAME seq (1-700)",
+ "pbr-map PBRMAP seq (1-700)",
"Create pbr-map or enter pbr-map command mode\n"
"The name of the PBR MAP\n"
"Sequence to insert to/delete from existing pbr-map entry\n"
@@ -1714,7 +1714,7 @@ DEFUNSH(VTYSH_BFDD, bfd_peer_enter, bfd_peer_enter_cmd,
}
#endif /* HAVE_BFDD */
-DEFSH(VTYSH_PBRD, vtysh_no_pbr_map_cmd, "no pbr-map WORD [seq (1-700)]",
+DEFSH(VTYSH_PBRD, vtysh_no_pbr_map_cmd, "no pbr-map PBRMAP [seq (1-700)]",
NO_STR
"Delete pbr-map\n"
"The name of the PBR MAP\n"
@@ -2114,7 +2114,7 @@ DEFSH(VTYSH_ZEBRA, vtysh_no_logicalrouter_cmd,
"The file name in " NS_RUN_DIR ", or a full pathname\n")
DEFUNSH(VTYSH_PBRD | VTYSH_SHARPD, vtysh_nexthop_group, vtysh_nexthop_group_cmd,
- "nexthop-group NAME",
+ "nexthop-group NHGNAME",
"Nexthop Group configuration\n"
"Name of the Nexthop Group\n")
{
@@ -2123,7 +2123,7 @@ DEFUNSH(VTYSH_PBRD | VTYSH_SHARPD, vtysh_nexthop_group, vtysh_nexthop_group_cmd,
}
DEFSH(VTYSH_PBRD | VTYSH_SHARPD, vtysh_no_nexthop_group_cmd,
- "no nexthop-group NAME",
+ "no nexthop-group NHGNAME",
NO_STR
"Nexthop Group Configuration\n"
"Name of the Nexthop Group\n")
diff --git a/zebra/zebra_rnh.c b/zebra/zebra_rnh.c
index a63d015716..1024f3a052 100644
--- a/zebra/zebra_rnh.c
+++ b/zebra/zebra_rnh.c
@@ -592,54 +592,6 @@ static void zebra_rnh_notify_protocol_clients(struct zebra_vrf *zvrf, afi_t afi,
zebra_rnh_clear_nexthop_rnh_filters(re);
}
-static void zebra_rnh_process_pbr_tables(afi_t afi, struct route_node *nrn,
- struct rnh *rnh,
- struct route_node *prn,
- struct route_entry *re)
-{
- struct zebra_router_table *zrt;
- struct route_entry *o_re;
- struct route_node *o_rn;
- struct listnode *node;
- struct zserv *client;
-
- /*
- * We are only concerned about nexthops that change for
- * anyone using PBR
- */
- for (ALL_LIST_ELEMENTS_RO(rnh->client_list, node, client)) {
- if (client->proto == ZEBRA_ROUTE_PBR)
- break;
- }
-
- if (!client)
- return;
-
- RB_FOREACH (zrt, zebra_router_table_head, &zrouter.tables) {
- if (afi != zrt->afi)
- continue;
-
- for (o_rn = route_top(zrt->table); o_rn;
- o_rn = srcdest_route_next(o_rn)) {
- RNODE_FOREACH_RE (o_rn, o_re) {
- if (o_re->type == ZEBRA_ROUTE_PBR)
- break;
-
- }
-
- /*
- * If we have a PBR route and a nexthop changes
- * just rethink it. Yes this is a hammer, but
- * a small one
- */
- if (o_re) {
- SET_FLAG(o_re->status, ROUTE_ENTRY_CHANGED);
- rib_queue_add(o_rn);
- }
- }
- }
-}
-
/*
* Utility to determine whether a candidate nexthop is useable. We make this
* check in a couple of places, so this is a single home for the logic we
@@ -834,8 +786,6 @@ static void zebra_rnh_eval_nexthop_entry(struct zebra_vrf *zvrf, afi_t afi,
zebra_rnh_notify_protocol_clients(zvrf, afi, nrn, rnh, prn,
rnh->state);
- zebra_rnh_process_pbr_tables(afi, nrn, rnh, prn, rnh->state);
-
/* Process pseudowires attached to this nexthop */
zebra_rnh_process_pseudowires(zvrf->vrf->vrf_id, rnh);
}