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