5 # Start/Stop the FRR Routing daemons
6 # <any general comments about this init script>
8 # chkconfig: 2345 15 85
10 # description: FRRouting (FRR) is a routing suite for IP routing protocols
11 # like BGP, OSPF, RIP and others. This script contols the main
12 # daemon "frr" as well as the individual protocol daemons.
16 # Required-Start: $local_fs $network $syslog
17 # Required-Stop: $local_fs $syslog
18 # Should-Start: $syslog
19 # Should-Stop: $network $syslog
20 # Default-Start: 2 3 4 5
22 # Short-Description: Start/Stop the FRR Routing daemons
23 # Description: FRRouting (FRR) is a routing suite for IP routing protocols
24 # like BGP, OSPF, RIP and others. This script contols the main
25 # daemon "frr" as well as the individual protocol daemons.
28 PATH
=/bin
:/usr
/bin
:/sbin
:/usr
/sbin
33 # Local Daemon selection may be done by using /etc/frr/daemons.
34 # See /usr/share/doc/frr/README.Debian.gz for further information.
35 # Keep zebra first and do not list watchfrr!
36 DAEMONS
="zebra bgpd ripd ripngd ospfd ospf6d isisd pimd ldpd nhrpd eigrpd babeld"
38 RELOAD_SCRIPT
=/usr
/lib
/frr
/frr-reload.py
40 .
/etc
/init.d
/functions
42 # Print the name of the pidfile.
48 # Print the name of the vtysh.
54 # Check if daemon is started by using the pidfile.
57 [ ! -e `pidfile $1` ] && return 3
58 if [ -n "$2" ] && [ "$2" == "log" ]; then
59 status
-p `pidfile $1` $1 && return 0 ||
return $?
61 kill -0 `cat \`pidfile
$1\
`` 2> /dev
/null ||
return 1
66 # Loads the config via vtysh -b if configured to do so.
69 # Rember, that all variables have been incremented by 1 in convert_daemon_prios()
70 if [ "$vtysh_enable" = 2 -a -f $C_PATH/frr.conf
]; then
75 # Check if the daemon is activated and if its executable and config files
78 # returns: 0=ok, 1=error
81 # If the integrated config file is used the others are not checked.
82 if [ -r "$C_PATH/frr.conf" ]; then
86 # vtysh_enable has no config file nor binary so skip check.
87 # (Not sure why vtysh_enable is in this list but does not hurt)
88 if [ $1 != "watchfrr" -a $1 != "vtysh_enable" ]; then
89 # check for daemon binary
90 if [ ! -x "$D_PATH/$1" ]; then return 1; fi
92 # check for config file
94 if [ ! -r "$C_PATH/$1-$2.conf" ]; then
95 touch "$C_PATH/$1-$2.conf"
96 chown frr
:frr
"$C_PATH/$1-$2.conf"
98 elif [ ! -r "$C_PATH/$1.conf" ]; then
99 touch "$C_PATH/$1.conf"
100 chown frr
:frr
"$C_PATH/$1.conf"
106 # Starts the server if it's not already running according to the pid file.
107 # The Frr daemons creates the pidfile when starting.
110 ulimit -n $MAX_FDS > /dev
/null
2> /dev
/null
111 if [ "$1" = "watchfrr" ]; then
113 # We may need to restart watchfrr if new daemons are added and/or
115 if started
"$1" ; then
118 # Echo only once. watchfrr is printed in the stop above
122 if [ -e /var
/run
/frr
/watchfrr.started
] ; then
123 rm /var
/run
/frr
/watchfrr.started
125 daemon
--pidfile=`pidfile $1` "$D_PATH/$1" -d "${watchfrr_options[@]}"
127 [ $RETVAL -ne 0 ] && break
130 if [ -e /var
/run
/frr
/watchfrr.started
] ; then
138 elif [ -n "$2" ]; then
140 if ! check_daemon
$1 $2 ; then
141 echo -n " (binary does not exist)"
144 daemon
--pidfile=`pidfile $1-$2` "$D_PATH/$1" -d `eval echo "$""$1""_options"` -n "$2"
148 if ! check_daemon
$1; then
149 echo " (binary does not exist)"
152 daemon
--pidfile=`pidfile $1` "$D_PATH/$1" -d `eval echo "$""$1""_options"`
156 [ $RETVAL -eq 0 ] && touch /var
/lock
/subsys
/$1
160 # Stop the daemon given in the parameter, printing its name to the terminal.
171 if ! started
"$inst" ; then
176 PIDFILE
=`pidfile $inst`
177 PID
=`cat $PIDFILE 2>/dev/null`
178 killproc
-p "$PIDFILE" "$D_PATH/$1"
180 [ $RETVAL -eq 0 ] && rm -f $lockfile
181 rm -f `pidfile $inst`
182 rm -f `vtyfile $inst`
188 # Converts values from /etc/frr/daemons to all-numeric values.
189 convert_daemon_prios
()
191 for name
in $DAEMONS zebra vtysh_enable watchfrr_enable
; do
192 # First, assign the value set by the user to $value
193 eval value
=\
${${name}:0:3}
195 # Daemon not activated or entry missing?
196 if [ "$value" = "no" -o "$value" = "" ]; then value
=0; fi
198 # These strings parsed for backwards compatibility.
199 if [ "$value" = "yes" -o "$value" = "true" ]; then
203 # Zebra is threatened special. It must be between 0=off and the first
204 # user assigned value "1" so we increase all other enabled daemons' values.
205 if [ "$name" != "zebra" -a "$value" -gt 0 ]; then value
=`expr "$value" + 1`; fi
207 # If e.g. name is zebra then we set "zebra=yes".
212 # Starts watchfrr for all wanted daemons.
220 # Start the monitor daemon only if desired.
221 if [ 0 -eq "$watchfrr_enable" ]; then
225 # Check variable type
226 if ! declare -p watchfrr_options |
grep -q '^declare \-a'; then
228 echo "ERROR: The variable watchfrr_options from /etc/frr/daemons must be a BASH array!"
229 echo "ERROR: Please convert config file and restart!"
233 # Which daemons have been started?
235 for daemon_name
in $DAEMONS; do
236 eval daemon_prio
=\$
$daemon_name
237 if [ "$daemon_prio" -gt 0 ]; then
238 eval "daemon_inst=\${${daemon_name}_instances//,/ }"
239 if [ -n "$daemon_inst" ]; then
240 for inst
in ${daemon_inst}; do
241 eval "inst_disable=\${${daemon_name}_${inst}}"
242 if [ -z ${inst_disable} ] ||
[ ${inst_disable} != 0 ]; then
243 if check_daemon
$daemon_name $inst; then
244 watchfrr_options
+=("${daemon_name}-${inst}")
249 if check_daemon
$daemon_name; then
250 watchfrr_options
+=($daemon_name)
257 # Start if at least one daemon is activated.
258 if [ $found_one -eq 1 ]; then
259 echo "Starting FRRouting monitor daemon:"
267 echo "Stopping FRRouting monitor daemon:"
271 # Stops all daemons that have a lower level of priority than the given.
272 # (technically if daemon_prio >= wanted_prio)
281 if [ -n "$2" ] && [[ "$2" =~
(.
*)-(.
*) ]]; then
282 daemon
=${BASH_REMATCH[1]}
283 inst
=${BASH_REMATCH[2]}
289 daemon_list
=${daemon:-$DAEMONS}
291 echo "Stopping FRRouting daemons (prio:$wanted_prio):"
293 for prio_i
in `seq 10 -1 $wanted_prio`; do
294 for daemon_name
in $daemon_list; do
295 eval daemon_prio
=\
${${daemon_name}:0:3}
297 if [ $daemon_prio -eq $prio_i ]; then
298 eval "daemon_inst=\${${daemon_name}_instances//,/ }"
299 if [ -n "$daemon_inst" ]; then
300 for i
in ${daemon_inst}; do
301 if [ -n "$inst" ] && [ "$i" == "$inst" ]; then
302 stop
"$daemon_name" "$inst"
303 elif [ x
"$inst" == x
]; then
304 stop
"$daemon_name" "$i"
314 if [ -z "$inst" ]; then
315 # Now stop other daemons that're prowling, coz the daemons file changed
316 echo "Stopping other FRRouting daemons"
317 if [ -n "$daemon" ]; then
318 eval "file_list_suffix="$V_PATH"/"$daemon*""
320 eval "file_list_suffix="$V_PATH/*""
322 for pidfile
in $file_list_suffix.pid
; do
323 if [ -f "$pidfile" ]; then
324 filename
=${pidfile##*/}
325 daemon
=${filename%.*}
327 killproc
-p "$pidfile" "$daemon"
329 [ $RETVAL -eq 0 ] && rm -f $lockfile
334 echo -n "Removing remaining .vty files"
335 for vtyfile
in $file_list_suffix.vty
; do
342 # Starts all daemons that have a higher level of priority than the given.
343 # (technically if daemon_prio <= wanted_prio)
353 if [ -n "$2" ] && [[ "$2" =~
(.
*)-(.
*) ]]; then
354 daemon
=${BASH_REMATCH[1]}
355 inst
=${BASH_REMATCH[2]}
361 daemon_list
=${daemon:-$DAEMONS}
363 echo "Starting FRRouting daemons (prio:$wanted_prio):"
365 for prio_i
in `seq 1 $wanted_prio`; do
366 for daemon_name
in $daemon_list; do
367 eval daemon_prio
=\$
${daemon_name}
369 if [ $daemon_prio -eq $prio_i ]; then
370 eval "daemon_inst=\${${daemon_name}_instances//,/ }"
371 if [ -n "$daemon_inst" ]; then
372 if [ `echo "$daemon_inst" | wc -w` -gt ${MAX_INSTANCES} ]; then
373 echo "Max instances supported is ${MAX_INSTANCES}. Aborting"
376 # Check if we're starting again by switching from single instance
378 if started
"$daemon_name"; then
379 PIDFILE
=`pidfile $daemon_name`
380 killproc
-p "$PIDFILE" "$daemon_name"
385 for i
in ${daemon_inst}; do
386 if [ -n "$inst" ] && [ "$i" == "$inst" ]; then
387 start
"$daemon_name" "$inst"
388 elif [ x
"$inst" == x
]; then
389 start
"$daemon_name" "$i"
393 # Check if we're starting again by switching from
394 # single instance to MI version
395 eval "file_list_suffix="$V_PATH"/"$daemon_name-*""
396 for pidfile
in $file_list_suffix.pid
; do
397 if [ -f "$pidfile" ]; then
398 killproc
-p "$pidfile" "$daemon_name"
402 for vtyfile
in $file_list_suffix.vty
; do
418 local failed_status
=0
420 if [ -n "$1" ] && [[ "$1" =~
(.
*)-(.
*) ]]; then
421 daemon
=${BASH_REMATCH[1]}
422 inst
=${BASH_REMATCH[2]}
427 daemon_list
=${daemon:-$DAEMONS}
429 # Which daemons have been started?
430 for daemon_name
in $daemon_list; do
431 eval daemon_prio
=\$
$daemon_name
432 if [ "$daemon_prio" -gt 0 ]; then
433 eval "daemon_inst=\${${daemon_name}_instances//,/ }"
434 if [ -n "$daemon_inst" ]; then
435 for i
in ${daemon_inst}; do
436 if [ -n "$inst" -a "$inst" = "$i" ]; then
437 started
"$1" "log" || failed_status
=$?
438 elif [ -z "$inst" ]; then
439 started
"$daemon_name-$i" "log" || failed_status
=$?
443 started
"$daemon_name" "log" || failed_status
=$?
448 # All daemons that need to have been started are up and running
449 return $failed_status
452 #########################################################
454 #########################################################
456 # Config broken but script must exit silently.
457 [ ! -r "$C_PATH/daemons" ] && exit 0
462 # Read configuration variable file if it is present
463 [ -r /etc
/sysconfig
/frr
] && .
/etc
/sysconfig
/frr
465 MAX_INSTANCES
=${MAX_INSTANCES:=5}
467 # Set priority of un-startable daemons to 'no' and substitute 'yes' to '0'
470 if [ ! -d $V_PATH ]; then
471 echo "Creating $V_PATH"
473 chown frr
:frr
$V_PATH
477 if [ -n "$3" ] && [ "$3" != "all" ]; then
479 elif [ -n "$2" ] && [ "$2" != "all" ]; then
485 # Try to load this necessary (at least for 2.6) module.
486 if [ -d /lib
/modules
/`uname -r` ] ; then
487 echo "Loading capability module if not yet done."
488 LC_ALL
=C modprobe
-a capability
2>&1 |
egrep -v "(not found|Can't locate)"
493 if [ "$2" != "watchfrr" ]; then
500 1|
2|
3|
4|
5|
6|
7|
8|
9|
10)
501 # Stop/start daemons for the appropriate priority level
508 # Stop all daemons at level '0' or 'stop'
510 if [ "$dmn" != "watchfrr" ]; then
511 [ -n "${dmn}" ] && eval "${dmn/-/_}=0"
515 if [ -z "$dmn" -o "$dmn" = "zebra" ]; then
516 echo "Removing all routes made by zebra."
517 ip route flush proto zebra
518 # At least in CentOS/RHEL 6, iproute2 doesn't know
519 # about the new protocol names, so we have to flush them
520 # by number (it also doesn't support rt_protos.d
521 ip route flush proto
186
522 ip route flush proto
187
523 ip route flush proto
188
524 ip route flush proto
189
525 ip route flush proto
190
526 ip route flush proto
191
527 ip route flush proto
192
528 ip route flush proto
193
529 ip route flush proto
194
531 [ -n "$dmn" ] && eval "${dmn/-/_}=0"
537 # Just apply the commands that have changed, no restart necessary
538 if [ ! -x "$RELOAD_SCRIPT" ]; then
539 echo "frr-reload - reload not supported. Use restart or install frr-pythontools package"
542 NEW_CONFIG_FILE
="${2:-$C_PATH/frr.conf}"
543 if [ ! -r $NEW_CONFIG_FILE ]; then
544 echo "Unable to read configuration file $NEW_CONFIG_FILE. Only supporting integrated config"
547 echo "Applying only incremental changes to running configuration from frr.conf"
548 "$RELOAD_SCRIPT" --reload /etc
/frr
/frr.conf
557 restart|force-reload
)
564 echo "Usage: /etc/init.d/frr {start|stop|status|reload|restart|force-reload|<priority>} [daemon]"
565 echo " E.g. '/etc/init.d/frr 5' would start all daemons with a prio 1-5."
566 echo " reload applies only modifications from the running config to all daemons."
567 echo " reload neither restarts starts any daemon nor starts any new ones."
568 echo " Read /usr/share/doc/frr/README.Debian for details."