mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-11 18:48:14 +00:00
Merge pull request #3434 from opensourcerouting/init-new
[master] init script & vtysh pager rework
This commit is contained in:
commit
ea2abdc22b
@ -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
|
||||
}
|
||||
|
@ -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"
|
||||
|
@ -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.
|
||||
|
@ -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.
|
||||
|
@ -1 +0,0 @@
|
||||
../../ubuntu14.04/debian/frr.install
|
@ -1 +0,0 @@
|
||||
../../ubuntu14.04/debian/frr.postinst
|
@ -1 +0,0 @@
|
||||
../../ubuntu14.04/debian/frr.postrm
|
@ -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
|
@ -1 +0,0 @@
|
||||
3.0 (quilt)
|
@ -1 +0,0 @@
|
||||
-1~ubuntu12.04+1
|
@ -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/
|
||||
|
@ -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#
|
||||
|
@ -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#
|
@ -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
|
||||
|
||||
|
@ -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')
|
||||
|
@ -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 \
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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:
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
3
tools/.gitignore
vendored
@ -3,3 +3,6 @@
|
||||
/gen_yang_deviations
|
||||
/permutations
|
||||
/ssd
|
||||
/watchfrr.sh
|
||||
/frrinit.sh
|
||||
/frrcommon.sh
|
||||
|
@ -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"
|
@ -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.
|
||||
|
@ -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.
|
||||
|
60
tools/frr.in
60
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
|
||||
|
@ -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
317
tools/frrcommon.sh.in
Normal 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
90
tools/frrinit.sh.in
Normal 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
|
@ -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
33
tools/watchfrr.sh.in
Normal 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 "$@"
|
@ -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);
|
||||
|
@ -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);
|
||||
|
||||
|
@ -675,8 +675,6 @@ int main(int argc, char **argv, char **env)
|
||||
exit(0);
|
||||
}
|
||||
|
||||
vtysh_pager_init();
|
||||
|
||||
vtysh_readline_init();
|
||||
|
||||
vty_hello(vty);
|
||||
|
@ -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;
|
||||
|
@ -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.
|
||||
*
|
||||
|
@ -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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user