Merge branch 'mainstream'
[sliver-openvswitch.git] / utilities / ovs-ctl.in
1 #! /bin/sh
2 # Copyright (C) 2009, 2010, 2011, 2012 Nicira, Inc.
3 #
4 # Licensed under the Apache License, Version 2.0 (the "License");
5 # you may not use this file except in compliance with the License.
6 # You may obtain a copy of the License at:
7 #
8 #     http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15
16 case $0 in
17     */*) dir0=`echo "$0" | sed 's,/[^/]*$,,'` ;;
18     *) dir0=./ ;;
19 esac
20 . "$dir0/ovs-lib" || exit 1
21
22 for dir in "$sbindir" "$bindir" /sbin /bin /usr/sbin /usr/bin; do
23     case :$PATH: in
24         *:$dir:*) ;;
25         *) PATH=$PATH:$dir ;;
26     esac
27 done
28
29 ## ----- ##
30 ## start ##
31 ## ----- ##
32
33 restore_datapaths () {
34     [ -n "${script_datapaths}" ] && \
35         action "Restoring datapath configuration" "${script_datapaths}"
36 }
37
38 insert_openvswitch_mod_if_required () {
39     # If openvswitch is already loaded then we're done.
40     test -e /sys/module/openvswitch -o -e /sys/module/openvswitch_mod && \
41      return 0
42
43     # Load openvswitch.  If that's successful then we're done.
44     if action "Inserting openvswitch module" modprobe openvswitch; then
45         restore_datapaths
46         return 0
47     fi
48
49     # If the bridge module is loaded, then that might be blocking
50     # openvswitch.  Try to unload it, if there are no bridges.
51     test -e /sys/module/bridge || return 1
52     bridges=`echo /sys/class/net/*/bridge | sed 's,/sys/class/net/,,g;s,/bridge,,g'`
53     if test "$bridges" != "*"; then
54         log_warning_msg "not removing bridge module because bridges exist ($bridges)"
55         return 1
56     fi
57     action "removing bridge module" rmmod bridge || return 1
58
59     # Try loading openvswitch again.
60     action "Inserting openvswitch module" modprobe openvswitch
61     restore_datapaths
62 }
63
64 insert_brcompat_mod_if_required () {
65     if test -e /sys/module/bridge; then
66         log_warning_msg "bridge module is loaded, not loading brcompat"
67         return 1
68     fi
69     test -e /sys/module/brcompat -o -e /sys/module/brcompat_mod && return 0
70     action "Inserting brcompat module" modprobe brcompat
71 }
72
73 insert_mod_if_required () {
74     insert_openvswitch_mod_if_required || return 1
75     if test X"$BRCOMPAT" = Xyes; then
76         if insert_brcompat_mod_if_required; then
77             :
78         else
79             log_warning_msg "could not load brcompat module, disabling bridge compatibility"
80             BRCOMPAT=no
81         fi
82     fi
83 }
84
85 ovs_vsctl () {
86     ovs-vsctl --no-wait --timeout=5 "$@"
87 }
88
89 ovsdb_tool () {
90     ovsdb-tool -vconsole:off "$@"
91 }
92
93 create_db () {
94     action "Creating empty database $DB_FILE" ovsdb_tool create "$DB_FILE" "$DB_SCHEMA"
95 }
96
97 upgrade_db () {
98     schemaver=`ovsdb_tool schema-version "$DB_SCHEMA"`
99     if test ! -e "$DB_FILE"; then
100         log_warning_msg "$DB_FILE does not exist"
101         install -d -m 755 -o root -g root `dirname $DB_FILE`
102         create_db
103     elif test X"`ovsdb_tool needs-conversion "$DB_FILE" "$DB_SCHEMA"`" != Xno; then
104         # Back up the old version.
105         version=`ovsdb_tool db-version "$DB_FILE"`
106         cksum=`ovsdb_tool db-cksum "$DB_FILE" | awk '{print $1}'`
107         backup=$DB_FILE.backup$version-$cksum
108         action "Backing up database to $backup" cp "$DB_FILE" "$backup" || return 1
109
110         # Compact database.  This is important if the old schema did not enable
111         # garbage collection (i.e. if it did not have any tables with "isRoot":
112         # true) but the new schema does.  In that situation the old database
113         # may contain a transaction that creates a record followed by a
114         # transaction that creates the first use of the record.  Replaying that
115         # series of transactions against the new database schema (as "convert"
116         # does) would cause the record to be dropped by the first transaction,
117         # then the second transaction would cause a referential integrity
118         # failure (for a strong reference).
119         #
120         # Errors might occur on an Open vSwitch downgrade if ovsdb-tool doesn't
121         # understand some feature of the schema used in the OVSDB version that
122         # we're downgrading from, so we don't give up on error.
123         action "Compacting database" ovsdb_tool compact "$DB_FILE"
124
125         # Upgrade or downgrade schema.
126         if action "Converting database schema" ovsdb_tool convert "$DB_FILE" "$DB_SCHEMA"; then
127             :
128         else
129             log_warning_msg "Schema conversion failed, using empty database instead"
130             rm -f "$DB_FILE"
131             create_db
132         fi
133     fi
134 }
135
136 set_system_ids () {
137     set ovs_vsctl set Open_vSwitch .
138
139     OVS_VERSION=`ovs-vswitchd --version | sed 's/.*) //;1q'`
140     set "$@" ovs-version="$OVS_VERSION"
141
142     case $SYSTEM_ID in
143         random)
144             id_file=$etcdir/system-id.conf
145             uuid_file=$etcdir/install_uuid.conf
146             if test -e "$id_file"; then
147                 SYSTEM_ID=`cat "$id_file"`
148             elif test -e "$uuid_file"; then
149                 # Migrate from old file name.
150                 . "$uuid_file"
151                 SYSTEM_ID=$INSTALLATION_UUID
152                 echo "$SYSTEM_ID" > "$id_file"
153             elif SYSTEM_ID=`uuidgen`; then
154                 echo "$SYSTEM_ID" > "$id_file"
155             else
156                 log_failure_msg "missing uuidgen, could not generate system ID"
157             fi
158             ;;
159
160         '')
161             log_failure_msg "system ID not configured, please use --system-id"
162             ;;
163
164         *)
165             ;;
166     esac
167     set "$@" external-ids:system-id="\"$SYSTEM_ID\""
168
169     if test X"$SYSTEM_TYPE" != X; then
170         set "$@" system-type="\"$SYSTEM_TYPE\""
171     else
172         log_failure_msg "no default system type, please use --system-type"
173     fi
174
175     if test X"$SYSTEM_VERSION" != X; then
176         set "$@" system-version="\"$SYSTEM_VERSION\""
177     else
178         log_failure_msg "no default system version, please use --system-version"
179     fi
180
181     action "Configuring Open vSwitch system IDs" "$@" $extra_ids
182 }
183
184 check_force_cores () {
185     if test X"$FORCE_COREFILES" = Xyes; then
186         ulimit -Sc 67108864
187     fi
188 }
189
190 start_ovsdb () {
191     check_force_cores
192
193     if daemon_is_running ovsdb-server; then
194         log_success_msg "ovsdb-server is already running"
195     else
196         # Create initial database or upgrade database schema.
197         upgrade_db || return 1
198
199         # Start ovsdb-server.
200         set ovsdb-server "$DB_FILE"
201         for db in $EXTRA_DBS; do
202             case $db in
203                 /*) ;;
204                 *) db=$dbdir/$db ;;
205             esac
206
207             if test ! -f "$db"; then
208                 log_warning_msg "$db (from \$EXTRA_DBS) does not exist."
209             elif ovsdb-tool db-version "$db" >/dev/null; then
210                 set "$@" "$db"
211             else
212                 log_warning_msg "$db (from \$EXTRA_DBS) cannot be read as a database (see error message above)"
213             fi
214         done
215         set "$@" -vconsole:emer -vsyslog:err -vfile:info
216         set "$@" --remote=punix:"$DB_SOCK"
217         set "$@" --remote=db:Open_vSwitch,Open_vSwitch,manager_options
218         set "$@" --private-key=db:Open_vSwitch,SSL,private_key
219         set "$@" --certificate=db:Open_vSwitch,SSL,certificate
220         set "$@" --bootstrap-ca-cert=db:Open_vSwitch,SSL,ca_cert
221         start_daemon "$OVSDB_SERVER_PRIORITY" "$OVSDB_SERVER_WRAPPER" "$@" \
222             || return 1
223
224         # Initialize database settings.
225         ovs_vsctl -- init -- set Open_vSwitch . db-version="$schemaver" \
226             || return 1
227         set_system_ids || return 1
228         if test X"$DELETE_BRIDGES" = Xyes; then
229             for bridge in `ovs_vsctl list-br`; do
230         ovs_vsctl del-br $bridge
231             done
232         fi
233     fi
234 }
235
236 start_forwarding () {
237     check_force_cores
238
239     insert_mod_if_required || return 1
240
241     if daemon_is_running ovs-vswitchd; then
242         log_success_msg "ovs-vswitchd is already running"
243     else
244         # Increase the limit on the number of open file descriptors.
245         # ovs-vswitchd needs 16 per datapath, plus a few extra, so this
246         # should allow for 256 (or more) bridges.
247         ulimit -n 5000
248
249             # Start ovs-vswitchd.
250             set ovs-vswitchd unix:"$DB_SOCK"
251             set "$@" -vconsole:emer -vsyslog:err -vfile:info
252             if test X"$MLOCKALL" != Xno; then
253                 set "$@" --mlockall
254             fi
255             start_daemon "$OVS_VSWITCHD_PRIORITY" "$OVS_VSWITCHD_WRAPPER" "$@"
256     fi
257
258     if daemon_is_running ovs-brcompatd; then
259             log_success_msg "ovs-brcompatd is already running"
260     elif test X"$BRCOMPAT" = Xyes; then
261         set ovs-brcompatd
262             set "$@" -vconsole:emer -vsyslog:err -vfile:info
263             start_daemon "$OVS_BRCOMPATD_PRIORITY" "$OVS_BRCOMPATD_WRAPPER" "$@"
264     fi
265 }
266
267 ## ---- ##
268 ## stop ##
269 ## ---- ##
270
271 stop_ovsdb () {
272     stop_daemon ovsdb-server
273 }
274
275 stop_forwarding () {
276     stop_daemon ovs-brcompatd
277     stop_daemon ovs-vswitchd
278 }
279
280 ## ----------------- ##
281 ## force-reload-kmod ##
282 ## ----------------- ##
283
284 internal_interfaces () {
285     # Outputs a list of internal interfaces:
286     #
287     #   - There is an internal interface for every bridge, whether it
288     #     has an Interface record or not and whether the Interface
289     #     record's 'type' is properly set or not.
290     #
291     #   - There is an internal interface for each Interface record whose
292     #     'type' is 'internal'.
293     #
294     # But ignore interfaces that don't really exist.
295     for d in `(ovs_vsctl --bare \
296                 -- --columns=name find Interface type=internal \
297                     -- list-br) | sort -u`
298     do
299         if test -e "/sys/class/net/$d"; then
300                 printf "%s " "$d"
301             fi
302     done
303 }
304
305 save_flows () {
306    if set X `ovs_vsctl list-br`; then
307         shift
308         if "$datadir/scripts/ovs-save" save-flows "$@" > "$script_flows"; then
309             chmod +x "$script_flows"
310             return 0
311         fi
312     fi
313     script_flows=
314     return 1
315 }
316
317 save_interfaces () {
318     "$datadir/scripts/ovs-save" save-interfaces ${ifaces} \
319         > "${script_interfaces}"
320 }
321
322 save_datapaths () {
323     "$datadir/scripts/ovs-save" save-datapaths ${datapaths} \
324         > "${script_datapaths}"
325 }
326
327 restore_flows () {
328     [ -n "${script_flows}" ] && \
329         action "Restoring saved flows" "${script_flows}"
330 }
331
332 force_reload_kmod () {
333     ifaces=`internal_interfaces`
334     action "Detected internal interfaces: $ifaces" true
335
336     script_interfaces=`mktemp`
337     script_datapaths=`mktemp`
338     script_flows=`mktemp`
339     trap 'rm -f "${script_interfaces}" "${script_flows}" \
340         "${script_datapaths}"' 0 1 2 13 15
341
342     action "Saving flows" save_flows
343
344     # Restart the database first, since a large database may take a
345     # while to load, and we want to minimize forwarding disruption.
346     stop_ovsdb
347     start_ovsdb
348
349     stop_forwarding
350
351     if action "Saving interface configuration" save_interfaces; then
352         :
353     else
354         log_warning_msg "Failed to save configuration, not replacing kernel module"
355         start_forwarding
356         exit 1
357     fi
358     chmod +x "$script_interfaces"
359
360     datapaths=`ovs-dpctl dump-dps`
361     if action "Saving datapath configuration" save_datapaths; then
362         chmod +x "${script_datapaths}"
363     else
364         log_warning_msg "Failed to save datapath configuration. The port\
365                          numbers may change after the restart"
366         script_datapaths=""
367     fi
368
369     for dp in ${datapaths}; do
370         action "Removing datapath: $dp" ovs-dpctl del-dp "$dp"
371     done
372
373     # try both old and new names in case this is post upgrade
374     if test -e /sys/module/brcompat_mod; then
375         action "Removing brcompat module" rmmod brcompat_mod
376     elif test -e /sys/module/brcompat; then
377         action "Removing brcompat module" rmmod brcompat
378     fi
379     if test -e /sys/module/openvswitch_mod; then
380         action "Removing openvswitch module" rmmod openvswitch_mod
381     elif test -e /sys/module/openvswitch; then
382         action "Removing openvswitch module" rmmod openvswitch
383     fi
384
385     start_forwarding
386
387     restore_flows
388
389     action "Restoring interface configuration" "$script_interfaces"
390     rc=$?
391     if test $rc = 0; then
392         level=debug
393     else
394         level=err
395     fi
396     log="logger -p daemon.$level -t ovs-save"
397     $log "force-reload-kmod interface restore script exited with status $rc:"
398     $log -f "$script_interfaces"
399
400     "$datadir/scripts/ovs-check-dead-ifs"
401 }
402
403 ## ------- ##
404 ## restart ##
405 ## ------- ##
406
407 restart () {
408     if daemon_is_running ovsdb-server && daemon_is_running ovs-vswitchd; then
409         script_flows=`mktemp`
410         trap 'rm -f "${script_flows}"' 0 1 2 13 15
411
412         action "Saving flows" save_flows
413     fi
414
415     # Restart the database first, since a large database may take a
416     # while to load, and we want to minimize forwarding disruption.
417     stop_ovsdb
418     start_ovsdb
419
420     stop_forwarding
421     start_forwarding
422
423     restore_flows
424 }
425
426 ## --------------- ##
427 ## enable-protocol ##
428 ## --------------- ##
429
430 enable_protocol () {
431     # Translate the protocol name to a number, because "iptables -n -L" prints
432     # some protocols by name (despite the -n) and therefore we need to look for
433     # both forms.
434     #
435     # (iptables -S output is more uniform but old iptables doesn't have it.)
436     protonum=`grep "^$PROTOCOL[         ]" /etc/protocols | awk '{print $2}'`
437     if expr X"$protonum" : X'[0-9]\{1,\}$' > /dev/null; then :; else
438         log_failure_msg "unknown protocol $PROTOCOL"
439         return 1
440     fi
441
442     name=$PROTOCOL
443     match="(\$2 == \"$PROTOCOL\" || \$2 == $protonum)"
444     insert="iptables -I INPUT -p $PROTOCOL"
445     if test X"$DPORT" != X; then
446         name="$name to port $DPORT"
447         match="$match && /dpt:$DPORT/"
448         insert="$insert --dport $DPORT"
449     fi
450     if test X"$SPORT" != X; then
451         name="$name from port $SPORT"
452         match="$match && /spt:$SPORT/"
453         insert="$insert --sport $SPORT"
454     fi
455     insert="$insert -j ACCEPT"
456
457     if (iptables -n -L INPUT) >/dev/null 2>&1; then
458         if iptables -n -L INPUT | awk "$match { n++ } END { exit n == 0 }"
459         then
460             # There's already a rule for this protocol.  Don't override it.
461             log_success_msg "iptables already has a rule for $name, not explicitly enabling"
462         else
463             action "Enabling $name with iptables" $insert
464         fi
465     elif (iptables --version) >/dev/null 2>&1; then
466         action "cannot list iptables rules, not adding a rule for $name"
467     else
468         action "iptables binary not installed, not adding a rule for $name"
469     fi
470 }
471
472 ## ---- ##
473 ## main ##
474 ## ---- ##
475
476 set_defaults () {
477     SYSTEM_ID=
478
479     DELETE_BRIDGES=no
480     BRCOMPAT=no
481
482     DAEMON_CWD=/
483     FORCE_COREFILES=yes
484     MLOCKALL=yes
485     OVSDB_SERVER_PRIORITY=-10
486     OVS_VSWITCHD_PRIORITY=-10
487     OVS_BRCOMPATD_PRIORITY=-10
488     OVSDB_SERVER_WRAPPER=
489     OVS_VSWITCHD_WRAPPER=
490     OVS_BRCOMPATD_WRAPPER=
491
492     DB_FILE=$dbdir/conf.db
493     DB_SOCK=$rundir/db.sock
494     DB_SCHEMA=$datadir/vswitch.ovsschema
495     EXTRA_DBS=
496
497     PROTOCOL=gre
498     DPORT=
499     SPORT=
500
501     type_file=$etcdir/system-type.conf
502     version_file=$etcdir/system-version.conf
503
504     if test -e "$type_file" ; then
505         SYSTEM_TYPE=`cat $type_file`
506         SYSTEM_VERSION=`cat $version_file`
507     elif (lsb_release --id) >/dev/null 2>&1; then
508         SYSTEM_TYPE=`lsb_release --id -s`
509         system_release=`lsb_release --release -s`
510         system_codename=`lsb_release --codename -s`
511         SYSTEM_VERSION="${system_release}-${system_codename}"
512     else
513         SYSTEM_TYPE=unknown
514         SYSTEM_VERSION=unknown
515     fi
516 }
517
518 usage () {
519     set_defaults
520     cat <<EOF
521 $0: controls Open vSwitch daemons
522 usage: $0 [OPTIONS] COMMAND
523
524 This program is intended to be invoked internally by Open vSwitch startup
525 scripts.  System administrators should not normally invoke it directly.
526
527 Commands:
528   start              start Open vSwitch daemons
529   stop               stop Open vSwitch daemons
530   restart            stop and start Open vSwitch daemons
531   status             check whether Open vSwitch daemons are running
532   version            print versions of Open vSwitch daemons
533   load-kmod          insert modules if not already present
534   force-reload-kmod  save OVS network device state, stop OVS, unload kernel
535                      module, reload kernel module, start OVS, restore state
536   enable-protocol    enable protocol specified in options with iptables
537   help               display this help message
538
539 One of the following options is required for "start", "restart" and "force-reload-kmod":
540   --system-id=UUID   set specific ID to uniquely identify this system
541   --system-id=random  use a random but persistent UUID to identify this system
542
543 Other important options for "start", "restart" and "force-reload-kmod":
544   --system-type=TYPE  set system type (e.g. "XenServer")
545   --system-version=VERSION  set system version (e.g. "5.6.100-39265p")
546   --external-id="key=value"
547                      add given key-value pair to Open_vSwitch external-ids
548   --delete-bridges   delete all bridges just before starting ovs-vswitchd
549
550 Less important options for "start", "restart" and "force-reload-kmod":
551   --daemon-cwd=DIR               set working dir for OVS daemons (default: $DAEMON_CWD)
552   --no-force-corefiles           do not force on core dumps for OVS daemons
553   --no-mlockall                  do not lock all of ovs-vswitchd into memory
554   --ovsdb-server-priority=NICE   set ovsdb-server's niceness (default: $OVSDB_SERVER_PRIORITY)
555   --ovs-vswitchd-priority=NICE   set ovs-vswitchd's niceness (default: $OVS_VSWITCHD_PRIORITY)
556   --ovs-brcompatd-priority=NICE  set ovs-brcompatd's niceness (default: $OVS_BRCOMPATD_PRIORITY)
557
558 Debugging options for "start", "restart" and "force-reload-kmod":
559   --ovsdb-server-wrapper=WRAPPER
560   --ovs-vswitchd-wrapper=WRAPPER
561   --ovs-vswitchd-wrapper=WRAPPER
562      run specified daemon under WRAPPER (either 'valgrind' or 'strace')
563
564 Options for "start", "restart", "force-reload-kmod", "load-kmod", "status", and "version":
565   --brcompat         enable Linux bridge compatibility module and daemon
566
567 File location options:
568   --db-file=FILE     database file name (default: $DB_FILE)
569   --db-sock=SOCKET   JSON-RPC socket name (default: $DB_SOCK)
570   --db-schema=FILE   database schema file name (default: $DB_SCHEMA)
571
572 Options for "enable-protocol":
573   --protocol=PROTOCOL  protocol to enable with iptables (default: gre)
574   --sport=PORT       source port to match (for tcp or udp protocol)
575   --dport=PORT       ddestination port to match (for tcp or udp protocol)
576
577 Other options:
578   -h, --help                  display this help message
579   -V, --version               display version information
580
581 Default directories with "configure" option and environment variable override:
582   logs: @LOGDIR@ (--with-logdir, OVS_LOGDIR)
583   pidfiles and sockets: @RUNDIR@ (--with-rundir, OVS_RUNDIR)
584   conf.db: @DBDIR@ (--with-dbdir, OVS_DBDIR)
585   system configuration: @sysconfdir@ (--sysconfdir, OVS_SYSCONFDIR)
586   data files: @pkgdatadir@ (--pkgdatadir, OVS_PKGDATADIR)
587   user binaries: @bindir@ (--bindir, OVS_BINDIR)
588   system binaries: @sbindir@ (--sbindir, OVS_SBINDIR)
589
590 Please report bugs to bugs@openvswitch.org (see REPORTING-BUGS for details).
591 EOF
592
593     exit 0
594 }
595
596 set_option () {
597     var=`echo "$option" | tr abcdefghijklmnopqrstuvwxyz- ABCDEFGHIJKLMNOPQRSTUVWXYZ_`
598     eval set=\${$var+yes}
599     eval old_value=\$$var
600     if test X$set = X || \
601         (test $type = bool && \
602         test X"$old_value" != Xno && test X"$old_value" != Xyes); then
603         echo >&2 "$0: unknown option \"$arg\" (use --help for help)"
604         return
605     fi
606     eval $var=\$value
607 }
608
609 daemons () {
610     echo ovsdb-server ovs-vswitchd
611     if test X"$BRCOMPAT" = Xyes; then
612         echo ovs-brcompatd
613     fi
614 }
615
616 set_defaults
617 extra_ids=
618 command=
619 for arg
620 do
621     case $arg in
622         -h | --help)
623             usage
624             ;;
625         -V | --version)
626             echo "$0 (Open vSwitch) $VERSION"
627             exit 0
628             ;;
629         --external-id=*)
630             value=`expr X"$arg" : 'X[^=]*=\(.*\)'`
631             case $value in
632                 *=*)
633                     extra_ids="$extra_ids external-ids:$value"
634                     ;;
635                 *)
636                     echo >&2 "$0: --external-id argument not in the form \"key=value\""
637                     exit 1
638                     ;;
639             esac
640             ;;
641         --[a-z]*=*)
642             option=`expr X"$arg" : 'X--\([^=]*\)'`
643             value=`expr X"$arg" : 'X[^=]*=\(.*\)'`
644             type=string
645             set_option
646             ;;
647         --no-[a-z]*)
648             option=`expr X"$arg" : 'X--no-\(.*\)'`
649             value=no
650             type=bool
651             set_option
652             ;;
653         --[a-z]*)
654             option=`expr X"$arg" : 'X--\(.*\)'`
655             value=yes
656             type=bool
657             set_option
658             ;;
659         -*)
660             echo >&2 "$0: unknown option \"$arg\" (use --help for help)"
661             exit 1
662             ;;
663         *)
664             if test X"$command" = X; then
665                 command=$arg
666             else
667                 echo >&2 "$0: exactly one non-option argument required (use --help for help)"
668                 exit 1
669             fi
670             ;;
671     esac
672 done
673 case $command in
674     start)
675         start_ovsdb
676         start_forwarding
677         ;;
678     stop)
679         stop_forwarding
680         stop_ovsdb
681         ;;
682     restart)
683         restart
684         ;;
685     status)
686         rc=0
687         for daemon in `daemons`; do
688             daemon_status $daemon || rc=$?
689         done
690         exit $rc
691         ;;
692     version)
693         for daemon in `daemons`; do
694             $daemon --version
695         done
696         ;;
697     force-reload-kmod)
698             force_reload_kmod
699         ;;
700     load-kmod)
701         insert_mod_if_required
702         ;;
703     enable-protocol)
704         enable_protocol
705         ;;
706     help)
707         usage
708         ;;
709     '')
710         echo >&2 "$0: missing command name (use --help for help)"
711         exit 1
712         ;;
713     *)
714         echo >&2 "$0: unknown command \"$command\" (use --help for help)"
715         exit 1
716         ;;
717 esac