Merge 'master' into 'next'.
authorBen Pfaff <blp@nicira.com>
Thu, 12 May 2011 19:05:42 +0000 (12:05 -0700)
committerBen Pfaff <blp@nicira.com>
Thu, 12 May 2011 19:05:42 +0000 (12:05 -0700)
65 files changed:
AUTHORS
ChangeLog
DESIGN
INSTALL.XenServer
datapath/actions.c
datapath/actions.h
datapath/datapath.c
datapath/flow.c
datapath/linux-2.6/.gitignore
datapath/linux-2.6/compat-2.6/include/linux/kernel.h
datapath/loop_counter.c
datapath/loop_counter.h
datapath/tunnel.c
datapath/tunnel.h
debian/ovs-monitor-ipsec
include/openflow/nicira-ext.h
include/openvswitch/tunnel.h
lib/automake.mk
lib/bond.c
lib/bond.h
lib/dpif-linux.c
lib/dpif.c
lib/dpif.h
lib/flow.h
lib/lacp.c
lib/lacp.h
lib/learning-switch.c
lib/netdev-linux.c
lib/netdev-linux.h [new file with mode: 0644]
lib/netdev-vport.c
lib/ofp-parse.c
lib/ofp-print.c
lib/ofp-util.c
lib/ofp-util.h
lib/stream-nossl.c [new file with mode: 0644]
lib/stream-ssl.h
ofproto/connmgr.c
ofproto/in-band.c
ofproto/ofproto-dpif.c
ofproto/ofproto.c
ofproto/ofproto.h
ofproto/private.h
ovsdb/ovsdb-client.c
ovsdb/ovsdb-server.c
tests/ofp-print.at
tests/ofproto.at
tests/ovs-ofctl.at
tests/test-flows.c
tests/test-jsonrpc.c
utilities/ovs-controller.c
utilities/ovs-dpctl.8.in
utilities/ovs-dpctl.c
utilities/ovs-ofctl.8.in
utilities/ovs-ofctl.c
utilities/ovs-openflowd.c
utilities/ovs-tcpundump.1.in
utilities/ovs-vsctl.8.in
utilities/ovs-vsctl.c
vswitchd/bridge.c
vswitchd/ovs-brcompatd.8.in
vswitchd/ovs-vswitchd.8.in
vswitchd/ovs-vswitchd.c
vswitchd/vswitch.ovsschema
vswitchd/vswitch.xml
xenserver/openvswitch-xen.spec

diff --git a/AUTHORS b/AUTHORS
index 38ca142..1aa1cb3 100644 (file)
--- a/AUTHORS
+++ b/AUTHORS
@@ -44,6 +44,7 @@ Aaron M. Ucko           ucko@debian.org
 Aaron Rosen             arosen@clemson.edu
 Alex Yip                alex@nicira.com
 Alexey I. Froloff       raorn@altlinux.org
+Bob Ball                bob.ball@citrix.com
 Brad Hall               brad@nicira.com
 Brandon Heller          brandonh@stanford.edu
 Bryan Fulton            bryan@nicira.com
@@ -55,6 +56,7 @@ DK Moon                 dkmoon@nicira.com
 Gaetano Catalli         gaetano.catalli@gmail.com
 Ghanem Bahri            bahri.ghanem@gmail.com
 Giuseppe de Candia      giuseppe.decandia@gmail.com
+Gregor Schaffrath       grsch@net.t-labs.tu-berlin.de
 Hassan Khan             hassan.khan@seecs.edu.pk
 Hector Oron             hector.oron@gmail.com
 Henrik Amren            henrik@nicira.com
index 76d8e29..bd0c40d 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+post v1.1.0
+------------------------
+    - The new "-s" option for "ovs-dpctl show" prints packet and byte
+      counters for each port.
+    - Feature removals:
+      - Dropped support for "tun_id_from_cookie" OpenFlow extension.
+       (Use the extensible match extensions instead.)
+
 v1.1.0 - 05 Apr 2011
 ------------------------
     - Ability to define policies over IPv6
diff --git a/DESIGN b/DESIGN
index 6e25f01..2e3fced 100644 (file)
--- a/DESIGN
+++ b/DESIGN
@@ -71,6 +71,169 @@ nodes that do not connect to link with such large MTUs.  Currently, Open
 vSwitch doesn't process jumbograms.
 
 
+In-Band Control
+===============
+
+In-band control allows a single network to be used for OpenFlow traffic and
+other data traffic.  See ovs-vswitchd.conf.db(5) for a description of
+configuring in-band control.
+
+This comment is an attempt to describe how in-band control works at a
+wire- and implementation-level.  Correctly implementing in-band
+control has proven difficult due to its many subtleties, and has thus
+gone through many iterations.  Please read through and understand the
+reasoning behind the chosen rules before making modifications.
+
+In Open vSwitch, in-band control is implemented as "hidden" flows (in that
+they are not visible through OpenFlow) and at a higher priority than
+wildcarded flows can be set up by through OpenFlow.  This is done so that
+the OpenFlow controller cannot interfere with them and possibly break
+connectivity with its switches.  It is possible to see all flows, including
+in-band ones, with the ovs-appctl "bridge/dump-flows" command.
+
+The Open vSwitch implementation of in-band control can hide traffic to
+arbitrary "remotes", where each remote is one TCP port on one IP address.
+Currently the remotes are automatically configured as the in-band OpenFlow
+controllers plus the OVSDB managers, if any.  (The latter is a requirement
+because OVSDB managers are responsible for configuring OpenFlow controllers,
+so if the manager cannot be reached then OpenFlow cannot be reconfigured.)
+
+The following rules (with the OFPP_NORMAL action) are set up on any bridge
+that has any remotes:
+
+   (a) DHCP requests sent from the local port.
+   (b) ARP replies to the local port's MAC address.
+   (c) ARP requests from the local port's MAC address.
+
+In-band also sets up the following rules for each unique next-hop MAC
+address for the remotes' IPs (the "next hop" is either the remote
+itself, if it is on a local subnet, or the gateway to reach the remote):
+
+   (d) ARP replies to the next hop's MAC address.
+   (e) ARP requests from the next hop's MAC address.
+
+In-band also sets up the following rules for each unique remote IP address:
+
+   (f) ARP replies containing the remote's IP address as a target.
+   (g) ARP requests containing the remote's IP address as a source.
+
+In-band also sets up the following rules for each unique remote (IP,port)
+pair:
+
+   (h) TCP traffic to the remote's IP and port.
+   (i) TCP traffic from the remote's IP and port.
+
+The goal of these rules is to be as narrow as possible to allow a
+switch to join a network and be able to communicate with the
+remotes.  As mentioned earlier, these rules have higher priority
+than the controller's rules, so if they are too broad, they may
+prevent the controller from implementing its policy.  As such,
+in-band actively monitors some aspects of flow and packet processing
+so that the rules can be made more precise.
+
+In-band control monitors attempts to add flows into the datapath that
+could interfere with its duties.  The datapath only allows exact
+match entries, so in-band control is able to be very precise about
+the flows it prevents.  Flows that miss in the datapath are sent to
+userspace to be processed, so preventing these flows from being
+cached in the "fast path" does not affect correctness.  The only type
+of flow that is currently prevented is one that would prevent DHCP
+replies from being seen by the local port.  For example, a rule that
+forwarded all DHCP traffic to the controller would not be allowed,
+but one that forwarded to all ports (including the local port) would.
+
+As mentioned earlier, packets that miss in the datapath are sent to
+the userspace for processing.  The userspace has its own flow table,
+the "classifier", so in-band checks whether any special processing
+is needed before the classifier is consulted.  If a packet is a DHCP
+response to a request from the local port, the packet is forwarded to
+the local port, regardless of the flow table.  Note that this requires
+L7 processing of DHCP replies to determine whether the 'chaddr' field
+matches the MAC address of the local port.
+
+It is interesting to note that for an L3-based in-band control
+mechanism, the majority of rules are devoted to ARP traffic.  At first
+glance, some of these rules appear redundant.  However, each serves an
+important role.  First, in order to determine the MAC address of the
+remote side (controller or gateway) for other ARP rules, we must allow
+ARP traffic for our local port with rules (b) and (c).  If we are
+between a switch and its connection to the remote, we have to
+allow the other switch's ARP traffic to through.  This is done with
+rules (d) and (e), since we do not know the addresses of the other
+switches a priori, but do know the remote's or gateway's.  Finally,
+if the remote is running in a local guest VM that is not reached
+through the local port, the switch that is connected to the VM must
+allow ARP traffic based on the remote's IP address, since it will
+not know the MAC address of the local port that is sending the traffic
+or the MAC address of the remote in the guest VM.
+
+With a few notable exceptions below, in-band should work in most
+network setups.  The following are considered "supported' in the
+current implementation:
+
+   - Locally Connected.  The switch and remote are on the same
+     subnet.  This uses rules (a), (b), (c), (h), and (i).
+
+   - Reached through Gateway.  The switch and remote are on
+     different subnets and must go through a gateway.  This uses
+     rules (a), (b), (c), (h), and (i).
+
+   - Between Switch and Remote.  This switch is between another
+     switch and the remote, and we want to allow the other
+     switch's traffic through.  This uses rules (d), (e), (h), and
+     (i).  It uses (b) and (c) indirectly in order to know the MAC
+     address for rules (d) and (e).  Note that DHCP for the other
+     switch will not work unless an OpenFlow controller explicitly lets this
+     switch pass the traffic.
+
+   - Between Switch and Gateway.  This switch is between another
+     switch and the gateway, and we want to allow the other switch's
+     traffic through.  This uses the same rules and logic as the
+     "Between Switch and Remote" configuration described earlier.
+
+   - Remote on Local VM.  The remote is a guest VM on the
+     system running in-band control.  This uses rules (a), (b), (c),
+     (h), and (i).
+
+   - Remote on Local VM with Different Networks.  The remote
+     is a guest VM on the system running in-band control, but the
+     local port is not used to connect to the remote.  For
+     example, an IP address is configured on eth0 of the switch.  The
+     remote's VM is connected through eth1 of the switch, but an
+     IP address has not been configured for that port on the switch.
+     As such, the switch will use eth0 to connect to the remote,
+     and eth1's rules about the local port will not work.  In the
+     example, the switch attached to eth0 would use rules (a), (b),
+     (c), (h), and (i) on eth0.  The switch attached to eth1 would use
+     rules (f), (g), (h), and (i).
+
+The following are explicitly *not* supported by in-band control:
+
+   - Specify Remote by Name.  Currently, the remote must be
+     identified by IP address.  A naive approach would be to permit
+     all DNS traffic.  Unfortunately, this would prevent the
+     controller from defining any policy over DNS.  Since switches
+     that are located behind us need to connect to the remote,
+     in-band cannot simply add a rule that allows DNS traffic from
+     the local port.  The "correct" way to support this is to parse
+     DNS requests to allow all traffic related to a request for the
+     remote's name through.  Due to the potential security
+     problems and amount of processing, we decided to hold off for
+     the time-being.
+
+   - Differing Remotes for Switches.  All switches must know
+     the L3 addresses for all the remotes that other switches
+     may use, since rules need to be set up to allow traffic related
+     to those remotes through.  See rules (f), (g), (h), and (i).
+
+   - Differing Routes for Switches.  In order for the switch to
+     allow other switches to connect to a remote through a
+     gateway, it allows the gateway's traffic through with rules (d)
+     and (e).  If the routes to the remote differ for the two
+     switches, we will not know the MAC address of the alternate
+     gateway.
+
+
 Suggestions
 ===========
 
index 48f8178..9d9012b 100644 (file)
@@ -69,6 +69,74 @@ To uninstall Open vSwitch from a XenServer host, remove the packages:
 After installing or uninstalling Open vSwitch, the XenServer should be
 rebooted as soon as possible.
 
+Open vSwitch Boot Sequence on XenServer
+---------------------------------------
+
+When Open vSwitch is installed on XenServer, its startup script
+/etc/init.d/openvswitch runs early in boot.  It does roughly the
+following:
+
+        * Loads the OVS kernel module, openvswitch_mod.
+
+        * Starts ovsdb-server, the OVS configuration database.
+
+        * XenServer expects there to be no bridges configured at
+          startup, but the OVS configuration database likely still has
+          bridges configured from before reboot.  To match XenServer
+          expectations, the startup script deletes all configured
+          bridges from the database.
+
+        * Starts ovs-vswitchd, the OVS switching daemon.
+
+At this point in the boot process, then, there are no Open vSwitch
+bridges, even though all of the Open vSwitch daemons are running.
+Later on in boot, /etc/init.d/management-interface (part of XenServer,
+not Open vSwitch) creates the bridge for the XAPI management interface
+by invoking /opt/xensource/libexec/interface-reconfigure.  Normally
+this program consults XAPI's database to obtain information about how
+to configure the bridge, but XAPI is not running yet[*] so it instead
+consults /var/xapi/network.dbcache, which is a cached copy of the most
+recent network configuration.
+
+[*] Even if XAPI were running, if this XenServer node is a pool slave
+    then the query would have to consult the master, which requires
+    network access, which begs the question of how to configure the
+    management interface.
+
+XAPI starts later on in the boot process.  XAPI can then create other
+bridges on demand using /opt/xensource/libexec/interface-reconfigure.
+Now that XAPI is running, that program consults XAPI directly instead
+of reading the cache.
+
+As part of its own startup, XAPI invokes the Open vSwitch XAPI plugin
+script /etc/xapi.d/openvswitch-cfg-update passing the "update"
+command.  The plugin script does roughly the following:
+
+        * Calls /opt/xensource/libexec/interface-reconfigure with the
+          "rewrite" command, to ensure that the network cache is
+          up-to-date.
+
+        * Queries the Open vSwitch manager setting (named
+          "vswitch_controller") from the XAPI database for the
+          XenServer pool.
+
+        * If XAPI and OVS are configured for different managers, or if
+          OVS is configured for a manager but XAPI is not, runs
+          "ovs-vsctl emer-reset" to bring the Open vSwitch
+          configuration to a known state.  One effect of emer-reset is
+          to deconfigure any manager from the OVS database.
+
+        * If XAPI is configured for a manger, configures the OVS
+          manager to match with "ovs-vsctl set-manager".
+
+The Open vSwitch boot sequence only configures an OVS configuration
+database manager.  There is no way to directly configure an OpenFlow
+controller on XenServer and, as a consequence of the step above that
+deletes all of the bridges at boot time, controller configuration only
+persists until XenServer reboot.  The configuration database manager
+can, however, configure controllers for bridges.  See the BUGS section
+of ovs-controller(8) for more information on this topic.
+
 Reporting Bugs
 --------------
 
index a2a572e..b6b7135 100644 (file)
 #include "actions.h"
 #include "checksum.h"
 #include "datapath.h"
+#include "loop_counter.h"
 #include "openvswitch/datapath-protocol.h"
 #include "vlan.h"
 #include "vport.h"
 
 static int do_execute_actions(struct datapath *, struct sk_buff *,
-                             const struct sw_flow_key *,
-                             const struct nlattr *actions, u32 actions_len);
+                             struct sw_flow_actions *acts);
 
 static struct sk_buff *make_writable(struct sk_buff *skb, unsigned min_headroom)
 {
@@ -112,35 +112,34 @@ static struct sk_buff *modify_vlan_tci(struct sk_buff *skb, __be16 tci)
        return skb;
 }
 
