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