diff --git a/alpine/APKBUILD.in b/alpine/APKBUILD.in index 42896c21a5..969b85f524 100644 --- a/alpine/APKBUILD.in +++ b/alpine/APKBUILD.in @@ -23,7 +23,7 @@ makedepends="ncurses-dev net-snmp-dev gawk texinfo perl checkdepends="pytest py-setuptools" install="$pkgname.pre-install $pkgname.pre-deinstall $pkgname.post-deinstall" subpackages="$pkgname-dev $pkgname-doc $pkgname-dbg" -source="$pkgname-$pkgver.tar.gz docker-start daemons daemons.conf" +source="$pkgname-$pkgver.tar.gz docker-start daemons" builddir="$srcdir"/$pkgname-$pkgver @@ -62,7 +62,6 @@ package() { install -Dm755 "$srcdir"/docker-start "$pkgdir"$_sbindir install -Dm644 "$srcdir"/daemons "$pkgdir"$_sysconfdir - install -Dm644 "$srcdir"/daemons.conf "$pkgdir"$_sysconfdir install -d "$pkgdir"/etc/init.d ln -s ${_sbindir}/frr "$pkgdir"/etc/init.d/frr } diff --git a/configure.ac b/configure.ac index 1de3081522..0d75f7d319 100755 --- a/configure.ac +++ b/configure.ac @@ -2180,6 +2180,9 @@ AC_CONFIG_FILES([ AC_CONFIG_FILES([vtysh/extract.pl], [chmod +x vtysh/extract.pl]) AC_CONFIG_FILES([tools/frr], [chmod +x tools/frr]) +AC_CONFIG_FILES([tools/watchfrr.sh], [chmod +x tools/watchfrr.sh]) +AC_CONFIG_FILES([tools/frrinit.sh], [chmod +x tools/frrinit.sh]) +AC_CONFIG_FILES([tools/frrcommon.sh]) AC_CONFIG_COMMANDS([lib/route_types.h], [ dst="${ac_abs_top_builddir}/lib/route_types.h" diff --git a/debianpkg/README.Debian b/debianpkg/README.Debian index 1b04803366..cd7be5e801 100644 --- a/debianpkg/README.Debian +++ b/debianpkg/README.Debian @@ -83,7 +83,7 @@ into the kernel. ===================================================================== If this message occurs the receive buffer should be increased by adding the -following to /etc/sysctl.conf and "--nl-bufsize" to /etc/frr/daemons.conf. +following to /etc/sysctl.conf and "--nl-bufsize" to /etc/frr/daemons. > net.core.rmem_default = 262144 > net.core.rmem_max = 262144 See message #4525 from 2005-05-09 in the quagga-users mailing list. diff --git a/debianpkg/backports/ubuntu12.04/debian/control b/debianpkg/backports/ubuntu12.04/debian/control deleted file mode 100644 index 9bae348840..0000000000 --- a/debianpkg/backports/ubuntu12.04/debian/control +++ /dev/null @@ -1,56 +0,0 @@ -Source: frr -Section: net -Priority: optional -Maintainer: Nobody -Uploaders: Nobody -XSBC-Original-Maintainer: -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, autotools-dev, libpcre3-dev, gawk, chrpath, libsnmp-dev, git, dh-autoreconf, libjson0, libjson0-dev, pkg-config, python (>= 2.7), python-ipaddr -Standards-Version: 3.9.6 -Homepage: http://www.frrouting.org/ -XS-Testsuite: autopkgtest - -Package: frr -Architecture: any -Depends: ${shlibs:Depends}, logrotate (>= 3.2-11), ${misc:Depends} -Pre-Depends: adduser -Conflicts: zebra, zebra-pj, quagga -Replaces: zebra, zebra-pj -Suggests: snmpd -Description: BGP/OSPF/RIP/RIPng/ISIS/PIM/LDP routing daemon forked from Quagga - FRR is free software which manages TCP/IP based routing protocols. - It supports BGP4, BGP4+, OSPFv2, OSPFv3, IS-IS, RIPv1, RIPv2, RIPng, - PIM and LDP as well as the IPv6 versions of these. - . - FRR is a fork of Quagga with an open community model. The main git - lives on https://github.com/frrouting/frr.git - -Package: frr-dbg -Architecture: any -Depends: ${shlibs:Depends}, ${misc:Depends}, frr (= ${binary:Version}) -Priority: extra -Section: debug -Description: BGP/OSPF/RIP/RIPng/ISIS/PIM/LDP routing daemon (debug symbols) - This package provides debugging symbols for all binary packages built - from frr source package. It's highly recommended to have this package - installed before reporting any FRR crashes to either FRR developers or - Debian package maintainers. - -Package: frr-doc -Section: net -Architecture: all -Depends: ${misc:Depends} -Suggests: frr -Description: documentation files for FRR - This package includes info files for frr, a free software which manages - TCP/IP based routing protocols. It supports BGP4, BGP4+, OSPFv2, OSPFv3, - IS-IS, RIPv1, RIPv2, RIPng, PIM and LDP as well as the IPv6 versions of these. - -Package: frr-pythontools -Section: net -Architecture: all -Depends: ${misc:Depends}, frr (= ${binary:Version}), python (>= 2.7), python-ipaddr -Description: BGP/OSPF/RIP/RIPng/ISIS/PIM/LDP routing daemon (Python Tools) - This package includes info files for frr, a free software which manages - TCP/IP based routing protocols. It supports BGP4, BGP4+, OSPFv2, OSPFv3, - IS-IS, RIPv1, RIPv2, RIPng, PIM and LDP as well as the IPv6 versions of these. - diff --git a/debianpkg/backports/ubuntu12.04/debian/frr.install b/debianpkg/backports/ubuntu12.04/debian/frr.install deleted file mode 120000 index 83ecca5958..0000000000 --- a/debianpkg/backports/ubuntu12.04/debian/frr.install +++ /dev/null @@ -1 +0,0 @@ -../../ubuntu14.04/debian/frr.install \ No newline at end of file diff --git a/debianpkg/backports/ubuntu12.04/debian/frr.postinst b/debianpkg/backports/ubuntu12.04/debian/frr.postinst deleted file mode 120000 index eb98053c7b..0000000000 --- a/debianpkg/backports/ubuntu12.04/debian/frr.postinst +++ /dev/null @@ -1 +0,0 @@ -../../ubuntu14.04/debian/frr.postinst \ No newline at end of file diff --git a/debianpkg/backports/ubuntu12.04/debian/frr.postrm b/debianpkg/backports/ubuntu12.04/debian/frr.postrm deleted file mode 120000 index 4f4380872f..0000000000 --- a/debianpkg/backports/ubuntu12.04/debian/frr.postrm +++ /dev/null @@ -1 +0,0 @@ -../../ubuntu14.04/debian/frr.postrm \ No newline at end of file diff --git a/debianpkg/backports/ubuntu12.04/debian/rules b/debianpkg/backports/ubuntu12.04/debian/rules deleted file mode 100755 index 7495db89cb..0000000000 --- a/debianpkg/backports/ubuntu12.04/debian/rules +++ /dev/null @@ -1,162 +0,0 @@ -#!/usr/bin/make -f - -# FRRouting Configuration options -###################################### -# -# WANT_xxxx --> Set to 1 for enable, 0 for disable -# The following are the defaults. They can be overridden by setting a -# env variable to a different value - -WANT_LDP ?= 1 -WANT_PIM ?= 1 -WANT_OSPFAPI ?= 1 -WANT_BGP_VNC ?= 1 -WANT_CUMULUS_MODE ?= 0 -WANT_MULTIPATH ?= 1 -WANT_SNMP ?= 0 - -# NOTES: -# -# If multipath is enabled (WANT_MULTIPATH=1), then set number of multipaths here -# Please be aware that 0 is NOT disabled, but treated as unlimited - -MULTIPATH ?= 256 - -# Set the following to the value required (or leave alone for the default below) -# WANT_FRR_USER is used for the username and groupname of the FRR user account - -WANT_FRR_USER ?= frr -WANT_FRR_VTY_GROUP ?= frrvty - -# Don't build PDF docs by default -GENERATE_PDF ?= 0 - -# -#################################### - -export DH_VERBOSE=1 -export DEB_BUILD_MAINT_OPTIONS = hardening=+all -export DH_OPTIONS=-v - -ifeq ($(WANT_SNMP), 1) - USE_SNMP=--enable-snmp - $(warning "DEBIAN: SNMP enabled, sorry for your inconvenience") -else - USE_SNMP=--disable-snmp - $(warning "DEBIAN: SNMP disabled, see README.Debian") -endif - -ifeq ($(WANT_LDP), 1) - USE_LDP=--enable-ldpd -else - USE_LDP=--disable-ldpd -endif - -ifeq ($(WANT_PIM), 1) - USE_PIM=--enable-pimd -else - USE_PIM=--disable-pimd -endif - -ifeq ($(WANT_OSPFAPI), 1) - USE_OSPFAPI=--enable-ospfapi=yes -else - USE_OSPFAPI=--enable-ospfapi=no -endif - -ifeq ($(WANT_BGP_VNC), 1) - USE_BGP_VNC=--enable-bgp-vnc=yes -else - USE_BGP_VNC=--enable-bgp-vnc=no -endif - -USE_FRR_USER=--enable-user=$(WANT_FRR_USER) -USE_FRR_GROUP=--enable-group=$(WANT_FRR_USER) -USE_FRR_VTY_GROUP=--enable-vty-group=$(WANT_FRR_VTY_GROUP) - -ifeq ($(WANT_MULTIPATH), 1) - USE_MULTIPATH=--enable-multipath=$(MULTIPATH) -else - USE_MULTIPATH=--disable-multipath -endif - -ifeq ($(WANT_CUMULUS_MODE), 1) - USE_CUMULUS=--enable-cumulus=yes -else - USE_CUMULUS=--enable-cumulus=no -endif - -ifneq (,$(filter parallel=%,$(DEB_BUILD_OPTIONS))) - DEBIAN_JOBS := $(subst parallel=,,$(filter parallel=%,$(DEB_BUILD_OPTIONS))) -endif - -ifdef DEBIAN_JOBS -MAKEFLAGS += -j$(DEBIAN_JOBS) -endif - -%: - dh $@ --with=autoreconf --parallel --dbg-package=frr-dbg --list-missing - -override_dh_auto_configure: - # Frr needs /proc to check some BSD vs Linux specific stuff. - # Else it fails with an obscure error message pointing out that - # IPCTL_FORWARDING is an undefined symbol which is not very helpful. - @if ! [ -d /proc/1 ]; then \ - echo "./configure needs a mounted /proc"; \ - exit 1; \ - fi - - if ! [ -e config.status ]; then \ - dh_auto_configure -- \ - --enable-exampledir=/usr/share/doc/frr/examples/ \ - --localstatedir=/var/run/frr \ - --sbindir=/usr/lib/frr \ - --sysconfdir=/etc/frr \ - $(USE_SNMP) \ - $(USE_OSPFAPI) \ - $(USE_MULTIPATH) \ - $(USE_LDP) \ - --enable-fpm \ - $(USE_FRR_USER) $(USE_FRR_GROUP) \ - $(USE_FRR_VTY_GROUP) \ - --enable-configfile-mask=0640 \ - --enable-logfile-mask=0640 \ - --with-libpam \ - --enable-systemd=no \ - --enable-poll=yes \ - $(USE_CUMULUS) \ - $(USE_PIM) \ - --disable-bfdd \ - --enable-dependency-tracking \ - $(USE_BGP_VNC) \ - $(shell dpkg-buildflags --export=configure); \ - fi - -override_dh_auto_build: -ifeq ($(GENERATE_PDF), 1) - dh_auto_build -- -C doc pdf -endif - rm -vf doc/user/_build/texinfo/frr.info - dh_auto_build -- -C doc info - -override_dh_auto_test: - -override_dh_auto_install: - dh_auto_install - - # installed in frr-pythontools - rm debian/tmp/usr/lib/frr/frr-reload.py - - # cleaning up the info dir - rm -f debian/tmp/usr/share/info/dir* - - # install config files - mkdir -p debian/tmp/etc/frr/ - perl -pi -e 's#^!log file #!log file /var/log/frr/#' debian/tmp/usr/share/doc/frr/examples/*sample* - - # leftover from previously shipping SMUX client OID MIB - mkdir -p debian/tmp/usr/share/snmp/mibs - - # cleaning .la files - sed -i "/dependency_libs/ s/'.*'/''/" debian/tmp/usr/lib/*.la - sed -i "/dependency_libs/ s/'.*'/''/" debian/tmp/usr/lib/frr/modules/*.la diff --git a/debianpkg/backports/ubuntu12.04/debian/source/format b/debianpkg/backports/ubuntu12.04/debian/source/format deleted file mode 100644 index 163aaf8d82..0000000000 --- a/debianpkg/backports/ubuntu12.04/debian/source/format +++ /dev/null @@ -1 +0,0 @@ -3.0 (quilt) diff --git a/debianpkg/backports/ubuntu12.04/exclude b/debianpkg/backports/ubuntu12.04/exclude deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/debianpkg/backports/ubuntu12.04/versionext b/debianpkg/backports/ubuntu12.04/versionext deleted file mode 100644 index 159e2e4160..0000000000 --- a/debianpkg/backports/ubuntu12.04/versionext +++ /dev/null @@ -1 +0,0 @@ --1~ubuntu12.04+1 diff --git a/debianpkg/backports/ubuntu14.04/debian/frr.install b/debianpkg/backports/ubuntu14.04/debian/frr.install index 199d264f1a..7fb81c44a0 100644 --- a/debianpkg/backports/ubuntu14.04/debian/frr.install +++ b/debianpkg/backports/ubuntu14.04/debian/frr.install @@ -3,7 +3,6 @@ usr/bin/vtysh usr/bin/mtracebis usr/include/frr/ usr/lib/ -tools/frr etc/init.d/ usr/share/doc/frr/ usr/share/snmp/mibs/ usr/share/yang/ diff --git a/debianpkg/backports/ubuntu14.04/debian/frr.postinst b/debianpkg/backports/ubuntu14.04/debian/frr.postinst deleted file mode 100644 index 5a14e510cd..0000000000 --- a/debianpkg/backports/ubuntu14.04/debian/frr.postinst +++ /dev/null @@ -1,38 +0,0 @@ -#!/bin/bash -e - -###################### -PASSWDFILE=/etc/passwd -GROUPFILE=/etc/group - -frruid=`egrep "^frr:" $PASSWDFILE | awk -F ":" '{ print $3 }'` -frrgid=`egrep "^frr:" $GROUPFILE | awk -F ":" '{ print $3 }'` -frrvtygid=`egrep "^frrvty:" $GROUPFILE | awk -F ":" '{ print $3 }'` - -[ -n ${frruid} ] || (echo "No uid for frr in ${PASSWDFILE}" && /bin/false) -[ -n ${frrgid} ] || (echo "No gid for frr in ${GROUPFILE}" && /bin/false) -[ -n ${frrVTYgid} ] || (echo "No gid for frrvty in ${GROUPFILE}" && /bin/false) - -chown -R ${frruid}:${frrgid} /etc/frr -touch /etc/frr/vtysh.conf -chgrp ${frrvtygid} /etc/frr/vtysh* -chmod 644 /etc/frr/* - -ENVIRONMENTFILE=/etc/environment -if ! egrep --quiet '^VTYSH_PAGER=' ${ENVIRONMENTFILE}; then - echo "VTYSH_PAGER=/bin/cat" >> ${ENVIRONMENTFILE} -fi -################################################## - -if [ -n "$DEBIAN_SCRIPT_DEBUG" ]; then set -v -x; DEBIAN_SCRIPT_TRACE=1; fi -${DEBIAN_SCRIPT_TRACE:+ echo "#42#DEBUG# RUNNING $0 $*"} - -# This is most likely due to the answer "no" to the "really stop the server" -# question in the prerm script. -if [ "$1" = "abort-upgrade" ]; then - exit 0 -fi - -update-rc.d frr defaults > /dev/null - -#DEBHELPER# - diff --git a/debianpkg/backports/ubuntu14.04/debian/frr.postrm b/debianpkg/backports/ubuntu14.04/debian/frr.postrm deleted file mode 100644 index 48c23321f7..0000000000 --- a/debianpkg/backports/ubuntu14.04/debian/frr.postrm +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/bash -e - -if [ -n "$DEBIAN_SCRIPT_DEBUG" ]; then set -v -x; DEBIAN_SCRIPT_TRACE=1; fi -${DEBIAN_SCRIPT_TRACE:+ echo "#42#DEBUG# RUNNING $0 $*"} -# set -u not because of debhelper - -update-rc.d -f frr remove >> /dev/null - -if [ "$1" = "purge" ]; then - rm -rf /etc/frr /var/run/frr /var/log/frr - userdel frr >/dev/null 2>&1 || true -fi - -#DEBHELPER# diff --git a/debianpkg/backports/ubuntu14.04/debian/rules b/debianpkg/backports/ubuntu14.04/debian/rules index 291233c147..21b442d85a 100755 --- a/debianpkg/backports/ubuntu14.04/debian/rules +++ b/debianpkg/backports/ubuntu14.04/debian/rules @@ -178,6 +178,8 @@ override_dh_auto_test: override_dh_auto_install: dh_auto_install + cp tools/frrinit.sh debian/frr.init + # installed in frr-pythontools rm debian/tmp/usr/lib/frr/frr-reload.py diff --git a/debianpkg/rules b/debianpkg/rules index 7cdb8fbaf7..12d6c3545c 100755 --- a/debianpkg/rules +++ b/debianpkg/rules @@ -171,7 +171,7 @@ override_dh_systemd_enable: # backports SRCPKG = frr -KNOWN_BACKPORTS = debian8 debian9 ubuntu12.04 ubuntu14.04 ubuntu16.04 ubuntu17.10 ubuntu18.04 +KNOWN_BACKPORTS = debian8 debian9 ubuntu14.04 ubuntu16.04 ubuntu17.10 ubuntu18.04 DEBIAN_VERSION := $(shell dh_testdir && \ dpkg-parsechangelog -c1 < debian/changelog | \ sed -rn 's/^Version: ?//p') diff --git a/debianpkg/subdir.am b/debianpkg/subdir.am index b6251962b7..af17e4642a 100644 --- a/debianpkg/subdir.am +++ b/debianpkg/subdir.am @@ -23,18 +23,8 @@ EXTRA_DIST += \ debianpkg/backports/debian9/debian/source/format \ debianpkg/backports/debian9/exclude \ debianpkg/backports/debian9/versionext \ - debianpkg/backports/ubuntu12.04/debian/control \ - debianpkg/backports/ubuntu12.04/debian/frr.install \ - debianpkg/backports/ubuntu12.04/debian/frr.postinst \ - debianpkg/backports/ubuntu12.04/debian/frr.postrm \ - debianpkg/backports/ubuntu12.04/debian/rules \ - debianpkg/backports/ubuntu12.04/debian/source/format \ - debianpkg/backports/ubuntu12.04/exclude \ - debianpkg/backports/ubuntu12.04/versionext \ debianpkg/backports/ubuntu14.04/debian/control \ debianpkg/backports/ubuntu14.04/debian/frr.install \ - debianpkg/backports/ubuntu14.04/debian/frr.postinst \ - debianpkg/backports/ubuntu14.04/debian/frr.postrm \ debianpkg/backports/ubuntu14.04/debian/rules \ debianpkg/backports/ubuntu14.04/debian/source/format \ debianpkg/backports/ubuntu14.04/exclude \ diff --git a/doc/developer/building-frr-for-alpine.rst b/doc/developer/building-frr-for-alpine.rst index d303784d4e..f88fc7bfdc 100644 --- a/doc/developer/building-frr-for-alpine.rst +++ b/doc/developer/building-frr-for-alpine.rst @@ -85,7 +85,6 @@ startup. To configure by hand: docker exec -it frr /bin/sh vi /etc/frr/daemons - vi /etc/frr/daemons.conf cp /etc/frr/zebra.conf.sample /etc/frr/zebra.conf vi /etc/frr/zebra.conf /etc/init.d/frr start diff --git a/doc/developer/building-frr-for-ubuntu1204.rst b/doc/developer/building-frr-for-ubuntu1204.rst index 9b2394f018..a2d58e2258 100644 --- a/doc/developer/building-frr-for-ubuntu1204.rst +++ b/doc/developer/building-frr-for-ubuntu1204.rst @@ -158,7 +158,6 @@ Install the init.d service sudo install -m 755 tools/frr /etc/init.d/frr sudo install -m 644 tools/etc/frr/daemons /etc/frr/daemons - sudo install -m 644 tools/etc/frr/daemons.conf /etc/frr/daemons.conf sudo install -m 644 -o frr -g frr tools/etc/frr/vtysh.conf /etc/frr/vtysh.conf Enable daemons diff --git a/doc/developer/building-frr-for-ubuntu1404.rst b/doc/developer/building-frr-for-ubuntu1404.rst index 81ca970469..7952cd682a 100644 --- a/doc/developer/building-frr-for-ubuntu1404.rst +++ b/doc/developer/building-frr-for-ubuntu1404.rst @@ -112,7 +112,6 @@ Install the init.d service sudo install -m 755 tools/frr /etc/init.d/frr sudo install -m 644 tools/etc/frr/daemons /etc/frr/daemons - sudo install -m 644 tools/etc/frr/daemons.conf /etc/frr/daemons.conf sudo install -m 644 -o frr -g frr tools/etc/frr/vtysh.conf /etc/frr/vtysh.conf Enable daemons diff --git a/doc/developer/building-frr-for-ubuntu1604.rst b/doc/developer/building-frr-for-ubuntu1604.rst index 9830b24dfc..f5329fef2c 100644 --- a/doc/developer/building-frr-for-ubuntu1604.rst +++ b/doc/developer/building-frr-for-ubuntu1604.rst @@ -139,9 +139,7 @@ Install the systemd service (if rebooted from last step, change directory back t :: sudo install -m 644 tools/frr.service /etc/systemd/system/frr.service - sudo install -m 644 tools/etc/default/frr /etc/default/frr sudo install -m 644 tools/etc/frr/daemons /etc/frr/daemons - sudo install -m 644 tools/etc/frr/daemons.conf /etc/frr/daemons.conf sudo install -m 644 tools/etc/frr/frr.conf /etc/frr/frr.conf sudo install -m 644 -o frr -g frr tools/etc/frr/vtysh.conf /etc/frr/vtysh.conf diff --git a/doc/developer/building-frr-for-ubuntu1804.rst b/doc/developer/building-frr-for-ubuntu1804.rst index e69ded8f73..110bc6a0ee 100644 --- a/doc/developer/building-frr-for-ubuntu1804.rst +++ b/doc/developer/building-frr-for-ubuntu1804.rst @@ -203,9 +203,7 @@ Install the systemd service :: sudo install -m 644 tools/frr.service /etc/systemd/system/frr.service - sudo install -m 644 tools/etc/default/frr /etc/default/frr sudo install -m 644 tools/etc/frr/daemons /etc/frr/daemons - sudo install -m 644 tools/etc/frr/daemons.conf /etc/frr/daemons.conf sudo install -m 644 tools/etc/frr/frr.conf /etc/frr/frr.conf sudo install -m 644 -o frr -g frr tools/etc/frr/vtysh.conf /etc/frr/vtysh.conf diff --git a/doc/user/rpki.rst b/doc/user/rpki.rst index f48ff2e6ba..295a26fda9 100644 --- a/doc/user/rpki.rst +++ b/doc/user/rpki.rst @@ -67,17 +67,17 @@ Enabling RPKI to configure at least one reachable cache server. See section :ref:`configuring-rpki-rtr-cache-servers` for configuring a cache server. -.. index:: RPKI and daemons.conf +.. index:: RPKI and daemons When first installing FRR with RPKI support from the pre-packaged binaries. Remember to add ``-M rpki`` to the variable ``bgpd_options`` in -:file:`/etc/frr/daemons.conf` , like so:: +:file:`/etc/frr/daemons` , like so:: - bgpd_options=" --daemon -A 127.0.0.1 -M rpki" + bgpd_options=" -A 127.0.0.1 -M rpki" instead of the default setting:: - bgpd_options=" --daemon -A 127.0.0.1" + bgpd_options=" -A 127.0.0.1" Otherwise you will encounter an error when trying to enter RPKI configuration mode due to the ``rpki`` module not being loaded when the BGP diff --git a/doc/user/setup.rst b/doc/user/setup.rst index 8a76a61e78..3a09c50309 100644 --- a/doc/user/setup.rst +++ b/doc/user/setup.rst @@ -41,7 +41,7 @@ Daemons Configuration File -------------------------- There is another file that controls the default options passed to daemons when starting FRR as a service. This file is located in your configuration -directory, usually at :file:`/etc/frr/daemons.conf`. +directory, usually at :file:`/etc/frr/daemons`. This file has several parts. Here is an example: diff --git a/redhat/daemons b/redhat/daemons index c301a1c23a..7f3ff36df9 100644 --- a/redhat/daemons +++ b/redhat/daemons @@ -35,7 +35,7 @@ # group "frrvty" and set to ug=rw,o= though. Check /etc/pam.d/frr, too. # watchfrr_enable=yes -watchfrr_options=("-b_" "-r/usr/lib/frr/frr_restart_%s" "-s/usr/lib/frr/frr_start_%s" "-k/usr/lib/frr/frr_stop_%s") +watchfrr_options="-r '/usr/lib/frr/frr restart %s' -s '/usr/lib/frr/frr start %s' -k '/usr/lib/frr/frr stop %s'" # zebra=no bgpd=no diff --git a/redhat/frr.init b/redhat/frr.init index 47a92eed32..b59656adcd 100755 --- a/redhat/frr.init +++ b/redhat/frr.init @@ -107,22 +107,28 @@ check_daemon() # The Frr daemons creates the pidfile when starting. start() { + local dmn inst + dmn="$1" + inst="$2" + ulimit -n $MAX_FDS > /dev/null 2> /dev/null - if [ "$1" = "watchfrr" ]; then + if [ "$dmn" = "watchfrr" ]; then # We may need to restart watchfrr if new daemons are added and/or # removed - if started "$1" ; then + if started "$dmn" ; then stop watchfrr else # Echo only once. watchfrr is printed in the stop above - echo -n " $1" + echo -n " $dmn" fi if [ -e /var/run/frr/watchfrr.started ] ; then rm /var/run/frr/watchfrr.started fi - daemon --pidfile=`pidfile $1` "$D_PATH/$1" -d "${watchfrr_options[@]}" + # redhat /etc/init.d/functions daemon() re-expands args :( + # eval "set - $watchfrr_options" + daemon --pidfile=`pidfile $dmn` "$D_PATH/$dmn" -d "$watchfrr_options" RETVAL=$? [ $RETVAL -ne 0 ] && break for i in `seq 1 10`; @@ -135,25 +141,25 @@ start() fi done RETVAL=1 - elif [ -n "$2" ]; then - echo -n " $1-$2" - if ! check_daemon $1 $2 ; then + elif [ -n "$inst" ]; then + echo -n " $dmn-$inst" + if ! check_daemon $dmn $inst ; then echo -n " (binary does not exist)" return; fi - daemon --pidfile=`pidfile $1-$2` "$D_PATH/$1" -d `eval echo "$""$1""_options"` -n "$2" + daemon --pidfile=`pidfile $dmn-$inst` "$D_PATH/$dmn" -d `eval echo "$""$dmn""_options"` -n "$inst" RETVAL=$? else - echo -n " $1 " - if ! check_daemon $1; then + echo -n " $dmn " + if ! check_daemon $dmn; then echo " (binary does not exist)" return; fi - daemon --pidfile=`pidfile $1` "$D_PATH/$1" -d `eval echo "$""$1""_options"` + daemon --pidfile=`pidfile $dmn` "$D_PATH/$dmn" -d `eval echo "$""$dmn""_options"` RETVAL=$? fi echo - [ $RETVAL -eq 0 ] && touch /var/lock/subsys/$1 + [ $RETVAL -eq 0 ] && touch /var/lock/subsys/$dmn return $RETVAL } @@ -223,11 +229,9 @@ start_watchfrr() fi # Check variable type - if ! declare -p watchfrr_options | grep -q '^declare \-a'; then - echo - echo "ERROR: The variable watchfrr_options from /etc/frr/daemons must be a BASH array!" - echo "ERROR: Please convert config file and restart!" - exit 1 + if declare -p watchfrr_options | grep -q '^declare \-a'; then + # old array support + watchfrr_options="${watchfrr_options[@]}" fi # Which daemons have been started? @@ -241,13 +245,13 @@ start_watchfrr() eval "inst_disable=\${${daemon_name}_${inst}}" if [ -z ${inst_disable} ] || [ ${inst_disable} != 0 ]; then if check_daemon $daemon_name $inst; then - watchfrr_options+=("${daemon_name}-${inst}") + watchfrr_options="$watchfrr_options ${daemon_name}-${inst}" fi fi done else if check_daemon $daemon_name; then - watchfrr_options+=($daemon_name) + watchfrr_options="$watchfrr_options $daemon_name" fi fi found_one=1 diff --git a/redhat/frr.spec.in b/redhat/frr.spec.in index d2da06faa6..7a6344aa4c 100644 --- a/redhat/frr.spec.in +++ b/redhat/frr.spec.in @@ -637,6 +637,9 @@ fi %config(noreplace) %{_sysconfdir}/pam.d/frr %config(noreplace) %{_sysconfdir}/logrotate.d/frr %{_sbindir}/frr-reload +%{_sbindir}/frrcommon.sh +%{_sbindir}/frrinit.sh +%{_sbindir}/watchfrr.sh %files contrib diff --git a/tools/.gitignore b/tools/.gitignore index c23322c4c6..85dae7fd36 100644 --- a/tools/.gitignore +++ b/tools/.gitignore @@ -3,3 +3,6 @@ /gen_yang_deviations /permutations /ssd +/watchfrr.sh +/frrinit.sh +/frrcommon.sh diff --git a/tools/etc/default/frr b/tools/etc/default/frr deleted file mode 100644 index 693fa63390..0000000000 --- a/tools/etc/default/frr +++ /dev/null @@ -1,10 +0,0 @@ -MAX_INSTANCES=5 -MAX_FDS=1024 -ZEBRA_OPTIONS="-s 16777216 -A 127.0.0.1" -BGPD_OPTIONS="-A 127.0.0.1" -OSPFD_OPTIONS="-A 127.0.0.1" -OSPF6D_OPTIONS="-A ::1" -RIPD_OPTIONS="-A 127.0.0.1" -RIPNGD_OPTIONS="-A ::1" -ISISD_OPTIONS="-A 127.0.0.1" -EIGRP_OPTIONS="-A 127.0.0.1" diff --git a/tools/etc/frr/daemons b/tools/etc/frr/daemons index 1514082e90..2d56fe1b98 100644 --- a/tools/etc/frr/daemons +++ b/tools/etc/frr/daemons @@ -1,11 +1,5 @@ # This file tells the frr package which daemons to start. # -# Entries are in the format: =(yes|no|priority) -# 0, "no" = disabled -# 1, "yes" = highest priority -# 2 .. 10 = lower priorities -# Read /usr/share/doc/frr/README.Debian for details. -# # Sample configurations for these daemons can be found in # /usr/share/doc/frr/examples/. # @@ -18,10 +12,8 @@ # When using "vtysh" such a config file is also needed. It should be owned by # group "frrvty" and set to ug=rw,o= though. Check /etc/pam.d/frr, too. # -# The watchfrr daemon is always started. Per default in monitoring-only but -# that can be changed via /etc/frr/daemons.conf. +# The watchfrr and zebra daemons are always started. # -zebra=no bgpd=no ospfd=no ospf6d=no @@ -37,3 +29,37 @@ sharpd=no pbrd=no bfdd=no fabricd=no + +# +# If this option is set the /etc/init.d/frr script automatically loads +# the config via "vtysh -b" when the servers are started. +# Check /etc/pam.d/frr if you intend to use "vtysh"! +# +vtysh_enable=yes +zebra_options=" -A 127.0.0.1 -s 90000000" +bgpd_options=" -A 127.0.0.1" +ospfd_options=" -A 127.0.0.1" +ospf6d_options=" -A ::1" +ripd_options=" -A 127.0.0.1" +ripngd_options=" -A ::1" +isisd_options=" -A 127.0.0.1" +pimd_options=" -A 127.0.0.1" +ldpd_options=" -A 127.0.0.1" +nhrpd_options=" -A 127.0.0.1" +eigrpd_options=" -A 127.0.0.1" +babeld_options=" -A 127.0.0.1" +sharpd_options=" -A 127.0.0.1" +pbrd_options=" -A 127.0.0.1" +staticd_options="-A 127.0.0.1" +bfdd_options=" -A 127.0.0.1" +fabricd_options="-A 127.0.0.1" + +# The list of daemons to watch is automatically generated by the init script. +watchfrr_options="-r '/usr/lib/frr/watchfrr.sh restart %s' -s '/usr/lib/frr/watchfrr.sh start %s' -k '/usr/lib/frr/watchfrr.sh stop %s'" + +# for debugging purposes, you can specify a "wrap" command to start instead +# of starting the daemon directly, e.g. to use valgrind on ospfd: +# ospfd_wrap="/usr/bin/valgrind" +# or you can use "all_wrap" for all daemons, e.g. to use perf record: +# all_wrap="/usr/bin/perf record --call-graph -" +# the normal daemon command is added to this at the end. diff --git a/tools/etc/frr/daemons.conf b/tools/etc/frr/daemons.conf index 94221301eb..70b96a9800 100644 --- a/tools/etc/frr/daemons.conf +++ b/tools/etc/frr/daemons.conf @@ -1,33 +1 @@ -# -# If this option is set the /etc/init.d/frr script automatically loads -# the config via "vtysh -b" when the servers are started. -# Check /etc/pam.d/frr if you intend to use "vtysh"! -# -vtysh_enable=yes -zebra_options=" -s 90000000 --daemon -A 127.0.0.1" -bgpd_options=" --daemon -A 127.0.0.1" -ospfd_options=" --daemon -A 127.0.0.1" -ospf6d_options=" --daemon -A ::1" -ripd_options=" --daemon -A 127.0.0.1" -ripngd_options=" --daemon -A ::1" -isisd_options=" --daemon -A 127.0.0.1" -pimd_options=" --daemon -A 127.0.0.1" -ldpd_options=" --daemon -A 127.0.0.1" -nhrpd_options=" --daemon -A 127.0.0.1" -eigrpd_options=" --daemon -A 127.0.0.1" -babeld_options=" --daemon -A 127.0.0.1" -sharpd_options=" --daemon -A 127.0.0.1" -pbrd_options=" --daemon -A 127.0.0.1" -staticd_options=" --daemon -A 127.0.0.1" -bfdd_options=" --daemon -A 127.0.0.1" -fabricd_options=" --daemon -A 127.0.0.1" - -# The list of daemons to watch is automatically generated by the init script. -watchfrr_enable=yes - -watchfrr_options=(-d -r /usr/lib/frr/frrbBrestartbB%s -s /usr/lib/frr/frrbBstartbB%s -k /usr/lib/frr/frrbBstopbB%s -b bB) - -# If valgrind_enable is 'yes' the frr daemons will be started via valgrind. -# The use case for doing so is tracking down memory leaks, etc in frr. -valgrind_enable=no -valgrind=/usr/bin/valgrind +# this file is deprecated, please use "daemons" instead. diff --git a/tools/frr.in b/tools/frr.in index ec383bc5a0..a443191fd0 100755 --- a/tools/frr.in +++ b/tools/frr.in @@ -115,41 +115,45 @@ check_daemon() # The Frr daemons creates the pidfile when starting. start() { - ulimit -n $MAX_FDS - if [ "$1" = "watchfrr" ]; then + local dmn inst + dmn="$1" + inst="$2" + + ulimit -n $MAX_FDS > /dev/null 2> /dev/null + if [ "$dmn" = "watchfrr" ]; then # We may need to restart watchfrr if new daemons are added and/or # removed - if started "$1" ; then + if started "$dmn" ; then stop watchfrr else # Echo only once. watchfrr is printed in the stop above - echo -n " $1" + echo -n " $dmn" fi - + eval "set - $watchfrr_options" ${SSD} \ --start \ - --pidfile=`pidfile $1` \ - --exec "$D_PATH/$1" \ + --pidfile=`pidfile $dmn` \ + --exec "$D_PATH/$dmn" \ -- \ - "${watchfrr_options[@]}" + "$@" - elif [ -n "$2" ]; then - echo -n " $1-$2" - if ! check_daemon $1 $2 ; then + elif [ -n "$inst" ]; then + echo -n " $dmn-$inst" + if ! check_daemon $dmn $inst ; then echo -n " (binary does not exist)" return; fi ${SSD} \ --start \ - --pidfile=`pidfile $1-$2` \ - --exec "$D_PATH/$1" \ + --pidfile=`pidfile $dmn-$inst` \ + --exec "$D_PATH/$dmn" \ -- \ - `eval echo "$""$1""_options"` -n "$2" + `eval echo "$""$dmn""_options"` -n "$inst" else - if ! check_daemon $1; then + if ! check_daemon $dmn; then echo -n " (binary does not exist)" return; fi @@ -157,22 +161,22 @@ start() if [ "$valgrind_enable" = "yes" ]; then ${SSD} \ --start \ - --pidfile=`pidfile $1` \ + --pidfile=`pidfile $dmn` \ --exec "$valgrind" \ - -- --trace-children=no --leak-check=full --log-file=/var/log/frr/$1-valgrind.log $D_PATH/$1 \ - `eval echo "$""$1""_options"` + -- --trace-children=no --leak-check=full --log-file=/var/log/frr/$dmn-valgrind.log $D_PATH/$dmn \ + `eval echo "$""$dmn""_options"` else ${SSD} \ --start \ - --pidfile=`pidfile $1` \ - --exec "$D_PATH/$1" \ + --pidfile=`pidfile $dmn` \ + --exec "$D_PATH/$dmn" \ -- \ - `eval echo "$""$1""_options"` + `eval echo "$""$dmn""_options"` fi fi # Start the staticd automatically - if [ "$1" = "zebra" ]; then + if [ "$dmn" = "zebra" ]; then echo -n "starting staticd since zebra is running" if ! check_daemon staticd ; then echo -n " (binary does not exist)" @@ -269,11 +273,9 @@ start_watchfrr() fi # Check variable type - if ! declare -p watchfrr_options | grep -q '^declare \-a'; then - echo - echo "ERROR: The variable watchfrr_options from /etc/frr/debian.cnf must be a BASH array!" - echo "ERROR: Please convert config file and restart!" - exit 1 + if declare -p watchfrr_options | grep -q '^declare \-a'; then + # old array support + watchfrr_options="${watchfrr_options[@]}" fi # Which daemons have been started? @@ -287,13 +289,13 @@ start_watchfrr() eval "inst_disable=\${${daemon_name}_${inst}}" if [ -z ${inst_disable} ] || [ ${inst_disable} != 0 ]; then if check_daemon $daemon_name $inst; then - watchfrr_options+=("${daemon_name}-${inst}") + watchfrr_options="$watchfrr_options ${daemon_name}-${inst}" fi fi done else if check_daemon $daemon_name; then - watchfrr_options+=($daemon_name) + watchfrr_options="$watchfrr_options $daemon_name" fi fi found_one=1 diff --git a/tools/frr.service b/tools/frr.service index 5f44274ec3..03112bd7cd 100644 --- a/tools/frr.service +++ b/tools/frr.service @@ -5,7 +5,6 @@ OnFailure=heartbeat-failed@%n.service [Service] Nice=-5 -EnvironmentFile=/etc/default/frr Type=forking NotifyAccess=all StartLimitInterval=3m @@ -15,8 +14,8 @@ WatchdogSec=60s RestartSec=5 Restart=on-abnormal LimitNOFILE=1024 -ExecStart=/usr/lib/frr/frr start -ExecStop=/usr/lib/frr/frr stop -ExecReload=/usr/lib/frr/frr-reload +ExecStart=/usr/lib/frr/frrinit.sh start +ExecStop=/usr/lib/frr/frrinit.sh stop +ExecReload=/usr/lib/frr/frrinit.sh reload [Install] WantedBy=network-online.target diff --git a/tools/frrcommon.sh.in b/tools/frrcommon.sh.in new file mode 100644 index 0000000000..7278e3f9df --- /dev/null +++ b/tools/frrcommon.sh.in @@ -0,0 +1,317 @@ +#!/bin/sh +# +# This is a "library" of sorts for use by the other FRR shell scripts. It +# has most of the daemon start/stop logic, but expects the following shell +# functions/commands to be provided by the "calling" script: +# +# log_success_msg +# log_warning_msg +# log_failure_msg +# +# (coincidentally, these are LSB standard functions.) +# +# Sourcing this file in a shell script will load FRR config variables but +# not perform any action. Note there is an "exit 1" if the main config +# file does not exist. +# +# This script should be installed in @CFG_SBIN@/frrcommon.sh + +PATH=/bin:/usr/bin:/sbin:/usr/sbin +D_PATH="@CFG_SBIN@" # /usr/lib/frr +C_PATH="@CFG_SYSCONF@" # /etc/frr +V_PATH="@CFG_STATE@" # /var/run/frr +VTYSH="@vtysh_bin@" # /usr/bin/vtysh +FRR_USER="@enable_user@" # frr +FRR_GROUP="@enable_group@" # frr +FRR_VTY_GROUP="@enable_vty_group@" # frrvty + +# ORDER MATTERS FOR $DAEMONS! +# - keep zebra first +# - watchfrr does NOT belong in this list + +DAEMONS="zebra bgpd ripd ripngd ospfd ospf6d isisd babeld pimd ldpd nhrpd eigrpd sharpd pbrd staticd bfdd fabricd" +RELOAD_SCRIPT="$D_PATH/frr-reload.py" + +# +# general helpers +# + +debug() { + [ -n "$watchfrr_debug" ] || return 0 + + printf '%s %s(%s):' "`date +%Y-%m-%dT%H:%M:%S.%N`" "$0" $$ >&2 + # this is to show how arguments are split regarding whitespace & co. + # (e.g. for use with `debug "message" "$@"`) + while [ $# -gt 0 ]; do + printf ' "%s"' "$1" >&2 + shift + done + printf '\n' >&2 +} + +chownfrr() { + [ -n "$FRR_USER" ] && chown "$FRR_USER" "$1" + [ -n "$FRR_GROUP" ] && chgrp "$FRR_GROUP" "$1" +} + +vtysh_b () { + [ "$1" = "watchfrr" ] && return 0 + [ -r "$C_PATH/frr.conf" ] || return 0 + if [ -n "$1" ]; then + "$VTYSH" -b -n -d "$1" + else + "$VTYSH" -b -n + fi +} + +daemon_inst() { + # note this sets global variables ($dmninst, $daemon, $inst) + dmninst="$1" + daemon="${dmninst%:*}" + inst="" + [ "$daemon" != "$dmninst" ] && inst="${dmninst#*:}" +} + +daemon_list() { + # note $1 and $2 specify names for global variables to be set + local enabled disabled evar dvar + enabled="" + disabled="" + evar="$1" + dvar="$2" + + for daemon in $DAEMONS; do + eval cfg=\$$daemon + eval inst=\$${daemon}_instances + [ "$daemon" = zebra ] && cfg=yes + if [ -n "$cfg" -a "$cfg" != "no" -a "$cfg" != "0" ]; then + debug "$daemon enabled" + enabled="$enabled $daemon" + if [ -n "$inst" ]; then + debug "$daemon multi-instance $inst" + for i in $inst; do + enabled="$enabled $daemon:$inst" + done + fi + else + debug "$daemon disabled" + disabled="$disabled $daemon" + fi + done + + enabled="${enabled# }" + disabled="${disabled# }" + [ -z "$evar" ] && echo "$enabled" + [ -n "$evar" ] && eval $evar="\"$enabled\"" + [ -n "$dvar" ] && eval $dvar="\"$disabled\"" +} + +# +# individual daemon management +# + +daemon_prep() { + local daemon inst cfg + daemon="$1" + inst="$2" + [ "$daemon" = "watchfrr" ] && return 0 + [ -x "$D_PATH/$daemon" ] || { + log_failure_msg "cannot start $daemon${inst:+ (instance $inst)}: daemon binary not installed\n" + return 1 + } + [ -r "$C_PATH/frr.conf" ] && return 0 + + cfg="$C_PATH/$daemon${inst:+-$inst}.conf" + if [ ! -r "$cfg" ]; then + touch "$cfg" + chownfrr "$cfg" + fi + return 0 +} + +daemon_start() { + local dmninst daemon inst args instopt wrap bin + daemon_inst "$1" + + ulimit -n $MAX_FDS > /dev/null 2> /dev/null + daemon_prep "$daemon" "$inst" || return 1 + + eval wrap="\$${daemon}_wrap" + bin="$D_PATH/$daemon" + instopt="${inst:+-n $inst}" + eval args="\$${daemon}_options" + + if eval "$all_wrap $wrap $bin -d $instopt $args"; then + log_success_msg "Started $dmninst" + vtysh_b "$daemon" + else + log_failure_msg "Failed to start $dmninst!" + fi +} + +daemon_stop() { + local dmninst daemon inst pidfile vtyfile pid cnt fail + daemon_inst "$1" + + pidfile="$V_PATH/$daemon${inst:+-$inst}.pid" + vtyfile="$V_PATH/$daemon${inst:+-$inst}.vty" + + [ -r "$pidfile" ] || fail="pid file not found" + [ -z "$fail" ] && pid="`cat \"$pidfile\"`" + [ -z "$fail" -a -z "$pid" ] && fail="pid file is empty" + [ -n "$fail" ] || kill -0 "$pid" 2>/dev/null || fail="pid $pid not running" + + if [ -n "$fail" ]; then + log_failure_msg "Cannot stop $dmninst: $fail" + return 1 + fi + + debug "kill -2 $pid" + kill -2 "$pid" + cnt=1200 + while kill -0 "$pid" 2>/dev/null; do + sleep .1 + [ $(( cnt -= 1 )) -gt 0 ] || break + done + if kill -0 "$pid" 2>/dev/null; then + log_failure_msg "Failed to stop $dmninst, pid $pid still running" + still_running=1 + return 1 + else + log_success_msg "Stopped $dmninst" + rm -f "$pidfile" + return 0 + fi +} + +daemon_status() { + local dmninst daemon inst pidfile pid fail + daemon_inst "$1" + + pidfile="$V_PATH/$daemon${inst:+-$inst}.pid" + + [ -r "$pidfile" ] || return 3 + pid="`cat \"$pidfile\"`" + [ -z "$pid" ] && return 1 + kill -0 "$pid" 2>/dev/null || return 1 + return 0 +} + +print_status() { + daemon_status "$1" + rv=$? + if [ "$rv" -eq 0 ]; then + log_success_msg "Status of $1: running" + else + log_failure_msg "Status of $1: FAILED" + fi + return $rv +} + +# +# all-daemon commands +# + +all_start() { + daemon_list daemons + for dmninst in $daemons; do + daemon_start "$dmninst" + done +} + +all_stop() { + local pids reversed + + daemon_list daemons disabled + [ "$1" = "--reallyall" ] && daemons="$daemons $disabled" + + reversed="" + for dmninst in $daemons; do + reversed="$dmninst $reversed" + done + + for dmninst in $reversed; do + daemon_stop "$dmninst" & + pids="$pids $!" + done + for pid in $pids; do + wait $pid + done +} + +all_status() { + local fail + + daemon_list daemons + fail=0 + for dmninst in $daemons; do + print_status "$dmninst" || fail=1 + done + return $fail +} + +# +# config sourcing +# + +load_old_config() { + oldcfg="$1" + [ -r "$oldcfg" ] || return 0 + [ -s "$oldcfg" ] || return 0 + grep -v '^[[:blank:]]*\(#\|$\)' "$oldcfg" > /dev/null || return 0 + + log_warning_msg "Reading deprecated $oldcfg. Please move its settings to $C_PATH/daemons and remove it." + + # save off settings from daemons for the OR below + for dmn in $DAEMONS; do eval "_new_$dmn=\${$dmn:-no}"; done + + . "$oldcfg" + + # OR together the daemon enabling options between config files + for dmn in $DAEMONS; do eval "test \$_new_$dmn != no && $dmn=\$_new_$dmn; unset _new_$dmn"; done +} + +[ -r "$C_PATH/daemons" ] || { + log_failure_msg "cannot run $@: $C_PATH/daemons does not exist\n" + exit 1 +} +. "$C_PATH/daemons" + +load_old_config "$C_PATH/daemons.conf" +load_old_config "/etc/default/frr" +load_old_config "/etc/sysconfig/frr" + +# +# other defaults and dispatch +# + +frrcommon_main() { + local cmd + + debug "frrcommon_main" "$@" + + cmd="$1" + shift + + if [ "$1" = "all" -o -z "$1" ]; then + case "$cmd" in + start) all_start;; + stop) all_stop;; + restart) + all_stop + all_start + ;; + *) $cmd "$@";; + esac + else + case "$cmd" in + start) daemon_start "$@";; + stop) daemon_stop "$@";; + restart) + daemon_stop "$@" + daemon_start "$@" + ;; + *) $cmd "$@";; + esac + fi +} diff --git a/tools/frrinit.sh.in b/tools/frrinit.sh.in new file mode 100644 index 0000000000..3dddf5bd44 --- /dev/null +++ b/tools/frrinit.sh.in @@ -0,0 +1,90 @@ +#!/bin/sh +# +### BEGIN INIT INFO +# Provides: frr +# Required-Start: $local_fs $network $remote_fs $syslog +# Required-Stop: $local_fs $network $remote_fs $syslog +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: start and stop the FRR routing suite +# Description: FRR is a routing suite for IP routing protocols like +# BGP, OSPF, RIP and others. This script contols the main +# "watchfrr" daemon. +### END INIT INFO +# +# This is the main init script for FRR. It mostly wraps frrcommon.sh which +# provides the actual functions to start/stop/restart things. +# + +if [ -r "/lib/lsb/init-functions" ]; then + . /lib/lsb/init-functions +else + log_success_msg() { + echo "$@" + } + log_warning_msg() { + echo "$@" >&2 + } + log_failure_msg() { + echo "$@" >&2 + } +fi + +self="`dirname $0`" +if [ -r "$self/frrcommon.sh" ]; then + . "$self/frrcommon.sh" +else + . "@CFG_SBIN@/frrcommon.sh" +fi + +case "$1" in +start) + daemon_list daemons + watchfrr_options="$watchfrr_options $daemons" + daemon_start watchfrr + ;; +stop) + daemon_stop watchfrr + all_stop --reallyall + exit ${still_running:-0} + ;; + +restart|force-reload) + daemon_stop watchfrr + all_stop --reallyall + + daemon_list daemons + watchfrr_options="$watchfrr_options $daemons" + daemon_start watchfrr + ;; + +status) + fail=0 + print_status watchfrr || fail=1 + all_status || fail=1 + exit $fail + ;; + +reload) + if [ ! -x "$RELOAD_SCRIPT" ]; then + log_failure_msg "The frr-pythontools package is required for reload functionality." + exit 1 + fi + + # restart watchfrr to pick up added daemons. + # NB: This will NOT cause the other daemons to be restarted. + daemon_list daemons + watchfrr_options="$watchfrr_options $daemons" + daemon_stop watchfrr && \ + daemon_start watchfrr + + NEW_CONFIG_FILE="${2:-$C_PATH/frr.conf}" + [ ! -r $NEW_CONFIG_FILE ] && log_failure_msg "Unable to read new configuration file $NEW_CONFIG_FILE" && exit 1 + "$RELOAD_SCRIPT" --reload "$NEW_CONFIG_FILE" + exit $? + ;; + +*) + log_failure_msg "Unknown command: $1" >&2 + exit 1 +esac diff --git a/tools/subdir.am b/tools/subdir.am index 2e68dfee09..ff41fe2c63 100644 --- a/tools/subdir.am +++ b/tools/subdir.am @@ -13,6 +13,10 @@ sbin_SCRIPTS += \ tools/frr-reload \ tools/frr-reload.py \ tools/frr \ + \ + tools/frrcommon.sh \ + tools/frrinit.sh \ + tools/watchfrr.sh \ # end tools_permutations_SOURCES = tools/permutations.c diff --git a/tools/watchfrr.sh.in b/tools/watchfrr.sh.in new file mode 100644 index 0000000000..3051d91044 --- /dev/null +++ b/tools/watchfrr.sh.in @@ -0,0 +1,33 @@ +#!/bin/sh +# +# This is NOT the init script! This is the watchfrr start/stop/restart +# command handler, passed to watchfrr with the -s/-r/-k commands. It is used +# internally by watchfrr to start the protocol daemons with the appropriate +# options. +# +# This script should be installed in @CFG_SBIN@/watchfrr.sh + +log_success_msg() { + : +} + +log_warning_msg() { + echo "$@" >&2 + [ -x /usr/bin/logger ] && echo "$@" \ + | /usr/bin/logger -t watchfrr.sh -p daemon.warn +} + +log_failure_msg() { + echo "$@" >&2 + [ -x /usr/bin/logger ] && echo "$@" \ + | /usr/bin/logger -t watchfrr.sh -p daemon.err +} + +self="`dirname $0`" +if [ -r "$self/frrcommon.sh" ]; then + . "$self/frrcommon.sh" +else + . "@CFG_SBIN@/frrcommon.sh" +fi + +frrcommon_main "$@" diff --git a/vtysh/vtysh.c b/vtysh/vtysh.c index f57a4d9ddf..2327f2b46d 100644 --- a/vtysh/vtysh.c +++ b/vtysh/vtysh.c @@ -104,7 +104,7 @@ static int vty_close_pager(struct vty *vty) return 0; } -void vtysh_pager_init(void) +static void vtysh_pager_envdef(void) { char *pager_defined; @@ -2881,52 +2881,58 @@ DEFUN (vtysh_copy_running_config, return vtysh_write_memory(self, vty, argc, argv); } +DEFUN (vtysh_terminal_paginate, + vtysh_terminal_paginate_cmd, + "[no] terminal paginate", + NO_STR + "Set terminal line parameters\n" + "Use pager for output scrolling\n") +{ + free(vtysh_pager_name); + vtysh_pager_name = NULL; + + if (strcmp(argv[0]->text, "no")) + vtysh_pager_envdef(); + return CMD_SUCCESS; +} + DEFUN (vtysh_terminal_length, vtysh_terminal_length_cmd, - "terminal length (0-512)", + "[no] terminal length (0-4294967295)", + NO_STR "Set terminal line parameters\n" "Set number of lines on a screen\n" - "Number of lines on screen (0 for no pausing)\n") + "Number of lines on screen (0 for no pausing, nonzero to use pager)\n") { int idx_number = 2; - int lines; - char *endptr = NULL; - char default_pager[10]; + unsigned long lines; - lines = strtol(argv[idx_number]->arg, &endptr, 10); - if (lines < 0 || lines > 512 || *endptr != '\0') { - vty_out(vty, "length is malformed\n"); - return CMD_WARNING; - } - - if (vtysh_pager_name) { - free(vtysh_pager_name); - vtysh_pager_name = NULL; + free(vtysh_pager_name); + vtysh_pager_name = NULL; + + if (!strcmp(argv[0]->text, "no") || !strcmp(argv[1]->text, "no")) { + /* "terminal no length" = use VTYSH_PAGER */ + vtysh_pager_envdef(); + return CMD_SUCCESS; } + lines = strtoul(argv[idx_number]->arg, NULL, 10); if (lines != 0) { - snprintf(default_pager, 10, "more -%i", lines); - vtysh_pager_name = strdup(default_pager); + vty_out(vty, + "%% The \"terminal length\" command is deprecated and its value is ignored.\n" + "%% Please use \"terminal paginate\" instead with OS TTY length handling.\n"); + vtysh_pager_envdef(); } return CMD_SUCCESS; } -DEFUN (vtysh_terminal_no_length, +ALIAS_DEPRECATED(vtysh_terminal_length, vtysh_terminal_no_length_cmd, "terminal no length", "Set terminal line parameters\n" NO_STR "Set number of lines on a screen\n") -{ - if (vtysh_pager_name) { - free(vtysh_pager_name); - vtysh_pager_name = NULL; - } - - vtysh_pager_init(); - return CMD_SUCCESS; -} DEFUN (vtysh_show_daemons, vtysh_show_daemons_cmd, @@ -3805,6 +3811,7 @@ void vtysh_init_vty(void) /* "write memory" command. */ install_element(ENABLE_NODE, &vtysh_write_memory_cmd); + install_element(VIEW_NODE, &vtysh_terminal_paginate_cmd); install_element(VIEW_NODE, &vtysh_terminal_length_cmd); install_element(VIEW_NODE, &vtysh_terminal_no_length_cmd); install_element(VIEW_NODE, &vtysh_show_daemons_cmd); diff --git a/vtysh/vtysh.h b/vtysh/vtysh.h index 430b117c50..eb69a20b83 100644 --- a/vtysh/vtysh.h +++ b/vtysh/vtysh.h @@ -98,8 +98,6 @@ void vtysh_config_dump(void); void vtysh_config_init(void); -void vtysh_pager_init(void); - void suid_on(void); void suid_off(void); diff --git a/vtysh/vtysh_main.c b/vtysh/vtysh_main.c index 777eed7b5d..2e4510a45a 100644 --- a/vtysh/vtysh_main.c +++ b/vtysh/vtysh_main.c @@ -675,8 +675,6 @@ int main(int argc, char **argv, char **env) exit(0); } - vtysh_pager_init(); - vtysh_readline_init(); vty_hello(vty); diff --git a/watchfrr/watchfrr.c b/watchfrr/watchfrr.c index e32bf3359b..e28da6db8c 100644 --- a/watchfrr/watchfrr.c +++ b/watchfrr/watchfrr.c @@ -65,6 +65,7 @@ static bool watch_only = false; typedef enum { PHASE_NONE = 0, + PHASE_INIT, PHASE_STOPS_PENDING, PHASE_WAITING_DOWN, PHASE_ZEBRA_RESTART_PENDING, @@ -72,7 +73,8 @@ typedef enum { } restart_phase_t; static const char *phase_str[] = { - "None", + "Idle", + "Startup", "Stop jobs running", "Waiting for other daemons to come down", "Zebra restart job running", @@ -112,7 +114,7 @@ static struct global_state { int numpids; int numdown; /* # of daemons that are not UP or UNRESPONSIVE */ } gs = { - .phase = PHASE_NONE, + .phase = PHASE_INIT, .vtydir = frr_vtydir, .period = 1000 * DEFAULT_PERIOD, .timeout = DEFAULT_TIMEOUT, @@ -177,6 +179,7 @@ static int try_connect(struct daemon *dmn); static int wakeup_send_echo(struct thread *t_wakeup); static void try_restart(struct daemon *dmn); static void phase_check(void); +static void restart_done(struct daemon *dmn); static const char *progname; static void printhelp(FILE *target) @@ -333,6 +336,7 @@ static void sigchild(void) const char *name; const char *what; struct restart_info *restart; + struct daemon *dmn; switch (child = waitpid(-1, &status, WNOHANG)) { case -1: @@ -378,9 +382,18 @@ static void sigchild(void) zlog_warn( "%s %s process %d exited with non-zero status %d", what, name, (int)child, WEXITSTATUS(status)); - else + else { zlog_debug("%s %s process %d exited normally", what, name, (int)child); + + if (restart && restart != &gs.restart) { + dmn = container_of(restart, struct daemon, + restart); + restart_done(dmn); + } else if (restart) + for (dmn = gs.daemons; dmn; dmn = dmn->next) + restart_done(dmn); + } } else flog_err_sys( EC_LIB_SYSTEM_CALL, @@ -494,15 +507,27 @@ static int wakeup_init(struct thread *t_wakeup) dmn->t_wakeup = NULL; if (try_connect(dmn) < 0) { - SET_WAKEUP_DOWN(dmn); flog_err(EC_WATCHFRR_CONNECTION, "%s state -> down : initial connection attempt failed", dmn->name); dmn->state = DAEMON_DOWN; } + phase_check(); return 0; } +static void restart_done(struct daemon *dmn) +{ + if (dmn->state != DAEMON_DOWN) { + zlog_warn("wtf?"); + return; + } + if (dmn->t_wakeup) + THREAD_OFF(dmn->t_wakeup); + if (try_connect(dmn) < 0) + SET_WAKEUP_DOWN(dmn); +} + static void daemon_down(struct daemon *dmn, const char *why) { if (IS_UP(dmn) || (dmn->state == DAEMON_INIT)) @@ -773,9 +798,25 @@ static void set_phase(restart_phase_t new_phase) static void phase_check(void) { + struct daemon *dmn; + switch (gs.phase) { case PHASE_NONE: break; + + case PHASE_INIT: + for (dmn = gs.daemons; dmn; dmn = dmn->next) + if (dmn->state == DAEMON_INIT) + return; + + /* startup complete, everything out of INIT */ + gs.phase = PHASE_NONE; + for (dmn = gs.daemons; dmn; dmn = dmn->next) + if (dmn->state == DAEMON_DOWN) { + SET_WAKEUP_DOWN(dmn); + try_restart(dmn); + } + break; case PHASE_STOPS_PENDING: if (gs.numpids) break; @@ -929,6 +970,31 @@ bool check_all_up(void) return true; } +void watchfrr_status(struct vty *vty) +{ + struct daemon *dmn; + struct timeval delay; + + vty_out(vty, "watchfrr global phase: %s\n", phase_str[gs.phase]); + if (gs.restart.pid) + vty_out(vty, " global restart running, pid %ld\n", + (long)gs.restart.pid); + + for (dmn = gs.daemons; dmn; dmn = dmn->next) { + vty_out(vty, " %-20s %s\n", dmn->name, state_str[dmn->state]); + if (dmn->restart.pid) + vty_out(vty, " restart running, pid %ld\n", + (long)dmn->restart.pid); + else if (dmn->state == DAEMON_DOWN && + time_elapsed(&delay, &dmn->restart.time)->tv_sec + < dmn->restart.interval) + vty_out(vty, " restarting in %ld seconds" + " (%lds backoff interval)\n", + dmn->restart.interval - delay.tv_sec, + dmn->restart.interval); + } +} + static void sigint(void) { zlog_notice("Terminating on signal"); @@ -980,8 +1046,7 @@ static void watchfrr_init(int argc, char **argv) gs.numdown++; dmn->fd = -1; dmn->t_wakeup = NULL; - thread_add_timer_msec(master, wakeup_init, dmn, - 100 + (random() % 900), + thread_add_timer_msec(master, wakeup_init, dmn, 0, &dmn->t_wakeup); dmn->restart.interval = gs.min_restart_interval; *add = dmn; diff --git a/watchfrr/watchfrr.h b/watchfrr/watchfrr.h index ee16846a1d..c5f54769bd 100644 --- a/watchfrr/watchfrr.h +++ b/watchfrr/watchfrr.h @@ -29,6 +29,10 @@ extern void watchfrr_vty_init(void); extern pid_t integrated_write_pid; extern void integrated_write_sigchld(int status); + +struct vty; +extern void watchfrr_status(struct vty *vty); + /* * Check if all daemons we are monitoring are in the DAEMON_UP state. * diff --git a/watchfrr/watchfrr_vty.c b/watchfrr/watchfrr_vty.c index 1bfc41f255..9b844d67f2 100644 --- a/watchfrr/watchfrr_vty.c +++ b/watchfrr/watchfrr_vty.c @@ -124,6 +124,16 @@ DEFUN_NOSH (show_debugging_watchfrr, return CMD_SUCCESS; } +DEFUN (show_watchfrr, + show_watchfrr_cmd, + "show watchfrr", + SHOW_STR + WATCHFRR_STR) +{ + watchfrr_status(vty); + return CMD_SUCCESS; +} + void integrated_write_sigchld(int status) { uint8_t reply[4] = {0, 0, 0, CMD_WARNING}; @@ -159,4 +169,5 @@ void watchfrr_vty_init(void) install_element(ENABLE_NODE, &config_write_integrated_cmd); install_element(ENABLE_NODE, &show_debugging_watchfrr_cmd); install_element(CONFIG_NODE, &show_debugging_watchfrr_cmd); + install_element(VIEW_NODE, &show_watchfrr_cmd); }