Merge pull request #3434 from opensourcerouting/init-new

[master] init script & vtysh pager rework
This commit is contained in:
Donald Sharp 2018-12-09 09:38:41 -05:00 committed by GitHub
commit ea2abdc22b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
43 changed files with 677 additions and 444 deletions

View File

@ -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
}

View File

@ -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"

View File

@ -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.

View File

@ -1,56 +0,0 @@
Source: frr
Section: net
Priority: optional
Maintainer: Nobody <nobody@frrouting.org>
Uploaders: Nobody <nobody@frrouting.org>
XSBC-Original-Maintainer: <maintainers@frrouting.org>
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.

View File

@ -1 +0,0 @@
../../ubuntu14.04/debian/frr.install

View File

@ -1 +0,0 @@
../../ubuntu14.04/debian/frr.postinst

View File

@ -1 +0,0 @@
../../ubuntu14.04/debian/frr.postrm

View File

@ -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

View File

@ -1 +0,0 @@
3.0 (quilt)

View File

@ -1 +0,0 @@
-1~ubuntu12.04+1

View File

@ -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/

View File

@ -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#

View File

@ -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#

View File

@ -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

View File

@ -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')

View File

@ -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 \

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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:

View File

@ -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

View File

@ -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

View File

@ -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

3
tools/.gitignore vendored
View File

@ -3,3 +3,6 @@
/gen_yang_deviations
/permutations
/ssd
/watchfrr.sh
/frrinit.sh
/frrcommon.sh

View File

@ -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"

View File

@ -1,11 +1,5 @@
# This file tells the frr package which daemons to start.
#
# Entries are in the format: <daemon>=(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.

View File

@ -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.

View File

@ -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

View File

@ -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

317
tools/frrcommon.sh.in Normal file
View File

@ -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
}

90
tools/frrinit.sh.in Normal file
View File

@ -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

View File

@ -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

33
tools/watchfrr.sh.in Normal file
View File

@ -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 "$@"

View File

@ -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);

View File

@ -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);

View File

@ -675,8 +675,6 @@ int main(int argc, char **argv, char **env)
exit(0);
}
vtysh_pager_init();
vtysh_readline_init();
vty_hello(vty);

View File

@ -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;

View File

@ -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.
*

View File

@ -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);
}