7febd1c2198527408ba544c22f1a98357375ac36
[openvswitch] / 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 the saved flows. Do not return error if restore fails.
424     restore_flows || true
425 }
426
427 ## --------------- ##
428 ## enable-protocol ##
429 ## --------------- ##
430
431 enable_protocol () {
432     # Translate the protocol name to a number, because "iptables -n -L" prints
433     # some protocols by name (despite the -n) and therefore we need to look for
434     # both forms.
435     #
436     # (iptables -S output is more uniform but old iptables doesn't have it.)
437     protonum=`grep "^$PROTOCOL[         ]" /etc/protocols | awk '{print $2}'`
438     if expr X"$protonum" : X'[0-9]\{1,\}$' > /dev/null; then :; else
439         log_failure_msg "unknown protocol $PROTOCOL"
440         return 1
441     fi
442
443     name=$PROTOCOL
444     match="(\$2 == \"$PROTOCOL\" || \$2 == $protonum)"
445     insert="iptables -I INPUT -p $PROTOCOL"
446     if test X"$DPORT" != X; then
447         name="$name to port $DPORT"
448         match="$match && /dpt:$DPORT/"
449         insert="$insert --dport $DPORT"
450     fi
451     if test X"$SPORT" != X; then
452         name="$name from port $SPORT"
453         match="$match && /spt:$SPORT/"
454         insert="$insert --sport $SPORT"
455     fi
456     insert="$insert -j ACCEPT"
457
458     if (iptables -n -L INPUT) >/dev/null 2>&1; then
459         if iptables -n -L INPUT | awk "$match { n++ } END { exit n == 0 }"
460         then
461             # There's already a rule for this protocol.  Don't override it.
462             log_success_msg "iptables already has a rule for $name, not explicitly enabling"
463         else
464             action "Enabling $name with iptables" $insert
465         fi
466     elif (iptables --version) >/dev/null 2>&1; then
467         action "cannot list iptables rules, not adding a rule for $name"
468     else
469         action "iptables binary not installed, not adding a rule for $name"
470     fi
471 }
472
473 ## ---- ##
474 ## main ##
475 ## ---- ##
476
477 set_defaults () {
478     SYSTEM_ID=
479
480     DELETE_BRIDGES=no
481     BRCOMPAT=no
482
483     DAEMON_CWD=/
484     FORCE_COREFILES=yes
485     MLOCKALL=yes
486     OVSDB_SERVER_PRIORITY=-10
487     OVS_VSWITCHD_PRIORITY=-10
488     OVS_BRCOMPATD_PRIORITY=-10
489     OVSDB_SERVER_WRAPPER=
490     OVS_VSWITCHD_WRAPPER=
491     OVS_BRCOMPATD_WRAPPER=
492
493     DB_FILE=$dbdir/conf.db
494     DB_SOCK=$rundir/db.sock
495     DB_SCHEMA=$datadir/vswitch.ovsschema
496     EXTRA_DBS=
497
498     PROTOCOL=gre
499     DPORT=
500     SPORT=
501
502     type_file=$etcdir/system-type.conf
503     version_file=$etcdir/system-version.conf
504
505     if test -e "$type_file" ; then
506         SYSTEM_TYPE=`cat $type_file`
507         SYSTEM_VERSION=`cat $version_file`
508     elif (lsb_release --id) >/dev/null 2>&1; then
509         SYSTEM_TYPE=`lsb_release --id -s`
510         system_release=`lsb_release --release -s`
511         system_codename=`lsb_release --codename -s`
512         SYSTEM_VERSION="${system_release}-${system_codename}"
513     else
514         SYSTEM_TYPE=unknown
515         SYSTEM_VERSION=unknown
516     fi
517 }
518
519 usage () {
520     set_defaults
521     cat <<EOF
522 $0: controls Open vSwitch daemons
523 usage: $0 [OPTIONS] COMMAND
524
525 This program is intended to be invoked internally by Open vSwitch startup
526 scripts.  System administrators should not normally invoke it directly.
527
528 Commands:
529   start              start Open vSwitch daemons
530   stop               stop Open vSwitch daemons
531   restart            stop and start Open vSwitch daemons
532   status             check whether Open vSwitch daemons are running
533   version            print versions of Open vSwitch daemons
534   load-kmod          insert modules if not already present
535   force-reload-kmod  save OVS network device state, stop OVS, unload kernel
536                      module, reload kernel module, start OVS, restore state
537   enable-protocol    enable protocol specified in options with iptables
538   help               display this help message
539
540 One of the following options is required for "start", "restart" and "force-reload-kmod":
541   --system-id=UUID   set specific ID to uniquely identify this system
542   --system-id=random  use a random but persistent UUID to identify this system
543
544 Other important options for "start", "restart" and "force-reload-kmod":
545   --system-type=TYPE  set system type (e.g. "XenServer")
546   --system-version=VERSION  set system version (e.g. "5.6.100-39265p")
547   --external-id="key=value"
548                      add given key-value pair to Open_vSwitch external-ids
549   --delete-bridges   delete all bridges just before starting ovs-vswitchd
550
551 Less important options for "start", "restart" and "force-reload-kmod":
552   --daemon-cwd=DIR               set working dir for OVS daemons (default: $DAEMON_CWD)
553   --no-force-corefiles           do not force on core dumps for OVS daemons
554   --no-mlockall                  do not lock all of ovs-vswitchd into memory
555   --ovsdb-server-priority=NICE   set ovsdb-server's niceness (default: $OVSDB_SERVER_PRIORITY)
556   --ovs-vswitchd-priority=NICE   set ovs-vswitchd's niceness (default: $OVS_VSWITCHD_PRIORITY)
557   --ovs-brcompatd-priority=NICE  set ovs-brcompatd's niceness (default: $OVS_BRCOMPATD_PRIORITY)
558
559 Debugging options for "start", "restart" and "force-reload-kmod":
560   --ovsdb-server-wrapper=WRAPPER
561   --ovs-vswitchd-wrapper=WRAPPER
562   --ovs-vswitchd-wrapper=WRAPPER
563      run specified daemon under WRAPPER (either 'valgrind' or 'strace')
564
565 Options for "start", "restart", "force-reload-kmod", "load-kmod", "status", and "version":
566   --brcompat         enable Linux bridge compatibility module and daemon
567
568 File location options:
569   --db-file=FILE     database file name (default: $DB_FILE)
570   --db-sock=SOCKET   JSON-RPC socket name (default: $DB_SOCK)
571   --db-schema=FILE   database schema file name (default: $DB_SCHEMA)
572
573 Options for "enable-protocol":
574   --protocol=PROTOCOL  protocol to enable with iptables (default: gre)
575   --sport=PORT       source port to match (for tcp or udp protocol)
576   --dport=PORT       ddestination port to match (for tcp or udp protocol)
577
578 Other options:
579   -h, --help                  display this help message
580   -V, --version               display version information
581
582 Default directories with "configure" option and environment variable override:
583   logs: @LOGDIR@ (--with-logdir, OVS_LOGDIR)
584   pidfiles and sockets: @RUNDIR@ (--with-rundir, OVS_RUNDIR)
585   conf.db: @DBDIR@ (--with-dbdir, OVS_DBDIR)
586   system configuration: @sysconfdir@ (--sysconfdir, OVS_SYSCONFDIR)
587   data files: @pkgdatadir@ (--pkgdatadir, OVS_PKGDATADIR)
588   user binaries: @bindir@ (--bindir, OVS_BINDIR)
589   system binaries: @sbindir@ (--sbindir, OVS_SBINDIR)
590
591 Please report bugs to bugs@openvswitch.org (see REPORTING-BUGS for details).
592 EOF
593
594     exit 0
595 }
596
597 set_option () {
598     var=`echo "$option" | tr abcdefghijklmnopqrstuvwxyz- ABCDEFGHIJKLMNOPQRSTUVWXYZ_`
599     eval set=\${$var+yes}
600     eval old_value=\$$var
601     if test X$set = X || \
602         (test $type = bool && \
603         test X"$old_value" != Xno && test X"$old_value" != Xyes); then
604         echo >&2 "$0: unknown option \"$arg\" (use --help for help)"
605         return
606     fi
607     eval $var=\$value
608 }
609
610 daemons () {
611     echo ovsdb-server ovs-vswitchd
612     if test X"$BRCOMPAT" = Xyes; then
613         echo ovs-brcompatd
614     fi
615 }
616
617 set_defaults
618 extra_ids=
619 command=
620 for arg
621 do
622     case $arg in
623         -h | --help)
624             usage
625             ;;
626         -V | --version)
627             echo "$0 (Open vSwitch) $VERSION"
628             exit 0
629             ;;
630         --external-id=*)
631             value=`expr X"$arg" : 'X[^=]*=\(.*\)'`
632             case $value in
633                 *=*)
634                     extra_ids="$extra_ids external-ids:$value"
635                     ;;
636                 *)
637                     echo >&2 "$0: --external-id argument not in the form \"key=value\""
638                     exit 1
639                     ;;
640             esac
641             ;;
642         --[a-z]*=*)
643             option=`expr X"$arg" : 'X--\([^=]*\)'`
644             value=`expr X"$arg" : 'X[^=]*=\(.*\)'`
645             type=string
646             set_option
647             ;;
648         --no-[a-z]*)
649             option=`expr X"$arg" : 'X--no-\(.*\)'`
650             value=no
651             type=bool
652             set_option
653             ;;
654         --[a-z]*)
655             option=`expr X"$arg" : 'X--\(.*\)'`
656             value=yes
657             type=bool
658             set_option
659             ;;
660         -*)
661             echo >&2 "$0: unknown option \"$arg\" (use --help for help)"
662             exit 1
663             ;;
664         *)
665             if test X"$command" = X; then
666                 command=$arg
667             else
668                 echo >&2 "$0: exactly one non-option argument required (use --help for help)"
669                 exit 1
670             fi
671             ;;
672     esac
673 done
674 case $command in
675     start)
676         start_ovsdb
677         start_forwarding
678         ;;
679     stop)
680         stop_forwarding
681         stop_ovsdb
682         ;;
683     restart)
684         restart
685         ;;
686     status)
687         rc=0
688         for daemon in `daemons`; do
689             daemon_status $daemon || rc=$?
690         done
691         exit $rc
692         ;;
693     version)
694         for daemon in `daemons`; do
695             $daemon --version
696         done
697         ;;
698     force-reload-kmod)
699             force_reload_kmod
700         ;;
701     load-kmod)
702         insert_mod_if_required
703         ;;
704     enable-protocol)
705         enable_protocol
706         ;;
707     help)
708         usage
709         ;;
710     '')
711         echo >&2 "$0: missing command name (use --help for help)"
712         exit 1
713         ;;
714     *)
715         echo >&2 "$0: unknown command \"$command\" (use --help for help)"
716         exit 1
717         ;;
718 esac