-static bool is_ip(struct sk_buff *skb, const struct sw_flow_key *key)
+static bool is_ip(struct sk_buff *skb)
 {
-       return (key->dl_type == htons(ETH_P_IP) &&
+       return (OVS_CB(skb)->flow->key.dl_type == htons(ETH_P_IP) &&
                skb->transport_header > skb->network_header);
 }
 
-static __sum16 *get_l4_checksum(struct sk_buff *skb, const struct sw_flow_key *key)
+static __sum16 *get_l4_checksum(struct sk_buff *skb)
 {
+       u8 nw_proto = OVS_CB(skb)->flow->key.nw_proto;
        int transport_len = skb->len - skb_transport_offset(skb);
-       if (key->nw_proto == IPPROTO_TCP) {
+       if (nw_proto == IPPROTO_TCP) {
                if (likely(transport_len >= sizeof(struct tcphdr)))
                        return &tcp_hdr(skb)->check;
-       } else if (key->nw_proto == IPPROTO_UDP) {
+       } else if (nw_proto == IPPROTO_UDP) {
                if (likely(transport_len >= sizeof(struct udphdr)))
                        return &udp_hdr(skb)->check;
        }
        return NULL;
 }
 
-static struct sk_buff *set_nw_addr(struct sk_buff *skb,
-                                  const struct sw_flow_key *key,
-                                  const struct nlattr *a)
+static struct sk_buff *set_nw_addr(struct sk_buff *skb, const struct nlattr *a)
 {
        __be32 new_nwaddr = nla_get_be32(a);
        struct iphdr *nh;
        __sum16 *check;
        __be32 *nwaddr;
 
-       if (unlikely(!is_ip(skb, key)))
+       if (unlikely(!is_ip(skb)))
                return skb;
 
        skb = make_writable(skb, 0);
@@ -150,7 +149,7 @@ static struct sk_buff *set_nw_addr(struct sk_buff *skb,
        nh = ip_hdr(skb);
        nwaddr = nla_type(a) == ODP_ACTION_ATTR_SET_NW_SRC ? &nh->saddr : &nh->daddr;
 
-       check = get_l4_checksum(skb, key);
+       check = get_l4_checksum(skb);
        if (likely(check))
                inet_proto_csum_replace4(check, skb, *nwaddr, new_nwaddr, 1);
        csum_replace4(&nh->check, *nwaddr, new_nwaddr);
@@ -162,11 +161,9 @@ static struct sk_buff *set_nw_addr(struct sk_buff *skb,
        return skb;
 }
 
-static struct sk_buff *set_nw_tos(struct sk_buff *skb,
-                                 const struct sw_flow_key *key,
-                                 u8 nw_tos)
+static struct sk_buff *set_nw_tos(struct sk_buff *skb, u8 nw_tos)
 {
-       if (unlikely(!is_ip(skb, key)))
+       if (unlikely(!is_ip(skb)))
                return skb;
 
        skb = make_writable(skb, 0);
@@ -185,15 +182,13 @@ static struct sk_buff *set_nw_tos(struct sk_buff *skb,
        return skb;
 }
 
-static struct sk_buff *set_tp_port(struct sk_buff *skb,
-                                  const struct sw_flow_key *key,
-                                  const struct nlattr *a)
+static struct sk_buff *set_tp_port(struct sk_buff *skb, const struct nlattr *a)
 {
        struct udphdr *th;
        __sum16 *check;
        __be16 *port;
 
-       if (unlikely(!is_ip(skb, key)))
+       if (unlikely(!is_ip(skb)))
                return skb;
 
        skb = make_writable(skb, 0);
@@ -201,7 +196,7 @@ static struct sk_buff *set_tp_port(struct sk_buff *skb,
                return NULL;
 
        /* Must follow make_writable() since that can move the skb data. */
-       check = get_l4_checksum(skb, key);
+       check = get_l4_checksum(skb);
        if (unlikely(!check))
                return skb;
 
@@ -226,17 +221,16 @@ static struct sk_buff *set_tp_port(struct sk_buff *skb,
  *
  * @skb: skbuff containing an Ethernet packet, with network header pointing
  * just past the Ethernet and optional 802.1Q header.
- * @key: flow key extracted from @skb by flow_extract()
  *
  * Returns true if @skb is an invalid Ethernet+IPv4 ARP packet: one with screwy
  * or truncated header fields or one whose inner and outer Ethernet address
  * differ.
  */
-static bool is_spoofed_arp(struct sk_buff *skb, const struct sw_flow_key *key)
+static bool is_spoofed_arp(struct sk_buff *skb)
 {
        struct arp_eth_header *arp;
 
-       if (key->dl_type != htons(ETH_P_ARP))
+       if (OVS_CB(skb)->flow->key.dl_type != htons(ETH_P_ARP))
                return false;
 
        if (skb_network_offset(skb) + sizeof(struct arp_eth_header) > skb->len)
@@ -268,8 +262,7 @@ error:
        kfree_skb(skb);
 }
 
-static int output_control(struct datapath *dp, struct sk_buff *skb, u64 arg,
-                         const struct sw_flow_key *key)
+static int output_control(struct datapath *dp, struct sk_buff *skb, u64 arg)
 {
        struct dp_upcall_info upcall;
 
@@ -278,7 +271,7 @@ static int output_control(struct datapath *dp, struct sk_buff *skb, u64 arg,
                return -ENOMEM;
 
        upcall.cmd = ODP_PACKET_CMD_ACTION;
-       upcall.key = key;
+       upcall.key = &OVS_CB(skb)->flow->key;
        upcall.userdata = arg;
        upcall.sample_pool = 0;
        upcall.actions = NULL;
@@ -288,8 +281,7 @@ static int output_control(struct datapath *dp, struct sk_buff *skb, u64 arg,
 
 /* Execute a list of actions against 'skb'. */
 static int do_execute_actions(struct datapath *dp, struct sk_buff *skb,
-                             const struct sw_flow_key *key,
-                             const struct nlattr *actions, u32 actions_len)
+                             struct sw_flow_actions *acts)
 {
        /* Every output action needs a separate clone of 'skb', but the common
         * case is just a single output action, so that doing a clone and
@@ -300,7 +292,8 @@ static int do_execute_actions(struct datapath *dp, struct sk_buff *skb,
        const struct nlattr *a;
        int rem, err;
 
-       for (a = actions, rem = actions_len; rem > 0; a = nla_next(a, &rem)) {
+       for (a = acts->actions, rem = acts->actions_len; rem > 0;
+            a = nla_next(a, &rem)) {
                if (prev_port != -1) {
                        do_output(dp, skb_clone(skb, GFP_ATOMIC), prev_port);
                        prev_port = -1;
@@ -312,7 +305,7 @@ static int do_execute_actions(struct datapath *dp, struct sk_buff *skb,
                        break;
 
                case ODP_ACTION_ATTR_CONTROLLER:
-                       err = output_control(dp, skb, nla_get_u64(a), key);
+                       err = output_control(dp, skb, nla_get_u64(a));
                        if (err) {
                                kfree_skb(skb);
                                return err;
@@ -347,16 +340,16 @@ static int do_execute_actions(struct datapath *dp, struct sk_buff *skb,
 
                case ODP_ACTION_ATTR_SET_NW_SRC:
                case ODP_ACTION_ATTR_SET_NW_DST:
-                       skb = set_nw_addr(skb, key, a);
+                       skb = set_nw_addr(skb, a);
                        break;
 
                case ODP_ACTION_ATTR_SET_NW_TOS:
-                       skb = set_nw_tos(skb, key, nla_get_u8(a));
+                       skb = set_nw_tos(skb, nla_get_u8(a));
                        break;
 
                case ODP_ACTION_ATTR_SET_TP_SRC:
                case ODP_ACTION_ATTR_SET_TP_DST:
-                       skb = set_tp_port(skb, key, a);
+                       skb = set_tp_port(skb, a);
                        break;
 
                case ODP_ACTION_ATTR_SET_PRIORITY:
@@ -368,7 +361,7 @@ static int do_execute_actions(struct datapath *dp, struct sk_buff *skb,
                        break;
 
                case ODP_ACTION_ATTR_DROP_SPOOFED_ARP:
-                       if (unlikely(is_spoofed_arp(skb, key)))
+                       if (unlikely(is_spoofed_arp(skb)))
                                goto exit;
                        break;
                }
@@ -384,8 +377,7 @@ exit:
 }
 
 static void sflow_sample(struct datapath *dp, struct sk_buff *skb,
-                        const struct sw_flow_key *key,
-                        const struct nlattr *a, u32 actions_len)
+                        struct sw_flow_actions *acts)
 {
        struct sk_buff *nskb;
        struct vport *p = OVS_CB(skb)->vport;
@@ -403,23 +395,46 @@ static void sflow_sample(struct datapath *dp, struct sk_buff *skb,
                return;
 
        upcall.cmd = ODP_PACKET_CMD_SAMPLE;
-       upcall.key = key;
+       upcall.key = &OVS_CB(skb)->flow->key;
        upcall.userdata = 0;
        upcall.sample_pool = atomic_read(&p->sflow_pool);
-       upcall.actions = a;
-       upcall.actions_len = actions_len;
+       upcall.actions = acts->actions;
+       upcall.actions_len = acts->actions_len;
        dp_upcall(dp, nskb, &upcall);
 }
 
 /* Execute a list of actions against 'skb'. */
-int execute_actions(struct datapath *dp, struct sk_buff *skb,
-                   const struct sw_flow_key *key,
-                   const struct nlattr *actions, u32 actions_len)
+int execute_actions(struct datapath *dp, struct sk_buff *skb)
 {
-       if (dp->sflow_probability)
-               sflow_sample(dp, skb, key, actions, actions_len);
+       struct sw_flow_actions *acts = rcu_dereference(OVS_CB(skb)->flow->sf_acts);
+       struct loop_counter *loop;
+       int error;
+
+       /* Check whether we've looped too much. */
+       loop = loop_get_counter();
+       if (unlikely(++loop->count > MAX_LOOPS))
+               loop->looping = true;
+       if (unlikely(loop->looping)) {
+               error = loop_suppress(dp, acts);
+               kfree_skb(skb);
+               goto out_loop;
+       }
 
+       /* Really execute actions. */
+       if (dp->sflow_probability)
+               sflow_sample(dp, skb, acts);
        OVS_CB(skb)->tun_id = 0;
+       error = do_execute_actions(dp, skb, acts);
+
+       /* Check whether sub-actions looped too much. */
+       if (unlikely(loop->looping))
+               error = loop_suppress(dp, acts);
+
+out_loop:
+       /* Decrement loop counter. */
+       if (!--loop->count)
+               loop->looping = false;
+       loop_put_counter();
 
-       return do_execute_actions(dp, skb, key, actions, actions_len);
+       return error;
 }
index 3348ae2..a832295 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2010 Nicira Networks.
+ * Copyright (c) 2009, 2010, 2011 Nicira Networks.
  * Distributed under the terms of the GNU GPL version 2.
  *
  * Significant portions of this file may be copied from parts of the Linux
@@ -16,9 +16,7 @@ struct datapath;
 struct sk_buff;
 struct sw_flow_key;
 
-int execute_actions(struct datapath *dp, struct sk_buff *skb,
-                   const struct sw_flow_key *,
-                   const struct nlattr *, u32 actions_len);
+int execute_actions(struct datapath *dp, struct sk_buff *skb);
 
 static inline void skb_clear_rxhash(struct sk_buff *skb)
 {
index 5ce77cd..fc00d78 100644 (file)
@@ -49,7 +49,6 @@
 #include "datapath.h"
 #include "actions.h"
 #include "flow.h"
-#include "loop_counter.h"
 #include "table.h"
 #include "vlan.h"
 #include "vport-internal_dev.h"
@@ -267,8 +266,6 @@ void dp_process_received_packet(struct vport *p, struct sk_buff *skb)
        struct datapath *dp = p->dp;
        struct dp_stats_percpu *stats;
        int stats_counter_off;
-       struct sw_flow_actions *acts;
-       struct loop_counter *loop;
        int error;
 
        OVS_CB(skb)->vport = p;
@@ -313,32 +310,7 @@ void dp_process_received_packet(struct vport *p, struct sk_buff *skb)
 
        stats_counter_off = offsetof(struct dp_stats_percpu, n_hit);
        flow_used(OVS_CB(skb)->flow, skb);
-
-       acts = rcu_dereference(OVS_CB(skb)->flow->sf_acts);
-
-       /* Check whether we've looped too much. */
-       loop = loop_get_counter();
-       if (unlikely(++loop->count > MAX_LOOPS))
-               loop->looping = true;
-       if (unlikely(loop->looping)) {
-               loop_suppress(dp, acts);
-               kfree_skb(skb);
-               goto out_loop;
-       }
-
-       /* Execute actions. */
-       execute_actions(dp, skb, &OVS_CB(skb)->flow->key, acts->actions,
-                       acts->actions_len);
-
-       /* Check whether sub-actions looped too much. */
-       if (unlikely(loop->looping))
-               loop_suppress(dp, acts);
-
-out_loop:
-       /* Decrement loop counter. */
-       if (!--loop->count)
-               loop->looping = false;
-       loop_put_counter();
+       execute_actions(dp, skb);
 
 out:
        /* Update datapath statistics. */
@@ -470,14 +442,8 @@ static int queue_control_packets(struct datapath *dp, struct sk_buff *skb,
 {
        u32 group = packet_mc_group(dp, upcall_info->cmd);
        struct sk_buff *nskb;
-       int port_no;
        int err;
 
-       if (OVS_CB(skb)->vport)
-               port_no = OVS_CB(skb)->vport->port_no;
-       else
-               port_no = ODPP_LOCAL;
-
        do {
                struct odp_header *upcall;
                struct sk_buff *user_skb; /* to be queued to userspace */
@@ -677,8 +643,9 @@ static int odp_packet_cmd_execute(struct sk_buff *skb, struct genl_info *info)
 {
        struct odp_header *odp_header = info->userhdr;
        struct nlattr **a = info->attrs;
+       struct sw_flow_actions *acts;
        struct sk_buff *packet;
-       struct sw_flow_key key;
+       struct sw_flow *flow;
        struct datapath *dp;
        struct ethhdr *eth;
        bool is_frag;
@@ -714,26 +681,40 @@ static int odp_packet_cmd_execute(struct sk_buff *skb, struct genl_info *info)
        else
                packet->protocol = htons(ETH_P_802_2);
 
-       /* Initialize OVS_CB (it came from Netlink so might not be zeroed). */
-       memset(OVS_CB(packet), 0, sizeof(struct ovs_skb_cb));
+       /* Build an sw_flow for sending this packet. */
+       flow = flow_alloc();
+       err = PTR_ERR(flow);
+       if (IS_ERR(flow))
+               goto err_kfree_skb;
 
-       err = flow_extract(packet, -1, &key, &is_frag);
+       err = flow_extract(packet, -1, &flow->key, &is_frag);
        if (err)
-               goto err_kfree_skb;
+               goto err_flow_put;
+       flow->tbl_node.hash = flow_hash(&flow->key);
+
+       acts = flow_actions_alloc(a[ODP_PACKET_ATTR_ACTIONS]);
+       err = PTR_ERR(acts);
+       if (IS_ERR(acts))
+               goto err_flow_put;
+       rcu_assign_pointer(flow->sf_acts, acts);
+
+       OVS_CB(packet)->flow = flow;
 
        rcu_read_lock();
        dp = get_dp(odp_header->dp_ifindex);
        err = -ENODEV;
        if (!dp)
                goto err_unlock;
-       err = execute_actions(dp, packet, &key,
-                             nla_data(a[ODP_PACKET_ATTR_ACTIONS]),
-                             nla_len(a[ODP_PACKET_ATTR_ACTIONS]));
+       err = execute_actions(dp, packet);
        rcu_read_unlock();
+
+       flow_put(flow);
        return err;
 
 err_unlock:
        rcu_read_unlock();
+err_flow_put:
+       flow_put(flow);
 err_kfree_skb:
        kfree_skb(packet);
 err:
index f264866..d678979 100644 (file)
 static struct kmem_cache *flow_cache;
 static unsigned int hash_seed __read_mostly;
 
+static int check_header(struct sk_buff *skb, int len)
+{
+       if (unlikely(skb->len < len))
+               return -EINVAL;
+       if (unlikely(!pskb_may_pull(skb, len)))
+               return -ENOMEM;
+       return 0;
+}
+
 static inline bool arphdr_ok(struct sk_buff *skb)
 {
-       return skb->len >= skb_network_offset(skb) + sizeof(struct arp_eth_header);
+       return pskb_may_pull(skb, skb_network_offset(skb) +
+                                 sizeof(struct arp_eth_header));
 }
 
 static inline int check_iphdr(struct sk_buff *skb)
 {
        unsigned int nh_ofs = skb_network_offset(skb);
        unsigned int ip_len;
+       int err;
 
-       if (skb->len < nh_ofs + sizeof(struct iphdr))
-               return -EINVAL;
+       err = check_header(skb, nh_ofs + sizeof(struct iphdr));
+       if (unlikely(err))
+               return err;
 
        ip_len = ip_hdrlen(skb);
-       if (ip_len < sizeof(struct iphdr) || skb->len < nh_ofs + ip_len)
+       if (unlikely(ip_len < sizeof(struct iphdr) ||
+                    skb->len < nh_ofs + ip_len))
                return -EINVAL;
 
-       /*
-        * Pull enough header bytes to account for the IP header plus the
-        * longest transport header that we parse, currently 20 bytes for TCP.
-        */
-       if (!pskb_may_pull(skb, min(nh_ofs + ip_len + 20, skb->len)))
-               return -ENOMEM;
-
        skb_set_transport_header(skb, nh_ofs + ip_len);
        return 0;
 }
@@ -70,22 +76,29 @@ static inline int check_iphdr(struct sk_buff *skb)
 static inline bool tcphdr_ok(struct sk_buff *skb)
 {
        int th_ofs = skb_transport_offset(skb);
-       if (skb->len >= th_ofs + sizeof(struct tcphdr)) {
-               int tcp_len = tcp_hdrlen(skb);
-               return (tcp_len >= sizeof(struct tcphdr)
-                       && skb->len >= th_ofs + tcp_len);
-       }
-       return false;
+       int tcp_len;
+
+       if (unlikely(!pskb_may_pull(skb, th_ofs + sizeof(struct tcphdr))))
+               return false;
+
+       tcp_len = tcp_hdrlen(skb);
+       if (unlikely(tcp_len < sizeof(struct tcphdr) ||
+                    skb->len < th_ofs + tcp_len))
+               return false;
+
+       return true;
 }
 
 static inline bool udphdr_ok(struct sk_buff *skb)
 {
-       return skb->len >= skb_transport_offset(skb) + sizeof(struct udphdr);
+       return pskb_may_pull(skb, skb_transport_offset(skb) +
+                                 sizeof(struct udphdr));
 }
 
 static inline bool icmphdr_ok(struct sk_buff *skb)
 {
-       return skb->len >= skb_transport_offset(skb) + sizeof(struct icmphdr);
+       return pskb_may_pull(skb, skb_transport_offset(skb) +
+                                 sizeof(struct icmphdr));
 }
 
 u64 flow_used_time(unsigned long flow_jiffies)
@@ -108,9 +121,11 @@ static int parse_ipv6hdr(struct sk_buff *skb, struct sw_flow_key *key)
        int payload_ofs;
        struct ipv6hdr *nh;
        uint8_t nexthdr;
+       int err;
 
-       if (unlikely(skb->len < nh_ofs + sizeof(*nh)))
-               return -EINVAL;
+       err = check_header(skb, nh_ofs + sizeof(*nh));
+       if (unlikely(err))
+               return err;
 
        nh = ipv6_hdr(skb);
        nexthdr = nh->nexthdr;
@@ -126,15 +141,6 @@ static int parse_ipv6hdr(struct sk_buff *skb, struct sw_flow_key *key)
                return -EINVAL;
 
        nh_len = payload_ofs - nh_ofs;
-
-       /* Pull enough header bytes to account for the IP header plus the
-        * longest transport header that we parse, currently 20 bytes for TCP.
-        * To dig deeper than the transport header, transport parsers may need
-        * to pull more header bytes.
-        */
-       if (unlikely(!pskb_may_pull(skb, min(nh_ofs + nh_len + 20, skb->len))))
-               return -ENOMEM;
-
        skb_set_transport_header(skb, nh_ofs + nh_len);
        key->nw_proto = nexthdr;
        return nh_len;
@@ -142,7 +148,8 @@ static int parse_ipv6hdr(struct sk_buff *skb, struct sw_flow_key *key)
 
 static bool icmp6hdr_ok(struct sk_buff *skb)
 {
-       return skb->len >= skb_transport_offset(skb) + sizeof(struct icmp6hdr);
+       return pskb_may_pull(skb, skb_transport_offset(skb) +
+                                 sizeof(struct icmp6hdr));
 }
 
 #define TCP_FLAGS_OFFSET 13
@@ -196,6 +203,7 @@ struct sw_flow *flow_alloc(void)
 
        spin_lock_init(&flow->lock);
        atomic_set(&flow->refcnt, 1);
+       flow->sf_acts = NULL;
        flow->dead = false;
 
        return flow;
@@ -256,7 +264,7 @@ void flow_deferred_free_acts(struct sw_flow_actions *sf_acts)
        call_rcu(&sf_acts->rcu, rcu_free_acts_callback);
 }
 
-static void parse_vlan(struct sk_buff *skb, struct sw_flow_key *key)
+static int parse_vlan(struct sk_buff *skb, struct sw_flow_key *key)
 {
        struct qtag_prefix {
                __be16 eth_type; /* ETH_P_8021Q */
@@ -264,12 +272,15 @@ static void parse_vlan(struct sk_buff *skb, struct sw_flow_key *key)
        };
        struct qtag_prefix *qp;
 
-       if (skb->len < sizeof(struct qtag_prefix) + sizeof(__be16))
-               return;
+       if (unlikely(!pskb_may_pull(skb, sizeof(struct qtag_prefix) +
+                                        sizeof(__be16))))
+               return -ENOMEM;
 
        qp = (struct qtag_prefix *) skb->data;
        key->dl_tci = qp->tci | htons(VLAN_TAG_PRESENT);
        __skb_pull(skb, sizeof(struct qtag_prefix));
+
+       return 0;
 }
 
 static __be16 parse_ethertype(struct sk_buff *skb)
@@ -290,9 +301,12 @@ static __be16 parse_ethertype(struct sk_buff *skb)
        if (ntohs(proto) >= 1536)
                return proto;
 
-       if (unlikely(skb->len < sizeof(struct llc_snap_hdr)))
+       if (skb->len < sizeof(struct llc_snap_hdr))
                return htons(ETH_P_802_2);
 
+       if (unlikely(!pskb_may_pull(skb, sizeof(struct llc_snap_hdr))))
+               return htons(0);
+
        llc = (struct llc_snap_hdr *) skb->data;
        if (llc->dsap != LLC_SAP_SNAP ||
            llc->ssap != LLC_SAP_SNAP ||
@@ -409,45 +423,28 @@ int flow_extract(struct sk_buff *skb, u16 in_port, struct sw_flow_key *key,
        key->in_port = in_port;
        *is_frag = false;
 
-       /*
-        * We would really like to pull as many bytes as we could possibly
-        * want to parse into the linear data area.  Currently, for IPv4,
-        * that is:
-        *
-        *    14     Ethernet header
-        *     4     VLAN header
-        *    60     max IP header with options
-        *    20     max TCP/UDP/ICMP header (don't care about options)
-        *    --
-        *    98
-        *
-        * But Xen only allocates 64 or 72 bytes for the linear data area in
-        * netback, which means that we would reallocate and copy the skb's
-        * linear data on every packet if we did that.  So instead just pull 64
-        * bytes, which is always sufficient without IP options, and then check
-        * whether we need to pull more later when we look at the IP header.
-        */
-       if (!pskb_may_pull(skb, min(skb->len, 64u)))
-               return -ENOMEM;
-
        skb_reset_mac_header(skb);
 
-       /* Link layer. */
+       /* Link layer.  We are guaranteed to have at least the 14 byte Ethernet
+        * header in the linear data area.
+        */
        eth = eth_hdr(skb);
        memcpy(key->dl_src, eth->h_source, ETH_ALEN);
        memcpy(key->dl_dst, eth->h_dest, ETH_ALEN);
-
-       /* dl_type, dl_vlan, dl_vlan_pcp. */
        __skb_pull(skb, 2 * ETH_ALEN);
 
        if (vlan_tx_tag_present(skb))
                key->dl_tci = htons(vlan_get_tci(skb));
        else if (eth->h_proto == htons(ETH_P_8021Q))
-               parse_vlan(skb, key);
+               if (unlikely(parse_vlan(skb, key)))
+                       return -ENOMEM;
 
        key->dl_type = parse_ethertype(skb);
+       if (unlikely(key->dl_type == htons(0)))
+               return -ENOMEM;
+
        skb_reset_network_header(skb);
-       __skb_push(skb, skb->data - (unsigned char *)eth);
+       __skb_push(skb, skb->data - skb_mac_header(skb));
 
        /* Network layer. */
        if (key->dl_type == htons(ETH_P_IP)) {
index f5edd50..e2a0cb7 100644 (file)
@@ -30,6 +30,7 @@
 /time.c
 /tmp
 /tunnel.c
+/vlan.c
 /vport-capwap.c
 /vport-generic.c
 /vport-gre.c
index 2c2220b..4af8851 100644 (file)
@@ -54,4 +54,8 @@
 #define SHRT_MIN       ((s16)(-SHRT_MAX - 1))
 #endif
 
+#ifndef DIV_ROUND_UP
+#define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
+#endif
+
 #endif /* linux/kernel.h */
index 491305d..3e1d890 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Distributed under the terms of the GNU GPL version 2.
- * Copyright (c) 2010 Nicira Networks.
+ * Copyright (c) 2010, 2011 Nicira Networks.
  *
  * Significant portions of this file may be copied from parts of the Linux
  * kernel, by Linus Torvalds and others.
 
 #include "loop_counter.h"
 
-void loop_suppress(struct datapath *dp, struct sw_flow_actions *actions)
+int loop_suppress(struct datapath *dp, struct sw_flow_actions *actions)
 {
        if (net_ratelimit())
                pr_warn("%s: flow looped %d times, dropping\n",
                        dp_name(dp), MAX_LOOPS);
        actions->actions_len = 0;
+       return -ELOOP;
 }
 
 #ifndef CONFIG_PREEMPT_RT
index e08afb1..0d1fdf9 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010 Nicira Networks.
+ * Copyright (c) 2010, 2011 Nicira Networks.
  * Distributed under the terms of the GNU GPL version 2.
  *
  * Significant portions of this file may be copied from parts of the Linux
@@ -23,6 +23,6 @@ struct loop_counter {
 
 struct loop_counter *loop_get_counter(void);
 void loop_put_counter(void);
-void loop_suppress(struct datapath *, struct sw_flow_actions *);
+int loop_suppress(struct datapath *, struct sw_flow_actions *);
 
 #endif /* loop_counter.h */
index 899d1cd..70a4cd7 100644 (file)
@@ -725,8 +725,9 @@ static bool check_mtu(struct sk_buff *skb,
                      const struct tnl_mutable_config *mutable,
                      const struct rtable *rt, __be16 *frag_offp)
 {
+       bool df_inherit = mutable->flags & TNL_F_DF_INHERIT;
        bool pmtud = mutable->flags & TNL_F_PMTUD;
-       __be16 frag_off = 0;
+       __be16 frag_off = mutable->flags & TNL_F_DF_DEFAULT ? htons(IP_DF) : 0;
        int mtu = 0;
        unsigned int packet_length = skb->len - ETH_HLEN;
 
@@ -738,8 +739,6 @@ static bool check_mtu(struct sk_buff *skb,
        if (pmtud) {
                int vlan_header = 0;
 
-               frag_off = htons(IP_DF);
-
                /* The tag needs to go in packet regardless of where it
                 * currently is, so subtract it from the MTU.
                 */
@@ -756,7 +755,8 @@ static bool check_mtu(struct sk_buff *skb,
        if (skb->protocol == htons(ETH_P_IP)) {
                struct iphdr *iph = ip_hdr(skb);
 
-               frag_off |= iph->frag_off & htons(IP_DF);
+               if (df_inherit)
+                       frag_off = iph->frag_off & htons(IP_DF);
 
                if (pmtud && iph->frag_off & htons(IP_DF)) {
                        mtu = max(mtu, IP_MIN_MTU);
@@ -769,8 +769,10 @@ static bool check_mtu(struct sk_buff *skb,
        }
 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
        else if (skb->protocol == htons(ETH_P_IPV6)) {
-               /* IPv6 requires PMTUD if the packet is above the minimum MTU. */
-               if (packet_length > IPV6_MIN_MTU)
+               /* IPv6 requires end hosts to do fragmentation
+                * if the packet is above the minimum MTU.
+                */
+               if (df_inherit && packet_length > IPV6_MIN_MTU)
                        frag_off = htons(IP_DF);
 
                if (pmtud) {
index 0fd6a69..784cda1 100644 (file)
@@ -42,7 +42,8 @@
 
 /* All public tunnel flags. */
 #define TNL_F_PUBLIC (TNL_F_CSUM | TNL_F_TOS_INHERIT | TNL_F_TTL_INHERIT | \
-                     TNL_F_PMTUD | TNL_F_HDR_CACHE | TNL_F_IPSEC)
+                     TNL_F_DF_INHERIT | TNL_F_DF_DEFAULT | TNL_F_PMTUD | \
+                     TNL_F_HDR_CACHE | TNL_F_IPSEC)
 
 /**
  * struct tnl_mutable_config - modifiable configuration for a tunnel.
index febd569..0a97c88 100755 (executable)
@@ -83,6 +83,7 @@ path certificate "%s";
     cert_entry = """remote %s {
         exchange_mode main;
         nat_traversal on;
+        ike_frag on;
         certificate_type x509 "%s" "%s";
         my_identifier asn1dn;
         peers_identifier asn1dn;
index 7df978b..738fd90 100644 (file)
@@ -134,10 +134,7 @@ enum nicira_type {
     NXT_FLOW_END_CONFIG__OBSOLETE,
     NXT_FLOW_END__OBSOLETE,
     NXT_MGMT__OBSOLETE,
-
-    /* Use the high 32 bits of the cookie field as the tunnel ID in the flow
-     * match. */
-    NXT_TUN_ID_FROM_COOKIE,
+    NXT_TUN_ID_FROM_COOKIE__OBSOLETE,
 
     /* Controller role support.  The request body is struct nx_role_request.
      * The reply echos the request. */
@@ -177,16 +174,6 @@ enum nicira_stats_type {
     NXST_AGGREGATE              /* Analogous to OFPST_AGGREGATE. */
 };
 
-/* NXT_TUN_ID_FROM_COOKIE request. */
-struct nxt_tun_id_cookie {
-    struct ofp_header header;
-    ovs_be32 vendor;            /* NX_VENDOR_ID. */
-    ovs_be32 subtype;           /* NXT_TUN_ID_FROM_COOKIE */
-    uint8_t set;                /* Nonzero to enable, zero to disable. */
-    uint8_t pad[7];
-};
-OFP_ASSERT(sizeof(struct nxt_tun_id_cookie) == 24);
-
 /* This command enables or disables an Open vSwitch extension that allows a
  * controller to specify the OpenFlow table to which a flow should be added,
  * instead of having the switch decide which table is most appropriate as
@@ -658,12 +645,6 @@ enum nx_mp_algorithm {
      */
     NX_MP_ALG_ITER_HASH         /* Iterative Hash. */
 };
-
-/* Wildcard for tunnel ID. */
-#define NXFW_TUN_ID  (1 << 25)
-
-#define NXFW_ALL NXFW_TUN_ID
-#define OVSFW_ALL (OFPFW_ALL | NXFW_ALL)
 \f
 /* Action structure for NXAST_AUTOPATH.
  *
@@ -1219,8 +1200,6 @@ OFP_ASSERT(sizeof(struct nx_action_autopath) == 24);
 
 enum nx_flow_format {
     NXFF_OPENFLOW10 = 0,         /* Standard OpenFlow 1.0 compatible. */
-    NXFF_TUN_ID_FROM_COOKIE = 1, /* OpenFlow 1.0, plus obtain tunnel ID from
-                                  * cookie. */
     NXFF_NXM = 2                 /* Nicira extended match. */
 };
 
index a394f8a..5e2e916 100644 (file)
@@ -65,8 +65,10 @@ enum {
 #define TNL_F_CSUM             (1 << 0) /* Checksum packets. */
 #define TNL_F_TOS_INHERIT      (1 << 1) /* Inherit the ToS from the inner packet. */
 #define TNL_F_TTL_INHERIT      (1 << 2) /* Inherit the TTL from the inner packet. */
-#define TNL_F_PMTUD            (1 << 3) /* Enable path MTU discovery. */
-#define TNL_F_HDR_CACHE                (1 << 4) /* Enable tunnel header caching. */
-#define TNL_F_IPSEC            (1 << 5) /* Traffic is IPsec encrypted. */
+#define TNL_F_DF_INHERIT       (1 << 3) /* Inherit the DF bit from the inner packet. */
+#define TNL_F_DF_DEFAULT       (1 << 4) /* Set the DF bit if inherit off or not IP. */
+#define TNL_F_PMTUD            (1 << 5) /* Enable path MTU discovery. */
+#define TNL_F_HDR_CACHE                (1 << 6) /* Enable tunnel header caching. */
+#define TNL_F_IPSEC            (1 << 7) /* Traffic is IPsec encrypted. */
 
 #endif /* openvswitch/tunnel.h */
index 878afe8..8c97100 100644 (file)
@@ -200,6 +200,7 @@ lib_libopenvswitch_a_SOURCES += \
        lib/dpif-linux.c \
        lib/dpif-linux.h \
        lib/netdev-linux.c \
+       lib/netdev-linux.h \
        lib/netdev-vport.c \
        lib/netdev-vport.h \
        lib/netlink-protocol.h \
@@ -223,6 +224,8 @@ lib/dhparams.c: lib/dh1024.pem lib/dh2048.pem lib/dh4096.pem
         openssl dhparam -C -in $(srcdir)/lib/dh4096.pem -noout)        \
        | sed 's/\(get_dh[0-9]*\)()/\1(void)/' > lib/dhparams.c.tmp
        mv lib/dhparams.c.tmp lib/dhparams.c
+else
+lib_libopenvswitch_a_SOURCES += lib/stream-nossl.c
 endif
 
 EXTRA_DIST += \
index 2083108..6f18824 100644 (file)
@@ -74,7 +74,7 @@ struct bond_slave {
     uint64_t tx_bytes;          /* Sum across 'tx_bytes' of entries. */
 
     /* BM_STABLE specific bonding info. */
-    uint16_t stb_id;            /* ID used for 'stb_slaves' ordering. */
+    uint32_t stb_id;            /* ID used for 'stb_slaves' ordering. */
 };
 
 /* A bond, that is, a set of network devices grouped to improve performance or
@@ -93,6 +93,7 @@ struct bond {
     int updelay, downdelay;     /* Delay before slave goes up/down, in ms. */
     bool lacp_negotiated;       /* LACP negotiations were successful. */
     bool bond_revalidate;       /* True if flows need revalidation. */
+    uint32_t basis;             /* Basis for flow hash function. */
 
     /* SLB specific bonding info. */
     struct bond_entry *hash;     /* An array of (BOND_MASK + 1) elements. */
@@ -129,8 +130,9 @@ static void bond_link_status_update(struct bond_slave *, struct tag_set *);
 static void bond_choose_active_slave(struct bond *, struct tag_set *);
 static bool bond_is_tcp_hash(const struct bond *);
 static unsigned int bond_hash_src(const uint8_t mac[ETH_ADDR_LEN],
-                                  uint16_t vlan);
-static unsigned int bond_hash_tcp(const struct flow *, uint16_t vlan);
+                                  uint16_t vlan, uint32_t basis);
+static unsigned int bond_hash_tcp(const struct flow *, uint16_t vlan,
+                                  uint32_t basis);
 static struct bond_entry *lookup_bond_entry(const struct bond *,
                                             const struct flow *,
                                             uint16_t vlan);
@@ -291,6 +293,11 @@ bond_reconfigure(struct bond *bond, const struct bond_settings *s)
         revalidate = true;
     }
 
+    if (bond->basis != s->basis) {
+        bond->basis = s->basis;
+        revalidate = true;
+    }
+
     if (bond->detect == BLSM_CARRIER) {
         struct bond_slave *slave;
 
@@ -359,7 +366,7 @@ bond_slave_set_netdev__(struct bond *bond, struct bond_slave *slave,
  * 'slave_' or destroying 'bond'.
  */
 void
-bond_slave_register(struct bond *bond, void *slave_, uint16_t stb_id,
+bond_slave_register(struct bond *bond, void *slave_, uint32_t stb_id,
                     struct netdev *netdev)
 {
     struct bond_slave *slave = bond_slave_lookup(bond, slave_);
@@ -999,6 +1006,8 @@ bond_unixctl_show(struct unixctl_conn *conn,
                       bond_is_tcp_hash(bond) ? "balance-tcp" : "balance-slb");
     }
 
+    ds_put_format(&ds, "bond-hash-basis: %"PRIu32"\n", bond->basis);
+
     ds_put_format(&ds, "bond-detect-mode: %s\n",
                   bond->monitor ? "carrier" : "miimon");
 
@@ -1227,11 +1236,13 @@ bond_unixctl_hash(struct unixctl_conn *conn, const char *args_,
     uint8_t hash;
     char *hash_cstr;
     unsigned int vlan;
-    char *mac_s, *vlan_s;
+    uint32_t basis;
+    char *mac_s, *vlan_s, *basis_s;
     char *save_ptr = NULL;
 
     mac_s  = strtok_r(args, " ", &save_ptr);
     vlan_s = strtok_r(NULL, " ", &save_ptr);
+    basis_s = strtok_r(NULL, " ", &save_ptr);
 
     if (vlan_s) {
         if (sscanf(vlan_s, "%u", &vlan) != 1) {
@@ -1242,9 +1253,18 @@ bond_unixctl_hash(struct unixctl_conn *conn, const char *args_,
         vlan = OFP_VLAN_NONE;
     }
 
+    if (basis_s) {
+        if (sscanf(basis_s, "%"PRIu32, &basis) != 1) {
+            unixctl_command_reply(conn, 501, "invalid basis");
+            return;
+        }
+    } else {
+        basis = 0;
+    }
+
     if (sscanf(mac_s, ETH_ADDR_SCAN_FMT, ETH_ADDR_SCAN_ARGS(mac))
         == ETH_ADDR_SCAN_COUNT) {
-        hash = bond_hash_src(mac, vlan) & BOND_MASK;
+        hash = bond_hash_src(mac, vlan, basis) & BOND_MASK;
 
         hash_cstr = xasprintf("%u", hash);
         unixctl_command_reply(conn, 200, hash_cstr);
@@ -1376,13 +1396,13 @@ bond_is_tcp_hash(const struct bond *bond)
 }
 
 static unsigned int
-bond_hash_src(const uint8_t mac[ETH_ADDR_LEN], uint16_t vlan)
+bond_hash_src(const uint8_t mac[ETH_ADDR_LEN], uint16_t vlan, uint32_t basis)
 {
-    return hash_bytes(mac, ETH_ADDR_LEN, vlan);
+    return hash_3words(hash_bytes(mac, ETH_ADDR_LEN, 0), vlan, basis);
 }
 
 static unsigned int
-bond_hash_tcp(const struct flow *flow, uint16_t vlan)
+bond_hash_tcp(const struct flow *flow, uint16_t vlan, uint32_t basis)
 {
     struct flow hash_flow = *flow;
     hash_flow.vlan_tci = vlan;
@@ -1390,7 +1410,7 @@ bond_hash_tcp(const struct flow *flow, uint16_t vlan)
     /* The symmetric quality of this hash function is not required, but
      * flow_hash_symmetric_l4 already exists, and is sufficient for our
      * purposes, so we use it out of convenience. */
-    return flow_hash_symmetric_l4(&hash_flow, 0);
+    return flow_hash_symmetric_l4(&hash_flow, basis);
 }
 
 static unsigned int
@@ -1399,8 +1419,8 @@ bond_hash(const struct bond *bond, const struct flow *flow, uint16_t vlan)
     assert(bond->balance != BM_AB);
 
     return (bond_is_tcp_hash(bond)
-            ? bond_hash_tcp(flow, vlan)
-            : bond_hash_src(flow->dl_src, vlan));
+            ? bond_hash_tcp(flow, vlan, bond->basis)
+            : bond_hash_src(flow->dl_src, vlan, bond->basis));
 }
 
 static struct bond_entry *
index 8736f4c..fe58792 100644 (file)
@@ -50,6 +50,7 @@ const char *bond_detect_mode_to_string(enum bond_detect_mode);
 /* Configuration for a bond as a whole. */
 struct bond_settings {
     char *name;                 /* Bond's name, for log messages. */
+    uint32_t basis;             /* Flow hashing basis. */
 
     /* Balancing configuration. */
     enum bond_mode balance;
@@ -74,7 +75,7 @@ void bond_destroy(struct bond *);
 
 bool bond_reconfigure(struct bond *, const struct bond_settings *);
 void bond_slave_register(struct bond *, void *slave_,
-                         uint16_t stable_id, struct netdev *);
+                         uint32_t stable_id, struct netdev *);
 void bond_slave_set_netdev(struct bond *, void *slave_, struct netdev *);
 void bond_slave_unregister(struct bond *, const void *slave);
 
index e2c911c..7e6c491 100644 (file)
@@ -35,6 +35,7 @@
 #include "bitmap.h"
 #include "dpif-provider.h"
 #include "netdev.h"
+#include "netdev-linux.h"
 #include "netdev-vport.h"
 #include "netlink-socket.h"
 #include "netlink.h"
@@ -431,6 +432,12 @@ dpif_linux_port_query__(const struct dpif *dpif, uint32_t port_no,
         dpif_port->name = xstrdup(reply.name);
         dpif_port->type = xstrdup(netdev_vport_get_netdev_type(&reply));
         dpif_port->port_no = reply.port_no;
+        if (reply.stats) {
+            netdev_stats_from_rtnl_link_stats64(&dpif_port->stats,
+                                                reply.stats);
+        } else {
+            memset(&dpif_port->stats, 0xff, sizeof dpif_port->stats);
+        }
         ofpbuf_delete(buf);
     }
     return error;
@@ -472,6 +479,8 @@ dpif_linux_flow_flush(struct dpif *dpif_)
 
 struct dpif_linux_port_state {
     struct nl_dump dump;
+    unsigned long *port_bitmap; /* Ports in the datapath. */
+    bool complete;              /* Dump completed without error. */
 };
 
 static int
@@ -483,6 +492,8 @@ dpif_linux_port_dump_start(const struct dpif *dpif_, void **statep)
     struct ofpbuf *buf;
 
     *statep = state = xmalloc(sizeof *state);
+    state->port_bitmap = bitmap_allocate(LRU_MAX_PORTS);
+    state->complete = false;
 
     dpif_linux_vport_init(&request);
     request.cmd = ODP_DP_CMD_GET;
@@ -506,6 +517,7 @@ dpif_linux_port_dump_next(const struct dpif *dpif OVS_UNUSED, void *state_,
     int error;
 
     if (!nl_dump_next(&state->dump, &buf)) {
+        state->complete = true;
         return EOF;
     }
 
@@ -514,17 +526,39 @@ dpif_linux_port_dump_next(const struct dpif *dpif OVS_UNUSED, void *state_,
         return error;
     }
 
+    if (vport.port_no < LRU_MAX_PORTS) {
+        bitmap_set1(state->port_bitmap, vport.port_no);
+    }
+
     dpif_port->name = (char *) vport.name;
     dpif_port->type = (char *) netdev_vport_get_netdev_type(&vport);
     dpif_port->port_no = vport.port_no;
+    if (vport.stats) {
+        netdev_stats_from_rtnl_link_stats64(&dpif_port->stats, vport.stats);
+    } else {
+        memset(&dpif_port->stats, 0xff, sizeof dpif_port->stats);
+    }
     return 0;
 }
 
 static int
-dpif_linux_port_dump_done(const struct dpif *dpif OVS_UNUSED, void *state_)
+dpif_linux_port_dump_done(const struct dpif *dpif_, void *state_)
 {
+    struct dpif_linux *dpif = dpif_linux_cast(dpif_);
     struct dpif_linux_port_state *state = state_;
     int error = nl_dump_done(&state->dump);
+
+    if (state->complete) {
+        uint16_t i;
+
+        for (i = 0; i < LRU_MAX_PORTS; i++) {
+            if (!bitmap_is_set(state->port_bitmap, i)) {
+                dpif_linux_push_port(dpif, i);
+            }
+        }
+    }
+
+    free(state->port_bitmap);
     free(state);
     return error;
 }
index 215ecfc..74e9856 100644 (file)
@@ -469,6 +469,7 @@ dpif_port_clone(struct dpif_port *dst, const struct dpif_port *src)
     dst->name = xstrdup(src->name);
     dst->type = xstrdup(src->type);
     dst->port_no = src->port_no;
+    dst->stats = src->stats;
 }
 
 /* Frees memory allocated to members of 'dpif_port'.
index 447ccd9..8452349 100644 (file)
@@ -23,6 +23,7 @@
 #include <stdint.h>
 #include "openflow/openflow.h"
 #include "openvswitch/datapath-protocol.h"
+#include "netdev.h"
 #include "util.h"
 
 #ifdef  __cplusplus
@@ -31,7 +32,6 @@ extern "C" {
 
 struct dpif;
 struct ds;
-struct netdev;
 struct nlattr;
 struct ofpbuf;
 struct sset;
@@ -72,6 +72,7 @@ struct dpif_port {
     char *name;                 /* Network device name, e.g. "eth0". */
     char *type;                 /* Network device type, e.g. "system". */
     uint32_t port_no;           /* Port number within datapath. */
+    struct netdev_stats stats;  /* Port statistics. */
 };
 void dpif_port_clone(struct dpif_port *, const struct dpif_port *);
 void dpif_port_destroy(struct dpif_port *);
index f5f965c..6bd2c3d 100644 (file)
@@ -118,7 +118,7 @@ typedef unsigned int OVS_BITWISE flow_wildcards_t;
 #define FWW_TP_DST      ((OVS_FORCE flow_wildcards_t) (1 << 7))
 /* Same meanings as corresponding OFPFW_* bits, but differ in value. */
 #define FWW_NW_TOS      ((OVS_FORCE flow_wildcards_t) (1 << 1))
-/* No corresponding OFPFW_* or OVSFW_* bits. */
+/* No corresponding OFPFW_* bits. */
 #define FWW_ETH_MCAST   ((OVS_FORCE flow_wildcards_t) (1 << 8))
                                                        /* multicast bit only */
 #define FWW_ARP_SHA     ((OVS_FORCE flow_wildcards_t) (1 << 9))
index a7f66a2..3fe5eff 100644 (file)
@@ -50,9 +50,9 @@ struct lacp {
 
     enum lacp_time lacp_time;  /* Fast, Slow or Custom LACP time. */
     long long int custom_time; /* LACP_TIME_CUSTOM transmission rate. */
-    bool strict;             /* True if in strict mode. */
     bool negotiated;         /* True if LACP negotiations were successful. */
     bool update;             /* True if lacp_update() needs to be called. */
+    bool heartbeat;          /* LACP heartbeat mode. */
 };
 
 struct slave {
@@ -62,6 +62,7 @@ struct slave {
     struct lacp *lacp;            /* LACP object containing this slave. */
     uint16_t port_id;             /* Port ID. */
     uint16_t port_priority;       /* Port Priority. */
+    uint16_t key;                 /* Aggregation Key. 0 if default. */
     char *name;                   /* Name of this slave. */
 
     enum slave_status status;     /* Slave status. */
@@ -181,10 +182,10 @@ lacp_configure(struct lacp *lacp, const struct lacp_settings *s)
 
     if (!eth_addr_equals(lacp->sys_id, s->id)
         || lacp->sys_priority != s->priority
-        || lacp->strict != s->strict) {
+        || lacp->heartbeat != s->heartbeat) {
         memcpy(lacp->sys_id, s->id, ETH_ADDR_LEN);
         lacp->sys_priority = s->priority;
-        lacp->strict = s->strict;
+        lacp->heartbeat = s->heartbeat;
         lacp->update = true;
     }
 
@@ -272,9 +273,12 @@ lacp_slave_register(struct lacp *lacp, void *slave_,
         slave->name = xstrdup(s->name);
     }
 
-    if (slave->port_id != s->id || slave->port_priority != s->priority) {
+    if (slave->port_id != s->id
+        || slave->port_priority != s->priority
+        || slave->key != s->key) {
         slave->port_id = s->id;
         slave->port_priority = s->priority;
+        slave->key = s->key;
 
         lacp->update = true;
 
@@ -425,6 +429,13 @@ lacp_update_attached(struct lacp *lacp)
     struct lacp_info lead_pri;
     static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 10);
 
+    if (lacp->heartbeat) {
+        HMAP_FOR_EACH (slave, node, &lacp->slaves) {
+            slave->attached = slave->status != LACP_DEFAULTED;
+        }
+        return;
+    }
+
     lacp->update = false;
 
     lead = NULL;
@@ -465,10 +476,6 @@ lacp_update_attached(struct lacp *lacp)
                 slave->attached = false;
             }
         }
-    } else if (lacp->strict) {
-        HMAP_FOR_EACH (slave, node, &lacp->slaves) {
-            slave->attached = false;
-        }
     }
 }
 
@@ -525,13 +532,15 @@ slave_set_expired(struct slave *slave)
 static void
 slave_get_actor(struct slave *slave, struct lacp_info *actor)
 {
+    struct lacp *lacp = slave->lacp;
+    uint16_t key;
     uint8_t state = 0;
 
-    if (slave->lacp->active) {
+    if (lacp->active) {
         state |= LACP_STATE_ACT;
     }
 
-    if (slave->lacp->lacp_time != LACP_TIME_SLOW) {
+    if (lacp->lacp_time != LACP_TIME_SLOW) {
         state |= LACP_STATE_TIME;
     }
 
@@ -547,20 +556,25 @@ slave_get_actor(struct slave *slave, struct lacp_info *actor)
         state |= LACP_STATE_EXP;
     }
 
-    if (hmap_count(&slave->lacp->slaves) > 1) {
+    if (lacp->heartbeat || hmap_count(&lacp->slaves) > 1) {
         state |= LACP_STATE_AGG;
     }
 
-    if (slave->attached || !slave->lacp->negotiated) {
+    if (slave->attached || !lacp->negotiated) {
         state |= LACP_STATE_COL | LACP_STATE_DIST;
     }
 
+    key = lacp->key_slave->key;
+    if (!key) {
+        key = lacp->key_slave->port_id;
+    }
+
     actor->state = state;
-    actor->key = htons(slave->lacp->key_slave->port_id);
+    actor->key = htons(key);
     actor->port_priority = htons(slave->port_priority);
     actor->port_id = htons(slave->port_id);
-    actor->sys_priority = htons(slave->lacp->sys_priority);
-    memcpy(&actor->sys_id, slave->lacp->sys_id, ETH_ADDR_LEN);
+    actor->sys_priority = htons(lacp->sys_priority);
+    memcpy(&actor->sys_id, lacp->sys_id, ETH_ADDR_LEN);
 }
 
 /* Given 'slave', populates 'priority' with data representing its LACP link
@@ -702,8 +716,8 @@ lacp_unixctl_show(struct unixctl_conn *conn,
     ds_put_format(&ds, "lacp: %s\n", lacp->name);
 
     ds_put_format(&ds, "\tstatus: %s", lacp->active ? "active" : "passive");
-    if (lacp->strict) {
-        ds_put_cstr(&ds, " strict");
+    if (lacp->heartbeat) {
+        ds_put_cstr(&ds, " heartbeat");
     }
     if (lacp->negotiated) {
         ds_put_cstr(&ds, " negotiated");
index 3965692..0fb797e 100644 (file)
@@ -88,7 +88,7 @@ struct lacp_settings {
     bool active;
     enum lacp_time lacp_time;
     long long int custom_time;
-    bool strict;
+    bool heartbeat;
 };
 
 void lacp_init(void);
@@ -106,6 +106,7 @@ struct lacp_slave_settings {
     char *name;
     uint16_t id;
     uint16_t priority;
+    uint16_t key;
 };
 
 void lacp_slave_register(struct lacp *, void *slave_,
index 75e04df..6bd2286 100644 (file)
@@ -238,7 +238,6 @@ lswitch_process_packet(struct lswitch *sw, struct rconn *rconn,
     case OFPUTIL_OFPST_PORT_REPLY:
     case OFPUTIL_OFPST_TABLE_REPLY:
     case OFPUTIL_OFPST_AGGREGATE_REPLY:
-    case OFPUTIL_NXT_TUN_ID_FROM_COOKIE:
     case OFPUTIL_NXT_ROLE_REQUEST:
     case OFPUTIL_NXT_ROLE_REPLY:
     case OFPUTIL_NXT_FLOW_MOD_TABLE_ID:
index 6b1124f..5f13f18 100644 (file)
@@ -15,6 +15,9 @@
  */
 
 #include <config.h>
+
+#include "netdev-linux.h"
+
 #include <assert.h>
 #include <errno.h>
 #include <fcntl.h>
@@ -3925,7 +3928,55 @@ tc_calc_buffer(unsigned int Bps, int mtu, uint64_t burst_bytes)
     unsigned int min_burst = tc_buffer_per_jiffy(Bps) + mtu;
     return tc_bytes_to_ticks(Bps, MAX(burst_bytes, min_burst));
 }
-
+\f
+/* Public utility functions. */
+
+#define COPY_NETDEV_STATS                                   \
+    dst->rx_packets = src->rx_packets;                      \
+    dst->tx_packets = src->tx_packets;                      \
+    dst->rx_bytes = src->rx_bytes;                          \
+    dst->tx_bytes = src->tx_bytes;                          \
+    dst->rx_errors = src->rx_errors;                        \
+    dst->tx_errors = src->tx_errors;                        \
+    dst->rx_dropped = src->rx_dropped;                      \
+    dst->tx_dropped = src->tx_dropped;                      \
+    dst->multicast = src->multicast;                        \
+    dst->collisions = src->collisions;                      \
+    dst->rx_length_errors = src->rx_length_errors;          \
+    dst->rx_over_errors = src->rx_over_errors;              \
+    dst->rx_crc_errors = src->rx_crc_errors;                \
+    dst->rx_frame_errors = src->rx_frame_errors;            \
+    dst->rx_fifo_errors = src->rx_fifo_errors;              \
+    dst->rx_missed_errors = src->rx_missed_errors;          \
+    dst->tx_aborted_errors = src->tx_aborted_errors;        \
+    dst->tx_carrier_errors = src->tx_carrier_errors;        \
+    dst->tx_fifo_errors = src->tx_fifo_errors;              \
+    dst->tx_heartbeat_errors = src->tx_heartbeat_errors;    \
+    dst->tx_window_errors = src->tx_window_errors
+
+/* Copies 'src' into 'dst', performing format conversion in the process. */
+void
+netdev_stats_from_rtnl_link_stats(struct netdev_stats *dst,
+                                  const struct rtnl_link_stats *src)
+{
+    COPY_NETDEV_STATS;
+}
+
+/* Copies 'src' into 'dst', performing format conversion in the process. */
+void
+netdev_stats_from_rtnl_link_stats64(struct netdev_stats *dst,
+                                    const struct rtnl_link_stats64 *src)
+{
+    COPY_NETDEV_STATS;
+}
+
+/* Copies 'src' into 'dst', performing format conversion in the process. */
+void
+netdev_stats_to_rtnl_link_stats64(struct rtnl_link_stats64 *dst,
+                                  const struct netdev_stats *src)
+{
+    COPY_NETDEV_STATS;
+}
 \f
 /* Utility functions. */
 
@@ -3945,7 +3996,6 @@ get_stats_via_netlink(int ifindex, struct netdev_stats *stats)
     struct ofpbuf request;
     struct ofpbuf *reply;
     struct ifinfomsg *ifi;
-    const struct rtnl_link_stats *rtnl_stats;
     struct nlattr *attrs[ARRAY_SIZE(rtnlgrp_link_policy)];
     int error;
 
@@ -3973,28 +4023,7 @@ get_stats_via_netlink(int ifindex, struct netdev_stats *stats)
         return EPROTO;
     }
 
-    rtnl_stats = nl_attr_get(attrs[IFLA_STATS]);
-    stats->rx_packets = rtnl_stats->rx_packets;
-    stats->tx_packets = rtnl_stats->tx_packets;
-    stats->rx_bytes = rtnl_stats->rx_bytes;
-    stats->tx_bytes = rtnl_stats->tx_bytes;
-    stats->rx_errors = rtnl_stats->rx_errors;
-    stats->tx_errors = rtnl_stats->tx_errors;
-    stats->rx_dropped = rtnl_stats->rx_dropped;
-    stats->tx_dropped = rtnl_stats->tx_dropped;
-    stats->multicast = rtnl_stats->multicast;
-    stats->collisions = rtnl_stats->collisions;
-    stats->rx_length_errors = rtnl_stats->rx_length_errors;
-    stats->rx_over_errors = rtnl_stats->rx_over_errors;
-    stats->rx_crc_errors = rtnl_stats->rx_crc_errors;
-    stats->rx_frame_errors = rtnl_stats->rx_frame_errors;
-    stats->rx_fifo_errors = rtnl_stats->rx_fifo_errors;
-    stats->rx_missed_errors = rtnl_stats->rx_missed_errors;
-    stats->tx_aborted_errors = rtnl_stats->tx_aborted_errors;
-    stats->tx_carrier_errors = rtnl_stats->tx_carrier_errors;
-    stats->tx_fifo_errors = rtnl_stats->tx_fifo_errors;
-    stats->tx_heartbeat_errors = rtnl_stats->tx_heartbeat_errors;
-    stats->tx_window_errors = rtnl_stats->tx_window_errors;
+    netdev_stats_from_rtnl_link_stats(stats, nl_attr_get(attrs[IFLA_STATS]));
 
     ofpbuf_delete(reply);
 
diff --git a/lib/netdev-linux.h b/lib/netdev-linux.h
new file mode 100644 (file)
index 0000000..7a11204
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2011 Nicira Networks.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef NETDEV_LINUX_H
+#define NETDEV_LINUX_H 1
+
+/* These functions are Linux specific, so they should be used directly only by
+ * Linux-specific code. */
+
+struct netdev_stats;
+struct rtnl_link_stats;
+struct rtnl_link_stats64;
+
+void netdev_stats_from_rtnl_link_stats(struct netdev_stats *dst,
+                                       const struct rtnl_link_stats *src);
+void netdev_stats_from_rtnl_link_stats64(struct netdev_stats *dst,
+                                         const struct rtnl_link_stats64 *src);
+void netdev_stats_to_rtnl_link_stats64(struct rtnl_link_stats64 *dst,
+                                       const struct netdev_stats *src);
+
+#endif /* netdev-linux.h */
index be26941..e11cb2a 100644 (file)
@@ -32,6 +32,7 @@
 #include "hash.h"
 #include "hmap.h"
 #include "list.h"
+#include "netdev-linux.h"
 #include "netdev-provider.h"
 #include "netlink.h"
 #include "netlink-socket.h"
@@ -416,27 +417,7 @@ netdev_vport_get_stats(const struct netdev *netdev, struct netdev_stats *stats)
         return EOPNOTSUPP;
     }
 
-    stats->rx_packets = reply.stats->rx_packets;
-    stats->tx_packets = reply.stats->tx_packets;
-    stats->rx_bytes = reply.stats->rx_bytes;
-    stats->tx_bytes = reply.stats->tx_bytes;
-    stats->rx_errors = reply.stats->rx_errors;
-    stats->tx_errors = reply.stats->tx_errors;
-    stats->rx_dropped = reply.stats->rx_dropped;
-    stats->tx_dropped = reply.stats->tx_dropped;
-    stats->multicast = reply.stats->multicast;
-    stats->collisions = reply.stats->collisions;
-    stats->rx_length_errors = reply.stats->rx_length_errors;
-    stats->rx_over_errors = reply.stats->rx_over_errors;
-    stats->rx_crc_errors = reply.stats->rx_crc_errors;
-    stats->rx_frame_errors = reply.stats->rx_frame_errors;
-    stats->rx_fifo_errors = reply.stats->rx_fifo_errors;
-    stats->rx_missed_errors = reply.stats->rx_missed_errors;
-    stats->tx_aborted_errors = reply.stats->tx_aborted_errors;
-    stats->tx_carrier_errors = reply.stats->tx_carrier_errors;
-    stats->tx_fifo_errors = reply.stats->tx_fifo_errors;
-    stats->tx_heartbeat_errors = reply.stats->tx_heartbeat_errors;
-    stats->tx_window_errors = reply.stats->tx_window_errors;
+    netdev_stats_from_rtnl_link_stats64(stats, reply.stats);
 
     ofpbuf_delete(buf);
 
@@ -450,27 +431,7 @@ netdev_vport_set_stats(struct netdev *netdev, const struct netdev_stats *stats)
     struct dpif_linux_vport vport;
     int err;
 
-    rtnl_stats.rx_packets = stats->rx_packets;
-    rtnl_stats.tx_packets = stats->tx_packets;
-    rtnl_stats.rx_bytes = stats->rx_bytes;
-    rtnl_stats.tx_bytes = stats->tx_bytes;
-    rtnl_stats.rx_errors = stats->rx_errors;
-    rtnl_stats.tx_errors = stats->tx_errors;
-    rtnl_stats.rx_dropped = stats->rx_dropped;
-    rtnl_stats.tx_dropped = stats->tx_dropped;
-    rtnl_stats.multicast = stats->multicast;
-    rtnl_stats.collisions = stats->collisions;
-    rtnl_stats.rx_length_errors = stats->rx_length_errors;
-    rtnl_stats.rx_over_errors = stats->rx_over_errors;
-    rtnl_stats.rx_crc_errors = stats->rx_crc_errors;
-    rtnl_stats.rx_frame_errors = stats->rx_frame_errors;
-    rtnl_stats.rx_fifo_errors = stats->rx_fifo_errors;
-    rtnl_stats.rx_missed_errors = stats->rx_missed_errors;
-    rtnl_stats.tx_aborted_errors = stats->tx_aborted_errors;
-    rtnl_stats.tx_carrier_errors = stats->tx_carrier_errors;
-    rtnl_stats.tx_fifo_errors = stats->tx_fifo_errors;
-    rtnl_stats.tx_heartbeat_errors = stats->tx_heartbeat_errors;
-    rtnl_stats.tx_window_errors = stats->tx_window_errors;
+    netdev_stats_to_rtnl_link_stats64(&rtnl_stats, stats);
 
     dpif_linux_vport_init(&vport);
     vport.cmd = ODP_VPORT_CMD_SET;
@@ -667,7 +628,7 @@ parse_tunnel_config(const char *name, const char *type,
     ovs_be32 daddr = htonl(0);
     uint32_t flags;
 
-    flags = TNL_F_PMTUD | TNL_F_HDR_CACHE;
+    flags = TNL_F_DF_DEFAULT | TNL_F_PMTUD | TNL_F_HDR_CACHE;
     if (!strcmp(type, "gre")) {
         is_gre = true;
     } else if (!strcmp(type, "ipsec_gre")) {
@@ -709,6 +670,14 @@ parse_tunnel_config(const char *name, const char *type,
             if (!strcmp(node->data, "true")) {
                 flags |= TNL_F_CSUM;
             }
+        } else if (!strcmp(node->name, "df_inherit")) {
+            if (!strcmp(node->data, "true")) {
+                flags |= TNL_F_DF_INHERIT;
+            }
+        } else if (!strcmp(node->name, "df_default")) {
+            if (!strcmp(node->data, "false")) {
+                flags &= ~TNL_F_DF_DEFAULT;
+            }
         } else if (!strcmp(node->name, "pmtud")) {
             if (!strcmp(node->data, "false")) {
                 flags &= ~TNL_F_PMTUD;
@@ -891,6 +860,12 @@ unparse_tunnel_config(const char *name OVS_UNUSED, const char *type OVS_UNUSED,
     if (flags & TNL_F_CSUM) {
         smap_add(args, "csum", "true");
     }
+    if (flags & TNL_F_DF_INHERIT) {
+        smap_add(args, "df_inherit", "true");
+    }
+    if (!(flags & TNL_F_DF_DEFAULT)) {
+        smap_add(args, "df_default", "false");
+    }
     if (!(flags & TNL_F_PMTUD)) {
         smap_add(args, "pmtud", "false");
     }
index c7ff4c3..29137ac 100644 (file)
@@ -853,7 +853,7 @@ parse_ofp_flow_mod_str(struct list *packets, enum nx_flow_format *cur_format,
     parse_ofp_str(&fm, is_del ? NULL : &actions, string);
     fm.command = command;
 
-    min_format = ofputil_min_flow_format(&fm.cr, true, fm.cookie);
+    min_format = ofputil_min_flow_format(&fm.cr);
     next_format = MAX(*cur_format, min_format);
     if (next_format != *cur_format) {
         struct ofpbuf *sff = ofputil_make_set_flow_format(next_format);
index 5b04d19..cbac1e4 100644 (file)
@@ -780,9 +780,6 @@ ofp_match_to_string(const struct ofp_match *om, int verbosity)
             skip_type = false;
         }
     }
-    if (w & NXFW_TUN_ID) {
-        ds_put_cstr(&f, "tun_id_wild,");
-    }
     print_wild(&f, "in_port=", w & OFPFW_IN_PORT, verbosity,
                "%d", ntohs(om->in_port));
     print_wild(&f, "dl_vlan=", w & OFPFW_DL_VLAN, verbosity,
@@ -837,7 +834,7 @@ ofp_print_flow_mod(struct ds *s, const struct ofp_header *oh,
     bool need_priority;
     int error;
 
-    error = ofputil_decode_flow_mod(&fm, oh, NXFF_OPENFLOW10, true);
+    error = ofputil_decode_flow_mod(&fm, oh, true);
     if (error) {
         ofp_print_error(s, error);
         return;
@@ -937,7 +934,7 @@ ofp_print_flow_removed(struct ds *string, const struct ofp_header *oh)
     struct ofputil_flow_removed fr;
     int error;
 
-    error = ofputil_decode_flow_removed(&fr, oh, NXFF_OPENFLOW10);
+    error = ofputil_decode_flow_removed(&fr, oh);
     if (error) {
         ofp_print_error(string, error);
         return;
@@ -1073,7 +1070,7 @@ ofp_print_flow_stats_request(struct ds *string, const struct ofp_header *oh)
     struct flow_stats_request fsr;
     int error;
 
-    error = ofputil_decode_flow_stats_request(&fsr, oh, NXFF_OPENFLOW10);
+    error = ofputil_decode_flow_stats_request(&fsr, oh);
     if (error) {
         ofp_print_error(string, error);
         return;
@@ -1106,7 +1103,7 @@ ofp_print_flow_stats_reply(struct ds *string, const struct ofp_header *oh)
         struct ofputil_flow_stats fs;
         int retval;
 
-        retval = ofputil_decode_flow_stats_reply(&fs, &b, NXFF_OPENFLOW10);
+        retval = ofputil_decode_flow_stats_reply(&fs, &b);
         if (retval) {
             if (retval != EOF) {
                 ds_put_cstr(string, " ***parse error***");
@@ -1334,13 +1331,6 @@ ofp_print_echo(struct ds *string, const struct ofp_header *oh, int verbosity)
     }
 }
 
-static void
-ofp_print_nxt_tun_id_from_cookie(struct ds *string,
-                                 const struct nxt_tun_id_cookie *ntic)
-{
-    ds_put_format(string, " set=%"PRIu8, ntic->set);
-}
-
 static void
 ofp_print_nxt_role_message(struct ds *string,
                            const struct nx_role_request *nrr)
@@ -1517,10 +1507,6 @@ ofp_to_string__(const struct ofp_header *oh,
         ofp_print_ofpst_aggregate_reply(string, oh);
         break;
 
-    case OFPUTIL_NXT_TUN_ID_FROM_COOKIE:
-        ofp_print_nxt_tun_id_from_cookie(string, msg);
-        break;
-
     case OFPUTIL_NXT_ROLE_REQUEST:
     case OFPUTIL_NXT_ROLE_REPLY:
         ofp_print_nxt_role_message(string, msg);
index 962727c..3487cba 100644 (file)
@@ -102,25 +102,17 @@ enum {
 };
 
 /* Converts the ofp_match in 'match' into a cls_rule in 'rule', with the given
- * 'priority'.
- *
- * 'flow_format' must either NXFF_OPENFLOW10 or NXFF_TUN_ID_FROM_COOKIE.  In
- * the latter case only, 'flow''s tun_id field will be taken from the high bits
- * of 'cookie', if 'match''s wildcards do not indicate that tun_id is
- * wildcarded. */
+ * 'priority'. */
 void
 ofputil_cls_rule_from_match(const struct ofp_match *match,
-                            unsigned int priority,
-                            enum nx_flow_format flow_format,
-                            ovs_be64 cookie, struct cls_rule *rule)
+                            unsigned int priority, struct cls_rule *rule)
 {
     struct flow_wildcards *wc = &rule->wc;
     unsigned int ofpfw;
     ovs_be16 vid, pcp;
 
     /* Initialize rule->priority. */
-    ofpfw = ntohl(match->wildcards);
-    ofpfw &= flow_format == NXFF_TUN_ID_FROM_COOKIE ? OVSFW_ALL : OFPFW_ALL;
+    ofpfw = ntohl(match->wildcards) & OFPFW_ALL;
     rule->priority = !ofpfw ? UINT16_MAX : priority;
 
     /* Initialize most of rule->wc. */
@@ -136,10 +128,6 @@ ofputil_cls_rule_from_match(const struct ofp_match *match,
     wc->nw_src_mask = ofputil_wcbits_to_netmask(ofpfw >> OFPFW_NW_SRC_SHIFT);
     wc->nw_dst_mask = ofputil_wcbits_to_netmask(ofpfw >> OFPFW_NW_DST_SHIFT);
 
-    if (flow_format == NXFF_TUN_ID_FROM_COOKIE && !(ofpfw & NXFW_TUN_ID)) {
-        cls_rule_set_tun_id(rule, htonll(ntohll(cookie) >> 32));
-    }
-
     if (ofpfw & OFPFW_DL_DST) {
         /* OpenFlow 1.0 OFPFW_DL_DST covers the whole Ethernet destination, but
          * Open vSwitch breaks the Ethernet destination into bits as FWW_DL_DST
@@ -206,21 +194,9 @@ ofputil_cls_rule_from_match(const struct ofp_match *match,
     cls_rule_zero_wildcarded_fields(rule);
 }
 
-/* Convert 'rule' into the OpenFlow match structure 'match'.  'flow_format'
- * must either NXFF_OPENFLOW10 or NXFF_TUN_ID_FROM_COOKIE.
- *
- * The NXFF_TUN_ID_FROM_COOKIE flow format requires modifying the flow cookie.
- * This function can help with that, if 'cookie_out' is nonnull.  For
- * NXFF_OPENFLOW10, or if the tunnel ID is wildcarded, 'cookie_in' will be
- * copied directly to '*cookie_out'.  For NXFF_TUN_ID_FROM_COOKIE when tunnel
- * ID is matched, 'cookie_in' will be modified appropriately before setting
- * '*cookie_out'.
- */
+/* Convert 'rule' into the OpenFlow match structure 'match'. */
 void
-ofputil_cls_rule_to_match(const struct cls_rule *rule,
-                          enum nx_flow_format flow_format,
-                          struct ofp_match *match,
-                          ovs_be64 cookie_in, ovs_be64 *cookie_out)
+ofputil_cls_rule_to_match(const struct cls_rule *rule, struct ofp_match *match)
 {
     const struct flow_wildcards *wc = &rule->wc;
     unsigned int ofpfw;
@@ -233,20 +209,6 @@ ofputil_cls_rule_to_match(const struct cls_rule *rule,
         ofpfw |= OFPFW_NW_TOS;
     }
 
-    /* Tunnel ID. */
-    if (flow_format == NXFF_TUN_ID_FROM_COOKIE) {
-        if (wc->tun_id_mask == htonll(0)) {
-            ofpfw |= NXFW_TUN_ID;
-        } else {
-            uint32_t cookie_lo = ntohll(cookie_in);
-            uint32_t cookie_hi = ntohll(rule->flow.tun_id);
-            cookie_in = htonll(cookie_lo | ((uint64_t) cookie_hi << 32));
-        }
-    }
-    if (cookie_out) {
-        *cookie_out = cookie_in;
-    }
-
     /* Translate VLANs. */
     match->dl_vlan = htons(0);
     match->dl_vlan_pcp = 0;
@@ -412,10 +374,6 @@ ofputil_decode_vendor(const struct ofp_header *oh,
                       != sizeof(struct nxt_flow_mod_table_id));
 
     static const struct ofputil_msg_type nxt_messages[] = {
-        { OFPUTIL_NXT_TUN_ID_FROM_COOKIE,
-          NXT_TUN_ID_FROM_COOKIE, "NXT_TUN_ID_FROM_COOKIE",
-          sizeof(struct nxt_tun_id_cookie), 0 },
-
         { OFPUTIL_NXT_ROLE_REQUEST,
           NXT_ROLE_REQUEST, "NXT_ROLE_REQUEST",
           sizeof(struct nx_role_request), 0 },
@@ -816,7 +774,6 @@ ofputil_flow_format_is_valid(enum nx_flow_format flow_format)
 {
     switch (flow_format) {
     case NXFF_OPENFLOW10:
-    case NXFF_TUN_ID_FROM_COOKIE:
     case NXFF_NXM:
         return true;
     }
@@ -830,8 +787,6 @@ ofputil_flow_format_to_string(enum nx_flow_format flow_format)
     switch (flow_format) {
     case NXFF_OPENFLOW10:
         return "openflow10";
-    case NXFF_TUN_ID_FROM_COOKIE:
-        return "tun_id_from_cookie";
     case NXFF_NXM:
         return "nxm";
     default:
@@ -843,7 +798,6 @@ int
 ofputil_flow_format_from_string(const char *s)
 {
     return (!strcmp(s, "openflow10") ? NXFF_OPENFLOW10
-            : !strcmp(s, "tun_id_from_cookie") ? NXFF_TUN_ID_FROM_COOKIE
             : !strcmp(s, "nxm") ? NXFF_NXM
             : -1);
 }
@@ -861,100 +815,43 @@ regs_fully_wildcarded(const struct flow_wildcards *wc)
     return true;
 }
 
-static inline bool
-is_nxm_required(const struct cls_rule *rule, bool cookie_support,
-                ovs_be64 cookie)
+/* Returns the minimum nx_flow_format to use for sending 'rule' to a switch
+ * (e.g. to add or remove a flow).  Only NXM can handle tunnel IDs, registers,
+ * or fixing the Ethernet multicast bit.  Otherwise, it's better to use
+ * NXFF_OPENFLOW10 for backward compatibility. */
+enum nx_flow_format
+ofputil_min_flow_format(const struct cls_rule *rule)
 {
     const struct flow_wildcards *wc = &rule->wc;
-    uint32_t cookie_hi;
-    uint64_t tun_id;
 
     /* Only NXM supports separately wildcards the Ethernet multicast bit. */
     if (!(wc->wildcards & FWW_DL_DST) != !(wc->wildcards & FWW_ETH_MCAST)) {
-        return true;
+        return NXFF_NXM;
     }
 
     /* Only NXM supports matching ARP hardware addresses. */
     if (!(wc->wildcards & FWW_ARP_SHA) || !(wc->wildcards & FWW_ARP_THA)) {
-        return true;
+        return NXFF_NXM;
     }
 
     /* Only NXM supports matching IPv6 traffic. */
     if (!(wc->wildcards & FWW_DL_TYPE)
             && (rule->flow.dl_type == htons(ETH_TYPE_IPV6))) {
-        return true;
+        return NXFF_NXM;
     }
 
     /* Only NXM supports matching registers. */
     if (!regs_fully_wildcarded(wc)) {
-        return true;
+        return NXFF_NXM;
     }
 
-    switch (wc->tun_id_mask) {
-    case CONSTANT_HTONLL(0):
-        /* Other formats can fully wildcard tun_id. */
-        break;
-
-    case CONSTANT_HTONLL(UINT64_MAX):
-        /* Only NXM supports tunnel ID matching without a cookie. */
-        if (!cookie_support) {
-            return true;
-        }
-
-        /* Only NXM supports 64-bit tunnel IDs. */
-        tun_id = ntohll(rule->flow.tun_id);
-        if (tun_id > UINT32_MAX) {
-            return true;
-        }
-
-        /* Only NXM supports a cookie whose top 32 bits conflict with the
-         * tunnel ID. */
-        cookie_hi = ntohll(cookie) >> 32;
-        if (cookie_hi && cookie_hi != tun_id) {
-            return true;
-        }
-        break;
-
-    default:
-        /* Only NXM supports partial matches on tunnel ID. */
-        return true;
+    /* Only NXM supports matching tun_id. */
+    if (wc->tun_id_mask != htonll(0)) {
+        return NXFF_NXM;
     }
 
     /* Other formats can express this rule. */
-    return false;
-}
-
-/* Returns the minimum nx_flow_format to use for sending 'rule' to a switch
- * (e.g. to add or remove a flow).  'cookie_support' should be true if the
- * command to be sent includes a flow cookie (as OFPT_FLOW_MOD does, for
- * example) or false if the command does not (OFPST_FLOW and OFPST_AGGREGATE do
- * not, for example).  If 'cookie_support' is true, then 'cookie' should be the
- * cookie to be sent; otherwise its value is ignored.
- *
- * The "best" flow format is chosen on this basis:
- *
- *   - It must be capable of expressing the rule.  NXFF_OPENFLOW10 flows can't
- *     handle tunnel IDs.  NXFF_TUN_ID_FROM_COOKIE flows can't handle registers
- *     or fixing the Ethernet multicast bit, and can't handle tunnel IDs that
- *     conflict with the high 32 bits of the cookie or commands that don't
- *     support cookies.
- *
- *   - Otherwise, the chosen format should be as backward compatible as
- *     possible.  (NXFF_OPENFLOW10 is more backward compatible than
- *     NXFF_TUN_ID_FROM_COOKIE, which is more backward compatible than
- *     NXFF_NXM.)
- */
-enum nx_flow_format
-ofputil_min_flow_format(const struct cls_rule *rule, bool cookie_support,
-                        ovs_be64 cookie)
-{
-    if (is_nxm_required(rule, cookie_support, cookie)) {
-        return NXFF_NXM;
-    } else if (rule->wc.tun_id_mask != htonll(0)) {
-        return NXFF_TUN_ID_FROM_COOKIE;
-    } else {
-        return NXFF_OPENFLOW10;
-    }
+    return NXFF_OPENFLOW10;
 }
 
 /* Returns an OpenFlow message that can be used to set the flow format to
@@ -962,20 +859,11 @@ ofputil_min_flow_format(const struct cls_rule *rule, bool cookie_support,
 struct ofpbuf *
 ofputil_make_set_flow_format(enum nx_flow_format flow_format)
 {
+    struct nxt_set_flow_format *sff;
     struct ofpbuf *msg;
 
-    if (flow_format == NXFF_OPENFLOW10
-        || flow_format == NXFF_TUN_ID_FROM_COOKIE) {
-        struct nxt_tun_id_cookie *tic;
-
-        tic = make_nxmsg(sizeof *tic, NXT_TUN_ID_FROM_COOKIE, &msg);
-        tic->set = flow_format == NXFF_TUN_ID_FROM_COOKIE;
-    } else {
-        struct nxt_set_flow_format *sff;
-
-        sff = make_nxmsg(sizeof *sff, NXT_SET_FLOW_FORMAT, &msg);
-        sff->format = htonl(flow_format);
-    }
+    sff = make_nxmsg(sizeof *sff, NXT_SET_FLOW_FORMAT, &msg);
+    sff->format = htonl(flow_format);
 
     return msg;
 }
@@ -997,17 +885,12 @@ ofputil_make_flow_mod_table_id(bool flow_mod_table_id)
  * flow_mod in 'fm'.  Returns 0 if successful, otherwise an OpenFlow error
  * code.
  *
- * For OFPT_FLOW_MOD messages, 'flow_format' should be the current flow format
- * at the time when the message was received.  Otherwise 'flow_format' is
- * ignored.
- *
  * 'flow_mod_table_id' should be true if the NXT_FLOW_MOD_TABLE_ID extension is
  * enabled, false otherwise.
  *
  * Does not validate the flow_mod actions. */
 int
 ofputil_decode_flow_mod(struct flow_mod *fm, const struct ofp_header *oh,
-                        enum nx_flow_format flow_format,
                         bool flow_mod_table_id)
 {
     const struct ofputil_msg_type *type;
@@ -1049,8 +932,7 @@ ofputil_decode_flow_mod(struct flow_mod *fm, const struct ofp_header *oh,
         }
 
         /* Translate the message. */
-        ofputil_cls_rule_from_match(&match, ntohs(ofm->priority), flow_format,
-                                    ofm->cookie, &fm->cr);
+        ofputil_cls_rule_from_match(&match, ntohs(ofm->priority), &fm->cr);
         fm->cookie = ofm->cookie;
         command = ntohs(ofm->command);
         fm->idle_timeout = ntohs(ofm->idle_timeout);
@@ -1116,15 +998,13 @@ ofputil_encode_flow_mod(const struct flow_mod *fm,
                ? (fm->command & 0xff) | (fm->table_id << 8)
                : fm->command);
 
-    if (flow_format == NXFF_OPENFLOW10
-        || flow_format == NXFF_TUN_ID_FROM_COOKIE) {
+    if (flow_format == NXFF_OPENFLOW10) {
         struct ofp_flow_mod *ofm;
 
         msg = ofpbuf_new(sizeof *ofm + actions_len);
         ofm = put_openflow(sizeof *ofm, OFPT_FLOW_MOD, msg);
-        ofputil_cls_rule_to_match(&fm->cr, flow_format, &ofm->match,
-                                  fm->cookie, &ofm->cookie);
-        ofm->command = htons(command);
+        ofputil_cls_rule_to_match(&fm->cr, &ofm->match);
+        ofm->command = htons(fm->command);
         ofm->idle_timeout = htons(fm->idle_timeout);
         ofm->hard_timeout = htons(fm->hard_timeout);
         ofm->priority = htons(fm->cr.priority);
@@ -1161,13 +1041,12 @@ ofputil_encode_flow_mod(const struct flow_mod *fm,
 static int
 ofputil_decode_ofpst_flow_request(struct flow_stats_request *fsr,
                                   const struct ofp_header *oh,
-                                  enum nx_flow_format flow_format,
                                   bool aggregate)
 {
     const struct ofp_flow_stats_request *ofsr = ofputil_stats_body(oh);
 
     fsr->aggregate = aggregate;
-    ofputil_cls_rule_from_match(&ofsr->match, 0, flow_format, 0, &fsr->match);
+    ofputil_cls_rule_from_match(&ofsr->match, 0, &fsr->match);
     fsr->out_port = ntohs(ofsr->out_port);
     fsr->table_id = ofsr->table_id;
 
@@ -1202,17 +1081,11 @@ ofputil_decode_nxst_flow_request(struct flow_stats_request *fsr,
 }
 
 /* Converts an OFPST_FLOW, OFPST_AGGREGATE, NXST_FLOW, or NXST_AGGREGATE
- * request 'oh', received when the current flow format was 'flow_format', into
- * an abstract flow_stats_request in 'fsr'.  Returns 0 if successful, otherwise
- * an OpenFlow error code.
- *
- * For OFPST_FLOW and OFPST_AGGREGATE messages, 'flow_format' should be the
- * current flow format at the time when the message was received.  Otherwise
- * 'flow_format' is ignored. */
+ * request 'oh', into an abstract flow_stats_request in 'fsr'.  Returns 0 if
+ * successful, otherwise an OpenFlow error code. */
 int
 ofputil_decode_flow_stats_request(struct flow_stats_request *fsr,
-                                  const struct ofp_header *oh,
-                                  enum nx_flow_format flow_format)
+                                  const struct ofp_header *oh)
 {
     const struct ofputil_msg_type *type;
     struct ofpbuf b;
@@ -1224,10 +1097,10 @@ ofputil_decode_flow_stats_request(struct flow_stats_request *fsr,
     code = ofputil_msg_type_code(type);
     switch (code) {
     case OFPUTIL_OFPST_FLOW_REQUEST:
-        return ofputil_decode_ofpst_flow_request(fsr, oh, flow_format, false);
+        return ofputil_decode_ofpst_flow_request(fsr, oh, false);
 
     case OFPUTIL_OFPST_AGGREGATE_REQUEST:
-        return ofputil_decode_ofpst_flow_request(fsr, oh, flow_format, true);
+        return ofputil_decode_ofpst_flow_request(fsr, oh, true);
 
     case OFPUTIL_NXST_FLOW_REQUEST:
         return ofputil_decode_nxst_flow_request(fsr, oh, false);
@@ -1250,8 +1123,7 @@ ofputil_encode_flow_stats_request(const struct flow_stats_request *fsr,
 {
     struct ofpbuf *msg;
 
-    if (flow_format == NXFF_OPENFLOW10
-        || flow_format == NXFF_TUN_ID_FROM_COOKIE) {
+    if (flow_format == NXFF_OPENFLOW10) {
         struct ofp_flow_stats_request *ofsr;
         int type;
 
@@ -1260,8 +1132,7 @@ ofputil_encode_flow_stats_request(const struct flow_stats_request *fsr,
 
         type = fsr->aggregate ? OFPST_AGGREGATE : OFPST_FLOW;
         ofsr = ofputil_make_stats_request(sizeof *ofsr, type, &msg);
-        ofputil_cls_rule_to_match(&fsr->match, flow_format, &ofsr->match,
-                                  0, NULL);
+        ofputil_cls_rule_to_match(&fsr->match, &ofsr->match);
         ofsr->table_id = fsr->table_id;
         ofsr->out_port = htons(fsr->out_port);
     } else if (flow_format == NXFF_NXM) {
@@ -1285,9 +1156,7 @@ ofputil_encode_flow_stats_request(const struct flow_stats_request *fsr,
 }
 
 /* Converts an OFPST_FLOW or NXST_FLOW reply in 'msg' into an abstract
- * ofputil_flow_stats in 'fs'.  For OFPST_FLOW messages, 'flow_format' should
- * be the current flow format at the time when the request corresponding to the
- * reply in 'msg' was sent.  Otherwise 'flow_format' is ignored.
+ * ofputil_flow_stats in 'fs'.
  *
  * Multiple OFPST_FLOW or NXST_FLOW replies can be packed into a single
  * OpenFlow message.  Calling this function multiple times for a single 'msg'
@@ -1298,8 +1167,7 @@ ofputil_encode_flow_stats_request(const struct flow_stats_request *fsr,
  * otherwise a positive errno value. */
 int
 ofputil_decode_flow_stats_reply(struct ofputil_flow_stats *fs,
-                                struct ofpbuf *msg,
-                                enum nx_flow_format flow_format)
+                                struct ofpbuf *msg)
 {
     const struct ofputil_msg_type *type;
     int code;
@@ -1344,7 +1212,7 @@ ofputil_decode_flow_stats_reply(struct ofputil_flow_stats *fs,
 
         fs->cookie = get_32aligned_be64(&ofs->cookie);
         ofputil_cls_rule_from_match(&ofs->match, ntohs(ofs->priority),
-                                    flow_format, fs->cookie, &fs->rule);
+                                    &fs->rule);
         fs->table_id = ofs->table_id;
         fs->duration_sec = ntohl(ofs->duration_sec);
         fs->duration_nsec = ntohl(ofs->duration_nsec);
@@ -1395,18 +1263,12 @@ ofputil_decode_flow_stats_reply(struct ofputil_flow_stats *fs,
     return 0;
 }
 
-/* Converts an OFPT_FLOW_REMOVED or NXT_FLOW_REMOVED message 'oh', received
- * when the current flow format was 'flow_format', into an abstract
- * ofputil_flow_removed in 'fr'.  Returns 0 if successful, otherwise an
- * OpenFlow error code.
- *
- * For OFPT_FLOW_REMOVED messages, 'flow_format' should be the current flow
- * format at the time when the message was received.  Otherwise 'flow_format'
- * is ignored. */
+/* Converts an OFPT_FLOW_REMOVED or NXT_FLOW_REMOVED message 'oh' into an
+ * abstract ofputil_flow_removed in 'fr'.  Returns 0 if successful, otherwise
+ * an OpenFlow error code. */
 int
 ofputil_decode_flow_removed(struct ofputil_flow_removed *fr,
-                            const struct ofp_header *oh,
-                            enum nx_flow_format flow_format)
+                            const struct ofp_header *oh)
 {
     const struct ofputil_msg_type *type;
     enum ofputil_msg_code code;
@@ -1418,7 +1280,7 @@ ofputil_decode_flow_removed(struct ofputil_flow_removed *fr,
 
         ofr = (const struct ofp_flow_removed *) oh;
         ofputil_cls_rule_from_match(&ofr->match, ntohs(ofr->priority),
-                                    flow_format, ofr->cookie, &fr->rule);
+                                    &fr->rule);
         fr->cookie = ofr->cookie;
         fr->reason = ofr->reason;
         fr->duration_sec = ntohl(ofr->duration_sec);
@@ -1466,14 +1328,12 @@ ofputil_encode_flow_removed(const struct ofputil_flow_removed *fr,
 {
     struct ofpbuf *msg;
 
-    if (flow_format == NXFF_OPENFLOW10
-        || flow_format == NXFF_TUN_ID_FROM_COOKIE) {
+    if (flow_format == NXFF_OPENFLOW10) {
         struct ofp_flow_removed *ofr;
 
         ofr = make_openflow_xid(sizeof *ofr, OFPT_FLOW_REMOVED, htonl(0),
                                 &msg);
-        ofputil_cls_rule_to_match(&fr->rule, flow_format, &ofr->match,
-                                  fr->cookie, &ofr->cookie);
+        ofputil_cls_rule_to_match(&fr->rule, &ofr->match);
         ofr->priority = htons(fr->rule.priority);
         ofr->reason = fr->reason;
         ofr->duration_sec = htonl(fr->duration_sec);
@@ -1768,7 +1628,7 @@ make_flow_mod(uint16_t command, const struct cls_rule *rule,
     ofm->header.length = htons(size);
     ofm->cookie = 0;
     ofm->priority = htons(MIN(rule->priority, UINT16_MAX));
-    ofputil_cls_rule_to_match(rule, NXFF_OPENFLOW10, &ofm->match, 0, NULL);
+    ofputil_cls_rule_to_match(rule, &ofm->match);
     ofm->command = htons(command);
     return out;
 }
@@ -2099,7 +1959,7 @@ check_action(const union ofp_action *a, unsigned int len,
         if (error) {
             return error;
         }
-        if (a->vlan_vid.vlan_vid & ~7) {
+        if (a->vlan_pcp.vlan_pcp & ~7) {
             return ofp_mkerr(OFPET_BAD_ACTION, OFPBAC_BAD_ARGUMENT);
         }
         return 0;
@@ -2212,7 +2072,7 @@ normalize_match(struct ofp_match *m)
     enum { OFPFW_TP = OFPFW_TP_SRC | OFPFW_TP_DST };
     uint32_t wc;
 
-    wc = ntohl(m->wildcards) & OVSFW_ALL;
+    wc = ntohl(m->wildcards) & OFPFW_ALL;
     if (wc & OFPFW_DL_TYPE) {
         m->dl_type = 0;
 
index 55c2c58..c87b04b 100644 (file)
@@ -71,7 +71,6 @@ enum ofputil_msg_code {
     OFPUTIL_OFPST_AGGREGATE_REPLY,
 
     /* NXT_* messages. */
-    OFPUTIL_NXT_TUN_ID_FROM_COOKIE,
     OFPUTIL_NXT_ROLE_REQUEST,
     OFPUTIL_NXT_ROLE_REPLY,
     OFPUTIL_NXT_SET_FLOW_FORMAT,
@@ -101,11 +100,8 @@ int ofputil_netmask_to_wcbits(ovs_be32 netmask);
 
 /* Work with OpenFlow 1.0 ofp_match. */
 void ofputil_cls_rule_from_match(const struct ofp_match *,
-                                 unsigned int priority, enum nx_flow_format,
-                                 ovs_be64 cookie, struct cls_rule *);
-void ofputil_cls_rule_to_match(const struct cls_rule *, enum nx_flow_format,
-                               struct ofp_match *,
-                               ovs_be64 cookie_in, ovs_be64 *cookie_out);
+                                 unsigned int priority, struct cls_rule *);
+void ofputil_cls_rule_to_match(const struct cls_rule *, struct ofp_match *);
 void normalize_match(struct ofp_match *);
 char *ofp_match_to_literal_string(const struct ofp_match *match);
 
@@ -117,9 +113,7 @@ ovs_be16 ofputil_dl_type_from_openflow(ovs_be16 ofp_dl_type);
 bool ofputil_flow_format_is_valid(enum nx_flow_format);
 const char *ofputil_flow_format_to_string(enum nx_flow_format);
 int ofputil_flow_format_from_string(const char *);
-enum nx_flow_format ofputil_min_flow_format(const struct cls_rule *,
-                                            bool cookie_support,
-                                            ovs_be64 cookie);
+enum nx_flow_format ofputil_min_flow_format(const struct cls_rule *);
 
 struct ofpbuf *ofputil_make_set_flow_format(enum nx_flow_format);
 
@@ -142,7 +136,7 @@ struct flow_mod {
 };
 
 int ofputil_decode_flow_mod(struct flow_mod *, const struct ofp_header *,
-                            enum nx_flow_format, bool flow_mod_table_id);
+                            bool flow_mod_table_id);
 struct ofpbuf *ofputil_encode_flow_mod(const struct flow_mod *,
                                        enum nx_flow_format,
                                        bool flow_mod_table_id);
@@ -156,8 +150,7 @@ struct flow_stats_request {
 };
 
 int ofputil_decode_flow_stats_request(struct flow_stats_request *,
-                                      const struct ofp_header *,
-                                      enum nx_flow_format);
+                                      const struct ofp_header *);
 struct ofpbuf *ofputil_encode_flow_stats_request(
     const struct flow_stats_request *, enum nx_flow_format);
 
@@ -177,8 +170,7 @@ struct ofputil_flow_stats {
 };
 
 int ofputil_decode_flow_stats_reply(struct ofputil_flow_stats *,
-                                    struct ofpbuf *msg,
-                                    enum nx_flow_format);
+                                    struct ofpbuf *msg);
 
 /* Flow removed message, independent of flow format. */
 struct ofputil_flow_removed {
@@ -193,8 +185,7 @@ struct ofputil_flow_removed {
 };
 
 int ofputil_decode_flow_removed(struct ofputil_flow_removed *,
-                                const struct ofp_header *,
-                                enum nx_flow_format);
+                                const struct ofp_header *);
 struct ofpbuf *ofputil_encode_flow_removed(const struct ofputil_flow_removed *,
                                            enum nx_flow_format);
 
diff --git a/lib/stream-nossl.c b/lib/stream-nossl.c
new file mode 100644 (file)
index 0000000..cdbbf5d
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2011 Nicira Networks.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <config.h>
+#include "stream-ssl.h"
+#include "vlog.h"
+
+VLOG_DEFINE_THIS_MODULE(stream_nossl);
+\f
+/* Dummy function definitions, used when OVS is built without OpenSSL. */
+
+bool
+stream_ssl_is_configured(void)
+{
+    return false;
+}
+
+static void NO_RETURN
+nossl_option(const char *detail)
+{
+    VLOG_FATAL("%s specified but Open vSwitch was built without SSL support",
+               detail);
+}
+
+void
+stream_ssl_set_private_key_file(const char *file_name)
+{
+    if (file_name != NULL) {
+        nossl_option("Private key");
+    }
+}
+
+void
+stream_ssl_set_certificate_file(const char *file_name)
+{
+    if (file_name != NULL) {
+        nossl_option("Certificate");
+    }
+}
+
+void
+stream_ssl_set_ca_cert_file(const char *file_name, bool bootstrap OVS_UNUSED)
+{
+    if (file_name != NULL) {
+        nossl_option("CA certificate");
+    }
+}
+
+void
+stream_ssl_set_peer_ca_cert_file(const char *file_name)
+{
+    if (file_name != NULL) {
+        nossl_option("Peer CA certificate");
+    }
+}
+
+void
+stream_ssl_set_key_and_cert(const char *private_key_file,
+                            const char *certificate_file)
+{
+    stream_ssl_set_private_key_file(private_key_file);
+    stream_ssl_set_certificate_file(certificate_file);
+}
index 6bea577..29c3120 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2009, 2010 Nicira Networks.
+ * Copyright (c) 2008, 2009, 2010, 2011 Nicira Networks.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
 
 #include <stdbool.h>
 
-#ifdef HAVE_OPENSSL
 bool stream_ssl_is_configured(void);
-
 void stream_ssl_set_private_key_file(const char *file_name);
 void stream_ssl_set_certificate_file(const char *file_name);
 void stream_ssl_set_ca_cert_file(const char *file_name, bool bootstrap);
-
+void stream_ssl_set_peer_ca_cert_file(const char *file_name);
 void stream_ssl_set_key_and_cert(const char *private_key_file,
                                  const char *certificate_file);
 
-
-void stream_ssl_set_peer_ca_cert_file(const char *file_name);
-
-/* Define the long options for SSL support.
- *
- * Note that the definition includes a final comma, and therefore a comma
- * must not be supplied when using the definition.  This is done so that
- * compilation succeeds whether or not HAVE_OPENSSL is defined. */
-#define STREAM_SSL_LONG_OPTIONS                      \
+#define STREAM_SSL_LONG_OPTIONS                     \
         {"private-key", required_argument, 0, 'p'}, \
         {"certificate", required_argument, 0, 'c'}, \
-        {"ca-cert",     required_argument, 0, 'C'},
+        {"ca-cert",     required_argument, 0, 'C'}
 
 #define STREAM_SSL_OPTION_HANDLERS                      \
         case 'p':                                       \
@@ -53,13 +43,5 @@ void stream_ssl_set_peer_ca_cert_file(const char *file_name);
         case 'C':                                       \
             stream_ssl_set_ca_cert_file(optarg, false); \
             break;
-#else /* !HAVE_OPENSSL */
-static inline bool stream_ssl_is_configured(void)
-{
-    return false;
-}
-#define STREAM_SSL_LONG_OPTIONS
-#define STREAM_SSL_OPTION_HANDLERS
-#endif /* !HAVE_OPENSSL */
 
 #endif /* stream-ssl.h */
index d49c069..7e7aaae 100644 (file)
@@ -395,7 +395,6 @@ connmgr_set_controllers(struct connmgr *mgr,
     struct shash new_controllers;
     struct ofconn *ofconn, *next_ofconn;
     struct ofservice *ofservice, *next_ofservice;
-    bool ss_exists;
     size_t i;
 
     /* Create newly configured controllers and services.
@@ -423,7 +422,6 @@ connmgr_set_controllers(struct connmgr *mgr,
 
     /* Delete controllers that are no longer configured.
      * Update configuration of all now-existing controllers. */
-    ss_exists = false;
     HMAP_FOR_EACH_SAFE (ofconn, next_ofconn, hmap_node, &mgr->controllers) {
         struct ofproto_controller *c;
 
index 5f3b9bf..e04ae60 100644 (file)
 
 VLOG_DEFINE_THIS_MODULE(in_band);
 
-/* In-band control allows a single network to be used for OpenFlow traffic and
- * other data traffic.  See ovs-vswitchd.conf.db(5) for a description of
- * configuring in-band control.
- *
- * This comment is an attempt to describe how in-band control works at a
- * wire- and implementation-level.  Correctly implementing in-band
- * control has proven difficult due to its many subtleties, and has thus
- * gone through many iterations.  Please read through and understand the
- * reasoning behind the chosen rules before making modifications.
- *
- * In Open vSwitch, in-band control is implemented as "hidden" flows (in that
- * they are not visible through OpenFlow) and at a higher priority than
- * wildcarded flows can be set up by through OpenFlow.  This is done so that
- * the OpenFlow controller cannot interfere with them and possibly break
- * connectivity with its switches.  It is possible to see all flows, including
- * in-band ones, with the ovs-appctl "bridge/dump-flows" command.
- *
- * The Open vSwitch implementation of in-band control can hide traffic to
- * arbitrary "remotes", where each remote is one TCP port on one IP address.
- * Currently the remotes are automatically configured as the in-band OpenFlow
- * controllers plus the OVSDB managers, if any.  (The latter is a requirement
- * because OVSDB managers are responsible for configuring OpenFlow controllers,
- * so if the manager cannot be reached then OpenFlow cannot be reconfigured.)
- *
- * The following rules (with the OFPP_NORMAL action) are set up on any bridge
- * that has any remotes:
- *
- *    (a) DHCP requests sent from the local port.
- *    (b) ARP replies to the local port's MAC address.
- *    (c) ARP requests from the local port's MAC address.
- *
- * In-band also sets up the following rules for each unique next-hop MAC
- * address for the remotes' IPs (the "next hop" is either the remote
- * itself, if it is on a local subnet, or the gateway to reach the remote):
- *
- *    (d) ARP replies to the next hop's MAC address.
- *    (e) ARP requests from the next hop's MAC address.
- *
- * In-band also sets up the following rules for each unique remote IP address:
- *
- *    (f) ARP replies containing the remote's IP address as a target.
- *    (g) ARP requests containing the remote's IP address as a source.
- *
- * In-band also sets up the following rules for each unique remote (IP,port)
- * pair:
- *
- *    (h) TCP traffic to the remote's IP and port.
- *    (i) TCP traffic from the remote's IP and port.
- *
- * The goal of these rules is to be as narrow as possible to allow a
- * switch to join a network and be able to communicate with the
- * remotes.  As mentioned earlier, these rules have higher priority
- * than the controller's rules, so if they are too broad, they may
- * prevent the controller from implementing its policy.  As such,
- * in-band actively monitors some aspects of flow and packet processing
- * so that the rules can be made more precise.
- *
- * In-band control monitors attempts to add flows into the datapath that
- * could interfere with its duties.  The datapath only allows exact
- * match entries, so in-band control is able to be very precise about
- * the flows it prevents.  Flows that miss in the datapath are sent to
- * userspace to be processed, so preventing these flows from being
- * cached in the "fast path" does not affect correctness.  The only type
- * of flow that is currently prevented is one that would prevent DHCP
- * replies from being seen by the local port.  For example, a rule that
- * forwarded all DHCP traffic to the controller would not be allowed,
- * but one that forwarded to all ports (including the local port) would.
- *
- * As mentioned earlier, packets that miss in the datapath are sent to
- * the userspace for processing.  The userspace has its own flow table,
- * the "classifier", so in-band checks whether any special processing
- * is needed before the classifier is consulted.  If a packet is a DHCP
- * response to a request from the local port, the packet is forwarded to
- * the local port, regardless of the flow table.  Note that this requires
- * L7 processing of DHCP replies to determine whether the 'chaddr' field
- * matches the MAC address of the local port.
- *
- * It is interesting to note that for an L3-based in-band control
- * mechanism, the majority of rules are devoted to ARP traffic.  At first
- * glance, some of these rules appear redundant.  However, each serves an
- * important role.  First, in order to determine the MAC address of the
- * remote side (controller or gateway) for other ARP rules, we must allow
- * ARP traffic for our local port with rules (b) and (c).  If we are
- * between a switch and its connection to the remote, we have to
- * allow the other switch's ARP traffic to through.  This is done with
- * rules (d) and (e), since we do not know the addresses of the other
- * switches a priori, but do know the remote's or gateway's.  Finally,
- * if the remote is running in a local guest VM that is not reached
- * through the local port, the switch that is connected to the VM must
- * allow ARP traffic based on the remote's IP address, since it will
- * not know the MAC address of the local port that is sending the traffic
- * or the MAC address of the remote in the guest VM.
- *
- * With a few notable exceptions below, in-band should work in most
- * network setups.  The following are considered "supported' in the
- * current implementation:
- *
- *    - Locally Connected.  The switch and remote are on the same
- *      subnet.  This uses rules (a), (b), (c), (h), and (i).
- *
- *    - Reached through Gateway.  The switch and remote are on
- *      different subnets and must go through a gateway.  This uses
- *      rules (a), (b), (c), (h), and (i).
- *
- *    - Between Switch and Remote.  This switch is between another
- *      switch and the remote, and we want to allow the other
- *      switch's traffic through.  This uses rules (d), (e), (h), and
- *      (i).  It uses (b) and (c) indirectly in order to know the MAC
- *      address for rules (d) and (e).  Note that DHCP for the other
- *      switch will not work unless an OpenFlow controller explicitly lets this
- *      switch pass the traffic.
- *
- *    - Between Switch and Gateway.  This switch is between another
- *      switch and the gateway, and we want to allow the other switch's
- *      traffic through.  This uses the same rules and logic as the
- *      "Between Switch and Remote" configuration described earlier.
- *
- *    - Remote on Local VM.  The remote is a guest VM on the
- *      system running in-band control.  This uses rules (a), (b), (c),
- *      (h), and (i).
- *
- *    - Remote on Local VM with Different Networks.  The remote
- *      is a guest VM on the system running in-band control, but the
- *      local port is not used to connect to the remote.  For
- *      example, an IP address is configured on eth0 of the switch.  The
- *      remote's VM is connected through eth1 of the switch, but an
- *      IP address has not been configured for that port on the switch.
- *      As such, the switch will use eth0 to connect to the remote,
- *      and eth1's rules about the local port will not work.  In the
- *      example, the switch attached to eth0 would use rules (a), (b),
- *      (c), (h), and (i) on eth0.  The switch attached to eth1 would use
- *      rules (f), (g), (h), and (i).
- *
- * The following are explicitly *not* supported by in-band control:
- *
- *    - Specify Remote by Name.  Currently, the remote must be
- *      identified by IP address.  A naive approach would be to permit
- *      all DNS traffic.  Unfortunately, this would prevent the
- *      controller from defining any policy over DNS.  Since switches
- *      that are located behind us need to connect to the remote,
- *      in-band cannot simply add a rule that allows DNS traffic from
- *      the local port.  The "correct" way to support this is to parse
- *      DNS requests to allow all traffic related to a request for the
- *      remote's name through.  Due to the potential security
- *      problems and amount of processing, we decided to hold off for
- *      the time-being.
- *
- *    - Differing Remotes for Switches.  All switches must know
- *      the L3 addresses for all the remotes that other switches
- *      may use, since rules need to be set up to allow traffic related
- *      to those remotes through.  See rules (f), (g), (h), and (i).
- *
- *    - Differing Routes for Switches.  In order for the switch to
- *      allow other switches to connect to a remote through a
- *      gateway, it allows the gateway's traffic through with rules (d)
- *      and (e).  If the routes to the remote differ for the two
- *      switches, we will not know the MAC address of the alternate
- *      gateway.
- */
-
 /* Priorities used in classifier for in-band rules.  These values are higher
  * than any that may be set with OpenFlow, and "18" kind of looks like "IB".
  * The ordering of priorities is not important because all of the rules set up
index ea0e9e4..93acd42 100644 (file)
@@ -284,6 +284,7 @@ struct ofport_dpif {
     struct list bundle_node;    /* In struct ofbundle's "ports" list. */
     struct cfm *cfm;            /* Connectivity Fault Management, if any. */
     tag_type tag;               /* Tag associated with this port. */
+    uint32_t bond_stable_id;    /* stable_id to use as bond slave, or 0. */
 };
 
 static struct ofport_dpif *
@@ -849,7 +850,8 @@ bundle_del_port(struct ofport_dpif *port)
 
 static bool
 bundle_add_port(struct ofbundle *bundle, uint32_t ofp_port,
-                struct lacp_slave_settings *lacp)
+                struct lacp_slave_settings *lacp,
+                uint32_t bond_stable_id)
 {
     struct ofport_dpif *port;
 
@@ -873,6 +875,8 @@ bundle_add_port(struct ofbundle *bundle, uint32_t ofp_port,
         lacp_slave_register(bundle->lacp, port, lacp);
     }
 
+    port->bond_stable_id = bond_stable_id;
+
     return true;
 }
 
@@ -976,7 +980,8 @@ bundle_set(struct ofproto *ofproto_, void *aux,
     ok = true;
     for (i = 0; i < s->n_slaves; i++) {
         if (!bundle_add_port(bundle, s->slaves[i],
-                             s->lacp ? &s->lacp_slaves[i] : NULL)) {
+                             s->lacp ? &s->lacp_slaves[i] : NULL,
+                             s->bond_stable_ids ? s->bond_stable_ids[i] : 0)) {
             ok = false;
         }
     }
@@ -1027,10 +1032,7 @@ bundle_set(struct ofproto *ofproto_, void *aux,
         }
 
         LIST_FOR_EACH (port, bundle_node, &bundle->ports) {
-            uint16_t stable_id = (bundle->lacp
-                                  ? lacp_slave_get_port_id(bundle->lacp, port)
-                                  : port->odp_port);
-            bond_slave_register(bundle->bond, port, stable_id,
+            bond_slave_register(bundle->bond, port, port->bond_stable_id,
                                 port->up.netdev);
         }
     } else {
index f0fc4ec..bfcae57 100644 (file)
@@ -1676,20 +1676,13 @@ handle_table_stats_request(struct ofconn *ofconn,
     for (i = 0; i < p->n_tables; i++) {
         ots[i].table_id = i;
         sprintf(ots[i].name, "table%d", i);
-        ots[i].wildcards = htonl(OVSFW_ALL);
+        ots[i].wildcards = htonl(OFPFW_ALL);
         ots[i].max_entries = htonl(1000000); /* An arbitrary big number. */
         ots[i].active_count = htonl(classifier_count(&p->tables[i]));
     }
 
     p->ofproto_class->get_tables(p, ots);
 
-    if (ofconn_get_flow_format(ofconn) == NXFF_OPENFLOW10) {
-        /* OpenFlow 1.0 only supports the OFPFW_* bits. */
-        for (i = 0; i < p->n_tables; i++) {
-            ots[i].wildcards &= htonl(OFPFW_ALL);
-        }
-    }
-
     ofconn_send_reply(ofconn, msg);
     return 0;
 }
@@ -1773,7 +1766,6 @@ put_ofp_flow_stats(struct ofconn *ofconn, struct rule *rule,
     struct ofproto *ofproto = ofconn_get_ofproto(ofconn);
     struct ofp_flow_stats *ofs;
     uint64_t packet_count, byte_count;
-    ovs_be64 cookie;
     size_t act_len, len;
 
     if (rule_is_hidden(rule) || !rule_has_out_port(rule, out_port)) {
@@ -1789,9 +1781,8 @@ put_ofp_flow_stats(struct ofconn *ofconn, struct rule *rule,
     ofs->length = htons(len);
     ofs->table_id = rule->table_id;
     ofs->pad = 0;
-    ofputil_cls_rule_to_match(&rule->cr, ofconn_get_flow_format(ofconn),
-                              &ofs->match, rule->flow_cookie, &cookie);
-    put_32aligned_be64(&ofs->cookie, cookie);
+    ofputil_cls_rule_to_match(&rule->cr, &ofs->match);
+    put_32aligned_be64(&ofs->cookie, rule->flow_cookie);
     calc_flow_duration(rule->created, &ofs->duration_sec, &ofs->duration_nsec);
     ofs->priority = htons(rule->cr.priority);
     ofs->idle_timeout = htons(rule->idle_timeout);
@@ -1860,7 +1851,7 @@ handle_flow_stats_request(struct ofconn *ofconn, const struct ofp_header *oh)
 
     COVERAGE_INC(ofproto_flows_req);
     reply = start_ofp_stats_reply(oh, 1024);
-    ofputil_cls_rule_from_match(&fsr->match, 0, NXFF_OPENFLOW10, 0, &target);
+    ofputil_cls_rule_from_match(&fsr->match, 0, &target);
     FOR_EACH_MATCHING_TABLE (cls, fsr->table_id, ofproto) {
         struct cls_cursor cursor;
         struct rule *rule;
@@ -2056,8 +2047,7 @@ handle_aggregate_stats_request(struct ofconn *ofconn,
     struct cls_rule target;
     struct ofpbuf *msg;
 
-    ofputil_cls_rule_from_match(&request->match, 0, NXFF_OPENFLOW10, 0,
-                                &target);
+    ofputil_cls_rule_from_match(&request->match, 0, &target);
 
     msg = start_ofp_stats_reply(oh, sizeof *reply);
     reply = append_ofp_stats_reply(sizeof *reply, ofconn, &msg);
@@ -2503,7 +2493,7 @@ handle_flow_mod(struct ofconn *ofconn, const struct ofp_header *oh)
         return error;
     }
 
-    error = ofputil_decode_flow_mod(&fm, oh, ofconn_get_flow_format(ofconn),
+    error = ofputil_decode_flow_mod(&fm, oh,
                                     ofconn_get_flow_mod_table_id(ofconn));
     if (error) {
         return error;
@@ -2544,19 +2534,6 @@ handle_flow_mod(struct ofconn *ofconn, const struct ofp_header *oh)
     }
 }
 
-static int
-handle_tun_id_from_cookie(struct ofconn *ofconn, const struct ofp_header *oh)
-{
-    const struct nxt_tun_id_cookie *msg
-        = (const struct nxt_tun_id_cookie *) oh;
-    enum nx_flow_format flow_format;
-
-    flow_format = msg->set ? NXFF_TUN_ID_FROM_COOKIE : NXFF_OPENFLOW10;
-    ofconn_set_flow_format(ofconn, flow_format);
-
-    return 0;
-}
-
 static int
 handle_role_request(struct ofconn *ofconn, const struct ofp_header *oh)
 {
@@ -2608,7 +2585,6 @@ handle_nxt_set_flow_format(struct ofconn *ofconn, const struct ofp_header *oh)
 
     format = ntohl(msg->format);
     if (format == NXFF_OPENFLOW10
-        || format == NXFF_TUN_ID_FROM_COOKIE
         || format == NXFF_NXM) {
         ofconn_set_flow_format(ofconn, format);
         return 0;
@@ -2673,9 +2649,6 @@ handle_openflow__(struct ofconn *ofconn, const struct ofpbuf *msg)
         return 0;
 
         /* Nicira extension requests. */
-    case OFPUTIL_NXT_TUN_ID_FROM_COOKIE:
-        return handle_tun_id_from_cookie(ofconn, oh);
-
     case OFPUTIL_NXT_ROLE_REQUEST:
         return handle_role_request(ofconn, oh);
 
index ed8d45b..ea9f98b 100644 (file)
@@ -187,6 +187,7 @@ struct ofproto_bundle_settings {
     unsigned long *trunks;      /* vlan_bitmap, NULL to trunk all VLANs. */
 
     struct bond_settings *bond; /* Must be nonnull iff if n_slaves > 1. */
+    uint32_t *bond_stable_ids;  /* Array of n_slaves elements. */
 
     struct lacp_settings *lacp;              /* Nonnull to enable LACP. */
     struct lacp_slave_settings *lacp_slaves; /* Array of n_slaves elements. */
index f2e3204..35a6d1c 100644 (file)
@@ -316,7 +316,7 @@ struct ofproto_class {
      *
      *   - 'name' to "table#" where # is the table ID.
      *
-     *   - 'wildcards' to OVSFW_ALL.
+     *   - 'wildcards' to OFPFW_ALL.
      *
      *   - 'max_entries' to 1,000,000.
      *
index a66b013..e8afdd6 100644 (file)
@@ -80,9 +80,9 @@ parse_options(int argc, char *argv[])
         DAEMON_LONG_OPTIONS,
 #ifdef HAVE_OPENSSL
         {"bootstrap-ca-cert", required_argument, 0, OPT_BOOTSTRAP_CA_CERT},
-        TABLE_LONG_OPTIONS,
-        STREAM_SSL_LONG_OPTIONS
+        STREAM_SSL_LONG_OPTIONS,
 #endif
+        TABLE_LONG_OPTIONS,
         {0, 0, 0, 0},
     };
     char *short_options = long_options_to_short_options(long_options);
@@ -111,13 +111,11 @@ parse_options(int argc, char *argv[])
 
         TABLE_OPTION_HANDLERS(&table_style)
 
-#ifdef HAVE_OPENSSL
         STREAM_SSL_OPTION_HANDLERS
 
         case OPT_BOOTSTRAP_CA_CERT:
             stream_ssl_set_ca_cert_file(optarg, true);
             break;
-#endif
 
         case '?':
             exit(EXIT_FAILURE);
index c9b0fdd..14f0fbf 100644 (file)
 
 VLOG_DEFINE_THIS_MODULE(ovsdb_server);
 
-#if HAVE_OPENSSL
 /* SSL configuration. */
 static char *private_key_file;
 static char *certificate_file;
 static char *ca_cert_file;
 static bool bootstrap_ca_cert;
-#endif
 
 static unixctl_cb_func ovsdb_server_exit;
 static unixctl_cb_func ovsdb_server_compact;
@@ -598,13 +596,11 @@ reconfigure_from_db(struct ovsdb_jsonrpc_server *jsonrpc,
     ovsdb_jsonrpc_server_set_remotes(jsonrpc, &resolved_remotes);
     shash_destroy_free_data(&resolved_remotes);
 
-#if HAVE_OPENSSL
     /* Configure SSL. */
     stream_ssl_set_key_and_cert(query_db_string(db, private_key_file),
                                 query_db_string(db, certificate_file));
     stream_ssl_set_ca_cert_file(query_db_string(db, ca_cert_file),
                                 bootstrap_ca_cert);
-#endif
 }
 
 static void
@@ -671,12 +667,10 @@ parse_options(int argc, char *argv[], char **file_namep,
         DAEMON_LONG_OPTIONS,
         VLOG_LONG_OPTIONS,
         LEAK_CHECKER_LONG_OPTIONS,
-#ifdef HAVE_OPENSSL
         {"bootstrap-ca-cert", required_argument, 0, OPT_BOOTSTRAP_CA_CERT},
         {"private-key", required_argument, 0, 'p'},
         {"certificate", required_argument, 0, 'c'},
         {"ca-cert",     required_argument, 0, 'C'},
-#endif
         {0, 0, 0, 0},
     };
     char *short_options = long_options_to_short_options(long_options);
@@ -714,7 +708,6 @@ parse_options(int argc, char *argv[], char **file_namep,
         DAEMON_OPTION_HANDLERS
         LEAK_CHECKER_OPTION_HANDLERS
 
-#ifdef HAVE_OPENSSL
         case 'p':
             private_key_file = optarg;
             break;
@@ -732,7 +725,6 @@ parse_options(int argc, char *argv[], char **file_namep,
             ca_cert_file = optarg;
             bootstrap_ca_cert = true;
             break;
-#endif
 
         case '?':
             exit(EXIT_FAILURE);
index 6e1e3bd..923e00e 100644 (file)
@@ -601,16 +601,6 @@ OFPT_BARRIER_REPLY (xid=0x1):
 ])
 AT_CLEANUP
 
-AT_SETUP([NXT_TUN_ID_FROM_COOKIE])
-AT_KEYWORDS([ofp-print])
-AT_CHECK([ovs-ofctl ofp-print "\
-01 04 00 18 00 00 00 02 00 00 23 20 00 00 00 09 \
-01 00 00 00 00 00 00 00 \
-"], [0], [dnl
-NXT_TUN_ID_FROM_COOKIE (xid=0x2): set=1
-])
-AT_CLEANUP
-
 AT_SETUP([NXT_ROLE_REQUEST])
 AT_KEYWORDS([ofp-print])
 AT_CHECK([ovs-ofctl ofp-print "\
index 6f785e9..713cc76 100644 (file)
@@ -48,13 +48,10 @@ AT_CHECK([ovs-ofctl dump-flows br0 | STRIP_XIDS], [0], [NXST_FLOW reply:
 ])
 AT_CHECK([echo 'in_port=1,actions=0' | ovs-ofctl add-flows br0 -])
 AT_CHECK([ovs-ofctl add-flow br0 in_port=0,actions=1])
-dnl Tests for a bug in which ofproto ignored tun_id in tun_id_from_cookie
-dnl flow_mod commands.
-AT_CHECK([ovs-ofctl add-flow -F tun_id_from_cookie br0 tun_id=1,actions=mod_vlan_vid:4])
 AT_CHECK([ovs-ofctl dump-flows br0 | STRIP_XIDS | STRIP_DURATION | sort], [0], [dnl
  cookie=0x0, duration=?s, table_id=0, n_packets=0, n_bytes=0, in_port=0 actions=output:1
  cookie=0x0, duration=?s, table_id=0, n_packets=0, n_bytes=0, in_port=1 actions=output:0
- cookie=0x100000000, duration=?s, table_id=0, n_packets=0, n_bytes=0, tun_id=0x1 actions=mod_vlan_vid:4
+ cookie=0x0, duration=?s, table_id=0, n_packets=0, n_bytes=0, in_port=65534 actions=output:1
 NXST_FLOW reply:
 ])
 AT_CHECK([ovs-ofctl del-flows br0])
index a9c3c20..a8cdbe9 100644 (file)
@@ -28,14 +28,12 @@ OFPT_FLOW_MOD: ADD tcp,nw_src=192.168.0.3,tp_dst=80 actions=set_queue:37,output:
 OFPT_FLOW_MOD: ADD udp,nw_src=192.168.0.3,tp_dst=53 actions=pop_queue,output:1
 OFPT_FLOW_MOD: ADD priority=60000 cookie:0x123456789abcdef hard:10 actions=CONTROLLER:65535
 OFPT_FLOW_MOD: ADD actions=note:41.42.43.00.00.00,note:00.01.02.03.04.05.06.07.00.00.00.00.00.00,note:00.00.00.00.00.00
-NXT_TUN_ID_FROM_COOKIE: set=1
-OFPT_FLOW_MOD: ADD cookie:0x123400005678 actions=FLOOD
-OFPT_FLOW_MOD: ADD actions=set_tunnel:0x1234,set_tunnel64:0x9876,set_tunnel64:0x123456789
-OFPT_FLOW_MOD: ADD actions=multipath(eth_src,50,hrw,12,0,NXM_NX_REG0[0..3]),multipath(symmetric_l4,1024,iter_hash,5000,5050,NXM_NX_REG0[0..12])
-NXT_FLOW_MOD_TABLE_ID: enable
-OFPT_FLOW_MOD: ADD table_id:1 actions=drop
 NXT_SET_FLOW_FORMAT: format=nxm
-NXT_FLOW_MOD: ADD table_id:255 tun_id=0x1234000056780000/0xffff0000ffff0000 actions=drop
+NXT_FLOW_MOD: ADD tun_id=0x1234 cookie:0x5678 actions=FLOOD
+NXT_FLOW_MOD: ADD actions=set_tunnel:0x1234,set_tunnel64:0x9876,set_tunnel64:0x123456789
+NXT_FLOW_MOD: ADD actions=multipath(eth_src,50,hrw,12,0,NXM_NX_REG0[0..3]),multipath(symmetric_l4,1024,iter_hash,5000,5050,NXM_NX_REG0[0..12])
+NXT_FLOW_MOD: ADD actions=drop
+NXT_FLOW_MOD: ADD tun_id=0x1234000056780000/0xffff0000ffff0000 actions=drop
 ]])
 AT_CHECK([sed 's/.*|//' stderr], [0], [dnl
 normalization changed ofp_match, details:
@@ -45,14 +43,8 @@ normalization changed ofp_match, details:
  pre: wildcards=  0x3820ff  in_port=    0  dl_src=00:00:00:00:00:00  dl_dst=00:00:00:00:00:00  dl_vlan=    0  dl_vlan_pcp=  0  dl_type=     0  nw_tos=   0  nw_proto=   0  nw_src=         0  nw_dst=         0  tp_src=    0  tp_dst=    0
 post: wildcards=  0x3fffff  in_port=    0  dl_src=00:00:00:00:00:00  dl_dst=00:00:00:00:00:00  dl_vlan=    0  dl_vlan_pcp=  0  dl_type=     0  nw_tos=   0  nw_proto=   0  nw_src=         0  nw_dst=         0  tp_src=    0  tp_dst=    0
 normalization changed ofp_match, details:
- pre: wildcards=  0x3820ff  in_port=    0  dl_src=00:00:00:00:00:00  dl_dst=00:00:00:00:00:00  dl_vlan=    0  dl_vlan_pcp=  0  dl_type=     0  nw_tos=   0  nw_proto=   0  nw_src=         0  nw_dst=         0  tp_src=    0  tp_dst=    0
-post: wildcards=  0x3fffff  in_port=    0  dl_src=00:00:00:00:00:00  dl_dst=00:00:00:00:00:00  dl_vlan=    0  dl_vlan_pcp=  0  dl_type=     0  nw_tos=   0  nw_proto=   0  nw_src=         0  nw_dst=         0  tp_src=    0  tp_dst=    0
-normalization changed ofp_match, details:
- pre: wildcards=  0x3820ff  in_port=    0  dl_src=00:00:00:00:00:00  dl_dst=00:00:00:00:00:00  dl_vlan=    0  dl_vlan_pcp=  0  dl_type=     0  nw_tos=   0  nw_proto=   0  nw_src=         0  nw_dst=         0  tp_src=    0  tp_dst=    0
-post: wildcards=  0x3fffff  in_port=    0  dl_src=00:00:00:00:00:00  dl_dst=00:00:00:00:00:00  dl_vlan=    0  dl_vlan_pcp=  0  dl_type=     0  nw_tos=   0  nw_proto=   0  nw_src=         0  nw_dst=         0  tp_src=    0  tp_dst=    0
-normalization changed ofp_match, details:
- pre: wildcards= 0x23820ff  in_port=    0  dl_src=00:00:00:00:00:00  dl_dst=00:00:00:00:00:00  dl_vlan=    0  dl_vlan_pcp=  0  dl_type=     0  nw_tos=   0  nw_proto=   0  nw_src=         0  nw_dst=         0  tp_src=    0  tp_dst=    0
-post: wildcards= 0x23fffff  in_port=    0  dl_src=00:00:00:00:00:00  dl_dst=00:00:00:00:00:00  dl_vlan=    0  dl_vlan_pcp=  0  dl_type=     0  nw_tos=   0  nw_proto=   0  nw_src=         0  nw_dst=         0  tp_src=    0  tp_dst=    0
+ pre: wildcards=  0x3820ff  in_port=65534  dl_src=00:00:00:00:00:00  dl_dst=00:00:00:00:00:00  dl_vlan=    0  dl_vlan_pcp=  0  dl_type=     0  nw_tos=   0  nw_proto=   0  nw_src=         0  nw_dst=         0  tp_src=    0  tp_dst=    0
+post: wildcards=  0x3fffff  in_port=65534  dl_src=00:00:00:00:00:00  dl_dst=00:00:00:00:00:00  dl_vlan=    0  dl_vlan_pcp=  0  dl_type=     0  nw_tos=   0  nw_proto=   0  nw_src=         0  nw_dst=         0  tp_src=    0  tp_dst=    0
 ])
 AT_CLEANUP
 
@@ -470,7 +462,7 @@ dnl Check that "-F openflow10" rejects a flow_mod with a tun_id, since
 dnl OpenFlow 1.0 doesn't support tunnels.
 AT_SETUP([ovs-ofctl -F option and tun_id])
 AT_CHECK([ovs-ofctl -F openflow10 add-flow dummy tun_id=123,actions=drop],
-  [1], [], [ovs-ofctl: flow cannot be expressed in flow format openflow10 (flow format tun_id_from_cookie or better is required)
+  [1], [], [ovs-ofctl: flow cannot be expressed in flow format openflow10 (flow format nxm or better is required)
 ])
 AT_CLEANUP
 
index 2edfa35..559af3a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2010 Nicira Networks.
+ * Copyright (c) 2009, 2010, 2011 Nicira Networks.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -70,8 +70,7 @@ main(int argc OVS_UNUSED, char *argv[])
 
         flow_extract(packet, 0, 1, &flow);
         cls_rule_init_exact(&flow, 0, &rule);
-        ofputil_cls_rule_to_match(&rule, NXFF_OPENFLOW10, &extracted_match,
-                                  0, NULL);
+        ofputil_cls_rule_to_match(&rule, &extracted_match);
 
         if (memcmp(&expected_match, &extracted_match, sizeof expected_match)) {
             char *exp_s = ofp_match_to_string(&expected_match, 2);
index 12bbc97..5d93850 100644 (file)
@@ -60,10 +60,8 @@ parse_options(int argc, char *argv[])
         {"verbose", optional_argument, 0, 'v'},
         {"help", no_argument, 0, 'h'},
         DAEMON_LONG_OPTIONS,
-#ifdef HAVE_OPENSSL
         {"bootstrap-ca-cert", required_argument, 0, OPT_BOOTSTRAP_CA_CERT},
-        STREAM_SSL_LONG_OPTIONS
-#endif
+        STREAM_SSL_LONG_OPTIONS,
         {0, 0, 0, 0},
     };
     char *short_options = long_options_to_short_options(long_options);
@@ -84,13 +82,11 @@ parse_options(int argc, char *argv[])
 
         DAEMON_OPTION_HANDLERS
 
-#ifdef HAVE_OPENSSL
         STREAM_SSL_OPTION_HANDLERS
 
         case OPT_BOOTSTRAP_CA_CERT:
             stream_ssl_set_ca_cert_file(optarg, true);
             break;
-#endif
 
         case '?':
             exit(EXIT_FAILURE);
index f131917..89e6a56 100644 (file)
@@ -328,10 +328,8 @@ parse_options(int argc, char *argv[])
         {"version",     no_argument, 0, 'V'},
         DAEMON_LONG_OPTIONS,
         VLOG_LONG_OPTIONS,
-#ifdef HAVE_OPENSSL
-        STREAM_SSL_LONG_OPTIONS
+        STREAM_SSL_LONG_OPTIONS,
         {"peer-ca-cert", required_argument, 0, OPT_PEER_CA_CERT},
-#endif
         {0, 0, 0, 0},
     };
     char *short_options = long_options_to_short_options(long_options);
@@ -404,13 +402,11 @@ parse_options(int argc, char *argv[])
         VLOG_OPTION_HANDLERS
         DAEMON_OPTION_HANDLERS
 
-#ifdef HAVE_OPENSSL
         STREAM_SSL_OPTION_HANDLERS
 
         case OPT_PEER_CA_CERT:
             stream_ssl_set_peer_ca_cert_file(optarg);
             break;
-#endif
 
         case '?':
             exit(EXIT_FAILURE);
index 58b3ea0..5b5941b 100644 (file)
@@ -78,10 +78,12 @@ Removes each \fInetdev\fR from the list of network devices datapath
 Prints the name of each configured datapath on a separate line.
 .
 .TP
-\fBshow \fR[\fIdp\fR...]
+[\fB\-s\fR | \fB\-\-statistics\fR] \fBshow \fR[\fIdp\fR...]
 Prints a summary of configured datapaths, including their datapath
 numbers and a list of ports connected to each datapath.  (The local
-port is identified as port 0.)
+port is identified as port 0.)  If \fB\-s\fR or \fB\-\-statistics\fR
+is specified, then packet and byte counters are also printed for each
+port.
 .IP
 If one or more datapaths are specified, information on only those
 datapaths are displayed.  Otherwise, \fBovs\-dpctl\fR displays information
@@ -104,6 +106,9 @@ not OpenFlow flow entries.  By deleting them, the process that set them
 up may be confused about their disappearance.
 .
 .SH OPTIONS
+.IP "\fB\-s\fR, \fB\-\-statistics\fR"
+Causes the \fBshow\fR command to print packet and byte counters for
+each port within the datapaths that it shows.
 .TP
 \fB\-t\fR, \fB\-\-timeout=\fIsecs\fR
 Limits \fBovs\-dpctl\fR runtime to approximately \fIsecs\fR seconds.  If
index 9d6bf98..40048b4 100644 (file)
@@ -45,6 +45,9 @@
 
 VLOG_DEFINE_THIS_MODULE(dpctl);
 
+/* -s, --statistics: Print port statistics? */
+bool print_statistics;
+
 static const struct command all_commands[];
 
 static void usage(void) NO_RETURN;
@@ -68,6 +71,7 @@ parse_options(int argc, char *argv[])
         VLOG_OPTION_ENUMS
     };
     static struct option long_options[] = {
+        {"statistics", no_argument, 0, 's'},
         {"timeout", required_argument, 0, 't'},
         {"help", no_argument, 0, 'h'},
         {"version", no_argument, 0, 'V'},
@@ -86,6 +90,10 @@ parse_options(int argc, char *argv[])
         }
 
         switch (c) {
+        case 's':
+            print_statistics = true;
+            break;
+
         case 't':
             timeout = strtoul(optarg, NULL, 10);
             if (timeout <= 0) {
@@ -320,6 +328,33 @@ do_del_if(int argc OVS_UNUSED, char *argv[])
     }
 }
 
+static void
+print_stat(const char *leader, uint64_t value)
+{
+    fputs(leader, stdout);
+    if (value != UINT64_MAX) {
+        printf("%"PRIu64, value);
+    } else {
+        putchar('?');
+    }
+}
+
+static void
+print_human_size(uint64_t value)
+{
+    if (value == UINT64_MAX) {
+        /* Nothing to do. */
+    } else if (value >= 1024ULL * 1024 * 1024 * 1024) {
+        printf(" (%.1f TiB)", value / (1024.0 * 1024 * 1024 * 1024));
+    } else if (value >= 1024ULL * 1024 * 1024) {
+        printf(" (%.1f GiB)", value / (1024.0 * 1024 * 1024));
+    } else if (value >= 1024ULL * 1024) {
+        printf(" (%.1f MiB)", value / (1024.0 * 1024));
+    } else if (value >= 1024) {
+        printf(" (%.1f KiB)", value / 1024.0);
+    }
+}
+
 static void
 show_dpif(struct dpif *dpif)
 {
@@ -371,6 +406,33 @@ show_dpif(struct dpif *dpif)
             putchar(')');
         }
         putchar('\n');
+
+        if (print_statistics) {
+            const struct netdev_stats *s = &dpif_port.stats;
+
+            print_stat("\t\tRX packets:", s->rx_packets);
+            print_stat(" errors:", s->rx_errors);
+            print_stat(" dropped:", s->rx_dropped);
+            print_stat(" overruns:", s->rx_over_errors);
+            print_stat(" frame:", s->rx_frame_errors);
+            printf("\n");
+
+            print_stat("\t\tTX packets:", s->tx_packets);
+            print_stat(" errors:", s->tx_errors);
+            print_stat(" dropped:", s->tx_dropped);
+            print_stat(" aborted:", s->tx_aborted_errors);
+            print_stat(" carrier:", s->tx_carrier_errors);
+            printf("\n");
+
+            print_stat("\t\tcollisions:", s->collisions);
+            printf("\n");
+
+            print_stat("\t\tRX bytes:", s->rx_bytes);
+            print_human_size(s->rx_bytes);
+            print_stat("  TX bytes:", s->tx_bytes);
+            print_human_size(s->tx_bytes);
+            printf("\n");
+        }
     }
     dpif_close(dpif);
 }
index 7452e70..06d61de 100644 (file)
@@ -775,11 +775,6 @@ increasing capability:
 This is the standard OpenFlow 1.0 flow format.  It should be supported
 by all OpenFlow switches.
 .
-.IP "\fBtun_id_from_cookie\fR"
-This Nicira extension to OpenFlow adds minimal and limited support for
-\fBtun_id\fR, but it does not support any other Nicira flow
-extensions.  (This flow format is deprecated.)
-.
 .IP "\fBnxm\fR (Nicira Extended Match)"
 This Nicira extension to OpenFlow is flexible and extensible.  It
 supports all of the Nicira flow extensions, such as \fBtun_id\fR and
index 11fcc3e..5fa11db 100644 (file)
@@ -92,7 +92,7 @@ parse_options(int argc, char *argv[])
         {"help", no_argument, 0, 'h'},
         {"version", no_argument, 0, 'V'},
         VLOG_LONG_OPTIONS,
-        STREAM_SSL_LONG_OPTIONS
+        STREAM_SSL_LONG_OPTIONS,
         {0, 0, 0, 0},
     };
     char *short_options = long_options_to_short_options(long_options);
@@ -502,8 +502,6 @@ negotiate_highest_flow_format(struct vconn *vconn,
 
         if (try_set_flow_format(vconn, NXFF_NXM)) {
             flow_format = NXFF_NXM;
-        } else if (try_set_flow_format(vconn, NXFF_TUN_ID_FROM_COOKIE)) {
-            flow_format = NXFF_TUN_ID_FROM_COOKIE;
         } else {
             flow_format = NXFF_OPENFLOW10;
         }
@@ -531,7 +529,7 @@ do_dump_flows__(int argc, char *argv[], bool aggregate)
     parse_ofp_flow_stats_request_str(&fsr, aggregate, argc > 2 ? argv[2] : "");
 
     open_vconn(argv[1], &vconn);
-    min_flow_format = ofputil_min_flow_format(&fsr.match, false, 0);
+    min_flow_format = ofputil_min_flow_format(&fsr.match);
     flow_format = negotiate_highest_flow_format(vconn, min_flow_format);
     request = ofputil_encode_flow_stats_request(&fsr, flow_format);
     dump_stats_transaction(argv[1], request);
@@ -1047,7 +1045,7 @@ read_flows_from_file(const char *filename, struct classifier *cls, int index)
         version->n_actions = actions.size / sizeof *version->actions;
         version->actions = ofpbuf_steal_data(&actions);
 
-        min_ff = ofputil_min_flow_format(&fm.cr, true, fm.cookie);
+        min_ff = ofputil_min_flow_format(&fm.cr);
         min_flow_format = MAX(min_flow_format, min_ff);
         check_final_format_for_flow_mod(min_flow_format);
 
@@ -1113,8 +1111,7 @@ read_flows_from_switch(struct vconn *vconn, enum nx_flow_format flow_format,
                 struct ofputil_flow_stats fs;
                 int retval;
 
-                retval = ofputil_decode_flow_stats_reply(&fs, reply,
-                                                         flow_format);
+                retval = ofputil_decode_flow_stats_reply(&fs, reply);
                 if (retval) {
                     if (retval != EOF) {
                         ovs_fatal(0, "parse error in reply");
index 2d2446e..9a9dffe 100644 (file)
@@ -269,10 +269,8 @@ parse_options(int argc, char *argv[], struct ofsettings *s)
         DAEMON_LONG_OPTIONS,
         VLOG_LONG_OPTIONS,
         LEAK_CHECKER_LONG_OPTIONS,
-#ifdef HAVE_OPENSSL
-        STREAM_SSL_LONG_OPTIONS
+        STREAM_SSL_LONG_OPTIONS,
         {"bootstrap-ca-cert", required_argument, 0, OPT_BOOTSTRAP_CA_CERT},
-#endif
         {0, 0, 0, 0},
     };
     char *short_options = long_options_to_short_options(long_options);
@@ -440,13 +438,11 @@ parse_options(int argc, char *argv[], struct ofsettings *s)
 
         LEAK_CHECKER_OPTION_HANDLERS
 
-#ifdef HAVE_OPENSSL
         STREAM_SSL_OPTION_HANDLERS
 
         case OPT_BOOTSTRAP_CA_CERT:
             stream_ssl_set_ca_cert_file(optarg, true);
             break;
-#endif
 
         case '?':
             exit(EXIT_FAILURE);
index e59f6db..0837dc3 100644 (file)
@@ -12,7 +12,8 @@ The \fBovs\-tcpundump\fR program reads \fBtcpdump \-xx\fR output on
 stdin, looking for hexadecimal packet data, and dumps each Ethernet as
 a single hexadecimal string on stdout.  This format is suitable for
 use with the \fBofproto/trace\fR command supported by
-\fBovs\-vswitchd\fR(8) and \fBovs-openflowd\fR(8).
+\fBovs\-vswitchd\fR(8) and \fBovs-openflowd\fR(8)
+via \fBovs\-appctl\fR(8).
 .PP
 At least two \fB\-x\fR or \fB\-X\fR options must be given, otherwise
 the output will omit the Ethernet header, which prevents the output
@@ -23,6 +24,7 @@ from being using with \fBofproto/trace\fR.
 .
 .SH "SEE ALSO"
 .
+.BR ovs\-appctl (8),
 .BR ovs\-vswitchd (8),
 .BR ovs\-openflowd (8),
 .BR ovs\-pcap (1),
index 0b3e164..fcfec02 100644 (file)
@@ -596,6 +596,11 @@ For a map column, without \fB\-\-if\-exists\fR it is an error if
 If \fB@\fIname\fR is specified, then the UUID for \fIrecord\fR may be
 referred to by that name later in the same \fBovs\-vsctl\fR
 invocation in contexts where a UUID is expected.
+.IP
+Both \fB\-\-id\fR and the \fIcolumn\fR arguments are optional, but
+usually at least one or the other should be specified.  If both are
+omitted, then \fBget\fR has no effect except to verify that
+\fIrecord\fR exists in \fItable\fR.
 .
 .IP "\fBset \fItable record column\fR[\fB:\fIkey\fR]\fB=\fIvalue\fR..."
 Sets the value of each specified \fIcolumn\fR in the given
index 2c1ba6d..8516966 100644 (file)
@@ -26,6 +26,7 @@
 #include <stdarg.h>
 #include <stdlib.h>
 #include <string.h>
+#include <unistd.h>
 
 #include "command-line.h"
 #include "compiler.h"
@@ -216,10 +217,8 @@ parse_options(int argc, char *argv[])
         {"version", no_argument, 0, 'V'},
         VLOG_LONG_OPTIONS,
         TABLE_LONG_OPTIONS,
-#ifdef HAVE_OPENSSL
-        STREAM_SSL_LONG_OPTIONS
+        STREAM_SSL_LONG_OPTIONS,
         {"peer-ca-cert", required_argument, 0, OPT_PEER_CA_CERT},
-#endif
         {0, 0, 0, 0},
     };
     char *tmp, *short_options;
@@ -277,13 +276,11 @@ parse_options(int argc, char *argv[])
         VLOG_OPTION_HANDLERS
         TABLE_OPTION_HANDLERS(&table_style)
 
-#ifdef HAVE_OPENSSL
         STREAM_SSL_OPTION_HANDLERS
 
         case OPT_PEER_CA_CERT:
             stream_ssl_set_peer_ca_cert_file(optarg);
             break;
-#endif
 
         case '?':
             exit(EXIT_FAILURE);
@@ -2547,10 +2544,20 @@ pre_parse_column_key_value(struct vsctl_context *ctx,
 static void
 pre_cmd_get(struct vsctl_context *ctx)
 {
+    const char *id = shash_find_data(&ctx->options, "--id");
     const char *table_name = ctx->argv[1];
     const struct vsctl_table_class *table;
     int i;
 
+    /* Using "get" without --id or a column name could possibly make sense.
+     * Maybe, for example, a ovs-vsctl run wants to assert that a row exists.
+     * But it is unlikely that an interactive user would want to do that, so
+     * issue a warning if we're running on a terminal. */
+    if (!id && ctx->argc <= 3 && isatty(STDOUT_FILENO)) {
+        VLOG_WARN("\"get\" command without row arguments or \"--id\" is "
+                  "possibly erroneous");
+    }
+
     table = pre_get_table(ctx, table_name);
     for (i = 3; i < ctx->argc; i++) {
         if (!strcasecmp(ctx->argv[i], "_uuid")
index 761d02b..127e0b7 100644 (file)
@@ -1392,7 +1392,7 @@ bridge_run(void)
     /* (Re)configure if necessary. */
     database_changed = ovsdb_idl_run(idl);
     cfg = ovsrec_open_vswitch_first(idl);
-#ifdef HAVE_OPENSSL
+
     /* Re-configure SSL.  We do this on every trip through the main loop,
      * instead of just when the database changes, because the contents of the
      * key and certificate files can change without the database changing.
@@ -1405,7 +1405,7 @@ bridge_run(void)
         stream_ssl_set_key_and_cert(ssl->private_key, ssl->certificate);
         stream_ssl_set_ca_cert_file(ssl->ca_cert, ssl->bootstrap_ca_cert);
     }
-#endif
+
     if (database_changed || datapath_destroyed) {
         if (cfg) {
             struct ovsdb_idl_txn *txn = ovsdb_idl_txn_create(idl);
@@ -2021,7 +2021,10 @@ port_del_ifaces(struct port *port)
     sset_init(&new_ifaces);
     for (i = 0; i < port->cfg->n_interfaces; i++) {
         const char *name = port->cfg->interfaces[i]->name;
-        sset_add(&new_ifaces, name);
+        const char *type = port->cfg->interfaces[i]->name;
+        if (strcmp(type, "null")) {
+            sset_add(&new_ifaces, name);
+        }
     }
 
     /* Get rid of deleted interfaces. */
@@ -2047,7 +2050,8 @@ port_add_ifaces(struct port *port)
     shash_init(&new_ifaces);
     for (i = 0; i < port->cfg->n_interfaces; i++) {
         const struct ovsrec_interface *cfg = port->cfg->interfaces[i];
-        if (!shash_add_once(&new_ifaces, cfg->name, cfg)) {
+        if (strcmp(cfg->type, "null")
+            && !shash_add_once(&new_ifaces, cfg->name, cfg)) {
             VLOG_WARN("port %s: %s specified twice as port interface",
                       port->name, cfg->name);
             iface_set_ofport(cfg, -1);
@@ -2159,9 +2163,10 @@ port_configure_lacp(struct port *port, struct lacp_settings *s)
                    ? priority
                    : UINT16_MAX - !list_is_short(&port->ifaces));
 
-    s->strict = !strcmp(get_port_other_config(port->cfg, "lacp-strict",
-                                              "false"),
-                        "true");
+    s->heartbeat = !strcmp(get_port_other_config(port->cfg,
+                                                 "lacp-heartbeat",
+                                                 "false"), "true");
+
 
     lacp_time = get_port_other_config(port->cfg, "lacp-time", "slow");
     custom_time = atoi(lacp_time);
@@ -2182,11 +2187,13 @@ port_configure_lacp(struct port *port, struct lacp_settings *s)
 static void
 iface_configure_lacp(struct iface *iface, struct lacp_slave_settings *s)
 {
-    int priority, portid;
+    int priority, portid, key;
 
     portid = atoi(get_interface_other_config(iface->cfg, "lacp-port-id", "0"));
     priority = atoi(get_interface_other_config(iface->cfg,
                                                "lacp-port-priority", "0"));
+    key = atoi(get_interface_other_config(iface->cfg, "lacp-aggregation-key",
+                                          "0"));
 
     if (portid <= 0 || portid > UINT16_MAX) {
         portid = iface->ofp_port;
@@ -2196,9 +2203,14 @@ iface_configure_lacp(struct iface *iface, struct lacp_slave_settings *s)
         priority = UINT16_MAX;
     }
 
+    if (key < 0 || key > UINT16_MAX) {
+        key = 0;
+    }
+
     s->name = iface->name;
     s->id = portid;
     s->priority = priority;
+    s->key = key;
 }
 
 static void
@@ -2231,6 +2243,7 @@ port_configure_bond(struct port *port, struct bond_settings *s)
 
     s->up_delay = MAX(0, port->cfg->bond_updelay);
     s->down_delay = MAX(0, port->cfg->bond_downdelay);
+    s->basis = atoi(get_port_other_config(port->cfg, "bond-hash-basis", "0"));
     s->rebalance_interval = atoi(
         get_port_other_config(port->cfg, "bond-rebalance-interval", "10000"));
     if (s->rebalance_interval < 1000) {
@@ -2446,7 +2459,7 @@ iface_delete_queues(unsigned int queue_id,
 static void
 iface_configure_qos(struct iface *iface, const struct ovsrec_qos *qos)
 {
-    if (!qos || qos->type[0] == '\0') {
+    if (!qos || qos->type[0] == '\0' || qos->n_queues < 1) {
         netdev_set_qos(iface->netdev, NULL, NULL);
     } else {
         struct iface_delete_queues_cbdata cbdata;
index 0cce84d..2ce164c 100644 (file)
@@ -52,6 +52,12 @@ pruned.  The default prune timeout is 5 seconds.
 .so lib/common.man
 .so lib/leak-checker.man
 .
+.SH BUGS
+.
+\fBovs\-brcompatd\fR requires the bridges that it manages to initially
+have no ports listed in their database records when it starts up.
+Otherwise, it may add duplicate ports to bridges.
+.
 .SH NOTES
 \fBovs\-brcompatd\fR requires the \fBbrcompat_mod.ko\fR kernel module to be
 loaded.
index 4c02f8a..4882574 100644 (file)
@@ -182,9 +182,9 @@ updelay (or downdelay).
 .IP
 This setting is not permanent: it persists only until the carrier
 status of \fIslave\fR changes.
-.IP "\fBbond/hash\fR \fImac\fR [\fIvlan\fR]"
+.IP "\fBbond/hash\fR \fImac\fR [\fIvlan\fR] [\fIbasis\fR]"
 Returns the hash value which would be used for \fImac\fR with \fIvlan\fR
-if specified.
+and \fIbasis\fR if specified.
 .
 .IP "\fBlacp/show\fR \fIport\fR"
 Lists all of the LACP related information about the given \fIport\fR:
index 203626c..66b78f0 100644 (file)
@@ -125,11 +125,9 @@ parse_options(int argc, char *argv[])
         DAEMON_LONG_OPTIONS,
         VLOG_LONG_OPTIONS,
         LEAK_CHECKER_LONG_OPTIONS,
-#ifdef HAVE_OPENSSL
-        STREAM_SSL_LONG_OPTIONS
+        STREAM_SSL_LONG_OPTIONS,
         {"peer-ca-cert", required_argument, 0, OPT_PEER_CA_CERT},
         {"bootstrap-ca-cert", required_argument, 0, OPT_BOOTSTRAP_CA_CERT},
-#endif
         {"enable-dummy", no_argument, 0, OPT_ENABLE_DUMMY},
         {0, 0, 0, 0},
     };
@@ -165,8 +163,6 @@ parse_options(int argc, char *argv[])
         VLOG_OPTION_HANDLERS
         DAEMON_OPTION_HANDLERS
         LEAK_CHECKER_OPTION_HANDLERS
-
-#ifdef HAVE_OPENSSL
         STREAM_SSL_OPTION_HANDLERS
 
         case OPT_PEER_CA_CERT:
@@ -176,7 +172,6 @@ parse_options(int argc, char *argv[])
         case OPT_BOOTSTRAP_CA_CERT:
             stream_ssl_set_ca_cert_file(optarg, true);
             break;
-#endif
 
         case OPT_ENABLE_DUMMY:
             dummy_enable();
index 90fedd9..96be69f 100644 (file)
@@ -1,6 +1,6 @@
 {"name": "Open_vSwitch",
- "version": "3.3.0",
- "cksum": "1105667635 15276",
+ "version": "3.4.2",
+ "cksum": "976911089 15276",
  "tables": {
    "Open_vSwitch": {
      "columns": {
index 4cdc1b1..a16c486 100644 (file)
             balancing is done.  Uses a similar hashing strategy to
             <code>balance-tcp</code>, falling back to <code>balance-slb</code>
             style hashing when LACP negotiations are unsuccessful.</p>
-          <p>Slave selection decisions are made based on LACP port ID when LACP
-            negotiations are successful, falling back to openflow port number
-            when unsuccessful.  Thus, decisions are consistent across all
-            ovs-vswitchd instances with equivalent port IDs.</p>
+          <p>Slave selection decisions are made based on
+            <code>bond-stable-id</code> if set.  Otherwise, OpenFlow port
+            number is used.  Decisions are consistent across all ovs-vswitchd
+            instances with equivalent <code>bond-stable-id</code>s.</p>
         </dd>
       </dl>
 
 
       <column name="lacp">
         <p>Configures LACP on this port.  LACP allows directly connected
-          switchs to negotiate which links may be bonded.  LACP may be enabled
-          on non-bonded ports for the benefit of any switchs they may be
+          switches to negotiate which links may be bonded.  LACP may be enabled
+          on non-bonded ports for the benefit of any switches they may be
           connected to.  <code>active</code> ports are allowed to initiate LACP
           negotiations.  <code>passive</code> ports are allowed to participate
           in LACP negotiations initiated by a remote switch, but not allowed to
           <dd> The number of milliseconds between successive attempts to
             poll each interface's MII.  Only relevant on ports which use
             <code>miimon</code> to detect failures. </dd>
+          <dt><code>bond-hash-basis</code></dt>
+          <dd> An integer hashed along with flows when choosing output slaves.
+            When changed, all flows will be assigned different hash values
+            possibly causing slave selection decisions to change.</dd>
           <dt><code>lacp-system-id</code></dt>
           <dd> The LACP system ID of this <ref table="Port"/>.  The system ID
             of a LACP bond is used to identify itself to its partners.  Must
               something other than <code>fast</code> or <code>slow</code> is
               not supported by the LACP specification.</p>
           </dd>
-          <dt><code>lacp-strict</code></dt>
-          <dd> When <code>true</code>, configures this <ref table="Port"/> to
-            require successful LACP negotiations to enable any slaves.
-            Defaults to <code>false</code> which safely allows LACP to be used
-            with switchs that do not support the protocol.</dd>
+          <dt><code>lacp-heartbeat</code></dt>
+          <dd> Treats LACP like a simple heartbeat protocol for link state
+            monitoring.  Most features of the LACP protocol are disabled when
+            this mode is in use.</dd>
         </dl>
       </column>
     </group>
                 adds value for the GRE and encapsulated Ethernet headers.
                 Default is disabled, set to <code>true</code> to enable.</dd>
             </dl>
+            <dl>
+              <dt><code>df_inherit</code></dt>
+              <dd>Optional.  If enabled, the Don't Fragment bit will be copied
+                from the inner IP headers (those of the encapsulated traffic)
+                to the outer (tunnel) headers.  Default is disabled; set to
+                <code>true</code> to enable.</dd>
+            </dl>
+            <dl>
+              <dt><code>df_default</code></dt>
+              <dd>Optional.  If enabled, the Don't Fragment bit will be set by
+                default on tunnel headers if the <code>df_inherit</code> option
+                is not set, or if the encapsulated packet is not IP.  Default
+                is enabled; set to <code>false</code> to disable.</dd>
+            </dl>
             <dl>
               <dt><code>pmtud</code></dt>
               <dd>Optional.  Enable tunnel path MTU discovery.  If enabled
-                ``ICMP destination unreachable - fragmentation'' needed
+                ``ICMP Destination Unreachable - Fragmentation Needed''
                 messages will be generated for IPv4 packets with the DF bit set
                 and IPv6 packets above the minimum MTU if the packet size
-                exceeds the path MTU minus the size of the tunnel headers.  It
-                also forces the encapsulating packet DF bit to be set (it is
-                always set if the inner packet implies path MTU discovery).
+                exceeds the path MTU minus the size of the tunnel headers.
                 Note that this option causes behavior that is typically
                 reserved for routers and therefore is not entirely in
                 compliance with the IEEE 802.1D specification for bridges.
-                Default is enabled, set to <code>false</code> to disable.</dd>
+                Default is enabled; set to <code>false</code> to disable.</dd>
             </dl>
             <dl>
               <dt><code>header_cache</code></dt>
                 adds value for the GRE and encapsulated Ethernet headers.
                 Default is disabled, set to <code>true</code> to enable.</dd>
             </dl>
+            <dl>
+              <dt><code>df_inherit</code></dt>
+              <dd>Optional.  If enabled, the Don't Fragment bit will be copied
+                from the inner IP headers (those of the encapsulated traffic)
+                to the outer (tunnel) headers.  Default is disabled; set to
+                <code>true</code> to enable.</dd>
+            </dl>
+            <dl>
+              <dt><code>df_default</code></dt>
+              <dd>Optional.  If enabled, the Don't Fragment bit will be set by
+                default on tunnel headers if the <code>df_inherit</code> option
+                is not set, or if the encapsulated packet is not IP.  Default
+                is enabled; set to <code>false</code> to disable.</dd>
+            </dl>
             <dl>
               <dt><code>pmtud</code></dt>
               <dd>Optional.  Enable tunnel path MTU discovery.  If enabled
-                ``ICMP destination unreachable - fragmentation'' needed
+                ``ICMP Destination Unreachable - Fragmentation Needed''
                 messages will be generated for IPv4 packets with the DF bit set
                 and IPv6 packets above the minimum MTU if the packet size
-                exceeds the path MTU minus the size of the tunnel headers.  It
-                also forces the encapsulating packet DF bit to be set (it is
-                always set if the inner packet implies path MTU discovery).
+                exceeds the path MTU minus the size of the tunnel headers.
                 Note that this option causes behavior that is typically
                 reserved for routers and therefore is not entirely in
                 compliance with the IEEE 802.1D specification for bridges.
-                Default is enabled, set to <code>false</code> to disable.</dd>
+                Default is enabled; set to <code>false</code> to disable.</dd>
             </dl>
           </dd>
           <dt><code>capwap</code></dt>
                 (otherwise it will be the system default, typically 64).
                 Default is the system default TTL.</dd>
             </dl>
+            <dl>
+              <dt><code>df_inherit</code></dt>
+              <dd>Optional.  If enabled, the Don't Fragment bit will be copied
+                from the inner IP headers (those of the encapsulated traffic)
+                to the outer (tunnel) headers.  Default is disabled; set to
+                <code>true</code> to enable.</dd>
+            </dl>
+            <dl>
+              <dt><code>df_default</code></dt>
+              <dd>Optional.  If enabled, the Don't Fragment bit will be set by
+                default on tunnel headers if the <code>df_inherit</code> option
+                is not set, or if the encapsulated packet is not IP.  Default
+                is enabled; set to <code>false</code> to disable.</dd>
+            </dl>
             <dl>
               <dt><code>pmtud</code></dt>
               <dd>Optional.  Enable tunnel path MTU discovery.  If enabled
-                ``ICMP destination unreachable - fragmentation'' needed
+                ``ICMP Destination Unreachable - Fragmentation Needed''
                 messages will be generated for IPv4 packets with the DF bit set
                 and IPv6 packets above the minimum MTU if the packet size
-                exceeds the path MTU minus the size of the tunnel headers.  It
-                also forces the encapsulating packet DF bit to be set (it is
-                always set if the inner packet implies path MTU discovery).
+                exceeds the path MTU minus the size of the tunnel headers.
                 Note that this option causes behavior that is typically
                 reserved for routers and therefore is not entirely in
                 compliance with the IEEE 802.1D specification for bridges.
-                Default is enabled, set to <code>false</code> to disable.</dd>
+                Default is enabled; set to <code>false</code> to disable.</dd>
             </dl>
             <dl>
               <dt><code>header_cache</code></dt>
               </dd>
             </dl>
           </dd>
+          <dt><code>null</code></dt>
+          <dd>An ignored interface.</dd>
         </dl>
       </column>
 
       <column name="other_config">
         Key-value pairs for rarely used interface features.
         <dl>
+          <dt><code>bond-stable-id</code></dt>
+          <dd> A positive integer using in <code>stable</code> bond mode to
+            make slave selection decisions.  Allocating
+            <code>bond-stable-id</code>s consistently across interfaces
+            participating in a bond will guarantee consistent slave selection
+            decisions across ovs-vswitchd instances when using
+            <code>stable</code> bonding mode.</dd>
           <dt><code>lacp-port-id</code></dt>
           <dd> The LACP port ID of this <ref table="Interface"/>.  Port IDs are
             used in LACP negotiations to identify individual ports
             LACP negotiations <ref table="Interface"/>s with numerically lower
             priorities are preferred for aggregation.  Must be a number between
             1 and 65535.</dd>
+          <dt><code>lacp-aggregation-key</code></dt>
+          <dd> The LACP aggregation key of this <ref table="Interface"/>.
+            <ref table="Interface"/>s with different aggregation keys may not
+            be active within a given <ref table="Port"/> at the same time. Must
+            be a number between 1 and 65535.</dd>
         </dl>
       </column>
 
index c428fc6..9d686ce 100644 (file)
@@ -112,8 +112,8 @@ install -m 644 \
         xenserver/usr_lib_xsconsole_plugins-base_XSFeatureVSwitch.py \
                $RPM_BUILD_ROOT/usr/lib/xsconsole/plugins-base/XSFeatureVSwitch.py
 
-install -d -m 755 $RPM_BUILD_ROOT/lib/modules/%{xen_version}/kernel/extra/openvswitch
-find datapath/linux-2.6 -name *.ko -exec install -m 755  \{\} $RPM_BUILD_ROOT/lib/modules/%{xen_version}/kernel/extra/openvswitch \;
+install -d -m 755 $RPM_BUILD_ROOT/lib/modules/%{xen_version}/extra/openvswitch
+find datapath/linux-2.6 -name *.ko -exec install -m 755  \{\} $RPM_BUILD_ROOT/lib/modules/%{xen_version}/extra/openvswitch \;
 install xenserver/uuid.py $RPM_BUILD_ROOT/usr/share/openvswitch/python
 
 # Get rid of stuff we don't want to make RPM happy.
@@ -224,15 +224,10 @@ for s in openvswitch openvswitch-xapi-update; do
     chkconfig $s on || printf "Could not enable $s init script."
 done
 
-if [ "$1" = "1" ]; then    # $1 = 2 for upgrade
+if [ "$1" = "1" ]; then    # $1 = 1 for install
     # Configure system to use Open vSwitch
-    echo vswitch > /etc/xensource/network.conf
-
-    printf "\nYou MUST reboot the server NOW to complete the change to\n"
-    printf "Open vSwitch.  Attempts to modify networking on the server\n"
-    printf "or any hosted VM will fail until after the reboot and could\n"
-    printf "leave the server in a state requiring manual recovery.\n\n"
-else
+    /opt/xensource/bin/xe-switch-network-backend vswitch
+else    # $1 = 2 for upgrade
 
     mode=$(cat /etc/xensource/network.conf)
     if [ "$mode" != "vswitch" ] && [ "$mode" != "openvswitch" ]; then
@@ -252,9 +247,16 @@ fi
 depmod %{xen_version}
 
 %preun
-if [ "$1" = "0" ]; then     # $1 = 1 for upgrade
+if [ "$1" = "0" ]; then     # $1 = 0 for uninstall
+    # Configure system to use bridge
+    /opt/xensource/bin/xe-switch-network-backend bridge
+
+    # The "openvswitch" service should have been removed from
+    # "xe-switch-network-backend bridge".
     for s in openvswitch openvswitch-xapi-update; do
-        chkconfig --del $s || printf "Could not remove $s init script."
+        if chkconfig --list $s >/dev/null 2>&1; then
+            chkconfig --del $s || printf "Could not remove $s init script."
+        fi
     done
 fi
 
@@ -290,7 +292,7 @@ do
     fi
 done
 
-if [ "$1" = "0" ]; then     # $1 = 1 for upgrade
+if [ "$1" = "0" ]; then     # $1 = 0 for uninstall
     rm -f /usr/lib/xsconsole/plugins-base/XSFeatureVSwitch.pyc \
         /usr/lib/xsconsole/plugins-base/XSFeatureVSwitch.pyo
 
@@ -305,20 +307,13 @@ if [ "$1" = "0" ]; then     # $1 = 1 for upgrade
     rm -f /etc/openvswitch/conf.db
     rm -f /etc/sysconfig/openvswitch
     rm -f /etc/openvswitch/vswitchd.cacert
-    rm -f /var/xapi/network.dbcache
 
     # Remove saved XenServer scripts directory, but only if it's empty
     rmdir -p /usr/lib/openvswitch/xs-saved 2>/dev/null
-
-    # Configure system to use bridge
-    echo bridge > /etc/xensource/network.conf
-
-    printf "\nYou MUST reboot the server now to complete the change to\n"
-    printf "standard Xen networking.  Attempts to modify networking on the\n"
-    printf "server or any hosted VM will fail until after the reboot and\n"
-    printf "could leave the server in a state requiring manual recovery.\n\n"
 fi
 
+exit 0
+
 %files
 %defattr(-,root,root)
 /etc/init.d/openvswitch
@@ -397,5 +392,5 @@ fi
 %exclude /usr/share/openvswitch/python/ovs/db/*.py[co]
 
 %files %{module_package}
-/lib/modules/%{xen_version}/kernel/extra/openvswitch/openvswitch_mod.ko
-%exclude /lib/modules/%{xen_version}/kernel/extra/openvswitch/brcompat_mod.ko
+/lib/modules/%{xen_version}/extra/openvswitch/openvswitch_mod.ko
+%exclude /lib/modules/%{xen_version}/extra/openvswitch/brcompat_mod.ko