5 # Required-Start: $local_fs $network $remote_fs $syslog
6 # Required-Stop: $local_fs $network $remote_fs $syslog
7 # Default-Start: 2 3 4 5
9 # Short-Description: start and stop the Frr routing suite
10 # Description: Frr is a routing suite for IP routing protocols like
11 # BGP, OSPF, RIP and others. This script contols the main
12 # daemon "frr" as well as the individual protocol daemons.
16 PATH
=/bin
:/usr
/bin
:/sbin
:/usr
/sbin
17 D_PATH
="@CFG_SBIN@" # /usr/lib/frr
18 C_PATH
="@CFG_SYSCONF@" # /etc/frr
19 V_PATH
="@CFG_STATE@" # /var/run/frr
20 VTYSH
="@vtysh_bin@" # /usr/bin/vtysh
21 FRR_USER
="@enable_user@" # frr
22 FRR_GROUP
="@enable_group@" # frr
23 FRR_VTY_GROUP
="@enable_vty_group@" # frrvty
24 FRR_CONFIG_MODE
="@enable_configfile_mask@" # 0600
25 FRR_DEFAULT_PROFILE
="@DFLT_NAME@" # traditional / datacenter
27 # Local Daemon selection may be done by using /etc/frr/daemons.
28 # See /usr/share/doc/frr/README.Debian.gz for further information.
29 # Keep zebra first and do not list watchfrr!
30 DAEMONS
="zebra bgpd ripd ripngd ospfd ospf6d isisd babeld pimd ldpd nhrpd eigrpd sharpd pbrd staticd bfdd fabricd vrrpd pathd"
32 RELOAD_SCRIPT
="$D_PATH/frr-reload.py"
34 if [ -e /lib
/lsb
/init-functions
]; then
35 .
/lib
/lsb
/init-functions
38 if [ -f $D_PATH/ssd
]; then
41 SSD
=`which start-stop-daemon`
44 # Print the name of the pidfile.
50 # Print the name of the vtysh.
58 test -n "$FRR_USER" && chown
"$FRR_USER" "$1"
59 test -n "$FRR_GROUP" && chgrp
"$FRR_GROUP" "$1"
60 test -n "$FRR_CONFIG_MODE" && chmod "$FRR_CONFIG_MODE" "$1"
63 # Check if daemon is started by using the pidfile.
66 [ ! -e `pidfile $1` ] && return 3
67 if [ -n "$2" ] && [ "$2" == "log" ]; then
68 status_of_proc
-p `pidfile $1` $1 $1 && return 0 ||
return $?
70 kill -0 `cat \`pidfile
$1\
`` 2> /dev
/null ||
return 1
75 # Loads the config via vtysh -b if configured to do so.
78 # Rember, that all variables have been incremented by 1 in convert_daemon_prios()
79 if [ "$vtysh_enable" = 2 -a -f $C_PATH/frr.conf
]; then
84 # Check if the daemon is activated and if its executable and config files
87 # returns: 0=ok, 1=error
90 if [ $1 != "watchfrr" -a $1 != "vtysh_enable" ]; then
91 # check for daemon binary
92 if [ ! -x "$D_PATH/$1" ]; then return 1; fi
95 # If the integrated config file is used the others are not checked.
96 if [ -r "$C_PATH/frr.conf" ]; then
100 # vtysh_enable has no config file nor binary so skip check.
101 # (Not sure why vtysh_enable is in this list but does not hurt)
102 if [ $1 != "watchfrr" -a $1 != "vtysh_enable" ]; then
103 # check for config file
105 if [ ! -r "$C_PATH/$1-$2.conf" ]; then
106 touch "$C_PATH/$1-$2.conf"
107 chownfrr
"$C_PATH/$1-$2.conf"
109 elif [ ! -r "$C_PATH/$1.conf" ]; then
110 touch "$C_PATH/$1.conf"
111 chownfrr
"$C_PATH/$1.conf"
117 # Starts the server if it's not alrady running according to the pid file.
118 # The Frr daemons creates the pidfile when starting.
125 ulimit -n $MAX_FDS > /dev
/null
2> /dev
/null
126 if [ "$dmn" = "watchfrr" ]; then
128 # We may need to restart watchfrr if new daemons are added and/or
130 if started
"$dmn" ; then
133 # Echo only once. watchfrr is printed in the stop above
137 eval "set - $watchfrr_options"
140 --pidfile=`pidfile $dmn` \
141 --exec "$D_PATH/$dmn" \
145 elif [ -n "$inst" ]; then
146 echo -n " $dmn-$inst"
147 if ! check_daemon
$dmn $inst ; then
148 echo -n " (binary does not exist)"
154 --pidfile=`pidfile $dmn-$inst` \
155 --exec "$D_PATH/$dmn" \
157 `eval echo "$""$dmn""_options"` $frr_global_options -n "$inst"
159 if ! check_daemon
$dmn; then
160 echo -n " (binary does not exist)"
164 if [ "$valgrind_enable" = "yes" ]; then
167 --pidfile=`pidfile $dmn` \
169 -- --trace-children=no
--leak-check=full
--log-file=/var
/log
/frr
/$dmn-valgrind.log
$D_PATH/$dmn \
170 `eval echo "$""$dmn""_options"` $frr_global_options
174 --pidfile=`pidfile $dmn` \
175 --exec "$D_PATH/$dmn" \
177 `eval echo "$""$dmn""_options"` $frr_global_options
181 # Start the staticd automatically
182 if [ "$dmn" = "zebra" ]; then
183 echo -n "starting staticd since zebra is running"
184 if ! check_daemon staticd
; then
185 echo -n " (binary does not exist)"
191 --pidfile=`pidfile staticd` \
192 --exec "$D_PATH/staticd" \
194 `eval echo "$"staticd"_options"` $frr_global_options
198 # Stop the daemon given in the parameter, printing its name to the terminal.
209 if ! started
"$inst" ; then
213 PIDFILE
=`pidfile $inst`
214 PID
=`cat $PIDFILE 2>/dev/null`
215 kill -2 $PID 2>/dev
/null
217 # Now we have to wait until $DAEMON has _really_ stopped.
219 if test -n "$PID" && kill -0 $PID 2>/dev
/null
; then
221 while kill -0 $PID 2>/dev
/null
; do
223 if [ $cnt -gt 60 ]; then
224 # Waited 120 secs now, fail.
231 rm -f `pidfile $inst`
232 rm -f `vtyfile $inst`
234 if [ "$1" = "zebra" ]; then
235 echo -n "Stopping staticd since zebra is running"
241 # Converts values from /etc/frr/daemons to all-numeric values.
242 convert_daemon_prios
()
244 for name
in $DAEMONS zebra vtysh_enable watchfrr_enable
; do
245 # First, assign the value set by the user to $value
246 eval value
=\
${${name}:0:3}
248 # Daemon not activated or entry missing?
249 if [ "$value" = "no" -o "$value" = "" ]; then value
=0; fi
251 # These strings parsed for backwards compatibility.
252 if [ "$value" = "yes" -o "$value" = "true" ]; then
256 # Zebra is threatened special. It must be between 0=off and the first
257 # user assigned value "1" so we increase all other enabled daemons' values.
258 if [ "$name" != "zebra" -a "$value" -gt 0 ]; then value
=`expr "$value" + 1`; fi
260 # If e.g. name is zebra then we set "zebra=yes".
265 # Starts watchfrr for all wanted daemons.
273 # Start the monitor daemon only if desired.
274 if [ 0 -eq "$watchfrr_enable" ]; then
278 # Check variable type
279 if declare -p watchfrr_options |
grep -q '^declare \-a'; then
281 watchfrr_options
="${watchfrr_options[@]}"
284 # Which daemons have been started?
286 for daemon_name
in $DAEMONS; do
287 eval daemon_prio
=\$
$daemon_name
288 if [ "$daemon_prio" -gt 0 ]; then
289 eval "daemon_inst=\${${daemon_name}_instances//,/ }"
290 if [ -n "$daemon_inst" ]; then
291 for inst
in ${daemon_inst}; do
292 eval "inst_disable=\${${daemon_name}_${inst}}"
293 if [ -z ${inst_disable} ] ||
[ ${inst_disable} != 0 ]; then
294 if check_daemon
$daemon_name $inst; then
295 watchfrr_options
="$watchfrr_options ${daemon_name}-${inst}"
300 if check_daemon
$daemon_name; then
301 watchfrr_options
="$watchfrr_options $daemon_name"
308 # Start if at least one daemon is activated.
309 if [ $found_one -eq 1 ]; then
318 echo -n "Stopping Frr monitor daemon:"
323 # Stops all daemons that have a lower level of priority than the given.
324 # (technically if daemon_prio >= wanted_prio)
333 if [ -n "$2" ] && [[ "$2" =~
(.
*)-(.
*) ]]; then
334 daemon
=${BASH_REMATCH[1]}
335 inst
=${BASH_REMATCH[2]}
341 daemon_list
=${daemon:-$DAEMONS}
343 echo -n "Stopping Frr daemons (prio:$wanted_prio):"
345 for prio_i
in `seq 10 -1 $wanted_prio`; do
346 for daemon_name
in $daemon_list; do
347 eval daemon_prio
=\
${${daemon_name}:0:3}
349 if [ $daemon_prio -eq $prio_i ]; then
350 eval "daemon_inst=\${${daemon_name}_instances//,/ }"
351 if [ -n "$daemon_inst" ]; then
352 for i
in ${daemon_inst}; do
353 if [ -n "$inst" ] && [ "$i" == "$inst" ]; then
354 stop
"$daemon_name" "$inst"
355 elif [ x
"$inst" == x
]; then
356 stop
"$daemon_name" "$i"
367 if [ -z "$inst" ]; then
368 # Now stop other daemons that're prowling, coz the daemons file changed
369 echo -n "Stopping other frr daemons"
370 if [ -n "$daemon" ]; then
371 eval "file_list_suffix="$V_PATH"/"$daemon*""
373 eval "file_list_suffix="$V_PATH/*""
375 for pidfile
in $file_list_suffix.pid
; do
376 PID
=`cat $pidfile 2>/dev/null`
377 ${SSD} --stop --quiet --oknodo --pidfile "$pidfile"
383 echo -n "Removing remaining .vty files"
384 for vtyfile
in $file_list_suffix.vty
; do
391 # Starts all daemons that have a higher level of priority than the given.
392 # (technically if daemon_prio <= wanted_prio)
402 if [ -n "$2" ] && [[ "$2" =~
(.
*)-(.
*) ]]; then
403 daemon
=${BASH_REMATCH[1]}
404 inst
=${BASH_REMATCH[2]}
410 daemon_list
=${daemon:-$DAEMONS}
412 for prio_i
in `seq 1 $wanted_prio`; do
413 for daemon_name
in $daemon_list; do
414 eval daemon_prio
=\$
${daemon_name}
416 if [ $daemon_prio -eq $prio_i ]; then
417 eval "daemon_inst=\${${daemon_name}_instances//,/ }"
418 if [ -n "$daemon_inst" ]; then
419 if [ `echo "$daemon_inst" | wc -w` -gt ${MAX_INSTANCES} ]; then
420 echo "Max instances supported is ${MAX_INSTANCES}. Aborting"
423 # Check if we're starting again by switching from single instance
425 if started
"$daemon_name"; then
426 PIDFILE
=`pidfile $daemon_name`
428 --stop --quiet --oknodo \
429 --pidfile "$PIDFILE" \
430 --exec "$D_PATH/$daemon_name"
436 for i
in ${daemon_inst}; do
437 if [ -n "$inst" ] && [ "$i" == "$inst" ]; then
438 start
"$daemon_name" "$inst"
439 elif [ x
"$inst" == x
]; then
440 start
"$daemon_name" "$i"
444 # Check if we're starting again by switching from
445 # single instance to MI version
446 eval "file_list_suffix="$V_PATH"/"$daemon_name-*""
447 for pidfile
in $file_list_suffix.pid
; do
448 ${SSD} --stop --quiet --oknodo --pidfile "$pidfile"
451 for vtyfile
in $file_list_suffix.vty
; do
467 local failed_status
=0
469 if [ -n "$1" ] && [[ "$1" =~
(.
*)-(.
*) ]]; then
470 daemon
=${BASH_REMATCH[1]}
471 inst
=${BASH_REMATCH[2]}
476 daemon_list
=${daemon:-$DAEMONS}
478 # Which daemons have been started?
479 for daemon_name
in $daemon_list; do
480 eval daemon_prio
=\$
$daemon_name
481 if [ "$daemon_prio" -gt 0 ]; then
482 eval "daemon_inst=\${${daemon_name}_instances//,/ }"
483 if [ -n "$daemon_inst" ]; then
484 for i
in ${daemon_inst}; do
485 if [ -n "$inst" -a "$inst" = "$i" ]; then
486 started
"$1" "log" || failed_status
=$?
487 elif [ -z "$inst" ]; then
488 started
"$daemon_name-$i" "log" || failed_status
=$?
492 started
"$daemon_name" "log" || failed_status
=$?
497 # All daemons that need to have been started are up and running
498 return $failed_status
501 #########################################################
503 #########################################################
505 # Config broken but script must exit silently.
506 [ ! -r "$C_PATH/daemons" ] && exit 0
510 if [ -e "$C_PATH/daemons.conf" ]; then
511 .
"$C_PATH/daemons.conf"
514 # Read configuration variable file if it is present
515 [ -r /etc
/default
/frr
] && .
/etc
/default
/frr
517 if test -z "$frr_profile"; then
518 # try to autodetect config profile
519 if test -d /etc
/cumulus
; then
520 frr_profile
=datacenter
521 # elif test ...; then
522 # -- add your distro/system here
523 elif test -n "$FRR_DEFAULT_PROFILE"; then
524 frr_profile
="$FRR_DEFAULT_PROFILE"
527 test -n "$frr_profile" && frr_global_options
="$frr_global_options -F $frr_profile"
529 MAX_INSTANCES
=${MAX_INSTANCES:=5}
531 # Set priority of un-startable daemons to 'no' and substitute 'yes' to '0'
534 if [ ! -d $V_PATH ]; then
535 echo "Creating $V_PATH"
541 if [ -n "$3" ] && [ "$3" != "all" ]; then
543 elif [ -n "$2" ] && [ "$2" != "all" ]; then
549 # Try to load this necessary (at least for 2.6) module.
550 if [ -d /lib
/modules
/`uname -r` ] ; then
551 echo "Loading capability module if not yet done."
552 set +e
; LC_ALL
=C modprobe
-a capability
2>&1 |
egrep -v "(not found|Can't locate)"; set -e
557 if [ "$2" != "watchfrr" ]; then
564 1|
2|
3|
4|
5|
6|
7|
8|
9|
10)
565 # Stop/start daemons for the appropriate priority level
572 # Stop all daemons at level '0' or 'stop'
574 if [ "$dmn" != "watchfrr" ]; then
575 [ -n "${dmn}" ] && eval "${dmn/-/_}=0"
579 if [ -n "$dmn" -a "$dmn" != "zebra" ]; then
580 [ -n "$dmn" ] && eval "${dmn/-/_}=0"
586 # Just apply the commands that have changed, no restart necessary
587 if [ ! -x "$RELOAD_SCRIPT" ]; then
588 echo "Please install frr-pythontools package. Required for reload"
592 NEW_CONFIG_FILE
="${2:-$C_PATH/frr.conf}"
593 [ ! -r $NEW_CONFIG_FILE ] && echo "Unable to read new configuration file $NEW_CONFIG_FILE" && exit 1
594 echo "Applying only incremental changes to running configuration from frr.conf"
595 "$RELOAD_SCRIPT" --reload $C_PATH/frr.conf
604 restart|force-reload
)
611 echo "Usage: /etc/init.d/frr {start|stop|status|reload|restart|force-reload|<priority>} [daemon]"
612 echo " E.g. '/etc/init.d/frr 5' would start all daemons with a prio 1-5."
613 echo " reload applies only modifications from the running config to all daemons."
614 echo " reload neither restarts starts any daemon nor starts any new ones."
615 echo " Read /usr/share/doc/frr/README.Debian for details."
620 echo "Exiting from the script"