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