Avoid inserting duplicate iptables rules when restarting vswitch.
authorBen Pfaff <blp@nicira.com>
Tue, 21 Jun 2011 23:40:44 +0000 (16:40 -0700)
committerBen Pfaff <blp@nicira.com>
Tue, 21 Jun 2011 23:40:44 +0000 (16:40 -0700)
On startup, some OVS initscripts insert an iptables rule to allow GRE
traffic (because GRE support is an important OVS feature).  I noticed that,
each time I restarted OVS, this added another GRE-related rule to the
iptables chain.  This is wasteful, because each additional rule increases
the time it takes to process a packet in the IP stack.

This commit avoids the problem by inserting an iptables rule when there
isn't already an appropriate rule.  It also avoids inserting an iptables
rule if the iptables policy is ACCEPT, meaning that packets are accepted
by default; in such a case, if the GRE packet would be dropped, it is
because the system administrator made that decision explicitly.

Signed-off-by: Ben Pfaff <blp@nicira.com>
debian/openvswitch-switch.init
utilities/ovs-ctl.8
utilities/ovs-ctl.in
xenserver/etc_init.d_openvswitch

index a65af0ce1546c52368b769bf1867ad9cb6153134..36bc20891beeaddff563378007a82c72c63975d0 100755 (executable)
@@ -34,11 +34,9 @@ start () {
     if test X"$FORCE_COREFILES" != X; then
        set "$@" --force-corefiles="$FORCE_COREFILES"
     fi
+    "$@" || exit $?
 
-    # Allow GRE traffic.
-    test ! -x /sbin/iptables || /sbin/iptables -I INPUT -p gre -j ACCEPT
-
-    "$@"
+    $ovs_ctl --protocol=gre enable-protocol
 }
 
 stop () {
index d649d5625b0847dc7c26994a7c04680222a9c166..7aa8408d7e4ce31b85ddf6e61ab8b078d36fdf8d 100644 (file)
@@ -17,7 +17,7 @@
 ovs\-ctl \- OVS startup helper script
 .
 .SH SYNOPSIS
-\fBovs\-ctl\fR [\fB\-\-system\-id=random\fR | \fIuuid\fR]
+\fBovs\-ctl\fR \fB\-\-system\-id=random\fR|\fIuuid\fR
 [\fIoptions\fR] \fBstart
 .br
 \fBovs\-ctl stop
@@ -26,7 +26,16 @@ ovs\-ctl \- OVS startup helper script
 .br
 \fBovs\-ctl version
 .br
-\fBovs\-ctl force-reload-kmod
+\fBovs\-ctl
+\fB\-\-system\-id=random\fR|\fIuuid\fR
+[\fIoptions\fR]
+\fBforce\-reload\-kmod\fR
+.br
+\fBovs\-ctl
+\fR[\fB\-\-protocol=\fIprotocol\fR]
+[\fB\-\-sport=\fIsport\fR]
+[\fB\-\-dport=\fIdport\fR]
+\fBenable\-protocol\fR
 .br
 \fBovs\-ctl help \fR| \fB\-h \fR| \fB\-\-help
 .br
@@ -231,9 +240,51 @@ ISC DHCP client is running on an OVS internal interface, then it will
 have to be restarted after completing the above procedure.
 .
 .PP
-Because \fBforce\-kmod\-reload\fR internally stops and starts OVS, it
+\fBforce\-kmod\-reload\fR internally stops and starts OVS, so it
 accepts all of the options accepted by the \fBstart\fR command.
 .
+.SS "The ``enable\-protocol'' command"
+.
+.PP
+The \fBenable\-protocol\fR command checks for rules related to a
+specified protocol in the system's \fBiptables\fR(8) configuration.  If there
+are no rules specifically related to that protocol, then it inserts a
+rule to accept the specified protocol.
+.
+.PP
+More specifically:
+.
+.IP \(bu
+If \fBiptables\fR is not installed or not enabled, this command does
+nothing, assuming that lack of filtering means that the protocol is
+enabled.
+.
+.IP \(bu
+If the \fBINPUT\fR chain has a rule that matches the specified
+protocol, then this command does nothing, assuming that whatever rule
+is installed reflects the system administrator's decisions.
+.
+.IP \(bu
+Otherwise, this command installs a rule that accepts traffic of the
+specified protocol.
+.
+.PP
+This command normally completes successfully, even if it does
+nothing.  Only the failure of an attempt to insert a rule normally
+causes it to return an exit code other than 0.
+.
+The following options control the protocol to be enabled:
+.
+.IP "\fB\-\-protocol=\fIprotocol\fR"
+The name of the IP protocol to be enabled, such as \fBgre\fR or
+\fBtcp\fR.  The default is \fBgre\fR.
+.
+.IP "\fB\-\-sport=\fIsport\fR"
+.IQ "\fB\-\-dport=\fIdport\fR"
+TCP or UDP source or destination port to match.  These are optional
+and allowed only with \fB\-\-protocol=tcp\fR or
+\fB\-\-protocol=udp\fR.
+.
 .SS "The ``help'' command"
 .
 Prints a usage message and exits successfully.
index 44afbd2727177f7c72f3b2383db685105ed163f1..4d1ce1881712e802d59673a63b5972ce47944160 100755 (executable)
@@ -265,6 +265,49 @@ force_reload_kmod () {
     $log -f "$script"
 }
 
+## --------------- ##
+## enable-protocol ##
+## --------------- ##
+
+enable_protocol () {
+    set X "-p $PROTOCOL"
+    name=$PROTOCOL
+    if test X"$DPORT" != X; then
+        set "$@" "--dport $DPORT"
+        name="$name to port $DPORT"
+    fi
+    if test X"$SPORT" != X; then
+        set "$@" "--sport $SPORT"
+        name="$name from port $SPORT"
+    fi
+    shift
+
+    search="/^-A INPUT/!d"
+    insert="iptables -I INPUT"
+    for arg; do
+        search="$search
+/ $arg /!d"
+        insert="$insert $arg"
+    done
+    insert="$insert -j ACCEPT"
+
+    if (iptables -S INPUT) >/dev/null 2>&1; then
+        case `iptables -S INPUT | sed "$search"` in
+            '')
+                action "Enabling $name with iptables" $insert
+                ;;
+            *)
+                # There's already a rule for this protocol.  Don't override it.
+                log_success_msg "iptables already has a rule for $name, not explicitly enabling"
+                ;;
+        esac
+    elif (iptables --version) >/dev/null 2>&1; then
+        action "iptables binary not installed, not adding a rule for $name"
+    else
+        action "cannot list iptables rules, not adding a rule for $name"
+    fi
+}
+
 ## ---- ##
 ## main ##
 ## ---- ##
@@ -284,6 +327,10 @@ set_defaults () {
     DB_SOCK=$rundir/db.sock
     DB_SCHEMA=$datadir/vswitch.ovsschema
 
+    PROTOCOL=gre
+    DPORT=
+    SPORT=
+
     if (lsb_release --id) >/dev/null 2>&1; then
         SYSTEM_TYPE=`lsb_release --id -s`
         system_release=`lsb_release --release -s`
@@ -311,6 +358,7 @@ Commands:
   version            print versions of Open vSwitch daemons
   force-reload-kmod  save OVS network device state, stop OVS, unload kernel
                      module, reload kernel module, start OVS, restore state
+  enable-protocol    enable protocol specified in options with iptables
   help               display this help message
 
 One of the following options should be specified when starting Open vSwitch:
@@ -339,6 +387,11 @@ File location options:
   --db-sock=SOCKET   JSON-RPC socket name (default: $DB_SOCK)
   --db-schema=FILE   database schema file name (default: $DB_SCHEMA)
 
+Options for enable-protocol:
+  --protocol=PROTOCOL  protocol to enable with iptables (default: gre)
+  --sport=PORT       source port to match (for tcp or udp protocol)
+  --dport=PORT       ddestination port to match (for tcp or udp protocol)
+
 Other options:
   -h, --help                  display this help message
   -V, --version               display version information
@@ -443,6 +496,9 @@ case $command in
     force-reload-kmod)
        force_reload_kmod
         ;;
+    enable-protocol)
+        enable_protocol
+        ;;
     help)
         usage
         ;;
index 39d4d364e824b92f3c0d3f612351cc5f88ebb669..81039004035d5ca3eb75a152354b1c0ab06832b1 100755 (executable)
@@ -76,8 +76,7 @@ start () {
             --pidfile --detach --monitor unix:/var/run/openvswitch/db.sock
     fi
 
-    # Allow GRE traffic.
-    /sbin/iptables -I INPUT -p gre -j ACCEPT
+    $ovs_ctl --protocol=gre enable-protocol
 
     touch /var/lock/subsys/openvswitch
 }