New function svec_join().
[sliver-openvswitch.git] / debian / openflow-switch.init
1 #! /bin/sh
2 #
3 # /etc/init.d/openflow-switch
4 #
5 # Written by Miquel van Smoorenburg <miquels@cistron.nl>.
6 # Modified for Debian by Ian Murdock <imurdock@gnu.ai.mit.edu>.
7 # Further changes by Javier Fernandez-Sanguino <jfs@debian.org>
8 # Modified for openflow-switch.
9 #
10 # Version:      @(#)skeleton  1.9  26-Feb-2001  miquels@cistron.nl
11 #
12 ### BEGIN INIT INFO
13 # Provides:          openflow-switch
14 # Required-Start:    $network $named $remote_fs $syslog
15 # Required-Stop:
16 # Default-Start:     2 3 4 5
17 # Default-Stop:      0 1 6
18 # Short-Description: OpenFlow switch
19 ### END INIT INFO
20
21 PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
22 DAEMON=/usr/sbin/secchan
23 NAME=secchan
24 DESC=secchan
25
26 test -x $DAEMON || exit 0
27
28 LOGDIR=/var/log/openflow
29 PIDFILE=/var/run/$NAME.pid
30 DHCLIENT_PIDFILE=/var/run/dhclient.of0.pid
31 DODTIME=1                   # Time to wait for the server to die, in seconds
32                             # If this value is set too low you might not
33                             # let some servers to die gracefully and
34                             # 'restart' will not work
35
36 # Include secchan defaults if available
37 unset NETDEVS
38 unset MODE
39 unset SWITCH_IP
40 unset CONTROLLER
41 unset PRIVKEY
42 unset CERT
43 unset CACERT
44 unset CACERT_MODE
45 unset MGMT_VCONNS
46 unset COMMANDS
47 unset DAEMON_OPTS
48 unset CORE_LIMIT
49 unset DATAPATH_ID
50 default=/etc/default/openflow-switch
51 if [ -f $default ] ; then
52         . $default
53 fi
54
55 set -e
56
57 running_pid()
58 {
59     # Check if a given process pid's cmdline matches a given name
60     pid=$1
61     name=$2
62     [ -z "$pid" ] && return 1 
63     [ ! -d /proc/$pid ] &&  return 1
64     cmd=`cat /proc/$pid/cmdline | tr "\000" "\n"|head -n 1 |cut -d : -f 1`
65     # Is this the expected child?
66     case $cmd in
67         $name|*/$name)
68             return 0
69             ;;
70         *)
71             return 1
72             ;;
73     esac
74 }
75
76 running()
77 {
78 # Check if the process is running looking at /proc
79 # (works for all users)
80
81     # No pidfile, probably no daemon present
82     [ ! -f "$PIDFILE" ] && return 1
83     # Obtain the pid and check it against the binary name
84     pid=`cat $PIDFILE`
85     running_pid $pid $NAME || return 1
86     return 0
87 }
88
89 force_stop() {
90 # Forcefully kill the process
91     [ ! -f "$PIDFILE" ] && return
92     if running ; then
93         kill -15 $pid
94         # Is it really dead?
95         [ -n "$DODTIME" ] && sleep "$DODTIME"s
96         if running ; then
97             kill -9 $pid
98             [ -n "$DODTIME" ] && sleep "$DODTIME"s
99             if running ; then
100                 echo "Cannot kill $NAME (pid=$pid)!"
101                 exit 1
102             fi
103         fi
104     fi
105     rm -f $PIDFILE
106     return 0
107 }
108
109 must_succeed() {
110     echo -n "$1: "
111     shift
112     if "$@"; then
113         echo "success."
114     else
115         echo " ERROR."
116         exit 1
117     fi
118 }
119
120 check_op() {
121     echo -n "$1: "
122     shift
123     if "$@"; then
124         echo "success."
125     else
126         echo " ERROR."
127     fi
128 }
129
130 configure_ssl() {
131     if (test "$CACERT_MODE" != secure && test "$CACERT_MODE" != bootstrap) \
132        || test ! -e "$PRIVKEY" || test ! -e "$CERT" \
133        || (test ! -e "$CACERT" && test "$CACERT_MODE" != bootstrap); then
134         if test "$CACERT_MODE" != secure && test "$CACERT_MODE" != bootstrap
135         then
136             echo "CACERT_MODE is not set to 'secure' or 'bootstrap'"
137         fi
138         if test ! -e "$PRIVKEY"; then
139             echo "$PRIVKEY: private key missing" >&2
140         fi
141         if test ! -e "$CERT"; then
142             echo "$CERT: certificate for private key missing" >&2
143         fi
144         if test ! -e "$CACERT" && test "$CACERT_MODE" != bootstrap; then
145             echo "$CACERT: CA certificate missing (and CA certificate bootstrapping not enabled)" >&2
146         fi
147         echo "Run ofp-switch-setup (in the openflow-switch-config package) or edit /etc/default/openflow-switch to configure" >&2
148         if test "$MODE" = discovery; then
149             echo "You may also delete or rename $PRIVKEY to disable SSL requirement" >&2
150         fi
151         exit 1
152     fi
153
154     SSL_OPTS="--private-key=$PRIVKEY --certificate=$CERT"
155     if test ! -e "$CACERT" && test "$CACERT_MODE" = bootstrap; then
156         SSL_OPTS="$SSL_OPTS --bootstrap-ca-cert=$CACERT"
157     else
158         SSL_OPTS="$SSL_OPTS --ca-cert=$CACERT"
159     fi
160 }
161
162 check_int_var() {
163     eval value=\$$1
164     if test -n "$value"; then
165         if expr "X$value" : 'X[0-9][0-9]*$'; then
166             if test $value -lt $2; then
167                 echo "warning: The $1 option may not be set to a value below $2, treating as $2" >&2
168                 eval $1=$2
169             fi
170         else
171             echo "warning: The $1 option must be set to a number, ignoring" >&2
172             unset $1
173         fi
174     fi
175 }
176
177 check_new_option() {
178     case $DAEMON_OPTS in
179         *$1*)
180             echo "warning: The $1 option in DAEMON_OPTS may now be set with the $2 variable in $default.  The setting in DAEMON_OPTS will override the $2 variable, which will prevent the switch UI from configuring $1." >&2
181             ;;
182     esac
183 }
184
185 case "$1" in
186     start)
187         if test -z "$NETDEVS"; then
188             echo "$default: No network devices configured, switch disabled" >&2
189             echo "Run ofp-switch-setup (in the openflow-switch-config package) or edit /etc/default/openflow-switch to configure" >&2
190             exit 0
191         fi
192         if test "$MODE" = discovery; then
193             unset CONTROLLER
194         elif test "$MODE" = in-band || test "$MODE" = out-of-band; then
195             if test -z "$CONTROLLER"; then
196                 echo "$default: No controller configured and not configured for discovery, switch disabled" >&2
197                 echo "Run ofp-switch-setup (in the openflow-switch-config package) or edit /etc/default/openflow-switch to configure" >&2
198                 exit 0
199             fi
200         else
201             echo "$default: MODE must set to 'discovery', 'in-band', or 'out-of-band'" >&2
202             echo "Run ofp-switch-setup (in the openflow-switch-config package) or edit /etc/default/openflow-switch to configure" >&2
203             exit 1
204         fi
205         : ${PRIVKEY:=/etc/openflow-switch/of0-privkey.pem}
206         : ${CERT:=/etc/openflow-switch/of0-cert.pem}
207         : ${CACERT:=/etc/openflow-switch/cacert.pem}
208         case $CONTROLLER in
209             '')
210                 # Discovery mode.
211                 if test -e "$PRIVKEY"; then
212                     configure_ssl
213                 fi
214                 ;;
215             tcp:*)
216                 ;;
217             ssl:*)
218                 configure_ssl
219                 ;;
220             *)
221                 echo "$default: CONTROLLER must be in the form 'ssl:HOST[:PORT]' or 'tcp:HOST[:PORT]' when not in discovery mode" >&2
222                 echo "Run ofp-switch-setup (in the openflow-switch-config package) or edit /etc/default/openflow-switch to configure" >&2
223                 exit 1
224         esac
225         case $DISCONNECTED_MODE in
226             ''|switch|drop) ;; 
227             *) echo "$default: warning: DISCONNECTED_MODE is not 'switch' or 'drop'" >&2 ;;
228         esac
229
230         check_int_var RATE_LIMIT 100
231         check_int_var INACTIVITY_PROBE 5
232         check_int_var MAX_BACKOFF 1
233
234         check_new_option --fail DISCONNECTED_MODE
235         check_new_option --stp STP
236         check_new_option --rate-limit RATE_LIMIT
237         check_new_option --inactivity INACTIVITY_PROBE
238         check_new_option --max-backoff MAX_BACKOFF
239         case $DAEMON_OPTS in
240             *--rate-limit*)
241                 echo "$default: --rate-limit may now be set with RATE_LIMIT" >&2
242         esac
243
244         echo -n "Loading openflow_mod: "
245         if grep -q '^openflow_mod$' /proc/modules; then
246             echo "already loaded, nothing to do."
247         elif modprobe openflow_mod; then
248             echo "success."
249         else
250             echo "ERROR."
251             echo "openflow_mod has probably not been built for this kernel."
252             if ! test -d /usr/share/doc/openflow-datapath-source; then
253                 echo "Install the openflow-datapath-source package, then read"
254                 echo "/usr/share/doc/openflow-datapath-source/README.Debian"
255             else
256                 echo "For instructions, read"
257                 echo "/usr/share/doc/openflow-datapath-source/README.Debian"
258             fi
259             exit 1
260         fi
261
262         must_succeed "Adding datapath" dpctl adddp nl:0
263         for netdev in $NETDEVS; do
264             must_succeed "Adding $netdev to datapath" dpctl addif nl:0 $netdev
265         done
266
267         xx='[0-9abcdefABCDEF][0-9abcdefABCDEF]'
268         case $DATAPATH_ID in
269             '')
270                 ;;
271             $xx:$xx:$xx:$xx:$xx:$xx)
272                 ifconfig of0 down
273                 must_succeed "Setting of0 MAC address to $DATAPATH_ID" ifconfig of0 hw ether $DATAPATH_ID
274                 ifconfig of0 up
275                 ;;
276             *)
277                 echo "DATAPATH_ID is not a valid MAC address in the form XX:XX:XX:XX:XX:XX, ignoring" >&2
278                 ;;
279         esac
280
281         if test "$MODE" = in-band; then
282             if test "$SWITCH_IP" = dhcp; then
283                 must_succeed "Temporarily disabling of0" ifconfig of0 down
284             else
285                 COMMAND="ifconfig of0 $SWITCH_IP"
286                 if test -n "$SWITCH_NETMASK"; then
287                     COMMAND="$COMMAND netmask $SWITCH_NETMASK"
288                 fi
289                 must_succeed "Configuring of0: $COMMAND" $COMMAND
290                 if test -n "$SWITCH_GATEWAY"; then
291                     # This can fail because the route already exists,
292                     # so we don't insist that it succeed.
293                     COMMAND="route add default gw $SWITCH_GATEWAY"
294                     check_op "Adding default route: $COMMAND" $COMMAND
295                 fi
296             fi
297         else
298             must_succeed "Disabling of0" ifconfig of0 down
299         fi
300
301         if test -n "$CORE_LIMIT"; then
302             check_op "Setting core limit to $CORE_LIMIT" ulimit -c "$CORE_LIMIT"
303         fi
304
305         # Compose secchan options.
306         set --
307         set -- "$@" --verbose=ANY:console:emer --verbose=ANY:syslog:err
308         set -- "$@" --log-file
309         set -- "$@" --detach --pidfile=$PIDFILE
310         for vconn in $MGMT_VCONNS; do
311             set -- "$@" --listen="$vconn"
312         done
313         if test -n "$MONITOR_VCONN"; then
314             set -- "$@" --monitor="$MONITOR_VCONN"
315         fi
316         if test -n "$COMMANDS"; then
317             set -- "$@" --command-acl="$COMMANDS"
318         fi
319         case $STP in
320             yes) set -- "$@" --stp ;;
321             no) set -- "$@" --no-stp ;;
322         esac
323         case $DISCONNECTED_MODE in
324             switch) set -- "$@" --fail=open ;;
325             drop) set -- "$@" --fail=closed ;;
326         esac
327         if test -n "$RATE_LIMIT"; then
328             set -- "$@" --rate-limit=$RATE_LIMIT
329         fi
330         if test -n "$INACTIVITY_PROBE"; then
331             set -- "$@" --inactivity-probe=$INACTIVITY_PROBE
332         fi
333         if test -n "$MAX_BACKOFF"; then
334             set -- "$@" --max-backoff=$MAX_BACKOFF
335         fi
336         set -- "$@" $SSL_OPTS $DAEMON_OPTS
337         if test "$MODE" = out-of-band; then
338             set -- "$@" --out-of-band
339         fi
340         set -- "$@" nl:0 "$CONTROLLER"
341         echo -n "Starting $DESC: "
342         start-stop-daemon --start --quiet --pidfile $PIDFILE \
343             --exec $DAEMON -- "$@"
344         if running; then
345             echo "$NAME."
346         else
347             echo " ERROR."
348         fi
349
350         if test "$MODE" = in-band && test "$SWITCH_IP" = dhcp; then
351             echo -n "Starting dhclient on of0: "
352             start-stop-daemon --start --quiet --pidfile $DHCLIENT_PIDFILE \
353                 --exec /sbin/dhclient -- -q -pf $DHCLIENT_PIDFILE of0
354             if running; then
355                 echo "dhclient."
356             else
357                 echo " ERROR."
358             fi
359         fi
360         ;;
361     stop)
362         if test -e /var/run/dhclient.of0.pid; then
363             echo -n "Stopping dhclient on of0: "
364             start-stop-daemon --stop --quiet --oknodo \
365                 --pidfile $DHCLIENT_PIDFILE --exec /sbin/dhclient
366             echo "dhclient."
367         fi            
368
369         echo -n "Stopping $DESC: "
370         start-stop-daemon --stop --quiet --oknodo --pidfile $PIDFILE \
371             --exec $DAEMON
372         echo "$NAME."
373
374         for netdev in $NETDEVS; do
375             check_op "Removing $netdev from datapath" dpctl delif nl:0 $netdev
376         done
377         check_op "Deleting datapath" dpctl deldp nl:0
378         check_op "Unloading kernel module" modprobe -r openflow_mod
379         ;;
380     force-stop)
381         echo -n "Forcefully stopping $DESC: "
382         force_stop
383         if ! running; then
384             echo "$NAME."
385         else
386             echo " ERROR."
387         fi
388         ;;
389     reload)
390         ;;
391     force-reload)
392         start-stop-daemon --stop --test --quiet --pidfile \
393             $PIDFILE --exec $DAEMON \
394             && $0 restart \
395             || exit 0
396         ;;
397     restart)
398         $0 stop || true
399         $0 start
400         ;;
401     status)
402         echo -n "$NAME is "
403         if running ;  then
404             echo "running"
405         else
406             echo " not running."
407             exit 1
408         fi
409         ;;
410     *)
411         N=/etc/init.d/$NAME
412         echo "Usage: $N {start|stop|restart|force-reload|status|force-stop}" >&2
413         exit 1
414         ;;
415 esac
416
417 exit 0