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
25 # Local Daemon selection may be done by using /etc/frr/daemons.
26 # See /usr/share/doc/frr/README.Debian.gz for further information.
27 # Keep zebra first and do not list watchfrr!
28 DAEMONS
="zebra bgpd ripd ripngd ospfd ospf6d isisd babeld pimd ldpd nhrpd eigrpd sharpd pbrd staticd bfdd fabricd"
30 RELOAD_SCRIPT
="$D_PATH/frr-reload.py"
32 if [ -e /lib
/lsb
/init-functions
]; then
33 .
/lib
/lsb
/init-functions
36 if [ -f $D_PATH/ssd
]; then
39 SSD
=`which start-stop-daemon`
42 # Print the name of the pidfile.
48 # Print the name of the vtysh.
56 test -n "$FRR_USER" && chown
"$FRR_USER" "$1"
57 test -n "$FRR_GROUP" && chgrp
"$FRR_GROUP" "$1"
60 # Check if daemon is started by using the pidfile.
63 [ ! -e `pidfile $1` ] && return 3
64 if [ -n "$2" ] && [ "$2" == "log" ]; then
65 status_of_proc
-p `pidfile $1` $1 $1 && return 0 ||
return $?
67 kill -0 `cat \`pidfile
$1\
`` 2> /dev
/null ||
return 1
72 # Loads the config via vtysh -b if configured to do so.
75 # Rember, that all variables have been incremented by 1 in convert_daemon_prios()
76 if [ "$vtysh_enable" = 2 -a -f $C_PATH/frr.conf
]; then
81 # Check if the daemon is activated and if its executable and config files
84 # returns: 0=ok, 1=error
87 if [ $1 != "watchfrr" -a $1 != "vtysh_enable" ]; then
88 # check for daemon binary
89 if [ ! -x "$D_PATH/$1" ]; then return 1; fi
92 # If the integrated config file is used the others are not checked.
93 if [ -r "$C_PATH/frr.conf" ]; then
97 # vtysh_enable has no config file nor binary so skip check.
98 # (Not sure why vtysh_enable is in this list but does not hurt)
99 if [ $1 != "watchfrr" -a $1 != "vtysh_enable" ]; then
100 # check for config file
102 if [ ! -r "$C_PATH/$1-$2.conf" ]; then
103 touch "$C_PATH/$1-$2.conf"
104 chownfrr
"$C_PATH/$1-$2.conf"
106 elif [ ! -r "$C_PATH/$1.conf" ]; then
107 touch "$C_PATH/$1.conf"
108 chownfrr
"$C_PATH/$1.conf"
114 # Starts the server if it's not alrady running according to the pid file.
115 # The Frr daemons creates the pidfile when starting.
122 ulimit -n $MAX_FDS > /dev
/null
2> /dev
/null
123 if [ "$dmn" = "watchfrr" ]; then
125 # We may need to restart watchfrr if new daemons are added and/or
127 if started
"$dmn" ; then
130 # Echo only once. watchfrr is printed in the stop above
134 eval "set - $watchfrr_options"
137 --pidfile=`pidfile $dmn` \
138 --exec "$D_PATH/$dmn" \
142 elif [ -n "$inst" ]; then
143 echo -n " $dmn-$inst"
144 if ! check_daemon
$dmn $inst ; then
145 echo -n " (binary does not exist)"
151 --pidfile=`pidfile $dmn-$inst` \
152 --exec "$D_PATH/$dmn" \
154 `eval echo "$""$dmn""_options"` -n "$inst"
156 if ! check_daemon
$dmn; then
157 echo -n " (binary does not exist)"
161 if [ "$valgrind_enable" = "yes" ]; then
164 --pidfile=`pidfile $dmn` \
166 -- --trace-children=no
--leak-check=full
--log-file=/var
/log
/frr
/$dmn-valgrind.log
$D_PATH/$dmn \
167 `eval echo "$""$dmn""_options"`
171 --pidfile=`pidfile $dmn` \
172 --exec "$D_PATH/$dmn" \
174 `eval echo "$""$dmn""_options"`
178 # Start the staticd automatically
179 if [ "$dmn" = "zebra" ]; then
180 echo -n "starting staticd since zebra is running"
181 if ! check_daemon staticd
; then
182 echo -n " (binary does not exist)"
188 --pidfile=`pidfile staticd` \
189 --exec "$D_PATH/staticd" \
191 `eval echo "$"staticd"_options"`
195 # Stop the daemon given in the parameter, printing its name to the terminal.
206 if ! started
"$inst" ; then
210 PIDFILE
=`pidfile $inst`
211 PID
=`cat $PIDFILE 2>/dev/null`
212 kill -2 $PID 2>/dev
/null
214 # Now we have to wait until $DAEMON has _really_ stopped.
216 if test -n "$PID" && kill -0 $PID 2>/dev
/null
; then
218 while kill -0 $PID 2>/dev
/null
; do
220 if [ $cnt -gt 60 ]; then
221 # Waited 120 secs now, fail.
228 rm -f `pidfile $inst`
229 rm -f `vtyfile $inst`
231 if [ "$1" = "zebra" ]; then
232 echo -n "Stopping staticd since zebra is running"
238 # Converts values from /etc/frr/daemons to all-numeric values.
239 convert_daemon_prios
()
241 for name
in $DAEMONS zebra vtysh_enable watchfrr_enable
; do
242 # First, assign the value set by the user to $value
243 eval value
=\
${${name}:0:3}
245 # Daemon not activated or entry missing?
246 if [ "$value" = "no" -o "$value" = "" ]; then value
=0; fi
248 # These strings parsed for backwards compatibility.
249 if [ "$value" = "yes" -o "$value" = "true" ]; then
253 # Zebra is threatened special. It must be between 0=off and the first
254 # user assigned value "1" so we increase all other enabled daemons' values.
255 if [ "$name" != "zebra" -a "$value" -gt 0 ]; then value
=`expr "$value" + 1`; fi
257 # If e.g. name is zebra then we set "zebra=yes".
262 # Starts watchfrr for all wanted daemons.
270 # Start the monitor daemon only if desired.
271 if [ 0 -eq "$watchfrr_enable" ]; then
275 # Check variable type
276 if declare -p watchfrr_options |
grep -q '^declare \-a'; then
278 watchfrr_options
="${watchfrr_options[@]}"
281 # Which daemons have been started?
283 for daemon_name
in $DAEMONS; do
284 eval daemon_prio
=\$
$daemon_name
285 if [ "$daemon_prio" -gt 0 ]; then
286 eval "daemon_inst=\${${daemon_name}_instances//,/ }"
287 if [ -n "$daemon_inst" ]; then
288 for inst
in ${daemon_inst}; do
289 eval "inst_disable=\${${daemon_name}_${inst}}"
290 if [ -z ${inst_disable} ] ||
[ ${inst_disable} != 0 ]; then
291 if check_daemon
$daemon_name $inst; then
292 watchfrr_options
="$watchfrr_options ${daemon_name}-${inst}"
297 if check_daemon
$daemon_name; then
298 watchfrr_options
="$watchfrr_options $daemon_name"
305 # Start if at least one daemon is activated.
306 if [ $found_one -eq 1 ]; then
315 echo -n "Stopping Frr monitor daemon:"
320 # Stops all daemons that have a lower level of priority than the given.
321 # (technically if daemon_prio >= wanted_prio)
330 if [ -n "$2" ] && [[ "$2" =~
(.
*)-(.
*) ]]; then
331 daemon
=${BASH_REMATCH[1]}
332 inst
=${BASH_REMATCH[2]}
338 daemon_list
=${daemon:-$DAEMONS}
340 echo -n "Stopping Frr daemons (prio:$wanted_prio):"
342 for prio_i
in `seq 10 -1 $wanted_prio`; do
343 for daemon_name
in $daemon_list; do
344 eval daemon_prio
=\
${${daemon_name}:0:3}
346 if [ $daemon_prio -eq $prio_i ]; then
347 eval "daemon_inst=\${${daemon_name}_instances//,/ }"
348 if [ -n "$daemon_inst" ]; then
349 for i
in ${daemon_inst}; do
350 if [ -n "$inst" ] && [ "$i" == "$inst" ]; then
351 stop
"$daemon_name" "$inst"
352 elif [ x
"$inst" == x
]; then
353 stop
"$daemon_name" "$i"
364 if [ -z "$inst" ]; then
365 # Now stop other daemons that're prowling, coz the daemons file changed
366 echo -n "Stopping other frr daemons"
367 if [ -n "$daemon" ]; then
368 eval "file_list_suffix="$V_PATH"/"$daemon*""
370 eval "file_list_suffix="$V_PATH/*""
372 for pidfile
in $file_list_suffix.pid
; do
373 PID
=`cat $pidfile 2>/dev/null`
374 ${SSD} --stop --quiet --oknodo --pidfile "$pidfile"
380 echo -n "Removing remaining .vty files"
381 for vtyfile
in $file_list_suffix.vty
; do
388 # Starts all daemons that have a higher level of priority than the given.
389 # (technically if daemon_prio <= wanted_prio)
399 if [ -n "$2" ] && [[ "$2" =~
(.
*)-(.
*) ]]; then
400 daemon
=${BASH_REMATCH[1]}
401 inst
=${BASH_REMATCH[2]}
407 daemon_list
=${daemon:-$DAEMONS}
409 for prio_i
in `seq 1 $wanted_prio`; do
410 for daemon_name
in $daemon_list; do
411 eval daemon_prio
=\$
${daemon_name}
413 if [ $daemon_prio -eq $prio_i ]; then
414 eval "daemon_inst=\${${daemon_name}_instances//,/ }"
415 if [ -n "$daemon_inst" ]; then
416 if [ `echo "$daemon_inst" | wc -w` -gt ${MAX_INSTANCES} ]; then
417 echo "Max instances supported is ${MAX_INSTANCES}. Aborting"
420 # Check if we're starting again by switching from single instance
422 if started
"$daemon_name"; then
423 PIDFILE
=`pidfile $daemon_name`
425 --stop --quiet --oknodo \
426 --pidfile "$PIDFILE" \
427 --exec "$D_PATH/$daemon_name"
433 for i
in ${daemon_inst}; do
434 if [ -n "$inst" ] && [ "$i" == "$inst" ]; then
435 start
"$daemon_name" "$inst"
436 elif [ x
"$inst" == x
]; then
437 start
"$daemon_name" "$i"
441 # Check if we're starting again by switching from
442 # single instance to MI version
443 eval "file_list_suffix="$V_PATH"/"$daemon_name-*""
444 for pidfile
in $file_list_suffix.pid
; do
445 ${SSD} --stop --quiet --oknodo --pidfile "$pidfile"
448 for vtyfile
in $file_list_suffix.vty
; do
464 local failed_status
=0
466 if [ -n "$1" ] && [[ "$1" =~
(.
*)-(.
*) ]]; then
467 daemon
=${BASH_REMATCH[1]}
468 inst
=${BASH_REMATCH[2]}
473 daemon_list
=${daemon:-$DAEMONS}
475 # Which daemons have been started?
476 for daemon_name
in $daemon_list; do
477 eval daemon_prio
=\$
$daemon_name
478 if [ "$daemon_prio" -gt 0 ]; then
479 eval "daemon_inst=\${${daemon_name}_instances//,/ }"
480 if [ -n "$daemon_inst" ]; then
481 for i
in ${daemon_inst}; do
482 if [ -n "$inst" -a "$inst" = "$i" ]; then
483 started
"$1" "log" || failed_status
=$?
484 elif [ -z "$inst" ]; then
485 started
"$daemon_name-$i" "log" || failed_status
=$?
489 started
"$daemon_name" "log" || failed_status
=$?
494 # All daemons that need to have been started are up and running
495 return $failed_status
498 #########################################################
500 #########################################################
502 # Config broken but script must exit silently.
503 [ ! -r "$C_PATH/daemons" ] && exit 0
507 if [ -e "$C_PATH/daemons.conf" ]; then
508 .
"$C_PATH/daemons.conf"
511 # Read configuration variable file if it is present
512 [ -r /etc
/default
/frr
] && .
/etc
/default
/frr
514 MAX_INSTANCES
=${MAX_INSTANCES:=5}
516 # Set priority of un-startable daemons to 'no' and substitute 'yes' to '0'
519 if [ ! -d $V_PATH ]; then
520 echo "Creating $V_PATH"
526 if [ -n "$3" ] && [ "$3" != "all" ]; then
528 elif [ -n "$2" ] && [ "$2" != "all" ]; then
534 # Try to load this necessary (at least for 2.6) module.
535 if [ -d /lib
/modules
/`uname -r` ] ; then
536 echo "Loading capability module if not yet done."
537 set +e
; LC_ALL
=C modprobe
-a capability
2>&1 |
egrep -v "(not found|Can't locate)"; set -e
542 if [ "$2" != "watchfrr" ]; then
549 1|
2|
3|
4|
5|
6|
7|
8|
9|
10)
550 # Stop/start daemons for the appropriate priority level
557 # Stop all daemons at level '0' or 'stop'
559 if [ "$dmn" != "watchfrr" ]; then
560 [ -n "${dmn}" ] && eval "${dmn/-/_}=0"
564 if [ -z "$dmn" -o "$dmn" = "zebra" ]; then
565 echo "Removing all routes made by FRR."
566 # Specific values for each proto can be found
567 # in /etc/iproute2/rt_protos as well as FRR
568 # specific ones in /etc/iproute2/rt_protos.d
569 # Additionally if a new protocol is added
570 # we need to add it here as well as
571 # in rt_netlink.h( follow the directions! )
572 ip route flush proto
4
573 ip route flush proto
11
574 ip route flush proto
42
575 ip route flush proto
186
576 ip route flush proto
187
577 ip route flush proto
188
578 ip route flush proto
189
579 ip route flush proto
190
580 ip route flush proto
191
581 ip route flush proto
192
582 ip route flush proto
193
583 ip route flush proto
194
584 ip route flush proto
195
585 ip route flush proto
196
586 ip route flush proto
197
588 [ -n "$dmn" ] && eval "${dmn/-/_}=0"
594 # Just apply the commands that have changed, no restart necessary
595 if [ ! -x "$RELOAD_SCRIPT" ]; then
596 echo "Please install frr-pythontools package. Required for reload"
600 NEW_CONFIG_FILE
="${2:-$C_PATH/frr.conf}"
601 [ ! -r $NEW_CONFIG_FILE ] && echo "Unable to read new configuration file $NEW_CONFIG_FILE" && exit 1
602 echo "Applying only incremental changes to running configuration from frr.conf"
603 "$RELOAD_SCRIPT" --reload $C_PATH/frr.conf
612 restart|force-reload
)
619 echo "Usage: /etc/init.d/frr {start|stop|status|reload|restart|force-reload|<priority>} [daemon]"
620 echo " E.g. '/etc/init.d/frr 5' would start all daemons with a prio 1-5."
621 echo " reload applies only modifications from the running config to all daemons."
622 echo " reload neither restarts starts any daemon nor starts any new ones."
623 echo " Read /usr/share/doc/frr/README.Debian for details."
628 echo "Exiting from the script"