Merge 'next' into 'master'.
authorBen Pfaff <blp@nicira.com>
Wed, 18 May 2011 21:01:13 +0000 (14:01 -0700)
committerBen Pfaff <blp@nicira.com>
Wed, 18 May 2011 21:01:13 +0000 (14:01 -0700)
I know already that this breaks the statsfixes that were implemented by the
following commits:

827ab71c97f "ofproto: Datapath statistics accounted twice."
6f1435fc8f7 "ofproto: Resubmit statistics improperly account during..."

These were already broken in a previous merge.  I will work on a fix.

107 files changed:
AUTHORS
acinclude.m4
configure.ac
datapath/actions.c
datapath/datapath.c
datapath/flow.c
datapath/flow.h
datapath/table.c
datapath/table.h
datapath/tunnel.c
debian/ovs-bugtool
include/automake.mk
include/openflow/openflow.h
include/openvswitch/types.h
include/sparse/arpa/inet.h [new file with mode: 0644]
include/sparse/assert.h [new file with mode: 0644]
include/sparse/automake.mk [new file with mode: 0644]
include/sparse/math.h [new file with mode: 0644]
include/sparse/netinet/in.h [new file with mode: 0644]
include/sparse/netinet/ip6.h [new file with mode: 0644]
include/sparse/sys/socket.h [new file with mode: 0644]
include/sparse/sys/wait.h [new file with mode: 0644]
lib/backtrace.c
lib/bond.c
lib/byte-order.h
lib/cfm.c
lib/cfm.h
lib/compiler.h
lib/coverage.h
lib/csum.c
lib/csum.h
lib/daemon.h
lib/dpif-linux.c
lib/dpif-netdev.c
lib/flow.c
lib/flow.h
lib/json.c
lib/jsonrpc.c
lib/leak-checker.h
lib/lockfile.c
lib/netdev-linux.c
lib/netdev-vport.c
lib/netdev.c
lib/netdev.h
lib/nx-match.c
lib/ofp-print.c
lib/ofp-util.c
lib/ofp-util.h
lib/packets.h
lib/poll-loop.c
lib/poll-loop.h
lib/rconn.c
lib/rtnetlink.c
lib/sflow_receiver.c
lib/socket-util.c
lib/socket-util.h
lib/stream-ssl.c
lib/stream-ssl.h
lib/stress.h
lib/table.h
lib/timer.c
lib/timer.h
lib/unaligned.h
lib/util.h
lib/vlog.h
m4/openvswitch.m4
ofproto/netflow.c
ofproto/ofproto-dpif.c
ofproto/ofproto-sflow.c
ofproto/ofproto.c
ovsdb/execution.c
ovsdb/jsonrpc-server.c
ovsdb/log.c
ovsdb/ovsdb-client.c
ovsdb/ovsdb-server.c
ovsdb/ovsdb-tool.c
ovsdb/ovsdb.c
ovsdb/table.c
tests/autopath.at
tests/daemon-py.at
tests/daemon.at
tests/jsonrpc-py.at
tests/jsonrpc.at
tests/library.at
tests/ofp-print.at
tests/ofproto-macros.at
tests/ovs-ofctl.at
tests/ovsdb-log.at
tests/ovsdb-server.at
tests/test-byte-order.c
tests/test-csum.c
tests/test-jsonrpc.c
tests/test-lockfile.c
tests/test-ovsdb.c
tests/test-sha1.c
tests/test-strtok_r.c
tests/test-vconn.c
utilities/ovs-appctl.c
utilities/ovs-controller.c
utilities/ovs-dpctl.c
utilities/ovs-ofctl.c
utilities/ovs-openflowd.c
utilities/ovs-vlan-bug-workaround.c
utilities/ovs-vsctl.c
vswitchd/bridge.c
vswitchd/ovs-brcompatd.c
vswitchd/ovs-vswitchd.c

diff --git a/AUTHORS b/AUTHORS
index 1aa1cb3..b7f6cf5 100644 (file)
--- a/AUTHORS
+++ b/AUTHORS
@@ -26,6 +26,7 @@ Paul Fazzone            pfazzone@nicira.com
 Reid Price              reid@nicira.com
 Romain Lenglet          romain.lenglet@berabera.info
 Sajjad Lateef           slateef@nicira.com
+Shih-Hao Li             shli@nicira.com
 Simon Horman            horms@verge.net.au
 Tetsuo NAKAGAWA         nakagawa@mxc.nes.nec.co.jp
 Thomas Lacroix          thomas.lacroix@citrix.com
index 69e61e0..3cf793d 100644 (file)
@@ -347,3 +347,38 @@ AC_DEFUN([OVS_CHECK_XENSERVER_VERSION],
       AC_MSG_ERROR([This appears to be XenServer $ovs_cv_xsversion, but only XenServer 5.6.100 or later is supported.  (If you are really using a supported version of XenServer, you may override this error message by specifying 'ovs_cv_xsversion=5.6.100' on the "configure" command line.)])
       ;;
   esac])
+
+dnl OVS_MAKE_HAS_IF([if-true], [if-false])
+dnl
+dnl Checks whether make has the GNU make $(if condition,then,else) extension.
+dnl Runs 'if-true' if so, 'if-false' otherwise.
+AC_DEFUN([OVS_MAKE_HAS_IF],
+  [AC_CACHE_CHECK(
+     [whether ${MAKE-make} has GNU make \$(if) extension],
+     [ovs_cv_gnu_make_if],
+     [cat <<'EOF' > conftest.mk
+conftest.out:
+       echo $(if x,y,z) > conftest.out
+.PHONY: all
+EOF
+      rm -f conftest.out
+      AS_ECHO(["$as_me:$LINENO: invoking ${MAKE-make} -f conftest.mk all:"]) >&AS_MESSAGE_LOG_FD 2>&1
+      ${MAKE-make} -f conftest.mk conftest.out >&AS_MESSAGE_LOG_FD 2>&1
+      AS_ECHO(["$as_me:$LINENO: conftest.out contains:"]) >&AS_MESSAGE_LOG_FD 2>&1
+      cat conftest.out >&AS_MESSAGE_LOG_FD 2>&1
+      result=`cat conftest.out`
+      rm -f conftest.mk conftest.out
+      if test "X$result" = "Xy"; then
+        ovs_cv_gnu_make_if=yes
+      else
+        ovs_cv_gnu_make_if=no
+      fi])
+   AS_IF([test $ovs_cv_gnu_make_if = yes], [$1], [$2])])
+
+dnl OVS_ENABLE_SPARSE
+AC_DEFUN([OVS_ENABLE_SPARSE],
+  [OVS_MAKE_HAS_IF(
+     [AC_CONFIG_COMMANDS_PRE(
+        [: ${SPARSE=sparse}
+         AC_SUBST([SPARSE])
+         CC='$(if $(C),REAL_CC="'"$CC"'" CHECK="$(SPARSE) -I $(top_srcdir)/include/sparse" cgcc,'"$CC"')'])])])
index 5b5f47e..dde42e0 100644 (file)
@@ -61,6 +61,7 @@ AC_CHECK_HEADERS([mntent.h sys/statvfs.h])
 
 OVS_CHECK_PKIDIR
 OVS_CHECK_RUNDIR
+OVS_CHECK_BACKTRACE
 OVS_CHECK_MALLOC_HOOKS
 OVS_CHECK_VALGRIND
 OVS_CHECK_SOCKET_LIBS
@@ -85,6 +86,7 @@ OVS_ENABLE_OPTION([-Wno-override-init])
 OVS_CONDITIONAL_CC_OPTION([-Wno-unused], [HAVE_WNO_UNUSED])
 OVS_CONDITIONAL_CC_OPTION([-Wno-unused-parameter], [HAVE_WNO_UNUSED_PARAMETER])
 OVS_ENABLE_WERROR
+OVS_ENABLE_SPARSE
 
 AC_ARG_VAR(KARCH, [Kernel Architecture String])
 AC_SUBST(KARCH)
index b6b7135..c578cc4 100644 (file)
@@ -114,13 +114,13 @@ static struct sk_buff *modify_vlan_tci(struct sk_buff *skb, __be16 tci)
 
 static bool is_ip(struct sk_buff *skb)
 {
-       return (OVS_CB(skb)->flow->key.dl_type == htons(ETH_P_IP) &&
+       return (OVS_CB(skb)->flow->key.eth.type == htons(ETH_P_IP) &&
                skb->transport_header > skb->network_header);
 }
 
 static __sum16 *get_l4_checksum(struct sk_buff *skb)
 {
-       u8 nw_proto = OVS_CB(skb)->flow->key.nw_proto;
+       u8 nw_proto = OVS_CB(skb)->flow->key.ip.nw_proto;
        int transport_len = skb->len - skb_transport_offset(skb);
        if (nw_proto == IPPROTO_TCP) {
                if (likely(transport_len >= sizeof(struct tcphdr)))
@@ -230,7 +230,7 @@ static bool is_spoofed_arp(struct sk_buff *skb)
 {
        struct arp_eth_header *arp;
 
-       if (OVS_CB(skb)->flow->key.dl_type != htons(ETH_P_ARP))
+       if (OVS_CB(skb)->flow->key.eth.type != htons(ETH_P_ARP))
                return false;
 
        if (skb_network_offset(skb) + sizeof(struct arp_eth_header) > skb->len)
index fc00d78..826d899 100644 (file)
@@ -273,10 +273,11 @@ void dp_process_received_packet(struct vport *p, struct sk_buff *skb)
        if (!OVS_CB(skb)->flow) {
                struct sw_flow_key key;
                struct tbl_node *flow_node;
+               int key_len;
                bool is_frag;
 
                /* Extract flow from 'skb' into 'key'. */
-               error = flow_extract(skb, p->port_no, &key, &is_frag);
+               error = flow_extract(skb, p->port_no, &key, &key_len, &is_frag);
                if (unlikely(error)) {
                        kfree_skb(skb);
                        return;
@@ -289,8 +290,8 @@ void dp_process_received_packet(struct vport *p, struct sk_buff *skb)
                }
 
                /* Look up flow. */
-               flow_node = tbl_lookup(rcu_dereference(dp->table), &key,
-                                       flow_hash(&key), flow_cmp);
+               flow_node = tbl_lookup(rcu_dereference(dp->table), &key, key_len,
+                                      flow_hash(&key, key_len), flow_cmp);
                if (unlikely(!flow_node)) {
                        struct dp_upcall_info upcall;
 
@@ -651,6 +652,7 @@ static int odp_packet_cmd_execute(struct sk_buff *skb, struct genl_info *info)
        bool is_frag;
        int len;
        int err;
+       int key_len;
 
        err = -EINVAL;
        if (!a[ODP_PACKET_ATTR_PACKET] || !a[ODP_PACKET_ATTR_ACTIONS] ||
@@ -687,10 +689,10 @@ static int odp_packet_cmd_execute(struct sk_buff *skb, struct genl_info *info)
        if (IS_ERR(flow))
                goto err_kfree_skb;
 
-       err = flow_extract(packet, -1, &flow->key, &is_frag);
+       err = flow_extract(packet, -1, &flow->key, &key_len, &is_frag);
        if (err)
                goto err_flow_put;
-       flow->tbl_node.hash = flow_hash(&flow->key);
+       flow->tbl_node.hash = flow_hash(&flow->key, key_len);
 
        acts = flow_actions_alloc(a[ODP_PACKET_ATTR_ACTIONS]);
        err = PTR_ERR(acts);
@@ -935,12 +937,13 @@ static int odp_flow_cmd_new_or_set(struct sk_buff *skb, struct genl_info *info)
        struct tbl *table;
        u32 hash;
        int error;
+       int key_len;
 
        /* Extract key. */
        error = -EINVAL;
        if (!a[ODP_FLOW_ATTR_KEY])
                goto error;
-       error = flow_from_nlattrs(&key, a[ODP_FLOW_ATTR_KEY]);
+       error = flow_from_nlattrs(&key, &key_len, a[ODP_FLOW_ATTR_KEY]);
        if (error)
                goto error;
 
@@ -959,9 +962,9 @@ static int odp_flow_cmd_new_or_set(struct sk_buff *skb, struct genl_info *info)
        if (!dp)
                goto error;
 
-       hash = flow_hash(&key);
+       hash = flow_hash(&key, key_len);
        table = get_table_protected(dp);
-       flow_node = tbl_lookup(table, &key, hash, flow_cmp);
+       flow_node = tbl_lookup(table, &key, key_len, hash, flow_cmp);
        if (!flow_node) {
                struct sw_flow_actions *acts;
 
@@ -1071,10 +1074,11 @@ static int odp_flow_cmd_get(struct sk_buff *skb, struct genl_info *info)
        struct datapath *dp;
        struct tbl *table;
        int err;
+       int key_len;
 
        if (!a[ODP_FLOW_ATTR_KEY])
                return -EINVAL;
-       err = flow_from_nlattrs(&key, a[ODP_FLOW_ATTR_KEY]);
+       err = flow_from_nlattrs(&key, &key_len, a[ODP_FLOW_ATTR_KEY]);
        if (err)
                return err;
 
@@ -1083,7 +1087,8 @@ static int odp_flow_cmd_get(struct sk_buff *skb, struct genl_info *info)
                return -ENODEV;
 
        table = get_table_protected(dp);
-       flow_node = tbl_lookup(table, &key, flow_hash(&key), flow_cmp);
+       flow_node = tbl_lookup(table, &key, key_len, flow_hash(&key, key_len),
+                              flow_cmp);
        if (!flow_node)
                return -ENOENT;
 
@@ -1106,10 +1111,11 @@ static int odp_flow_cmd_del(struct sk_buff *skb, struct genl_info *info)
        struct datapath *dp;
        struct tbl *table;
        int err;
+       int key_len;
 
        if (!a[ODP_FLOW_ATTR_KEY])
                return flush_flows(odp_header->dp_ifindex);
-       err = flow_from_nlattrs(&key, a[ODP_FLOW_ATTR_KEY]);
+       err = flow_from_nlattrs(&key, &key_len, a[ODP_FLOW_ATTR_KEY]);
        if (err)
                return err;
 
@@ -1118,7 +1124,8 @@ static int odp_flow_cmd_del(struct sk_buff *skb, struct genl_info *info)
                return -ENODEV;
 
        table = get_table_protected(dp);
-       flow_node = tbl_lookup(table, &key, flow_hash(&key), flow_cmp);
+       flow_node = tbl_lookup(table, &key, key_len, flow_hash(&key, key_len),
+                              flow_cmp);
        if (!flow_node)
                return -ENOENT;
        flow = flow_cast(flow_node);
index d678979..2b80c6d 100644 (file)
@@ -114,7 +114,12 @@ u64 flow_used_time(unsigned long flow_jiffies)
        return cur_ms - idle_ms;
 }
 
-static int parse_ipv6hdr(struct sk_buff *skb, struct sw_flow_key *key)
+#define SW_FLOW_KEY_OFFSET(field)              \
+       offsetof(struct sw_flow_key, field) +   \
+       FIELD_SIZEOF(struct sw_flow_key, field)
+
+static int parse_ipv6hdr(struct sk_buff *skb, struct sw_flow_key *key,
+                        int *key_lenp)
 {
        unsigned int nh_ofs = skb_network_offset(skb);
        unsigned int nh_len;
@@ -123,6 +128,8 @@ static int parse_ipv6hdr(struct sk_buff *skb, struct sw_flow_key *key)
        uint8_t nexthdr;
        int err;
 
+       *key_lenp = SW_FLOW_KEY_OFFSET(ipv6.addr);
+
        err = check_header(skb, nh_ofs + sizeof(*nh));
        if (unlikely(err))
                return err;
@@ -131,10 +138,10 @@ static int parse_ipv6hdr(struct sk_buff *skb, struct sw_flow_key *key)
        nexthdr = nh->nexthdr;
        payload_ofs = (u8 *)(nh + 1) - skb->data;
 
-       ipv6_addr_copy(&key->ipv6_src, &nh->saddr);
-       ipv6_addr_copy(&key->ipv6_dst, &nh->daddr);
-       key->nw_tos = ipv6_get_dsfield(nh) & ~INET_ECN_MASK;
-       key->nw_proto = NEXTHDR_NONE;
+       key->ip.nw_proto = NEXTHDR_NONE;
+       key->ip.nw_tos = ipv6_get_dsfield(nh) & ~INET_ECN_MASK;
+       ipv6_addr_copy(&key->ipv6.addr.src, &nh->saddr);
+       ipv6_addr_copy(&key->ipv6.addr.dst, &nh->daddr);
 
        payload_ofs = ipv6_skip_exthdr(skb, payload_ofs, &nexthdr);
        if (unlikely(payload_ofs < 0))
@@ -142,7 +149,7 @@ static int parse_ipv6hdr(struct sk_buff *skb, struct sw_flow_key *key)
 
        nh_len = payload_ofs - nh_ofs;
        skb_set_transport_header(skb, nh_ofs + nh_len);
-       key->nw_proto = nexthdr;
+       key->ip.nw_proto = nexthdr;
        return nh_len;
 }
 
@@ -159,8 +166,8 @@ void flow_used(struct sw_flow *flow, struct sk_buff *skb)
 {
        u8 tcp_flags = 0;
 
-       if (flow->key.dl_type == htons(ETH_P_IP) &&
-           flow->key.nw_proto == IPPROTO_TCP) {
+       if (flow->key.eth.type == htons(ETH_P_IP) &&
+           flow->key.ip.nw_proto == IPPROTO_TCP) {
                u8 *tcp = (u8 *)tcp_hdr(skb);
                tcp_flags = *(tcp + TCP_FLAGS_OFFSET) & TCP_FLAG_MASK;
        }
@@ -277,7 +284,7 @@ static int parse_vlan(struct sk_buff *skb, struct sw_flow_key *key)
                return -ENOMEM;
 
        qp = (struct qtag_prefix *) skb->data;
-       key->dl_tci = qp->tci | htons(VLAN_TAG_PRESENT);
+       key->eth.tci = qp->tci | htons(VLAN_TAG_PRESENT);
        __skb_pull(skb, sizeof(struct qtag_prefix));
 
        return 0;
@@ -318,15 +325,18 @@ static __be16 parse_ethertype(struct sk_buff *skb)
 }
 
 static int parse_icmpv6(struct sk_buff *skb, struct sw_flow_key *key,
-                       int nh_len)
+                       int *key_lenp, int nh_len)
 {
        struct icmp6hdr *icmp = icmp6_hdr(skb);
+       int error = 0;
+       int key_len;
 
        /* The ICMPv6 type and code fields use the 16-bit transport port
         * fields, so we need to store them in 16-bit network byte order.
         */
-       key->tp_src = htons(icmp->icmp6_type);
-       key->tp_dst = htons(icmp->icmp6_code);
+       key->ipv6.tp.src = htons(icmp->icmp6_type);
+       key->ipv6.tp.dst = htons(icmp->icmp6_code);
+       key_len = SW_FLOW_KEY_OFFSET(ipv6.tp);
 
        if (icmp->icmp6_code == 0 &&
            (icmp->icmp6_type == NDISC_NEIGHBOUR_SOLICITATION ||
@@ -335,16 +345,21 @@ static int parse_icmpv6(struct sk_buff *skb, struct sw_flow_key *key,
                struct nd_msg *nd;
                int offset;
 
+               key_len = SW_FLOW_KEY_OFFSET(ipv6.nd);
+
                /* In order to process neighbor discovery options, we need the
                 * entire packet.
                 */
                if (unlikely(icmp_len < sizeof(*nd)))
-                       return 0;
-               if (unlikely(skb_linearize(skb)))
-                       return -ENOMEM;
+                       goto out;
+               if (unlikely(skb_linearize(skb))) {
+                       error = -ENOMEM;
+                       goto out;
+               }
 
                nd = (struct nd_msg *)skb_transport_header(skb);
-               ipv6_addr_copy(&key->nd_target, &nd->target);
+               ipv6_addr_copy(&key->ipv6.nd.target, &nd->target);
+               key_len = SW_FLOW_KEY_OFFSET(ipv6.nd);
 
                icmp_len -= sizeof(*nd);
                offset = 0;
@@ -361,15 +376,15 @@ static int parse_icmpv6(struct sk_buff *skb, struct sw_flow_key *key,
                         */
                        if (nd_opt->nd_opt_type == ND_OPT_SOURCE_LL_ADDR
                            && opt_len == 8) {
-                               if (unlikely(!is_zero_ether_addr(key->arp_sha)))
+                               if (unlikely(!is_zero_ether_addr(key->ipv6.nd.sll)))
                                        goto invalid;
-                               memcpy(key->arp_sha,
+                               memcpy(key->ipv6.nd.sll,
                                    &nd->opt[offset+sizeof(*nd_opt)], ETH_ALEN);
                        } else if (nd_opt->nd_opt_type == ND_OPT_TARGET_LL_ADDR
                                   && opt_len == 8) {
-                               if (unlikely(!is_zero_ether_addr(key->arp_tha)))
+                               if (unlikely(!is_zero_ether_addr(key->ipv6.nd.tll)))
                                        goto invalid;
-                               memcpy(key->arp_tha,
+                               memcpy(key->ipv6.nd.tll,
                                    &nd->opt[offset+sizeof(*nd_opt)], ETH_ALEN);
                        }
 
@@ -378,14 +393,16 @@ static int parse_icmpv6(struct sk_buff *skb, struct sw_flow_key *key,
                }
        }
 
-       return 0;
+       goto out;
 
 invalid:
-       memset(&key->nd_target, 0, sizeof(key->nd_target));
-       memset(key->arp_sha, 0, sizeof(key->arp_sha));
-       memset(key->arp_tha, 0, sizeof(key->arp_tha));
+       memset(&key->ipv6.nd.target, 0, sizeof(key->ipv6.nd.target));
+       memset(key->ipv6.nd.sll, 0, sizeof(key->ipv6.nd.sll));
+       memset(key->ipv6.nd.tll, 0, sizeof(key->ipv6.nd.tll));
 
-       return 0;
+out:
+       *key_lenp = key_len;
+       return error;
 }
 
 /**
@@ -394,6 +411,7 @@ invalid:
  * Ethernet header
  * @in_port: port number on which @skb was received.
  * @key: output flow key
+ * @key_lenp: length of output flow key
  * @is_frag: set to 1 if @skb contains an IPv4 fragment, or to 0 if @skb does
  * not contain an IPv4 packet or if it is not a fragment.
  *
@@ -414,13 +432,15 @@ invalid:
  *      For other key->dl_type values it is left untouched.
  */
 int flow_extract(struct sk_buff *skb, u16 in_port, struct sw_flow_key *key,
-                bool *is_frag)
+                int *key_lenp, bool *is_frag)
 {
+       int error = 0;
+       int key_len = SW_FLOW_KEY_OFFSET(eth);
        struct ethhdr *eth;
 
        memset(key, 0, sizeof(*key));
-       key->tun_id = OVS_CB(skb)->tun_id;
-       key->in_port = in_port;
+       key->eth.tun_id = OVS_CB(skb)->tun_id;
+       key->eth.in_port = in_port;
        *is_frag = false;
 
        skb_reset_mac_header(skb);
@@ -429,72 +449,77 @@ int flow_extract(struct sk_buff *skb, u16 in_port, struct sw_flow_key *key,
         * 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);
+       memcpy(key->eth.src, eth->h_source, ETH_ALEN);
+       memcpy(key->eth.dst, eth->h_dest, ETH_ALEN);
+
        __skb_pull(skb, 2 * ETH_ALEN);
 
        if (vlan_tx_tag_present(skb))
-               key->dl_tci = htons(vlan_get_tci(skb));
+               key->eth.tci = htons(vlan_get_tci(skb));
        else if (eth->h_proto == htons(ETH_P_8021Q))
                if (unlikely(parse_vlan(skb, key)))
                        return -ENOMEM;
 
-       key->dl_type = parse_ethertype(skb);
-       if (unlikely(key->dl_type == htons(0)))
+       key->eth.type = parse_ethertype(skb);
+       if (unlikely(key->eth.type == htons(0)))
                return -ENOMEM;
 
        skb_reset_network_header(skb);
        __skb_push(skb, skb->data - skb_mac_header(skb));
 
        /* Network layer. */
-       if (key->dl_type == htons(ETH_P_IP)) {
+       if (key->eth.type == htons(ETH_P_IP)) {
                struct iphdr *nh;
-               int error;
+
+               key_len = SW_FLOW_KEY_OFFSET(ipv4.addr);
 
                error = check_iphdr(skb);
                if (unlikely(error)) {
                        if (error == -EINVAL) {
                                skb->transport_header = skb->network_header;
-                               return 0;
+                               error = 0;
                        }
-                       return error;
+                       goto out;
                }
 
                nh = ip_hdr(skb);
-               key->ipv4_src = nh->saddr;
-               key->ipv4_dst = nh->daddr;
-               key->nw_tos = nh->tos & ~INET_ECN_MASK;
-               key->nw_proto = nh->protocol;
+               key->ipv4.addr.src = nh->saddr;
+               key->ipv4.addr.dst = nh->daddr;
+               key->ip.nw_tos = nh->tos & ~INET_ECN_MASK;
+               key->ip.nw_proto = nh->protocol;
 
                /* Transport layer. */
                if (!(nh->frag_off & htons(IP_MF | IP_OFFSET)) &&
                    !(skb_shinfo(skb)->gso_type & SKB_GSO_UDP)) {
-                       if (key->nw_proto == IPPROTO_TCP) {
+                       if (key->ip.nw_proto == IPPROTO_TCP) {
+                               key_len = SW_FLOW_KEY_OFFSET(ipv4.tp);
                                if (tcphdr_ok(skb)) {
                                        struct tcphdr *tcp = tcp_hdr(skb);
-                                       key->tp_src = tcp->source;
-                                       key->tp_dst = tcp->dest;
+                                       key->ipv4.tp.src = tcp->source;
+                                       key->ipv4.tp.dst = tcp->dest;
                                }
-                       } else if (key->nw_proto == IPPROTO_UDP) {
+                       } else if (key->ip.nw_proto == IPPROTO_UDP) {
+                               key_len = SW_FLOW_KEY_OFFSET(ipv4.tp);
                                if (udphdr_ok(skb)) {
                                        struct udphdr *udp = udp_hdr(skb);
-                                       key->tp_src = udp->source;
-                                       key->tp_dst = udp->dest;
+                                       key->ipv4.tp.src = udp->source;
+                                       key->ipv4.tp.dst = udp->dest;
                                }
-                       } else if (key->nw_proto == IPPROTO_ICMP) {
+                       } else if (key->ip.nw_proto == IPPROTO_ICMP) {
+                               key_len = SW_FLOW_KEY_OFFSET(ipv4.tp);
                                if (icmphdr_ok(skb)) {
                                        struct icmphdr *icmp = icmp_hdr(skb);
                                        /* The ICMP type and code fields use the 16-bit
                                         * transport port fields, so we need to store them
                                         * in 16-bit network byte order. */
-                                       key->tp_src = htons(icmp->type);
-                                       key->tp_dst = htons(icmp->code);
+                                       key->ipv4.tp.src = htons(icmp->type);
+                                       key->ipv4.tp.dst = htons(icmp->code);
                                }
                        }
                } else
                        *is_frag = true;
 
-       } else if (key->dl_type == htons(ETH_P_ARP) && arphdr_ok(skb)) {
+       } else if (key->eth.type == htons(ETH_P_ARP) && arphdr_ok(skb)) {
                struct arp_eth_header *arp;
 
                arp = (struct arp_eth_header *)skb_network_header(skb);
@@ -506,69 +531,77 @@ int flow_extract(struct sk_buff *skb, u16 in_port, struct sw_flow_key *key,
 
                        /* We only match on the lower 8 bits of the opcode. */
                        if (ntohs(arp->ar_op) <= 0xff)
-                               key->nw_proto = ntohs(arp->ar_op);
-
-                       if (key->nw_proto == ARPOP_REQUEST
-                                       || key->nw_proto == ARPOP_REPLY) {
-                               memcpy(&key->ipv4_src, arp->ar_sip, sizeof(key->ipv4_src));
-                               memcpy(&key->ipv4_dst, arp->ar_tip, sizeof(key->ipv4_dst));
-                               memcpy(key->arp_sha, arp->ar_sha, ETH_ALEN);
-                               memcpy(key->arp_tha, arp->ar_tha, ETH_ALEN);
+                               key->ip.nw_proto = ntohs(arp->ar_op);
+
+                       if (key->ip.nw_proto == ARPOP_REQUEST
+                                       || key->ip.nw_proto == ARPOP_REPLY) {
+                               memcpy(&key->ipv4.addr.src, arp->ar_sip, sizeof(key->ipv4.addr.src));
+                               memcpy(&key->ipv4.addr.dst, arp->ar_tip, sizeof(key->ipv4.addr.dst));
+                               memcpy(key->ipv4.arp.sha, arp->ar_sha, ETH_ALEN);
+                               memcpy(key->ipv4.arp.tha, arp->ar_tha, ETH_ALEN);
+                               key_len = SW_FLOW_KEY_OFFSET(ipv4.arp);
                        }
                }
-       } else if (key->dl_type == htons(ETH_P_IPV6)) {
+       } else if (key->eth.type == htons(ETH_P_IPV6)) {
                int nh_len;             /* IPv6 Header + Extensions */
 
-               nh_len = parse_ipv6hdr(skb, key);
+               nh_len = parse_ipv6hdr(skb, key, &key_len);
                if (unlikely(nh_len < 0)) {
-                       if (nh_len == -EINVAL) {
+                       if (nh_len == -EINVAL)
                                skb->transport_header = skb->network_header;
-                               return 0;
-                       }
-                       return nh_len;
+                       else
+                               error = nh_len;
+                       goto out;
                }
 
                /* Transport layer. */
-               if (key->nw_proto == NEXTHDR_TCP) {
+               if (key->ip.nw_proto == NEXTHDR_TCP) {
+                       key_len = SW_FLOW_KEY_OFFSET(ipv6.tp);
                        if (tcphdr_ok(skb)) {
                                struct tcphdr *tcp = tcp_hdr(skb);
-                               key->tp_src = tcp->source;
-                               key->tp_dst = tcp->dest;
+                               key->ipv6.tp.src = tcp->source;
+                               key->ipv6.tp.dst = tcp->dest;
                        }
-               } else if (key->nw_proto == NEXTHDR_UDP) {
+               } else if (key->ip.nw_proto == NEXTHDR_UDP) {
+                       key_len = SW_FLOW_KEY_OFFSET(ipv6.tp);
                        if (udphdr_ok(skb)) {
                                struct udphdr *udp = udp_hdr(skb);
-                               key->tp_src = udp->source;
-                               key->tp_dst = udp->dest;
+                               key->ipv6.tp.src = udp->source;
+                               key->ipv6.tp.dst = udp->dest;
                        }
-               } else if (key->nw_proto == NEXTHDR_ICMP) {
+               } else if (key->ip.nw_proto == NEXTHDR_ICMP) {
+                       key_len = SW_FLOW_KEY_OFFSET(ipv6.tp);
                        if (icmp6hdr_ok(skb)) {
-                               int error = parse_icmpv6(skb, key, nh_len);
+                               error = parse_icmpv6(skb, key, &key_len, nh_len);
                                if (error < 0)
-                                       return error;
+                                       goto out;
                        }
                }
        }
-       return 0;
+
+out:
+       *key_lenp = key_len;
+       return error;
 }
 
-u32 flow_hash(const struct sw_flow_key *key)
+u32 flow_hash(const struct sw_flow_key *key, int key_len)
 {
-       return jhash2((u32*)key, sizeof(*key) / sizeof(u32), hash_seed);
+       return jhash2((u32*)key, DIV_ROUND_UP(key_len, sizeof(u32)), hash_seed);
 }
 
-int flow_cmp(const struct tbl_node *node, void *key2_)
+int flow_cmp(const struct tbl_node *node, void *key2_, int len)
 {
        const struct sw_flow_key *key1 = &flow_cast(node)->key;
        const struct sw_flow_key *key2 = key2_;
 
-       return !memcmp(key1, key2, sizeof(struct sw_flow_key));
+       return !memcmp(key1, key2, len);
 }
 
 /**
  * flow_from_nlattrs - parses Netlink attributes into a flow key.
  * @swkey: receives the extracted flow key.
- * @key: Netlink attribute holding nested %ODP_KEY_ATTR_* Netlink attribute
+ * @key_lenp: number of bytes used in @swkey.
+ * @attr: Netlink attribute holding nested %ODP_KEY_ATTR_* Netlink attribute
  * sequence.
  *
  * This state machine accepts the following forms, with [] for optional
@@ -577,14 +610,18 @@ int flow_cmp(const struct tbl_node *node, void *key2_)
  * [tun_id] in_port ethernet [8021q] [ethertype \
  *              [IPv4 [TCP|UDP|ICMP] | IPv6 [TCP|UDP|ICMPv6 [ND]] | ARP]]
  */
-int flow_from_nlattrs(struct sw_flow_key *swkey, const struct nlattr *attr)
+int flow_from_nlattrs(struct sw_flow_key *swkey, int *key_lenp,
+                     const struct nlattr *attr)
 {
+       int error = 0;
        const struct nlattr *nla;
        u16 prev_type;
        int rem;
+       int key_len;
 
        memset(swkey, 0, sizeof(*swkey));
-       swkey->dl_type = htons(ETH_P_802_2);
+       swkey->eth.type = htons(ETH_P_802_2);
+       key_len = SW_FLOW_KEY_OFFSET(eth);
 
        prev_type = ODP_KEY_ATTR_UNSPEC;
        nla_for_each_nested(nla, attr, rem) {
@@ -618,185 +655,217 @@ int flow_from_nlattrs(struct sw_flow_key *swkey, const struct nlattr *attr)
                 int type = nla_type(nla);
 
                 if (type > ODP_KEY_ATTR_MAX || nla_len(nla) != key_lens[type])
-                        return -EINVAL;
+                        goto invalid;
 
 #define TRANSITION(PREV_TYPE, TYPE) (((PREV_TYPE) << 16) | (TYPE))
                switch (TRANSITION(prev_type, type)) {
                case TRANSITION(ODP_KEY_ATTR_UNSPEC, ODP_KEY_ATTR_TUN_ID):
-                       swkey->tun_id = nla_get_be64(nla);
+                       swkey->eth.tun_id = nla_get_be64(nla);
                        break;
 
                case TRANSITION(ODP_KEY_ATTR_UNSPEC, ODP_KEY_ATTR_IN_PORT):
                case TRANSITION(ODP_KEY_ATTR_TUN_ID, ODP_KEY_ATTR_IN_PORT):
                        if (nla_get_u32(nla) >= DP_MAX_PORTS)
-                               return -EINVAL;
-                       swkey->in_port = nla_get_u32(nla);
+                               goto invalid;
+                       swkey->eth.in_port = nla_get_u32(nla);
                        break;
 
                case TRANSITION(ODP_KEY_ATTR_IN_PORT, ODP_KEY_ATTR_ETHERNET):
                        eth_key = nla_data(nla);
-                       memcpy(swkey->dl_src, eth_key->eth_src, ETH_ALEN);
-                       memcpy(swkey->dl_dst, eth_key->eth_dst, ETH_ALEN);
+                       memcpy(swkey->eth.src, eth_key->eth_src, ETH_ALEN);
+                       memcpy(swkey->eth.dst, eth_key->eth_dst, ETH_ALEN);
                        break;
 
                case TRANSITION(ODP_KEY_ATTR_ETHERNET, ODP_KEY_ATTR_8021Q):
                        q_key = nla_data(nla);
                        /* Only standard 0x8100 VLANs currently supported. */
                        if (q_key->q_tpid != htons(ETH_P_8021Q))
-                               return -EINVAL;
+                               goto invalid;
                        if (q_key->q_tci & htons(VLAN_TAG_PRESENT))
-                               return -EINVAL;
-                       swkey->dl_tci = q_key->q_tci | htons(VLAN_TAG_PRESENT);
+                               goto invalid;
+                       swkey->eth.tci = q_key->q_tci | htons(VLAN_TAG_PRESENT);
                        break;
 
                case TRANSITION(ODP_KEY_ATTR_8021Q, ODP_KEY_ATTR_ETHERTYPE):
                case TRANSITION(ODP_KEY_ATTR_ETHERNET, ODP_KEY_ATTR_ETHERTYPE):
-                       swkey->dl_type = nla_get_be16(nla);
-                       if (ntohs(swkey->dl_type) < 1536)
-                               return -EINVAL;
+                       swkey->eth.type = nla_get_be16(nla);
+                       if (ntohs(swkey->eth.type) < 1536)
+                               goto invalid;
                        break;
 
                case TRANSITION(ODP_KEY_ATTR_ETHERTYPE, ODP_KEY_ATTR_IPV4):
-                       if (swkey->dl_type != htons(ETH_P_IP))
-                               return -EINVAL;
+                       key_len = SW_FLOW_KEY_OFFSET(ipv4.addr);
+                       if (swkey->eth.type != htons(ETH_P_IP))
+                               goto invalid;
                        ipv4_key = nla_data(nla);
-                       swkey->ipv4_src = ipv4_key->ipv4_src;
-                       swkey->ipv4_dst = ipv4_key->ipv4_dst;
-                       swkey->nw_proto = ipv4_key->ipv4_proto;
-                       swkey->nw_tos = ipv4_key->ipv4_tos;
-                       if (swkey->nw_tos & INET_ECN_MASK)
-                               return -EINVAL;
+                       swkey->ip.nw_proto = ipv4_key->ipv4_proto;
+                       swkey->ip.nw_tos = ipv4_key->ipv4_tos;
+                       swkey->ipv4.addr.src = ipv4_key->ipv4_src;
+                       swkey->ipv4.addr.dst = ipv4_key->ipv4_dst;
+                       if (swkey->ip.nw_tos & INET_ECN_MASK)
+                               goto invalid;
                        break;
 
                case TRANSITION(ODP_KEY_ATTR_ETHERTYPE, ODP_KEY_ATTR_IPV6):
-                       if (swkey->dl_type != htons(ETH_P_IPV6))
-                               return -EINVAL;
+                       key_len = SW_FLOW_KEY_OFFSET(ipv6.addr);
+                       if (swkey->eth.type != htons(ETH_P_IPV6))
+                               goto invalid;
                        ipv6_key = nla_data(nla);
-                       memcpy(&swkey->ipv6_src, ipv6_key->ipv6_src,
-                                       sizeof(swkey->ipv6_src));
-                       memcpy(&swkey->ipv6_dst, ipv6_key->ipv6_dst,
-                                       sizeof(swkey->ipv6_dst));
-                       swkey->nw_proto = ipv6_key->ipv6_proto;
-                       swkey->nw_tos = ipv6_key->ipv6_tos;
-                       if (swkey->nw_tos & INET_ECN_MASK)
-                               return -EINVAL;
+                       swkey->ip.nw_proto = ipv6_key->ipv6_proto;
+                       swkey->ip.nw_tos = ipv6_key->ipv6_tos;
+                       memcpy(&swkey->ipv6.addr.src, ipv6_key->ipv6_src,
+                                       sizeof(swkey->ipv6.addr.src));
+                       memcpy(&swkey->ipv6.addr.dst, ipv6_key->ipv6_dst,
+                                       sizeof(swkey->ipv6.addr.dst));
+                       if (swkey->ip.nw_tos & INET_ECN_MASK)
+                               goto invalid;
                        break;
 
                case TRANSITION(ODP_KEY_ATTR_IPV4, ODP_KEY_ATTR_TCP):
+                       key_len = SW_FLOW_KEY_OFFSET(ipv4.tp);
+                       if (swkey->ip.nw_proto != IPPROTO_TCP)
+                               goto invalid;
+                       tcp_key = nla_data(nla);
+                       swkey->ipv4.tp.src = tcp_key->tcp_src;
+                       swkey->ipv4.tp.dst = tcp_key->tcp_dst;
+                       break;
+
                case TRANSITION(ODP_KEY_ATTR_IPV6, ODP_KEY_ATTR_TCP):
-                       if (swkey->nw_proto != IPPROTO_TCP)
-                               return -EINVAL;
+                       key_len = SW_FLOW_KEY_OFFSET(ipv6.tp);
+                       if (swkey->ip.nw_proto != IPPROTO_TCP)
+                               goto invalid;
                        tcp_key = nla_data(nla);
-                       swkey->tp_src = tcp_key->tcp_src;
-                       swkey->tp_dst = tcp_key->tcp_dst;
+                       swkey->ipv6.tp.src = tcp_key->tcp_src;
+                       swkey->ipv6.tp.dst = tcp_key->tcp_dst;
                        break;
 
                case TRANSITION(ODP_KEY_ATTR_IPV4, ODP_KEY_ATTR_UDP):
+                       key_len = SW_FLOW_KEY_OFFSET(ipv4.tp);
+                       if (swkey->ip.nw_proto != IPPROTO_UDP)
+                               goto invalid;
+                       udp_key = nla_data(nla);
+                       swkey->ipv4.tp.src = udp_key->udp_src;
+                       swkey->ipv4.tp.dst = udp_key->udp_dst;
+                       break;
+
                case TRANSITION(ODP_KEY_ATTR_IPV6, ODP_KEY_ATTR_UDP):
-                       if (swkey->nw_proto != IPPROTO_UDP)
-                               return -EINVAL;
+                       key_len = SW_FLOW_KEY_OFFSET(ipv6.tp);
+                       if (swkey->ip.nw_proto != IPPROTO_UDP)
+                               goto invalid;
                        udp_key = nla_data(nla);
-                       swkey->tp_src = udp_key->udp_src;
-                       swkey->tp_dst = udp_key->udp_dst;
+                       swkey->ipv6.tp.src = udp_key->udp_src;
+                       swkey->ipv6.tp.dst = udp_key->udp_dst;
                        break;
 
                case TRANSITION(ODP_KEY_ATTR_IPV4, ODP_KEY_ATTR_ICMP):
-                       if (swkey->nw_proto != IPPROTO_ICMP)
-                               return -EINVAL;
+                       key_len = SW_FLOW_KEY_OFFSET(ipv4.tp);
+                       if (swkey->ip.nw_proto != IPPROTO_ICMP)
+                               goto invalid;
                        icmp_key = nla_data(nla);
-                       swkey->tp_src = htons(icmp_key->icmp_type);
-                       swkey->tp_dst = htons(icmp_key->icmp_code);
+                       swkey->ipv4.tp.src = htons(icmp_key->icmp_type);
+                       swkey->ipv4.tp.dst = htons(icmp_key->icmp_code);
                        break;
 
                case TRANSITION(ODP_KEY_ATTR_IPV6, ODP_KEY_ATTR_ICMPV6):
-                       if (swkey->nw_proto != IPPROTO_ICMPV6)
-                               return -EINVAL;
+                       key_len = SW_FLOW_KEY_OFFSET(ipv6.tp);
+                       if (swkey->ip.nw_proto != IPPROTO_ICMPV6)
+                               goto invalid;
                        icmpv6_key = nla_data(nla);
-                       swkey->tp_src = htons(icmpv6_key->icmpv6_type);
-                       swkey->tp_dst = htons(icmpv6_key->icmpv6_code);
+                       swkey->ipv6.tp.src = htons(icmpv6_key->icmpv6_type);
+                       swkey->ipv6.tp.dst = htons(icmpv6_key->icmpv6_code);
                        break;
 
                case TRANSITION(ODP_KEY_ATTR_ETHERTYPE, ODP_KEY_ATTR_ARP):
-                       if (swkey->dl_type != htons(ETH_P_ARP))
-                               return -EINVAL;
+                       key_len = SW_FLOW_KEY_OFFSET(ipv4.arp);
+                       if (swkey->eth.type != htons(ETH_P_ARP))
+                               goto invalid;
                        arp_key = nla_data(nla);
-                       swkey->ipv4_src = arp_key->arp_sip;
-                       swkey->ipv4_dst = arp_key->arp_tip;
+                       swkey->ipv4.addr.src = arp_key->arp_sip;
+                       swkey->ipv4.addr.dst = arp_key->arp_tip;
                        if (arp_key->arp_op & htons(0xff00))
-                               return -EINVAL;
-                       swkey->nw_proto = ntohs(arp_key->arp_op);
-                       memcpy(swkey->arp_sha, arp_key->arp_sha, ETH_ALEN);
-                       memcpy(swkey->arp_tha, arp_key->arp_tha, ETH_ALEN);
+                               goto invalid;
+                       swkey->ip.nw_proto = ntohs(arp_key->arp_op);
+                       memcpy(swkey->ipv4.arp.sha, arp_key->arp_sha, ETH_ALEN);
+                       memcpy(swkey->ipv4.arp.tha, arp_key->arp_tha, ETH_ALEN);
                        break;
 
                case TRANSITION(ODP_KEY_ATTR_ICMPV6, ODP_KEY_ATTR_ND):
-                       if (swkey->tp_src != htons(NDISC_NEIGHBOUR_SOLICITATION)
-                           && swkey->tp_src != htons(NDISC_NEIGHBOUR_ADVERTISEMENT))
-                               return -EINVAL;
+                       key_len = SW_FLOW_KEY_OFFSET(ipv6.nd);
+                       if (swkey->ipv6.tp.src != htons(NDISC_NEIGHBOUR_SOLICITATION)
+                           && swkey->ipv6.tp.src != htons(NDISC_NEIGHBOUR_ADVERTISEMENT))
+                               goto invalid;
                        nd_key = nla_data(nla);
-                       memcpy(&swkey->nd_target, nd_key->nd_target,
-                                       sizeof(swkey->nd_target));
-                       memcpy(swkey->arp_sha, nd_key->nd_sll, ETH_ALEN);
-                       memcpy(swkey->arp_tha, nd_key->nd_tll, ETH_ALEN);
+                       memcpy(&swkey->ipv6.nd.target, nd_key->nd_target,
+                                       sizeof(swkey->ipv6.nd.target));
+                       memcpy(swkey->ipv6.nd.sll, nd_key->nd_sll, ETH_ALEN);
+                       memcpy(swkey->ipv6.nd.tll, nd_key->nd_tll, ETH_ALEN);
                        break;
 
                default:
-                       return -EINVAL;
+                       goto invalid;
                }
 
                prev_type = type;
        }
        if (rem)
-               return -EINVAL;
+               goto invalid;
 
        switch (prev_type) {
        case ODP_KEY_ATTR_UNSPEC:
-               return -EINVAL;
+               goto invalid;
 
        case ODP_KEY_ATTR_TUN_ID:
        case ODP_KEY_ATTR_IN_PORT:
-               return -EINVAL;
+               goto invalid;
 
        case ODP_KEY_ATTR_ETHERNET:
        case ODP_KEY_ATTR_8021Q:
-               return 0;
+               goto ok;
 
        case ODP_KEY_ATTR_ETHERTYPE:
-               if (swkey->dl_type == htons(ETH_P_IP) ||
-                   swkey->dl_type == htons(ETH_P_ARP))
-                       return -EINVAL;
-               return 0;
+               if (swkey->eth.type == htons(ETH_P_IP) ||
+                   swkey->eth.type == htons(ETH_P_ARP))
+                       goto invalid;
+               goto ok;
 
        case ODP_KEY_ATTR_IPV4:
-               if (swkey->nw_proto == IPPROTO_TCP ||
-                   swkey->nw_proto == IPPROTO_UDP ||
-                   swkey->nw_proto == IPPROTO_ICMP)
-                       return -EINVAL;
-               return 0;
+               if (swkey->ip.nw_proto == IPPROTO_TCP ||
+                   swkey->ip.nw_proto == IPPROTO_UDP ||
+                   swkey->ip.nw_proto == IPPROTO_ICMP)
+                       goto invalid;
+               goto ok;
 
        case ODP_KEY_ATTR_IPV6:
-               if (swkey->nw_proto == IPPROTO_TCP ||
-                   swkey->nw_proto == IPPROTO_UDP ||
-                   swkey->nw_proto == IPPROTO_ICMPV6)
-                       return -EINVAL;
-               return 0;
+               if (swkey->ip.nw_proto == IPPROTO_TCP ||
+                   swkey->ip.nw_proto == IPPROTO_UDP ||
+                   swkey->ip.nw_proto == IPPROTO_ICMPV6)
+                       goto invalid;
+               goto ok;
 
        case ODP_KEY_ATTR_ICMPV6:
-               if (swkey->tp_src == htons(NDISC_NEIGHBOUR_SOLICITATION) ||
-                   swkey->tp_src == htons(NDISC_NEIGHBOUR_ADVERTISEMENT))
-                       return -EINVAL;
-               return 0;
+               if (swkey->ipv6.tp.src == htons(NDISC_NEIGHBOUR_SOLICITATION) ||
+                   swkey->ipv6.tp.src == htons(NDISC_NEIGHBOUR_ADVERTISEMENT))
+                       goto invalid;
+               goto ok;
 
        case ODP_KEY_ATTR_TCP:
        case ODP_KEY_ATTR_UDP:
        case ODP_KEY_ATTR_ICMP:
        case ODP_KEY_ATTR_ARP:
        case ODP_KEY_ATTR_ND:
-               return 0;
+               goto ok;
+
+       default:
+               WARN_ON_ONCE(1);
        }
 
-       WARN_ON_ONCE(1);
-       return -EINVAL;
+invalid:
+       error = -EINVAL;
+
+ok:
+       WARN_ON_ONCE(!key_len && !error);
+       *key_lenp = key_len;
+       return error;
 }
 
 int flow_to_nlattrs(const struct sw_flow_key *swkey, struct sk_buff *skb)
@@ -809,32 +878,32 @@ int flow_to_nlattrs(const struct sw_flow_key *swkey, struct sk_buff *skb)
         * types are added. */
        BUILD_BUG_ON(__ODP_KEY_ATTR_MAX != 14);
 
-       if (swkey->tun_id != cpu_to_be64(0))
-               NLA_PUT_BE64(skb, ODP_KEY_ATTR_TUN_ID, swkey->tun_id);
+       if (swkey->eth.tun_id != cpu_to_be64(0))
+               NLA_PUT_BE64(skb, ODP_KEY_ATTR_TUN_ID, swkey->eth.tun_id);
 
-       NLA_PUT_U32(skb, ODP_KEY_ATTR_IN_PORT, swkey->in_port);
+       NLA_PUT_U32(skb, ODP_KEY_ATTR_IN_PORT, swkey->eth.in_port);
 
        nla = nla_reserve(skb, ODP_KEY_ATTR_ETHERNET, sizeof(*eth_key));
        if (!nla)
                goto nla_put_failure;
        eth_key = nla_data(nla);
-       memcpy(eth_key->eth_src, swkey->dl_src, ETH_ALEN);
-       memcpy(eth_key->eth_dst, swkey->dl_dst, ETH_ALEN);
+       memcpy(eth_key->eth_src, swkey->eth.src, ETH_ALEN);
+       memcpy(eth_key->eth_dst, swkey->eth.dst, ETH_ALEN);
 
-       if (swkey->dl_tci != htons(0)) {
+       if (swkey->eth.tci != htons(0)) {
                struct odp_key_8021q q_key;
 
                q_key.q_tpid = htons(ETH_P_8021Q);
-               q_key.q_tci = swkey->dl_tci & ~htons(VLAN_TAG_PRESENT);
+               q_key.q_tci = swkey->eth.tci & ~htons(VLAN_TAG_PRESENT);
                NLA_PUT(skb, ODP_KEY_ATTR_8021Q, sizeof(q_key), &q_key);
        }
 
-       if (swkey->dl_type == htons(ETH_P_802_2))
+       if (swkey->eth.type == htons(ETH_P_802_2))
                return 0;
 
-       NLA_PUT_BE16(skb, ODP_KEY_ATTR_ETHERTYPE, swkey->dl_type);
+       NLA_PUT_BE16(skb, ODP_KEY_ATTR_ETHERTYPE, swkey->eth.type);
 
-       if (swkey->dl_type == htons(ETH_P_IP)) {
+       if (swkey->eth.type == htons(ETH_P_IP)) {
                struct odp_key_ipv4 *ipv4_key;
 
                nla = nla_reserve(skb, ODP_KEY_ATTR_IPV4, sizeof(*ipv4_key));
@@ -842,11 +911,11 @@ int flow_to_nlattrs(const struct sw_flow_key *swkey, struct sk_buff *skb)
                        goto nla_put_failure;
                ipv4_key = nla_data(nla);
                memset(ipv4_key, 0, sizeof(struct odp_key_ipv4));
-               ipv4_key->ipv4_src = swkey->ipv4_src;
-               ipv4_key->ipv4_dst = swkey->ipv4_dst;
-               ipv4_key->ipv4_proto = swkey->nw_proto;
-               ipv4_key->ipv4_tos = swkey->nw_tos;
-       } else if (swkey->dl_type == htons(ETH_P_IPV6)) {
+               ipv4_key->ipv4_src = swkey->ipv4.addr.src;
+               ipv4_key->ipv4_dst = swkey->ipv4.addr.dst;
+               ipv4_key->ipv4_proto = swkey->ip.nw_proto;
+               ipv4_key->ipv4_tos = swkey->ip.nw_tos;
+       } else if (swkey->eth.type == htons(ETH_P_IPV6)) {
                struct odp_key_ipv6 *ipv6_key;
 
                nla = nla_reserve(skb, ODP_KEY_ATTR_IPV6, sizeof(*ipv6_key));
@@ -854,13 +923,13 @@ int flow_to_nlattrs(const struct sw_flow_key *swkey, struct sk_buff *skb)
                        goto nla_put_failure;
                ipv6_key = nla_data(nla);
                memset(ipv6_key, 0, sizeof(struct odp_key_ipv6));
-               memcpy(ipv6_key->ipv6_src, &swkey->ipv6_src,
+               memcpy(ipv6_key->ipv6_src, &swkey->ipv6.addr.src,
                                sizeof(ipv6_key->ipv6_src));
-               memcpy(ipv6_key->ipv6_dst, &swkey->ipv6_dst,
+               memcpy(ipv6_key->ipv6_dst, &swkey->ipv6.addr.dst,
                                sizeof(ipv6_key->ipv6_dst));
-               ipv6_key->ipv6_proto = swkey->nw_proto;
-               ipv6_key->ipv6_tos = swkey->nw_tos;
-       } else if (swkey->dl_type == htons(ETH_P_ARP)) {
+               ipv6_key->ipv6_proto = swkey->ip.nw_proto;
+               ipv6_key->ipv6_tos = swkey->ip.nw_tos;
+       } else if (swkey->eth.type == htons(ETH_P_ARP)) {
                struct odp_key_arp *arp_key;
 
                nla = nla_reserve(skb, ODP_KEY_ATTR_ARP, sizeof(*arp_key));
@@ -868,46 +937,56 @@ int flow_to_nlattrs(const struct sw_flow_key *swkey, struct sk_buff *skb)
                        goto nla_put_failure;
                arp_key = nla_data(nla);
                memset(arp_key, 0, sizeof(struct odp_key_arp));
-               arp_key->arp_sip = swkey->ipv4_src;
-               arp_key->arp_tip = swkey->ipv4_dst;
-               arp_key->arp_op = htons(swkey->nw_proto);
-               memcpy(arp_key->arp_sha, swkey->arp_sha, ETH_ALEN);
-               memcpy(arp_key->arp_tha, swkey->arp_tha, ETH_ALEN);
+               arp_key->arp_sip = swkey->ipv4.addr.src;
+               arp_key->arp_tip = swkey->ipv4.addr.dst;
+               arp_key->arp_op = htons(swkey->ip.nw_proto);
+               memcpy(arp_key->arp_sha, swkey->ipv4.arp.sha, ETH_ALEN);
+               memcpy(arp_key->arp_tha, swkey->ipv4.arp.tha, ETH_ALEN);
        }
 
-       if (swkey->dl_type == htons(ETH_P_IP) ||
-           swkey->dl_type == htons(ETH_P_IPV6)) {
+       if (swkey->eth.type == htons(ETH_P_IP) ||
+           swkey->eth.type == htons(ETH_P_IPV6)) {
 
-               if (swkey->nw_proto == IPPROTO_TCP) {
+               if (swkey->ip.nw_proto == IPPROTO_TCP) {
                        struct odp_key_tcp *tcp_key;
 
                        nla = nla_reserve(skb, ODP_KEY_ATTR_TCP, sizeof(*tcp_key));
                        if (!nla)
                                goto nla_put_failure;
                        tcp_key = nla_data(nla);
-                       tcp_key->tcp_src = swkey->tp_src;
-                       tcp_key->tcp_dst = swkey->tp_dst;
-               } else if (swkey->nw_proto == IPPROTO_UDP) {
+                       if (swkey->eth.type == htons(ETH_P_IP)) {
+                               tcp_key->tcp_src = swkey->ipv4.tp.src;
+                               tcp_key->tcp_dst = swkey->ipv4.tp.dst;
+                       } else if (swkey->eth.type == htons(ETH_P_IPV6)) {
+                               tcp_key->tcp_src = swkey->ipv6.tp.src;
+                               tcp_key->tcp_dst = swkey->ipv6.tp.dst;
+                       }
+               } else if (swkey->ip.nw_proto == IPPROTO_UDP) {
                        struct odp_key_udp *udp_key;
 
                        nla = nla_reserve(skb, ODP_KEY_ATTR_UDP, sizeof(*udp_key));
                        if (!nla)
                                goto nla_put_failure;
                        udp_key = nla_data(nla);
-                       udp_key->udp_src = swkey->tp_src;
-                       udp_key->udp_dst = swkey->tp_dst;
-               } else if (swkey->dl_type == htons(ETH_P_IP) &&
-                          swkey->nw_proto == IPPROTO_ICMP) {
+                       if (swkey->eth.type == htons(ETH_P_IP)) {
+                               udp_key->udp_src = swkey->ipv4.tp.src;
+                               udp_key->udp_dst = swkey->ipv4.tp.dst;
+                       } else if (swkey->eth.type == htons(ETH_P_IPV6)) {
+                               udp_key->udp_src = swkey->ipv6.tp.src;
+                               udp_key->udp_dst = swkey->ipv6.tp.dst;
+                       }
+               } else if (swkey->eth.type == htons(ETH_P_IP) &&
+                          swkey->ip.nw_proto == IPPROTO_ICMP) {
                        struct odp_key_icmp *icmp_key;
 
                        nla = nla_reserve(skb, ODP_KEY_ATTR_ICMP, sizeof(*icmp_key));
                        if (!nla)
                                goto nla_put_failure;
                        icmp_key = nla_data(nla);
-                       icmp_key->icmp_type = ntohs(swkey->tp_src);
-                       icmp_key->icmp_code = ntohs(swkey->tp_dst);
-               } else if (swkey->dl_type == htons(ETH_P_IPV6) &&
-                          swkey->nw_proto == IPPROTO_ICMPV6) {
+                       icmp_key->icmp_type = ntohs(swkey->ipv4.tp.src);
+                       icmp_key->icmp_code = ntohs(swkey->ipv4.tp.dst);
+               } else if (swkey->eth.type == htons(ETH_P_IPV6) &&
+                          swkey->ip.nw_proto == IPPROTO_ICMPV6) {
                        struct odp_key_icmpv6 *icmpv6_key;
 
                        nla = nla_reserve(skb, ODP_KEY_ATTR_ICMPV6,
@@ -915,8 +994,8 @@ int flow_to_nlattrs(const struct sw_flow_key *swkey, struct sk_buff *skb)
                        if (!nla)
                                goto nla_put_failure;
                        icmpv6_key = nla_data(nla);
-                       icmpv6_key->icmpv6_type = ntohs(swkey->tp_src);
-                       icmpv6_key->icmpv6_code = ntohs(swkey->tp_dst);
+                       icmpv6_key->icmpv6_type = ntohs(swkey->ipv6.tp.src);
+                       icmpv6_key->icmpv6_code = ntohs(swkey->ipv6.tp.dst);
 
                        if (icmpv6_key->icmpv6_type == NDISC_NEIGHBOUR_SOLICITATION ||
                            icmpv6_key->icmpv6_type == NDISC_NEIGHBOUR_ADVERTISEMENT) {
@@ -926,10 +1005,10 @@ int flow_to_nlattrs(const struct sw_flow_key *swkey, struct sk_buff *skb)
                                if (!nla)
                                        goto nla_put_failure;
                                nd_key = nla_data(nla);
-                               memcpy(nd_key->nd_target, &swkey->nd_target,
+                               memcpy(nd_key->nd_target, &swkey->ipv6.nd.target,
                                                        sizeof(nd_key->nd_target));
-                               memcpy(nd_key->nd_sll, swkey->arp_sha, ETH_ALEN);
-                               memcpy(nd_key->nd_tll, swkey->arp_tha, ETH_ALEN);
+                               memcpy(nd_key->nd_sll, swkey->ipv6.nd.sll, ETH_ALEN);
+                               memcpy(nd_key->nd_tll, swkey->ipv6.nd.tll, ETH_ALEN);
                        }
                }
        }
index 5c23279..1d75a01 100644 (file)
@@ -31,29 +31,51 @@ struct sw_flow_actions {
 };
 
 struct sw_flow_key {
-       __be64  tun_id;     /* Encapsulating tunnel ID. */
+       struct {
+               __be64 tun_id;          /* Encapsulating tunnel ID. */
+               u16    in_port;         /* Input switch port. */
+               u8     src[ETH_ALEN];   /* Ethernet source address. */
+               u8     dst[ETH_ALEN];   /* Ethernet destination address. */
+               __be16 tci;             /* 0 if no VLAN, VLAN_TAG_PRESENT set otherwise. */
+               __be16 type;            /* Ethernet frame type. */
+       } eth;
+       struct {
+               u8     nw_proto;        /* IP protocol or lower 8 bits of ARP opcode. */
+               u8     nw_tos;          /* IP ToS (DSCP field, 6 bits). */
+       } ip;
        union {
                struct {
-                       __be32  ipv4_src;        /* IPv4 source address. */
-                       __be32  ipv4_dst;        /* IPv4 destination address. */
-               };
+                       struct {
+                               __be32 src;     /* IP source address. */
+                               __be32 dst;     /* IP destination address. */
+                       } addr;
+                       union {
+                               struct {
+                                       __be16 src;             /* TCP/UDP source port. */
+                                       __be16 dst;             /* TCP/UDP destination port. */
+                               } tp;
+                               struct {
+                                       u8 sha[ETH_ALEN];       /* ARP source hardware address. */
+                                       u8 tha[ETH_ALEN];       /* ARP target hardware address. */
+                               } arp;
+                       };
+               } ipv4;
                struct {
-                       struct in6_addr ipv6_src; /* IPv6 source address. */
-                       struct in6_addr ipv6_dst; /* IPv6 source address. */
-               };
+                       struct {
+                               struct in6_addr src;    /* IPv6 source address. */
+                               struct in6_addr dst;    /* IPv6 destination address. */
+                       } addr;
+                       struct {
+                               __be16 src;             /* TCP/UDP source port. */
+                               __be16 dst;             /* TCP/UDP destination port. */
+                       } tp;
+                       struct {
+                               struct in6_addr target; /* ND target address. */
+                               u8 sll[ETH_ALEN];       /* ND source link layer address. */
+                               u8 tll[ETH_ALEN];       /* ND target link layer address. */
+                       } nd;
+               } ipv6;
        };
-       struct in6_addr nd_target; /* IPv6 ND target address. */
-       u16     in_port;    /* Input switch port. */
-       __be16  dl_tci;     /* 0 if no VLAN, VLAN_TAG_PRESENT set otherwise. */
-       __be16  dl_type;    /* Ethernet frame type. */
-       __be16  tp_src;     /* TCP/UDP source port. */
-       __be16  tp_dst;     /* TCP/UDP destination port. */
-       u8      dl_src[ETH_ALEN]; /* Ethernet source address. */
-       u8      dl_dst[ETH_ALEN]; /* Ethernet destination address. */
-       u8      nw_proto;   /* IP protocol or lower 8 bits of ARP opcode. */
-       u8      nw_tos;     /* IP ToS (DSCP field, 6 bits). */
-       u8      arp_sha[ETH_ALEN]; /* ARP/ND source hardware address. */
-       u8      arp_tha[ETH_ALEN]; /* ARP/ND target hardware address. */
 };
 
 struct sw_flow {
@@ -101,12 +123,13 @@ void flow_deferred_free_acts(struct sw_flow_actions *);
 void flow_hold(struct sw_flow *);
 void flow_put(struct sw_flow *);
 
-int flow_extract(struct sk_buff *, u16 in_port, struct sw_flow_key *, bool *is_frag);
+int flow_extract(struct sk_buff *, u16 in_port, struct sw_flow_key *,
+                int *key_lenp, bool *is_frag);
 void flow_used(struct sw_flow *, struct sk_buff *);
 u64 flow_used_time(unsigned long flow_jiffies);
 
-u32 flow_hash(const struct sw_flow_key *);
-int flow_cmp(const struct tbl_node *, void *target);
+u32 flow_hash(const struct sw_flow_key *, int key_lenp);
+int flow_cmp(const struct tbl_node *, void *target, int len);
 
 /* Upper bound on the length of a nlattr-formatted flow key.  The longest
  * nlattr-formatted flow key would be:
@@ -127,7 +150,8 @@ int flow_cmp(const struct tbl_node *, void *target);
 #define FLOW_BUFSIZE 132
 
 int flow_to_nlattrs(const struct sw_flow_key *, struct sk_buff *);
-int flow_from_nlattrs(struct sw_flow_key *swkey, const struct nlattr *);
+int flow_from_nlattrs(struct sw_flow_key *swkey, int *key_lenp,
+                     const struct nlattr *);
 
 static inline struct sw_flow *flow_cast(const struct tbl_node *node)
 {
index 47fa016..725845d 100644 (file)
@@ -178,14 +178,14 @@ static struct tbl_bucket __rcu **find_bucket(struct tbl *table, u32 hash)
        return &table->buckets[l1][l2];
 }
 
-static int search_bucket(const struct tbl_bucket *bucket, void *target, u32 hash,
-                        int (*cmp)(const struct tbl_node *, void *))
+static int search_bucket(const struct tbl_bucket *bucket, void *target, int len, u32 hash,
+                        int (*cmp)(const struct tbl_node *, void *, int len))
 {
        int i;
 
        for (i = 0; i < bucket->n_objs; i++) {
                struct tbl_node *obj = bucket->objs[i];
-               if (obj->hash == hash && likely(cmp(obj, target)))
+               if (obj->hash == hash && likely(cmp(obj, target, len)))
                        return i;
        }
 
@@ -197,6 +197,8 @@ static int search_bucket(const struct tbl_bucket *bucket, void *target, u32 hash
  * @table: hash table to search
  * @target: identifier for the object that is being searched for, will be
  * provided as an argument to @cmp when making comparisions
+ * @len: length of @target in bytes, will be provided as an argument to @cmp
+ * when making comparisons
  * @hash: hash of @target
  * @cmp: comparision function to match objects with the given hash, returns
  * nonzero if the objects match, zero otherwise
@@ -204,8 +206,8 @@ static int search_bucket(const struct tbl_bucket *bucket, void *target, u32 hash
  * Searches @table for an object identified by @target.  Returns the tbl_node
  * contained in the object if successful, otherwise %NULL.
  */
-struct tbl_node *tbl_lookup(struct tbl *table, void *target, u32 hash,
-                           int (*cmp)(const struct tbl_node *, void *))
+struct tbl_node *tbl_lookup(struct tbl *table, void *target, int len, u32 hash,
+                           int (*cmp)(const struct tbl_node *, void *, int))
 {
        struct tbl_bucket __rcu **bucketp = find_bucket(table, hash);
        struct tbl_bucket *bucket = get_bucket(*bucketp);
@@ -214,7 +216,7 @@ struct tbl_node *tbl_lookup(struct tbl *table, void *target, u32 hash,
        if (!bucket)
                return NULL;
 
-       index = search_bucket(bucket, target, hash, cmp);
+       index = search_bucket(bucket, target, len, hash, cmp);
        if (index < 0)
                return NULL;
 
index 22574be..3a0c2a6 100644 (file)
@@ -55,8 +55,8 @@ struct tbl {
 
 struct tbl *tbl_create(unsigned int n_buckets);
 void tbl_destroy(struct tbl *, void (*destructor)(struct tbl_node *));
-struct tbl_node *tbl_lookup(struct tbl *, void *target, u32 hash,
-                           int (*cmp)(const struct tbl_node *, void *target));
+struct tbl_node *tbl_lookup(struct tbl *, void *target, int len, u32 hash,
+                           int (*cmp)(const struct tbl_node *, void *target, int len));
 int tbl_insert(struct tbl *, struct tbl_node *, u32 hash);
 int tbl_remove(struct tbl *, struct tbl_node *);
 unsigned int tbl_count(struct tbl *);
index 70a4cd7..3263223 100644 (file)
@@ -186,7 +186,7 @@ struct port_lookup_key {
  * Modifies 'target' to store the rcu_dereferenced pointer that was used to do
  * the comparision.
  */
-static int port_cmp(const struct tbl_node *node, void *target)
+static int port_cmp(const struct tbl_node *node, void *target, int unused)
 {
        const struct tnl_vport *tnl_vport = tnl_vport_table_cast(node);
        struct port_lookup_key *lookup = target;
@@ -337,7 +337,8 @@ struct vport *tnl_find_port(__be32 saddr, __be32 daddr, __be64 key,
                lookup.tunnel_type = tunnel_type & ~TNL_T_KEY_MATCH;
 
                if (key_local_remote_ports) {
-                       tbl_node = tbl_lookup(table, &lookup, port_hash(&lookup), port_cmp);
+                       tbl_node = tbl_lookup(table, &lookup, sizeof(lookup),
+                                             port_hash(&lookup), port_cmp);
                        if (tbl_node)
                                goto found;
                }
@@ -345,7 +346,8 @@ struct vport *tnl_find_port(__be32 saddr, __be32 daddr, __be64 key,
                if (key_remote_ports) {
                        lookup.saddr = 0;
 
-                       tbl_node = tbl_lookup(table, &lookup, port_hash(&lookup), port_cmp);
+                       tbl_node = tbl_lookup(table, &lookup, sizeof(lookup),
+                                             port_hash(&lookup), port_cmp);
                        if (tbl_node)
                                goto found;
 
@@ -358,7 +360,8 @@ struct vport *tnl_find_port(__be32 saddr, __be32 daddr, __be64 key,
                lookup.tunnel_type = tunnel_type & ~TNL_T_KEY_EXACT;
 
                if (local_remote_ports) {
-                       tbl_node = tbl_lookup(table, &lookup, port_hash(&lookup), port_cmp);
+                       tbl_node = tbl_lookup(table, &lookup, sizeof(lookup),
+                                             port_hash(&lookup), port_cmp);
                        if (tbl_node)
                                goto found;
                }
@@ -366,7 +369,8 @@ struct vport *tnl_find_port(__be32 saddr, __be32 daddr, __be64 key,
                if (remote_ports) {
                        lookup.saddr = 0;
 
-                       tbl_node = tbl_lookup(table, &lookup, port_hash(&lookup), port_cmp);
+                       tbl_node = tbl_lookup(table, &lookup, sizeof(lookup),
+                                             port_hash(&lookup), port_cmp);
                        if (tbl_node)
                                goto found;
                }
@@ -940,6 +944,7 @@ static struct tnl_cache *build_cache(struct vport *vport,
                struct sk_buff *skb;
                bool is_frag;
                int err;
+               int flow_key_len;
 
                dst_vport = internal_dev_get_vport(rt_dst(rt).dev);
                if (!dst_vport)
@@ -952,14 +957,16 @@ static struct tnl_cache *build_cache(struct vport *vport,
                __skb_put(skb, cache->len);
                memcpy(skb->data, get_cached_header(cache), cache->len);
 
-               err = flow_extract(skb, dst_vport->port_no, &flow_key, &is_frag);
+               err = flow_extract(skb, dst_vport->port_no, &flow_key,
+                                  &flow_key_len, &is_frag);
 
                kfree_skb(skb);
                if (err || is_frag)
                        goto done;
 
                flow_node = tbl_lookup(rcu_dereference(dst_vport->dp->table),
-                                      &flow_key, flow_hash(&flow_key),
+                                      &flow_key, flow_key_len,
+                                      flow_hash(&flow_key, flow_key_len),
                                       flow_cmp);
                if (flow_node) {
                        struct sw_flow *flow = flow_cast(flow_node);
index 209d937..09c879b 100755 (executable)
@@ -389,7 +389,7 @@ def main(argv = None):
             return 0
 
         if k == '--output':
-            if  v in ['tar', 'tar.bz2', 'zip']:
+            if  v in ['tar', 'tar.bz2', 'tar.gz', 'zip']:
                 output_type = v
             else:
                 print >>sys.stderr, "Invalid output format '%s'" % v
@@ -780,6 +780,8 @@ def make_tar(subdir, suffix, output_fd):
     mode = 'w'
     if suffix == 'tar.bz2':
         mode = 'w:bz2'
+    elif suffix == 'tar.gz':
+        mode = 'w:gz'
     filename = "%s/%s.%s" % (BUG_DIR, subdir, suffix)
 
     if output_fd == -1:
index 5c07a6a..f34e5c9 100644 (file)
@@ -1,3 +1,4 @@
 include include/linux/automake.mk
 include include/openflow/automake.mk
 include include/openvswitch/automake.mk
+include include/sparse/automake.mk
index e92e70c..f539543 100644 (file)
@@ -114,8 +114,8 @@ enum ofp_type {
 struct ofp_header {
     uint8_t version;    /* OFP_VERSION. */
     uint8_t type;       /* One of the OFPT_ constants. */
-    uint16_t length;    /* Length including this ofp_header. */
-    uint32_t xid;       /* Transaction id associated with this packet.
+    ovs_be16 length;    /* Length including this ofp_header. */
+    ovs_be32 xid;       /* Transaction id associated with this packet.
                            Replies use the same id as was in the request
                            to facilitate pairing. */
 };
@@ -140,8 +140,8 @@ enum ofp_config_flags {
 /* Switch configuration. */
 struct ofp_switch_config {
     struct ofp_header header;
-    uint16_t flags;             /* OFPC_* flags. */
-    uint16_t miss_send_len;     /* Max bytes of new flow that datapath should
+    ovs_be16 flags;             /* OFPC_* flags. */
+    ovs_be16 miss_send_len;     /* Max bytes of new flow that datapath should
                                    send to the controller. */
 };
 OFP_ASSERT(sizeof(struct ofp_switch_config) == 12);
@@ -210,37 +210,37 @@ enum ofp_port_features {
 
 /* Description of a physical port */
 struct ofp_phy_port {
-    uint16_t port_no;
+    ovs_be16 port_no;
     uint8_t hw_addr[OFP_ETH_ALEN];
     char name[OFP_MAX_PORT_NAME_LEN]; /* Null-terminated */
 
-    uint32_t config;        /* Bitmap of OFPPC_* flags. */
-    uint32_t state;         /* Bitmap of OFPPS_* flags. */
+    ovs_be32 config;        /* Bitmap of OFPPC_* flags. */
+    ovs_be32 state;         /* Bitmap of OFPPS_* flags. */
 
     /* Bitmaps of OFPPF_* that describe features.  All bits zeroed if
      * unsupported or unavailable. */
-    uint32_t curr;          /* Current features. */
-    uint32_t advertised;    /* Features being advertised by the port. */
-    uint32_t supported;     /* Features supported by the port. */
-    uint32_t peer;          /* Features advertised by peer. */
+    ovs_be32 curr;          /* Current features. */
+    ovs_be32 advertised;    /* Features being advertised by the port. */
+    ovs_be32 supported;     /* Features supported by the port. */
+    ovs_be32 peer;          /* Features advertised by peer. */
 };
 OFP_ASSERT(sizeof(struct ofp_phy_port) == 48);
 
 /* Switch features. */
 struct ofp_switch_features {
     struct ofp_header header;
-    uint64_t datapath_id;   /* Datapath unique ID.  The lower 48-bits are for
+    ovs_be64 datapath_id;   /* Datapath unique ID.  The lower 48-bits are for
                                a MAC address, while the upper 16-bits are
                                implementer-defined. */
 
-    uint32_t n_buffers;     /* Max packets buffered at once. */
+    ovs_be32 n_buffers;     /* Max packets buffered at once. */
 
     uint8_t n_tables;       /* Number of tables supported by datapath. */
     uint8_t pad[3];         /* Align to 64-bits. */
 
     /* Features. */
-    uint32_t capabilities;  /* Bitmap of support "ofp_capabilities". */
-    uint32_t actions;       /* Bitmap of supported "ofp_action_type"s. */
+    ovs_be32 capabilities;  /* Bitmap of support "ofp_capabilities". */
+    ovs_be32 actions;       /* Bitmap of supported "ofp_action_type"s. */
 
     /* Port info.*/
     struct ofp_phy_port ports[0];  /* Port definitions.  The number of ports
@@ -268,17 +268,17 @@ OFP_ASSERT(sizeof(struct ofp_port_status) == 64);
 /* Modify behavior of the physical port */
 struct ofp_port_mod {
     struct ofp_header header;
-    uint16_t port_no;
+    ovs_be16 port_no;
     uint8_t hw_addr[OFP_ETH_ALEN]; /* The hardware address is not
                                       configurable.  This is used to
                                       sanity-check the request, so it must
                                       be the same as returned in an
                                       ofp_phy_port struct. */
 
-    uint32_t config;        /* Bitmap of OFPPC_* flags. */
-    uint32_t mask;          /* Bitmap of OFPPC_* flags to be changed. */
+    ovs_be32 config;        /* Bitmap of OFPPC_* flags. */
+    ovs_be32 mask;          /* Bitmap of OFPPC_* flags to be changed. */
 
-    uint32_t advertise;     /* Bitmap of "ofp_port_features"s.  Zero all
+    ovs_be32 advertise;     /* Bitmap of "ofp_port_features"s.  Zero all
                                bits to prevent any action taking place. */
     uint8_t pad[4];         /* Pad to 64-bits. */
 };
@@ -293,9 +293,9 @@ enum ofp_packet_in_reason {
 /* Packet received on port (datapath -> controller). */
 struct ofp_packet_in {
     struct ofp_header header;
-    uint32_t buffer_id;     /* ID assigned by datapath. */
-    uint16_t total_len;     /* Full length of frame. */
-    uint16_t in_port;       /* Port on which frame was received. */
+    ovs_be32 buffer_id;     /* ID assigned by datapath. */
+    ovs_be16 total_len;     /* Full length of frame. */
+    ovs_be16 in_port;       /* Port on which frame was received. */
     uint8_t reason;         /* Reason packet is being sent (one of OFPR_*) */
     uint8_t pad;
     uint8_t data[0];        /* Ethernet frame, halfway through 32-bit word,
@@ -328,10 +328,10 @@ enum ofp_action_type {
  * number of bytes to send.  A 'max_len' of zero means no bytes of the
  * packet should be sent. */
 struct ofp_action_output {
-    uint16_t type;                  /* OFPAT_OUTPUT. */
-    uint16_t len;                   /* Length is 8. */
-    uint16_t port;                  /* Output port. */
-    uint16_t max_len;               /* Max length to send to controller. */
+    ovs_be16 type;                  /* OFPAT_OUTPUT. */
+    ovs_be16 len;                   /* Length is 8. */
+    ovs_be16 port;                  /* Output port. */
+    ovs_be16 max_len;               /* Max length to send to controller. */
 };
 OFP_ASSERT(sizeof(struct ofp_action_output) == 8);
 
@@ -342,17 +342,17 @@ OFP_ASSERT(sizeof(struct ofp_action_output) == 8);
 
 /* Action structure for OFPAT_SET_VLAN_VID. */
 struct ofp_action_vlan_vid {
-    uint16_t type;                  /* OFPAT_SET_VLAN_VID. */
-    uint16_t len;                   /* Length is 8. */
-    uint16_t vlan_vid;              /* VLAN id. */
+    ovs_be16 type;                  /* OFPAT_SET_VLAN_VID. */
+    ovs_be16 len;                   /* Length is 8. */
+    ovs_be16 vlan_vid;              /* VLAN id. */
     uint8_t pad[2];
 };
 OFP_ASSERT(sizeof(struct ofp_action_vlan_vid) == 8);
 
 /* Action structure for OFPAT_SET_VLAN_PCP. */
 struct ofp_action_vlan_pcp {
-    uint16_t type;                  /* OFPAT_SET_VLAN_PCP. */
-    uint16_t len;                   /* Length is 8. */
+    ovs_be16 type;                  /* OFPAT_SET_VLAN_PCP. */
+    ovs_be16 len;                   /* Length is 8. */
     uint8_t vlan_pcp;               /* VLAN priority. */
     uint8_t pad[3];
 };
@@ -360,8 +360,8 @@ OFP_ASSERT(sizeof(struct ofp_action_vlan_pcp) == 8);
 
 /* Action structure for OFPAT_SET_DL_SRC/DST. */
 struct ofp_action_dl_addr {
-    uint16_t type;                  /* OFPAT_SET_DL_SRC/DST. */
-    uint16_t len;                   /* Length is 16. */
+    ovs_be16 type;                  /* OFPAT_SET_DL_SRC/DST. */
+    ovs_be16 len;                   /* Length is 16. */
     uint8_t dl_addr[OFP_ETH_ALEN];  /* Ethernet address. */
     uint8_t pad[6];
 };
@@ -369,16 +369,16 @@ OFP_ASSERT(sizeof(struct ofp_action_dl_addr) == 16);
 
 /* Action structure for OFPAT_SET_NW_SRC/DST. */
 struct ofp_action_nw_addr {
-    uint16_t type;                  /* OFPAT_SET_TW_SRC/DST. */
-    uint16_t len;                   /* Length is 8. */
-    uint32_t nw_addr;               /* IP address. */
+    ovs_be16 type;                  /* OFPAT_SET_TW_SRC/DST. */
+    ovs_be16 len;                   /* Length is 8. */
+    ovs_be32 nw_addr;               /* IP address. */
 };
 OFP_ASSERT(sizeof(struct ofp_action_nw_addr) == 8);
 
 /* Action structure for OFPAT_SET_NW_TOS. */
 struct ofp_action_nw_tos {
-    uint16_t type;                  /* OFPAT_SET_TW_TOS. */
-    uint16_t len;                   /* Length is 8. */
+    ovs_be16 type;                  /* OFPAT_SET_TW_TOS. */
+    ovs_be16 len;                   /* Length is 8. */
     uint8_t nw_tos;                 /* IP TOS (DSCP field, 6 bits). */
     uint8_t pad[3];
 };
@@ -386,18 +386,18 @@ OFP_ASSERT(sizeof(struct ofp_action_nw_tos) == 8);
 
 /* Action structure for OFPAT_SET_TP_SRC/DST. */
 struct ofp_action_tp_port {
-    uint16_t type;                  /* OFPAT_SET_TP_SRC/DST. */
-    uint16_t len;                   /* Length is 8. */
-    uint16_t tp_port;               /* TCP/UDP port. */
+    ovs_be16 type;                  /* OFPAT_SET_TP_SRC/DST. */
+    ovs_be16 len;                   /* Length is 8. */
+    ovs_be16 tp_port;               /* TCP/UDP port. */
     uint8_t pad[2];
 };
 OFP_ASSERT(sizeof(struct ofp_action_tp_port) == 8);
 
 /* Action header for OFPAT_VENDOR. The rest of the body is vendor-defined. */
 struct ofp_action_vendor_header {
-    uint16_t type;                  /* OFPAT_VENDOR. */
-    uint16_t len;                   /* Length is a multiple of 8. */
-    uint32_t vendor;                /* Vendor ID, which takes the same form
+    ovs_be16 type;                  /* OFPAT_VENDOR. */
+    ovs_be16 len;                   /* Length is a multiple of 8. */
+    ovs_be32 vendor;                /* Vendor ID, which takes the same form
                                        as in "struct ofp_vendor_header". */
 };
 OFP_ASSERT(sizeof(struct ofp_action_vendor_header) == 8);
@@ -406,8 +406,8 @@ OFP_ASSERT(sizeof(struct ofp_action_vendor_header) == 8);
  * header and any padding used to make the action 64-bit aligned.
  * NB: The length of an action *must* always be a multiple of eight. */
 struct ofp_action_header {
-    uint16_t type;                  /* One of OFPAT_*. */
-    uint16_t len;                   /* Length of action, including this
+    ovs_be16 type;                  /* One of OFPAT_*. */
+    ovs_be16 len;                   /* Length of action, including this
                                        header.  This is the length of action,
                                        including any padding to make it
                                        64-bit aligned. */
@@ -417,18 +417,18 @@ OFP_ASSERT(sizeof(struct ofp_action_header) == 8);
 
 /* OFPAT_ENQUEUE action struct: send packets to given queue on port. */
 struct ofp_action_enqueue {
-    uint16_t type;            /* OFPAT_ENQUEUE. */
-    uint16_t len;             /* Len is 16. */
-    uint16_t port;            /* Port that queue belongs. Should
+    ovs_be16 type;            /* OFPAT_ENQUEUE. */
+    ovs_be16 len;             /* Len is 16. */
+    ovs_be16 port;            /* Port that queue belongs. Should
                                  refer to a valid physical port
                                  (i.e. < OFPP_MAX) or OFPP_IN_PORT. */
     uint8_t pad[6];           /* Pad for 64-bit alignment. */
-    uint32_t queue_id;        /* Where to enqueue the packets. */
+    ovs_be32 queue_id;        /* Where to enqueue the packets. */
 };
 OFP_ASSERT(sizeof(struct ofp_action_enqueue) == 16);
 
 union ofp_action {
-    uint16_t type;
+    ovs_be16 type;
     struct ofp_action_header header;
     struct ofp_action_vendor_header vendor;
     struct ofp_action_output output;
@@ -443,9 +443,9 @@ OFP_ASSERT(sizeof(union ofp_action) == 8);
 /* Send packet (controller -> datapath). */
 struct ofp_packet_out {
     struct ofp_header header;
-    uint32_t buffer_id;           /* ID assigned by datapath (-1 if none). */
-    uint16_t in_port;             /* Packet's input port (OFPP_NONE if none). */
-    uint16_t actions_len;         /* Size of action array in bytes. */
+    ovs_be32 buffer_id;           /* ID assigned by datapath (-1 if none). */
+    ovs_be16 in_port;             /* Packet's input port (OFPP_NONE if none). */
+    ovs_be16 actions_len;         /* Size of action array in bytes. */
     struct ofp_action_header actions[0]; /* Actions. */
     /* uint8_t data[0]; */        /* Packet data.  The length is inferred
                                      from the length field in the header.
@@ -517,22 +517,22 @@ enum ofp_flow_wildcards {
 
 /* Fields to match against flows */
 struct ofp_match {
-    uint32_t wildcards;        /* Wildcard fields. */
-    uint16_t in_port;          /* Input switch port. */
+    ovs_be32 wildcards;        /* Wildcard fields. */
+    ovs_be16 in_port;          /* Input switch port. */
     uint8_t dl_src[OFP_ETH_ALEN]; /* Ethernet source address. */
     uint8_t dl_dst[OFP_ETH_ALEN]; /* Ethernet destination address. */
-    uint16_t dl_vlan;          /* Input VLAN. */
+    ovs_be16 dl_vlan;          /* Input VLAN. */
     uint8_t dl_vlan_pcp;       /* Input VLAN priority. */
     uint8_t pad1[1];           /* Align to 64-bits. */
-    uint16_t dl_type;          /* Ethernet frame type. */
+    ovs_be16 dl_type;          /* Ethernet frame type. */
     uint8_t nw_tos;            /* IP ToS (DSCP field, 6 bits). */
     uint8_t nw_proto;          /* IP protocol or lower 8 bits of
                                   ARP opcode. */
     uint8_t pad2[2];           /* Align to 64-bits. */
-    uint32_t nw_src;           /* IP source address. */
-    uint32_t nw_dst;           /* IP destination address. */
-    uint16_t tp_src;           /* TCP/UDP source port. */
-    uint16_t tp_dst;           /* TCP/UDP destination port. */
+    ovs_be32 nw_src;           /* IP source address. */
+    ovs_be32 nw_dst;           /* IP destination address. */
+    ovs_be16 tp_src;           /* TCP/UDP source port. */
+    ovs_be16 tp_dst;           /* TCP/UDP destination port. */
 };
 OFP_ASSERT(sizeof(struct ofp_match) == 40);
 
@@ -559,20 +559,20 @@ enum ofp_flow_mod_flags {
 struct ofp_flow_mod {
     struct ofp_header header;
     struct ofp_match match;      /* Fields to match */
-    uint64_t cookie;             /* Opaque controller-issued identifier. */
+    ovs_be64 cookie;             /* Opaque controller-issued identifier. */
 
     /* Flow actions. */
-    uint16_t command;             /* One of OFPFC_*. */
-    uint16_t idle_timeout;        /* Idle time before discarding (seconds). */
-    uint16_t hard_timeout;        /* Max time before discarding (seconds). */
-    uint16_t priority;            /* Priority level of flow entry. */
-    uint32_t buffer_id;           /* Buffered packet to apply to (or -1).
+    ovs_be16 command;             /* One of OFPFC_*. */
+    ovs_be16 idle_timeout;        /* Idle time before discarding (seconds). */
+    ovs_be16 hard_timeout;        /* Max time before discarding (seconds). */
+    ovs_be16 priority;            /* Priority level of flow entry. */
+    ovs_be32 buffer_id;           /* Buffered packet to apply to (or -1).
                                      Not meaningful for OFPFC_DELETE*. */
-    uint16_t out_port;            /* For OFPFC_DELETE* commands, require
+    ovs_be16 out_port;            /* For OFPFC_DELETE* commands, require
                                      matching entries to include this as an
                                      output port.  A value of OFPP_NONE
                                      indicates no restriction. */
-    uint16_t flags;               /* One of OFPFF_*. */
+    ovs_be16 flags;               /* One of OFPFF_*. */
     struct ofp_action_header actions[0]; /* The action length is inferred
                                             from the length field in the
                                             header. */
@@ -590,19 +590,19 @@ enum ofp_flow_removed_reason {
 struct ofp_flow_removed {
     struct ofp_header header;
     struct ofp_match match;   /* Description of fields. */
-    uint64_t cookie;          /* Opaque controller-issued identifier. */
+    ovs_be64 cookie;          /* Opaque controller-issued identifier. */
 
-    uint16_t priority;        /* Priority level of flow entry. */
+    ovs_be16 priority;        /* Priority level of flow entry. */
     uint8_t reason;           /* One of OFPRR_*. */
     uint8_t pad[1];           /* Align to 32-bits. */
 
-    uint32_t duration_sec;    /* Time flow was alive in seconds. */
-    uint32_t duration_nsec;   /* Time flow was alive in nanoseconds beyond
+    ovs_be32 duration_sec;    /* Time flow was alive in seconds. */
+    ovs_be32 duration_nsec;   /* Time flow was alive in nanoseconds beyond
                                  duration_sec. */
-    uint16_t idle_timeout;    /* Idle timeout from original flow mod. */
+    ovs_be16 idle_timeout;    /* Idle timeout from original flow mod. */
     uint8_t pad2[2];          /* Align to 64-bits. */
-    uint64_t packet_count;
-    uint64_t byte_count;
+    ovs_be64 packet_count;
+    ovs_be64 byte_count;
 };
 OFP_ASSERT(sizeof(struct ofp_flow_removed) == 88);
 
@@ -687,8 +687,8 @@ enum ofp_queue_op_failed_code {
 struct ofp_error_msg {
     struct ofp_header header;
 
-    uint16_t type;
-    uint16_t code;
+    ovs_be16 type;
+    ovs_be16 code;
     uint8_t data[0];          /* Variable-length data.  Interpreted based
                                  on the type and code. */
 };
@@ -734,8 +734,8 @@ enum ofp_stats_types {
 
 struct ofp_stats_request {
     struct ofp_header header;
-    uint16_t type;              /* One of the OFPST_* constants. */
-    uint16_t flags;             /* OFPSF_REQ_* flags (none yet defined). */
+    ovs_be16 type;              /* One of the OFPST_* constants. */
+    ovs_be16 flags;             /* OFPSF_REQ_* flags (none yet defined). */
     uint8_t body[0];            /* Body of the request. */
 };
 OFP_ASSERT(sizeof(struct ofp_stats_request) == 12);
@@ -746,8 +746,8 @@ enum ofp_stats_reply_flags {
 
 struct ofp_stats_reply {
     struct ofp_header header;
-    uint16_t type;              /* One of the OFPST_* constants. */
-    uint16_t flags;             /* OFPSF_REPLY_* flags. */
+    ovs_be16 type;              /* One of the OFPST_* constants. */
+    ovs_be16 flags;             /* OFPSF_REPLY_* flags. */
     uint8_t body[0];            /* Body of the reply. */
 };
 OFP_ASSERT(sizeof(struct ofp_stats_reply) == 12);
@@ -772,7 +772,7 @@ struct ofp_flow_stats_request {
     uint8_t table_id;         /* ID of table to read (from ofp_table_stats)
                                  or 0xff for all tables. */
     uint8_t pad;              /* Align to 32 bits. */
-    uint16_t out_port;        /* Require matching entries to include this
+    ovs_be16 out_port;        /* Require matching entries to include this
                                  as an output port.  A value of OFPP_NONE
                                  indicates no restriction. */
 };
@@ -780,17 +780,17 @@ OFP_ASSERT(sizeof(struct ofp_flow_stats_request) == 44);
 
 /* Body of reply to OFPST_FLOW request. */
 struct ofp_flow_stats {
-    uint16_t length;          /* Length of this entry. */
+    ovs_be16 length;          /* Length of this entry. */
     uint8_t table_id;         /* ID of table flow came from. */
     uint8_t pad;
     struct ofp_match match;   /* Description of fields. */
-    uint32_t duration_sec;    /* Time flow has been alive in seconds. */
-    uint32_t duration_nsec;   /* Time flow has been alive in nanoseconds
+    ovs_be32 duration_sec;    /* Time flow has been alive in seconds. */
+    ovs_be32 duration_nsec;   /* Time flow has been alive in nanoseconds
                                  beyond duration_sec. */
-    uint16_t priority;        /* Priority of the entry. Only meaningful
+    ovs_be16 priority;        /* Priority of the entry. Only meaningful
                                  when this is not an exact-match entry. */
-    uint16_t idle_timeout;    /* Number of seconds idle before expiration. */
-    uint16_t hard_timeout;    /* Number of seconds before expiration. */
+    ovs_be16 idle_timeout;    /* Number of seconds idle before expiration. */
+    ovs_be16 hard_timeout;    /* Number of seconds before expiration. */
     uint8_t pad2[6];          /* Align to 64 bits. */
     ovs_32aligned_be64 cookie;       /* Opaque controller-issued identifier. */
     ovs_32aligned_be64 packet_count; /* Number of packets in flow. */
@@ -805,7 +805,7 @@ struct ofp_aggregate_stats_request {
     uint8_t table_id;         /* ID of table to read (from ofp_table_stats)
                                  or 0xff for all tables. */
     uint8_t pad;              /* Align to 32 bits. */
-    uint16_t out_port;        /* Require matching entries to include this
+    ovs_be16 out_port;        /* Require matching entries to include this
                                  as an output port.  A value of OFPP_NONE
                                  indicates no restriction. */
 };
@@ -815,7 +815,7 @@ OFP_ASSERT(sizeof(struct ofp_aggregate_stats_request) == 44);
 struct ofp_aggregate_stats_reply {
     ovs_32aligned_be64 packet_count; /* Number of packets in flows. */
     ovs_32aligned_be64 byte_count;   /* Number of bytes in flows. */
-    uint32_t flow_count;      /* Number of flows. */
+    ovs_be32 flow_count;      /* Number of flows. */
     uint8_t pad[4];           /* Align to 64 bits. */
 };
 OFP_ASSERT(sizeof(struct ofp_aggregate_stats_reply) == 24);
@@ -826,10 +826,10 @@ struct ofp_table_stats {
                                 are consulted first. */
     uint8_t pad[3];          /* Align to 32-bits. */
     char name[OFP_MAX_TABLE_NAME_LEN];
-    uint32_t wildcards;      /* Bitmap of OFPFW_* wildcards that are
+    ovs_be32 wildcards;      /* Bitmap of OFPFW_* wildcards that are
                                 supported by the table. */
-    uint32_t max_entries;    /* Max number of entries supported. */
-    uint32_t active_count;   /* Number of active entries. */
+    ovs_be32 max_entries;    /* Max number of entries supported. */
+    ovs_be32 active_count;   /* Number of active entries. */
     ovs_32aligned_be64 lookup_count;  /* # of packets looked up in table. */
     ovs_32aligned_be64 matched_count; /* Number of packets that hit table. */
 };
@@ -837,7 +837,7 @@ OFP_ASSERT(sizeof(struct ofp_table_stats) == 64);
 
 /* Body for ofp_stats_request of type OFPST_PORT. */
 struct ofp_port_stats_request {
-    uint16_t port_no;        /* OFPST_PORT message may request statistics
+    ovs_be16 port_no;        /* OFPST_PORT message may request statistics
                                 for a single port (specified with port_no)
                                 or for all ports (port_no == OFPP_NONE). */
     uint8_t pad[6];
@@ -847,7 +847,7 @@ OFP_ASSERT(sizeof(struct ofp_port_stats_request) == 8);
 /* Body of reply to OFPST_PORT request. If a counter is unsupported, set
  * the field to all ones. */
 struct ofp_port_stats {
-    uint16_t port_no;
+    ovs_be16 port_no;
     uint8_t pad[6];          /* Align to 64-bits. */
     ovs_32aligned_be64 rx_packets;     /* Number of received packets. */
     ovs_32aligned_be64 tx_packets;     /* Number of transmitted packets. */
@@ -873,18 +873,18 @@ OFP_ASSERT(sizeof(struct ofp_port_stats) == 104);
 
 /* Body for ofp_stats_request of type OFPST_QUEUE. */
 struct ofp_queue_stats_request {
-    uint16_t port_no;        /* All ports if OFPP_ALL. */
+    ovs_be16 port_no;        /* All ports if OFPP_ALL. */
     uint8_t pad[2];          /* Align to 32-bits. */
-    uint32_t queue_id;       /* All queues if OFPQ_ALL. */
+    ovs_be32 queue_id;       /* All queues if OFPQ_ALL. */
 };
 OFP_ASSERT(sizeof(struct ofp_queue_stats_request) == 8);
 
 /* Body for ofp_stats_reply of type OFPST_QUEUE consists of an array of this
  * structure type. */
 struct ofp_queue_stats {
-    uint16_t port_no;
+    ovs_be16 port_no;
     uint8_t pad[2];          /* Align to 32-bits. */
-    uint32_t queue_id;       /* Queue id. */
+    ovs_be32 queue_id;       /* Queue id. */
     ovs_32aligned_be64 tx_bytes;   /* Number of transmitted bytes. */
     ovs_32aligned_be64 tx_packets; /* Number of transmitted packets. */
     ovs_32aligned_be64 tx_errors;  /* # of packets dropped due to overrun. */
@@ -894,7 +894,7 @@ OFP_ASSERT(sizeof(struct ofp_queue_stats) == 32);
 /* Vendor extension. */
 struct ofp_vendor_header {
     struct ofp_header header;   /* Type OFPT_VENDOR. */
-    uint32_t vendor;            /* Vendor ID:
+    ovs_be32 vendor;            /* Vendor ID:
                                  * - MSB 0: low-order bytes are IEEE OUI.
                                  * - MSB != 0: defined by OpenFlow
                                  *   consortium. */
index 9ddb857..4d2a1e9 100644 (file)
@@ -17,7 +17,6 @@
 #ifndef OPENVSWITCH_TYPES_H
 #define OPENVSWITCH_TYPES_H 1
 
-#include <arpa/inet.h>
 #include <sys/types.h>
 #include <stdint.h>
 
diff --git a/include/sparse/arpa/inet.h b/include/sparse/arpa/inet.h
new file mode 100644 (file)
index 0000000..c545f29
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * 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 __CHECKER__
+#error "Use this header only with sparse.  It is not a correct implementation."
+#endif
+
+#include <netinet/in.h>
diff --git a/include/sparse/assert.h b/include/sparse/assert.h
new file mode 100644 (file)
index 0000000..f396761
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * 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 __CHECKER__
+#error "Use this header only with sparse.  It is not a correct implementation."
+#endif
+
+extern void __ovs_assert(_Bool);
+#define assert(EXPRESSION) __ovs_assert(EXPRESSION)
diff --git a/include/sparse/automake.mk b/include/sparse/automake.mk
new file mode 100644 (file)
index 0000000..1a77500
--- /dev/null
@@ -0,0 +1,8 @@
+noinst_HEADERS += \
+        include/sparse/arpa/inet.h \
+        include/sparse/assert.h \
+        include/sparse/math.h \
+        include/sparse/netinet/in.h \
+        include/sparse/netinet/ip6.h \
+        include/sparse/sys/socket.h \
+        include/sparse/sys/wait.h
diff --git a/include/sparse/math.h b/include/sparse/math.h
new file mode 100644 (file)
index 0000000..884c6de
--- /dev/null
@@ -0,0 +1,203 @@
+/*
+ * 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 __CHECKER__
+#error "Use this header only with sparse.  It is not a correct implementation."
+#endif
+
+#ifndef __SYS_MATH_SPARSE
+#define __SYS_MATH_SPARSE 1
+
+double acos(double);
+float acosf(float);
+double acosh(double);
+float acoshf(float);
+long double acoshl(long double);
+long double acosl(long double);
+double asin(double);
+float asinf(float);
+double asinh(double);
+float asinhf(float);
+long double asinhl(long double);
+long double asinl(long double);
+double atan(double);
+double atan2(double, double);
+float atan2f(float, float);
+long double atan2l(long double, long double);
+float atanf(float);
+double atanh(double);
+float atanhf(float);
+long double atanhl(long double);
+long double atanl(long double);
+double cbrt(double);
+float cbrtf(float);
+long double cbrtl(long double);
+double ceil(double);
+float ceilf(float);
+long double ceill(long double);
+double copysign(double, double);
+float copysignf(float, float);
+long double copysignl(long double, long double);
+double cos(double);
+float cosf(float);
+double cosh(double);
+float coshf(float);
+long double coshl(long double);
+long double cosl(long double);
+double erf(double);
+double erfc(double);
+float erfcf(float);
+long double erfcl(long double);
+float erff(float);
+long double erfl(long double);
+double exp(double);
+double exp2(double);
+float exp2f(float);
+long double exp2l(long double);
+float expf(float);
+long double expl(long double);
+double expm1(double);
+float expm1f(float);
+long double expm1l(long double);
+double fabs(double);
+float fabsf(float);
+long double fabsl(long double);
+double fdim(double, double);
+float fdimf(float, float);
+long double fdiml(long double, long double);
+double floor(double);
+float floorf(float);
+long double floorl(long double);
+double fma(double, double, double);
+float fmaf(float, float, float);
+long double fmal(long double, long double, long double);
+double fmax(double, double);
+float fmaxf(float, float);
+long double fmaxl(long double, long double);
+double fmin(double, double);
+float fminf(float, float);
+long double fminl(long double, long double);
+double fmod(double, double);
+float fmodf(float, float);
+long double fmodl(long double, long double);
+double frexp(double, int *);
+float frexpf(float value, int *);
+long double frexpl(long double value, int *);
+double hypot(double, double);
+float hypotf(float, float);
+long double hypotl(long double, long double);
+int ilogb(double);
+int ilogbf(float);
+int ilogbl(long double);
+double j0(double);
+double j1(double);
+double jn(int, double);
+double ldexp(double, int);
+float ldexpf(float, int);
+long double ldexpl(long double, int);
+double lgamma(double);
+float lgammaf(float);
+long double lgammal(long double);
+long long llrint(double);
+long long llrintf(float);
+long long llrintl(long double);
+long long llround(double);
+long long llroundf(float);
+long long llroundl(long double);
+double log(double);
+double log10(double);
+float log10f(float);
+long double log10l(long double);
+double log1p(double);
+float log1pf(float);
+long double log1pl(long double);
+double log2(double);
+float log2f(float);
+long double log2l(long double);
+double logb(double);
+float logbf(float);
+long double logbl(long double);
+float logf(float);
+long double logl(long double);
+long lrint(double);
+long lrintf(float);
+long lrintl(long double);
+long lround(double);
+long lroundf(float);
+long lroundl(long double);
+double modf(double, double *);
+float modff(float, float *);
+long double modfl(long double, long double *);
+double nan(const char *);
+float nanf(const char *);
+long double nanl(const char *);
+double nearbyint(double);
+float nearbyintf(float);
+long double nearbyintl(long double);
+double nextafter(double, double);
+float nextafterf(float, float);
+long double nextafterl(long double, long double);
+double nexttoward(double, long double);
+float nexttowardf(float, long double);
+long double nexttowardl(long double, long double);
+double pow(double, double);
+float powf(float, float);
+long double powl(long double, long double);
+double remainder(double, double);
+float remainderf(float, float);
+long double remainderl(long double, long double);
+double remquo(double, double, int *);
+float remquof(float, float, int *);
+long double remquol(long double, long double, int *);
+double rint(double);
+float rintf(float);
+long double rintl(long double);
+double round(double);
+float roundf(float);
+long double roundl(long double);
+double scalb(double, double);
+double scalbln(double, long);
+float scalblnf(float, long);
+long double scalblnl(long double, long);
+double scalbn(double, int);
+float scalbnf(float, int);
+long double scalbnl(long double, int);
+double sin(double);
+float sinf(float);
+double sinh(double);
+float sinhf(float);
+long double sinhl(long double);
+long double sinl(long double);
+double sqrt(double);
+float sqrtf(float);
+long double sqrtl(long double);
+double tan(double);
+float tanf(float);
+double tanh(double);
+float tanhf(float);
+long double tanhl(long double);
+long double tanl(long double);
+double tgamma(double);
+float tgammaf(float);
+long double tgammal(long double);
+double trunc(double);
+float truncf(float);
+long double truncl(long double);
+double y0(double);
+double y1(double);
+double yn(int, double);
+
+#endif /* <sys/math.h> for sparse */
diff --git a/include/sparse/netinet/in.h b/include/sparse/netinet/in.h
new file mode 100644 (file)
index 0000000..d86431a
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+ * 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 __CHECKER__
+#error "Use this header only with sparse.  It is not a correct implementation."
+#endif
+
+#ifndef __NETINET_IN_SPARSE
+#define __NETINET_IN_SPARSE 1
+
+#include "openvswitch/types.h"
+#include <inttypes.h>
+#include <sys/socket.h>
+
+typedef ovs_be16 in_port_t;
+typedef ovs_be32 in_addr_t;
+
+struct in_addr {
+    in_addr_t s_addr;
+};
+
+struct sockaddr_in {
+    sa_family_t sin_family;
+    in_port_t sin_port;
+    struct in_addr sin_addr;
+};
+
+struct in6_addr {
+    union {
+        uint8_t u_s6_addr[16];
+    } u;
+};
+
+#define s6_addr u.u_s6_addr
+
+extern const struct in6_addr in6addr_any;
+
+#define IPPROTO_IP 0
+#define IPPROTO_HOPOPTS 0
+#define IPPROTO_ICMP 1
+#define IPPROTO_TCP 6
+#define IPPROTO_UDP 17
+#define IPPROTO_ROUTING 43
+#define IPPROTO_FRAGMENT 44
+#define IPPROTO_AH 51
+#define IPPROTO_ICMPV6 58
+#define IPPROTO_NONE 59
+#define IPPROTO_DSTOPTS 60
+
+#define INADDR_ANY              0x00000000
+#define INADDR_BROADCAST        0xffffffff
+#define INADDR_NONE             0xffffffff
+
+#define INET6_ADDRSTRLEN 46
+
+static inline ovs_be32 htonl(uint32_t x)
+{
+    return (OVS_FORCE ovs_be32) x;
+}
+
+static inline ovs_be16 htons(uint16_t x)
+{
+    return (OVS_FORCE ovs_be16) x;
+}
+
+static inline uint32_t ntohl(ovs_be32 x)
+{
+    return (OVS_FORCE uint32_t) x;
+}
+
+static inline uint16_t ntohs(ovs_be16 x)
+{
+    return (OVS_FORCE uint16_t) x;
+}
+
+in_addr_t inet_addr(const char *);
+int inet_aton (const char *, struct in_addr *);
+char *inet_ntoa(struct in_addr);
+const char *inet_ntop(int, const void *, char *, socklen_t);
+int inet_pton(int, const char *, void *);
+
+#endif /* <netinet/in.h> sparse */
diff --git a/include/sparse/netinet/ip6.h b/include/sparse/netinet/ip6.h
new file mode 100644 (file)
index 0000000..c6608a1
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * 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 __CHECKER__
+#error "Use this header only with sparse.  It is not a correct implementation."
+#endif
+
+#ifndef __NETINET_IP6_SPARSE
+#define __NETINET_IP6_SPARSE 1
+
+#include <netinet/in.h>
+
+struct ip6_hdr {
+    union {
+        struct ip6_hdrctl {
+            ovs_be32 ip6_un1_flow;
+            ovs_be16 ip6_un1_plen;
+            uint8_t ip6_un1_nxt;
+            uint8_t ip6_un1_hlim;
+        } ip6_un1;
+        uint8_t ip6_un2_vfc;
+    } ip6_ctlun;
+    struct in6_addr ip6_src;
+    struct in6_addr ip6_dst;
+};
+
+#define ip6_vfc   ip6_ctlun.ip6_un2_vfc
+#define ip6_flow  ip6_ctlun.ip6_un1.ip6_un1_flow
+#define ip6_plen  ip6_ctlun.ip6_un1.ip6_un1_plen
+#define ip6_nxt   ip6_ctlun.ip6_un1.ip6_un1_nxt
+#define ip6_hlim  ip6_ctlun.ip6_un1.ip6_un1_hlim
+#define ip6_hops  ip6_ctlun.ip6_un1.ip6_un1_hlim
+
+struct ip6_ext {
+    uint8_t ip6e_nxt;
+    uint8_t ip6e_len;
+};
+
+struct ip6_frag {
+    uint8_t ip6f_nxt;
+    uint8_t ip6f_reserved;
+    ovs_be16 ip6f_offlg;
+    ovs_be32 ip6f_ident;
+};
+
+#define IP6F_OFF_MASK ((OVS_FORCE ovs_be16) 0xfff8)
+
+#endif /* netinet/ip6.h sparse */
diff --git a/include/sparse/sys/socket.h b/include/sparse/sys/socket.h
new file mode 100644 (file)
index 0000000..89e3c2d
--- /dev/null
@@ -0,0 +1,133 @@
+/*
+ * 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 __CHECKER__
+#error "Use this header only with sparse.  It is not a correct implementation."
+#endif
+
+#ifndef __SYS_SOCKET_SPARSE
+#define __SYS_SOCKET_SPARSE 1
+
+#include "openvswitch/types.h"
+#include <sys/uio.h>
+
+typedef unsigned short int sa_family_t;
+typedef __socklen_t socklen_t;
+
+struct sockaddr {
+    sa_family_t sa_family;
+    char sa_data[64];
+};
+
+struct sockaddr_storage {
+    sa_family_t ss_family;
+    char sa_data[64];
+};
+
+struct msghdr {
+    void *msg_name;
+    socklen_t      msg_namelen;
+    struct iovec  *msg_iov;
+    int            msg_iovlen;
+    void          *msg_control;
+    socklen_t      msg_controllen;
+    int            msg_flags;
+};
+
+enum {
+    SOCK_DGRAM,
+    SOCK_RAW,
+    SOCK_SEQPACKET,
+    SOCK_STREAM
+};
+
+enum {
+    SOL_SOCKET
+};
+
+enum {
+    SO_ACCEPTCONN,
+    SO_BROADCAST,
+    SO_DEBUG,
+    SO_DONTROUTE,
+    SO_ERROR,
+    SO_KEEPALIVE,
+    SO_LINGER,
+    SO_OOBINLINE,
+    SO_RCVBUF,
+    SO_RCVLOWAT,
+    SO_RCVTIMEO,
+    SO_REUSEADDR,
+    SO_SNDBUF,
+    SO_SNDLOWAT,
+    SO_SNDTIMEO,
+    SO_TYPE
+};
+
+enum {
+    MSG_CTRUNC,
+    MSG_DONTROUTE,
+    MSG_EOR,
+    MSG_OOB,
+    MSG_NOSIGNAL,
+    MSG_PEEK,
+    MSG_TRUNC,
+    MSG_WAITALL,
+    MSG_DONTWAIT
+};
+
+enum {
+    AF_UNSPEC,
+    PF_UNSPEC = AF_UNSPEC,
+    AF_INET,
+    PF_INET = AF_INET,
+    AF_INET6,
+    PF_INET6 = AF_INET6,
+    AF_UNIX,
+    PF_UNIX = AF_UNIX,
+    AF_NETLINK,
+    PF_NETLINK = AF_NETLINK,
+    AF_PACKET,
+    PF_PACKET = AF_PACKET
+};
+
+enum {
+    SHUT_RD,
+    SHUT_RDWR,
+    SHUT_WR
+};
+
+int accept(int, struct sockaddr *, socklen_t *);
+int bind(int, const struct sockaddr *, socklen_t);
+int connect(int, const struct sockaddr *, socklen_t);
+int getpeername(int, struct sockaddr *, socklen_t *);
+int getsockname(int, struct sockaddr *, socklen_t *);
+int getsockopt(int, int, int, void *, socklen_t *);
+int listen(int, int);
+ssize_t recv(int, void *, size_t, int);
+ssize_t recvfrom(int, void *, size_t, int, struct sockaddr *, socklen_t *);
+ssize_t recvmsg(int, struct msghdr *, int);
+ssize_t send(int, const void *, size_t, int);
+ssize_t sendmsg(int, const struct msghdr *, int);
+ssize_t sendto(int, const void *, size_t, int, const struct sockaddr *,
+               socklen_t);
+int setsockopt(int, int, int, const void *, socklen_t);
+int shutdown(int, int);
+int sockatmark(int);
+int socket(int, int, int);
+int socketpair(int, int, int, int[2]);
+
+#endif /* <sys/socket.h> for sparse */
diff --git a/include/sparse/sys/wait.h b/include/sparse/sys/wait.h
new file mode 100644 (file)
index 0000000..31e1d76
--- /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 __CHECKER__
+#error "Use this header only with sparse.  It is not a correct implementation."
+#endif
+
+#ifndef __SYS_WAIT_SPARSE
+#define __SYS_WAIT_SPARSE 1
+
+#include_next <sys/wait.h>
+
+#undef wait
+#define wait(a) rpl_wait(a)
+pid_t rpl_wait(int *);
+
+#undef waitpid
+#define waitpid(a, b, c) rpl_waitpid(a, b, c)
+pid_t rpl_waitpid(pid_t, int *, int);
+
+#endif /* <sys/wait.h> for sparse */
index 91549db..1c0dfd6 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 <config.h>
+
 #include "backtrace.h"
+
 #include <errno.h>
 #include <inttypes.h>
 #include <stdbool.h>
 #include <stdio.h>
+
 #include "compiler.h"
 #include "vlog.h"
 
 VLOG_DEFINE_THIS_MODULE(backtrace);
 
-static uintptr_t OVS_UNUSED
+#ifdef HAVE_BACKTRACE
+#include <execinfo.h>
+void
+backtrace_capture(struct backtrace *b)
+{
+    void *frames[BACKTRACE_MAX_FRAMES];
+    int i;
+
+    b->n_frames = backtrace(frames, BACKTRACE_MAX_FRAMES);
+    for (i = 0; i < b->n_frames; i++) {
+        b->frames[i] = (uintptr_t) frames[i];
+    }
+}
+#elif __GNUC__
+static uintptr_t
 get_max_stack(void)
 {
     static const char file_name[] = "/proc/self/maps";
@@ -83,7 +100,6 @@ in_stack(void *p)
 void
 backtrace_capture(struct backtrace *backtrace)
 {
-#ifdef __GNUC__
     void **frame;
     size_t n;
 
@@ -96,7 +112,11 @@ backtrace_capture(struct backtrace *backtrace)
         backtrace->frames[n++] = (uintptr_t) frame[1];
     }
     backtrace->n_frames = n;
-#else
+}
+#else  /* !HAVE_BACKTRACE && !__GNUC__ */
+void
+backtrace_capture(struct backtrace *backtrace)
+{
     backtrace->n_frames = 0;
-#endif
 }
+#endif
index 6f18824..9caa3f2 100644 (file)
@@ -487,6 +487,10 @@ bond_run(struct bond *bond, struct tag_set *tags, bool lacp_negotiated)
         bond->miimon_next_update = time_msec() + bond->miimon_interval;
     }
 
+    if (bond->monitor) {
+        netdev_monitor_flush(bond->monitor);
+    }
+
     /* Enable slaves based on link status and LACP feedback. */
     HMAP_FOR_EACH (slave, hmap_node, &bond->slaves) {
         bond_link_status_update(slave, tags);
@@ -1405,7 +1409,7 @@ static unsigned int
 bond_hash_tcp(const struct flow *flow, uint16_t vlan, uint32_t basis)
 {
     struct flow hash_flow = *flow;
-    hash_flow.vlan_tci = vlan;
+    hash_flow.vlan_tci = htons(vlan);
 
     /* The symmetric quality of this hash function is not required, but
      * flow_hash_symmetric_l4 already exists, and is sufficient for our
index d2bc8db..993137f 100644 (file)
@@ -21,6 +21,7 @@
 #include <inttypes.h>
 #include "openvswitch/types.h"
 
+#ifndef __CHECKER__
 static inline ovs_be64
 htonll(uint64_t n)
 {
@@ -32,14 +33,21 @@ ntohll(ovs_be64 n)
 {
     return htonl(1) == 1 ? n : ((uint64_t) ntohl(n) << 32) | ntohl(n >> 32);
 }
+#else
+/* Making sparse happy with these functions also makes them unreadable, so
+ * don't bother to show it their implementations. */
+ovs_be64 htonll(uint64_t);
+uint64_t ntohll(ovs_be64);
+#endif
 
 /* These macros may substitute for htons(), htonl(), and htonll() in contexts
  * where function calls are not allowed, such as case labels.  They should not
  * be used elsewhere because all of them evaluate their argument many times. */
-#ifdef WORDS_BIGENDIAN
-#define CONSTANT_HTONS(VALUE) ((ovs_be16) (VALUE))
-#define CONSTANT_HTONL(VALUE) ((ovs_be32) (VALUE))
-#define CONSTANT_HTONLL(VALUE) ((ovs_be64) (VALUE))
+#if defined(WORDS_BIGENDIAN) || __CHECKER__
+#define CONSTANT_HTONS(VALUE) ((OVS_FORCE ovs_be16) ((VALUE) & 0xffff))
+#define CONSTANT_HTONL(VALUE) ((OVS_FORCE ovs_be32) ((VALUE) & 0xffffffff))
+#define CONSTANT_HTONLL(VALUE) \
+        ((OVS_FORCE ovs_be64) ((VALUE) & UINT64_C(0xffffffffffffffff)))
 #else
 #define CONSTANT_HTONS(VALUE)                       \
         (((((ovs_be16) (VALUE)) & 0xff00) >> 8) |   \
index a504714..a605c09 100644 (file)
--- a/lib/cfm.c
+++ b/lib/cfm.c
@@ -45,10 +45,10 @@ struct cfm_internal {
 
     struct timer tx_timer;    /* Send CCM when expired. */
     struct timer fault_timer; /* Check for faults when expired. */
-
-    long long x_recv_time;
 };
 
+static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 20);
+
 static int
 ccm_interval_to_ms(uint8_t interval)
 {
@@ -129,8 +129,9 @@ lookup_remote_mp(const struct hmap *hmap, uint16_t mpid)
 }
 
 /* Allocates a 'cfm' object.  This object should have its 'mpid', 'maid',
- * 'eth_src', and 'interval' filled out.  When changes are made to the 'cfm'
- * object, cfm_configure should be called before using it. */
+ * 'eth_src', and 'interval' filled out.  cfm_configure() should be called
+ * whenever changes are made to 'cfm', and before cfm_run() is called for the
+ * first time. */
 struct cfm *
 cfm_create(void)
 {
@@ -139,7 +140,6 @@ cfm_create(void)
 
     cfmi = xzalloc(sizeof *cfmi);
     cfm  = &cfmi->cfm;
-    cfmi->x_recv_time = LLONG_MIN;
 
     hmap_init(&cfm->remote_mps);
     return cfm;
@@ -168,29 +168,28 @@ cfm_destroy(struct cfm *cfm)
 void
 cfm_run(struct cfm *cfm)
 {
-    long long now = time_msec();
     struct cfm_internal *cfmi = cfm_to_internal(cfm);
 
     if (timer_expired(&cfmi->fault_timer)) {
-        bool fault;
+        long long int interval = cfm_fault_interval(cfmi);
         struct remote_mp *rmp;
-        long long int interval;
-
-        interval = cfm_fault_interval(cfmi);
-        fault = now < cfmi->x_recv_time + interval;
 
+        cfm->fault = false;
         HMAP_FOR_EACH (rmp, node, &cfm->remote_mps) {
-            if (rmp->recv_time < timer_enabled_at(&cfmi->fault_timer, interval)
-                || timer_expired_at(&cfmi->fault_timer, rmp->recv_time)) {
-                rmp->fault = true;
-            }
+            rmp->fault = !rmp->recv;
+            rmp->recv = false;
 
             if (rmp->fault) {
-                fault = true;
+                cfm->fault = true;
+                VLOG_DBG("No CCM from RMP %"PRIu16" in the last %lldms",
+                         rmp->mpid, interval);
             }
         }
 
-        cfm->fault = fault;
+        if (!cfm->fault) {
+            VLOG_DBG("All RMPs received CCMs in the last %lldms", interval);
+        }
+
         timer_set_duration(&cfmi->fault_timer, interval);
     }
 }
@@ -360,9 +359,7 @@ cfm_process_heartbeat(struct cfm *cfm, const struct ofpbuf *p)
     uint8_t ccm_interval;
     struct remote_mp *rmp;
     struct eth_header *eth;
-
-    struct cfm_internal *cfmi        = cfm_to_internal(cfm);
-    static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 20);
+    struct cfm_internal *cfmi = cfm_to_internal(cfm);
 
     eth = p->l2;
     ccm = ofpbuf_at(p, (uint8_t *)p->l3 - (uint8_t *)p->data, CCM_LEN);
@@ -378,9 +375,16 @@ cfm_process_heartbeat(struct cfm *cfm, const struct ofpbuf *p)
         return;
     }
 
+    /* According to the 802.1ag specification, reception of a CCM with an
+     * incorrect ccm_interval, unexpected MAID, or unexpected MPID should
+     * trigger a fault.  We ignore this requirement for several reasons.
+     *
+     * Faults can cause a controller or Open vSwitch to make potentially
+     * expensive changes to the network topology.  It seems prudent to trigger
+     * them judiciously, especially when CFM is used to check slave status of
+     * bonds. Furthermore, faults can be maliciously triggered by crafting
+     * invalid CCMs. */
     if (memcmp(ccm->maid, cfm->maid, sizeof ccm->maid)) {
-        cfmi->x_recv_time = time_msec();
-        cfm->fault = true;
         VLOG_WARN_RL(&rl, "Received unexpected remote MAID from MAC "
                      ETH_ADDR_FMT, ETH_ADDR_ARGS(eth->eth_src));
     } else {
@@ -390,15 +394,20 @@ cfm_process_heartbeat(struct cfm *cfm, const struct ofpbuf *p)
         rmp = lookup_remote_mp(&cfm->remote_mps, ccm_mpid);
 
         if (rmp) {
-            rmp->recv_time = time_msec();
-            rmp->fault = ccm_interval != cfmi->ccm_interval;
-            cfm->fault = rmp->fault || cfm->fault;
+            rmp->recv = true;
+
+            if (ccm_interval != cfmi->ccm_interval) {
+                VLOG_WARN_RL(&rl, "received a CCM with an invalid interval"
+                             " (%"PRIu8") from RMP %"PRIu16, ccm_interval,
+                             rmp->mpid);
+            }
         } else {
-            cfmi->x_recv_time = time_msec();
-            cfm->fault = true;
             VLOG_WARN_RL(&rl, "Received unexpected remote MPID %d from MAC "
                          ETH_ADDR_FMT, ccm_mpid, ETH_ADDR_ARGS(eth->eth_src));
         }
+
+        VLOG_DBG("Received CCM (mpid %"PRIu16") (interval %"PRIu8")", ccm_mpid,
+                 ccm_interval);
     }
 }
 
@@ -406,7 +415,6 @@ void
 cfm_dump_ds(const struct cfm *cfm, struct ds *ds)
 {
     const struct cfm_internal *cfmi = cfm_to_internal(cfm);
-    long long int now = time_msec();
     struct remote_mp *rmp;
 
     ds_put_format(ds, "MPID %"PRIu16": %s\n", cfm->mpid,
@@ -418,16 +426,11 @@ cfm_dump_ds(const struct cfm *cfm, struct ds *ds)
     ds_put_format(ds, "\tnext fault check: %lldms\n",
                   timer_msecs_until_expired(&cfmi->fault_timer));
 
-    if (cfmi->x_recv_time != LLONG_MIN) {
-        ds_put_format(ds, "\ttime since bad CCM rx: %lldms\n",
-                      now - cfmi->x_recv_time);
-    }
-
     ds_put_cstr(ds, "\n");
     HMAP_FOR_EACH (rmp, node, &cfm->remote_mps) {
         ds_put_format(ds, "Remote MPID %"PRIu16": %s\n", rmp->mpid,
                       rmp->fault ? "fault" : "");
-        ds_put_format(ds, "\ttime since CCM rx: %lldms\n",
-                      time_msec() - rmp->recv_time);
+        ds_put_format(ds, "\trecv since check: %s",
+                      rmp->recv ? "true" : "false");
     }
 }
index 1be1981..4bb8dc9 100644 (file)
--- a/lib/cfm.h
+++ b/lib/cfm.h
@@ -69,7 +69,7 @@ struct remote_mp {
     uint16_t mpid;         /* The Maintenance Point ID of this 'remote_mp'. */
     struct hmap_node node; /* In 'cfm' 'remote_mps' or 'x_remote_mps'. */
 
-    long long recv_time; /* Time the most recent CCM was received. */
+    bool recv;           /* CCM was received since last fault check. */
     bool fault;          /* Indicates a connectivity fault. */
 };
 
index 6bf5144..9e9eb82 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.
@@ -17,7 +17,7 @@
 #ifndef COMPILER_H
 #define COMPILER_H 1
 
-#ifdef __GNUC__
+#if __GNUC__ && !__CHECKER__
 #define NO_RETURN __attribute__((__noreturn__))
 #define OVS_UNUSED __attribute__((__unused__))
 #define PRINTF_FORMAT(FMT, ARG1) __attribute__((__format__(printf, FMT, ARG1)))
index d816fb6..b7db6c4 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.
@@ -41,6 +41,7 @@ struct coverage_counter {
 #if USE_LINKER_SECTIONS
 #define COVERAGE_DEFINE(COUNTER)                                        \
         COVERAGE_DEFINE__(COUNTER);                                     \
+        extern struct coverage_counter *counter_ptr_##COUNTER;          \
         struct coverage_counter *counter_ptr_##COUNTER                  \
             __attribute__((section("coverage"))) = &counter_##COUNTER
 #else
@@ -60,6 +61,7 @@ void coverage_clear(void);
 
 /* Implementation detail. */
 #define COVERAGE_DEFINE__(COUNTER)                              \
+        extern struct coverage_counter counter_##COUNTER;       \
         struct coverage_counter counter_##COUNTER = { #COUNTER, 0, 0 }
 
 #endif /* coverage.h */
index 33ec28b..47e803e 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 "csum.h"
 #include "unaligned.h"
 
+#ifndef __CHECKER__
+
 /* Returns the IP checksum of the 'n' bytes in 'data'.
  *
  * The return value has the same endianness as the data.  That is, if 'data'
  * consists of a packet in network byte order, then the return value is a value
  * in network byte order, and if 'data' consists of a data structure in host
  * byte order, then the return value is in host byte order. */
-uint16_t
+ovs_be16
 csum(const void *data, size_t n)
 {
     return csum_finish(csum_continue(0, data, n));
@@ -34,7 +36,7 @@ csum(const void *data, size_t n)
  * the updated checksum.  (To start a new checksum, pass 0 for 'partial'.  To
  * obtain the finished checksum, pass the return value to csum_finish().) */
 uint32_t
-csum_add16(uint32_t partial, uint16_t new)
+csum_add16(uint32_t partial, ovs_be16 new)
 {
     return partial + new;
 }
@@ -43,7 +45,7 @@ csum_add16(uint32_t partial, uint16_t new)
  * the updated checksum.  (To start a new checksum, pass 0 for 'partial'.  To
  * obtain the finished checksum, pass the return value to csum_finish().) */
 uint32_t
-csum_add32(uint32_t partial, uint32_t new)
+csum_add32(uint32_t partial, ovs_be32 new)
 {
     return partial + (new >> 16) + (new & 0xffff);
 }
@@ -56,10 +58,10 @@ csum_add32(uint32_t partial, uint32_t new)
 uint32_t
 csum_continue(uint32_t partial, const void *data_, size_t n)
 {
-    const uint16_t *data = data_;
+    const ovs_be16 *data = data_;
 
     for (; n > 1; n -= 2, data++) {
-        partial = csum_add16(partial, get_unaligned_u16(data));
+        partial = csum_add16(partial, get_unaligned_be16(data));
     }
     if (n) {
         partial += *(uint8_t *) data;
@@ -74,7 +76,7 @@ csum_continue(uint32_t partial, const void *data_, size_t n)
  * if the data consist of a packet in network byte order, then the return value
  * is a value in network byte order, and if the data are a data structure in
  * host byte order, then the return value is in host byte order. */
-uint16_t
+ovs_be16
 csum_finish(uint32_t partial)
 {
     while (partial >> 16) {
@@ -86,8 +88,8 @@ csum_finish(uint32_t partial)
 /* Returns the new checksum for a packet in which the checksum field previously
  * contained 'old_csum' and in which a field that contained 'old_u16' was
  * changed to contain 'new_u16'. */
-uint16_t
-recalc_csum16(uint16_t old_csum, uint16_t old_u16, uint16_t new_u16)
+ovs_be16
+recalc_csum16(ovs_be16 old_csum, ovs_be16 old_u16, ovs_be16 new_u16)
 {
     /* Ones-complement arithmetic is endian-independent, so this code does not
      * use htons() or ntohs().
@@ -103,9 +105,14 @@ recalc_csum16(uint16_t old_csum, uint16_t old_u16, uint16_t new_u16)
 /* Returns the new checksum for a packet in which the checksum field previously
  * contained 'old_csum' and in which a field that contained 'old_u32' was
  * changed to contain 'new_u32'. */
-uint16_t
-recalc_csum32(uint16_t old_csum, uint32_t old_u32, uint32_t new_u32)
+ovs_be16
+recalc_csum32(ovs_be16 old_csum, ovs_be32 old_u32, ovs_be32 new_u32)
 {
     return recalc_csum16(recalc_csum16(old_csum, old_u32, new_u32),
                          old_u32 >> 16, new_u32 >> 16);
 }
+
+#else  /* __CHECKER__ */
+/* Making sparse happy with these functions also makes them unreadable, so
+ * don't bother to show it their implementations. */
+#endif
index 5213055..e5f35e9 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Nicira Networks.
+ * Copyright (c) 2008, 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 <stddef.h>
 #include <stdint.h>
+#include "openvswitch/types.h"
 
-uint16_t csum(const void *, size_t);
-uint32_t csum_add16(uint32_t partial, uint16_t);
-uint32_t csum_add32(uint32_t partial, uint32_t);
+ovs_be16 csum(const void *, size_t);
+uint32_t csum_add16(uint32_t partial, ovs_be16);
+uint32_t csum_add32(uint32_t partial, ovs_be32);
 uint32_t csum_continue(uint32_t partial, const void *, size_t);
-uint16_t csum_finish(uint32_t partial);
-uint16_t recalc_csum16(uint16_t old_csum, uint16_t old_u16, uint16_t new_u16);
-uint16_t recalc_csum32(uint16_t old_csum, uint32_t old_u32, uint32_t new_u32);
+ovs_be16 csum_finish(uint32_t partial);
+ovs_be16 recalc_csum16(ovs_be16 old_csum, ovs_be16 old_u16, ovs_be16 new_u16);
+ovs_be16 recalc_csum32(ovs_be16 old_csum, ovs_be32 old_u32, ovs_be32 new_u32);
 
 #endif /* csum.h */
index 4af98f6..eb38d5d 100644 (file)
     OPT_PIDFILE,                                \
     OPT_MONITOR
 
-#define DAEMON_LONG_OPTIONS                                          \
-        {"detach",            no_argument, 0, OPT_DETACH},           \
-        {"no-chdir",          no_argument, 0, OPT_NO_CHDIR},         \
-        {"pidfile",           optional_argument, 0, OPT_PIDFILE},    \
-        {"overwrite-pidfile", no_argument, 0, OPT_OVERWRITE_PIDFILE},\
-        {"monitor",           no_argument, 0, OPT_MONITOR}
+#define DAEMON_LONG_OPTIONS                                             \
+        {"detach",            no_argument, NULL, OPT_DETACH},           \
+        {"no-chdir",          no_argument, NULL, OPT_NO_CHDIR},         \
+        {"pidfile",           optional_argument, NULL, OPT_PIDFILE},    \
+        {"overwrite-pidfile", no_argument, NULL, OPT_OVERWRITE_PIDFILE}, \
+        {"monitor",           no_argument, NULL, OPT_MONITOR}
 
 #define DAEMON_OPTION_HANDLERS                  \
         case OPT_DETACH:                        \
index 7e6c491..d84b5fa 100644 (file)
@@ -1473,7 +1473,7 @@ dpif_linux_dp_to_ofpbuf(const struct dpif_linux_dp *dp, struct ofpbuf *buf)
 }
 
 /* Clears 'dp' to "empty" values. */
-void
+static void
 dpif_linux_dp_init(struct dpif_linux_dp *dp)
 {
     memset(dp, 0, sizeof *dp);
@@ -1500,7 +1500,7 @@ dpif_linux_dp_dump_start(struct nl_dump *dump)
  * result of the command is expected to be of the same form, which is decoded
  * and stored in '*reply' and '*bufp'.  The caller must free '*bufp' when the
  * reply is no longer needed ('reply' will contain pointers into '*bufp'). */
-int
+static int
 dpif_linux_dp_transact(const struct dpif_linux_dp *request,
                        struct dpif_linux_dp *reply, struct ofpbuf **bufp)
 {
@@ -1530,7 +1530,7 @@ dpif_linux_dp_transact(const struct dpif_linux_dp *request,
 /* Obtains information about 'dpif_' and stores it into '*reply' and '*bufp'.
  * The caller must free '*bufp' when the reply is no longer needed ('reply'
  * will contain pointers into '*bufp').  */
-int
+static int
 dpif_linux_dp_get(const struct dpif *dpif_, struct dpif_linux_dp *reply,
                   struct ofpbuf **bufp)
 {
@@ -1640,7 +1640,7 @@ dpif_linux_flow_to_ofpbuf(const struct dpif_linux_flow *flow,
 }
 
 /* Clears 'flow' to "empty" values. */
-void
+static void
 dpif_linux_flow_init(struct dpif_linux_flow *flow)
 {
     memset(flow, 0, sizeof *flow);
@@ -1652,7 +1652,7 @@ dpif_linux_flow_init(struct dpif_linux_flow *flow)
  * result of the command is expected to be a flow also, which is decoded and
  * stored in '*reply' and '*bufp'.  The caller must free '*bufp' when the reply
  * is no longer needed ('reply' will contain pointers into '*bufp'). */
-int
+static int
 dpif_linux_flow_transact(const struct dpif_linux_flow *request,
                          struct dpif_linux_flow *reply, struct ofpbuf **bufp)
 {
index 5005270..53574aa 100644 (file)
@@ -114,7 +114,7 @@ struct dp_netdev_flow {
     long long int used;         /* Last used time, in monotonic msecs. */
     long long int packet_count; /* Number of packets matched. */
     long long int byte_count;   /* Number of bytes matched. */
-    uint16_t tcp_ctl;           /* Bitwise-OR of seen tcp_ctl values. */
+    ovs_be16 tcp_ctl;           /* Bitwise-OR of seen tcp_ctl values. */
 
     /* Actions. */
     struct nlattr *actions;
@@ -1174,7 +1174,7 @@ dp_netdev_set_nw_addr(struct ofpbuf *packet, const struct flow *key,
         struct ip_header *nh = packet->l3;
         ovs_be32 ip = nl_attr_get_be32(a);
         uint16_t type = nl_attr_type(a);
-        uint32_t *field;
+        ovs_be32 *field;
 
         field = type == ODP_ACTION_ATTR_SET_NW_SRC ? &nh->ip_src : &nh->ip_dst;
         if (key->nw_proto == IPPROTO_TCP && packet->l7) {
@@ -1185,7 +1185,7 @@ dp_netdev_set_nw_addr(struct ofpbuf *packet, const struct flow *key,
             if (uh->udp_csum) {
                 uh->udp_csum = recalc_csum32(uh->udp_csum, *field, ip);
                 if (!uh->udp_csum) {
-                    uh->udp_csum = 0xffff;
+                    uh->udp_csum = htons(0xffff);
                 }
             }
         }
@@ -1218,7 +1218,7 @@ dp_netdev_set_tp_port(struct ofpbuf *packet, const struct flow *key,
        if (is_ip(packet, key)) {
         uint16_t type = nl_attr_type(a);
         ovs_be16 port = nl_attr_get_be16(a);
-        uint16_t *field;
+        ovs_be16 *field;
 
         if (key->nw_proto == IPPROTO_TCP && packet->l7) {
             struct tcp_header *th = packet->l4;
index ea7746c..0a0e9f5 100644 (file)
@@ -556,7 +556,7 @@ flow_wildcards_is_exact(const struct flow_wildcards *wc)
     }
 
     for (i = 0; i < FLOW_N_REGS; i++) {
-        if (wc->reg_masks[i] != htonl(UINT32_MAX)) {
+        if (wc->reg_masks[i] != UINT32_MAX) {
             return false;
         }
     }
index 6bd2c3d..a83987b 100644 (file)
@@ -70,7 +70,7 @@ BUILD_ASSERT_DECL(offsetof(struct flow, nd_target) == FLOW_SIG_SIZE - 16);
 BUILD_ASSERT_DECL(sizeof(((struct flow *)0)->nd_target) == 16);
 BUILD_ASSERT_DECL(sizeof(struct flow) == FLOW_SIG_SIZE + FLOW_PAD_SIZE);
 
-int flow_extract(struct ofpbuf *, uint64_t tun_id, uint16_t in_port,
+int flow_extract(struct ofpbuf *, ovs_be64 tun_id, uint16_t in_port,
                  struct flow *);
 void flow_extract_stats(const struct flow *flow, struct ofpbuf *packet,
                         struct dpif_flow_stats *);
index 0a8bca2..37bdece 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.
@@ -23,7 +23,6 @@
 #include <errno.h>
 #include <float.h>
 #include <limits.h>
-#include <math.h>
 #include <string.h>
 
 #include "dynamic-string.h"
index afcc520..705cef7 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.
@@ -293,7 +293,7 @@ void
 jsonrpc_recv_wait(struct jsonrpc *rpc)
 {
     if (rpc->status || rpc->received || !byteq_is_empty(&rpc->input)) {
-        poll_immediate_wake();
+        (poll_immediate_wake)(rpc->name);
     } else {
         stream_recv_wait(rpc->stream);
     }
index 8d7624d..f6ee5c1 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2009 Nicira Networks.
+ * Copyright (c) 2008, 2009, 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.
@@ -23,8 +23,8 @@
     OPT_CHECK_LEAKS,                            \
     OPT_LEAK_LIMIT
 #define LEAK_CHECKER_LONG_OPTIONS                           \
-    {"check-leaks", required_argument, 0, OPT_CHECK_LEAKS}, \
-    {"leak-limit", required_argument, 0, OPT_LEAK_LIMIT}
+    {"check-leaks", required_argument, NULL, OPT_CHECK_LEAKS}, \
+    {"leak-limit", required_argument, NULL, OPT_LEAK_LIMIT}
 #define LEAK_CHECKER_OPTION_HANDLERS                \
         case OPT_CHECK_LEAKS:                       \
             leak_checker_start(optarg);             \
index 771ad70..43ccaf9 100644 (file)
@@ -1,4 +1,4 @@
- /* 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.
@@ -111,17 +111,12 @@ lockfile_lock(const char *file, int timeout, struct lockfile **lockfilep)
         }
     } while (error == EINTR && (timeout == INT_MAX || elapsed < timeout));
 
-    if (!error) {
-        if (elapsed) {
-            VLOG_WARN("%s: waited %lld ms for lock file",
-                      lock_name, elapsed);
-        }
-    } else if (error == EINTR) {
+    if (error == EINTR) {
         COVERAGE_INC(lockfile_timeout);
         VLOG_WARN("%s: giving up on lock file after %lld ms",
                   lock_name, elapsed);
         error = ETIMEDOUT;
-    } else {
+    } else if (error) {
         COVERAGE_INC(lockfile_error);
         if (error == EACCES) {
             error = EAGAIN;
index c41b19d..a401c60 100644 (file)
@@ -373,7 +373,6 @@ struct netdev_linux {
 
 /* Sockets used for ioctl operations. */
 static int af_inet_sock = -1;   /* AF_INET, SOCK_DGRAM. */
-static int af_packet_sock = -1; /* AF_PACKET, SOCK_RAW. */
 
 /* A Netlink routing socket that is not subscribed to any multicast groups. */
 static struct nl_sock *rtnl_sock;
@@ -411,6 +410,7 @@ static int set_etheraddr(const char *netdev_name, int hwaddr_family,
                          const uint8_t[ETH_ADDR_LEN]);
 static int get_stats_via_netlink(int ifindex, struct netdev_stats *stats);
 static int get_stats_via_proc(const char *netdev_name, struct netdev_stats *stats);
+static int af_packet_sock(void);
 
 static bool
 is_netdev_linux_class(const struct netdev_class *netdev_class)
@@ -447,15 +447,6 @@ netdev_linux_init(void)
         status = af_inet_sock >= 0 ? 0 : errno;
         if (status) {
             VLOG_ERR("failed to create inet socket: %s", strerror(status));
-        } else {
-            /* Create AF_PACKET socket. */
-            af_packet_sock = socket(AF_PACKET, SOCK_RAW, 0);
-            status = af_packet_sock >= 0 ? 0 : errno;
-            if (status) {
-                VLOG_ERR("failed to create packet socket: %s",
-                         strerror(status));
-            }
-            set_nonblocking(af_packet_sock);
         }
 
         /* Create rtnetlink socket. */
@@ -682,7 +673,8 @@ netdev_linux_open(struct netdev_dev *netdev_dev_, int ethertype,
         protocol = (ethertype == NETDEV_ETH_TYPE_ANY ? ETH_P_ALL
                     : ethertype == NETDEV_ETH_TYPE_802_2 ? ETH_P_802_2
                     : ethertype);
-        netdev->fd = socket(PF_PACKET, SOCK_RAW, htons(protocol));
+        netdev->fd = socket(PF_PACKET, SOCK_RAW,
+                            (OVS_FORCE int) htons(protocol));
         if (netdev->fd < 0) {
             error = errno;
             goto error;
@@ -843,6 +835,12 @@ netdev_linux_send(struct netdev *netdev_, const void *data, size_t size)
             struct iovec iov;
             int ifindex;
             int error;
+            int sock;
+
+            sock = af_packet_sock();
+            if (sock < 0) {
+                return sock;
+            }
 
             error = get_ifindex(netdev_, &ifindex);
             if (error) {
@@ -866,7 +864,7 @@ netdev_linux_send(struct netdev *netdev_, const void *data, size_t size)
             msg.msg_controllen = 0;
             msg.msg_flags = 0;
 
-            retval = sendmsg(af_packet_sock, &msg, 0);
+            retval = sendmsg(sock, &msg, 0);
         } else {
             /* Use the netdev's own fd to send to this device.  This is
              * essential for tap devices, because packets sent to a tap device
@@ -4240,3 +4238,22 @@ netdev_linux_get_ipv4(const struct netdev *netdev, struct in_addr *ip,
     }
     return error;
 }
+
+/* Returns an AF_PACKET raw socket or a negative errno value. */
+static int
+af_packet_sock(void)
+{
+    static int sock = INT_MIN;
+
+    if (sock == INT_MIN) {
+        sock = socket(AF_PACKET, SOCK_RAW, 0);
+        if (sock >= 0) {
+            set_nonblocking(sock);
+        } else {
+            sock = -errno;
+            VLOG_ERR("failed to create packet socket: %s", strerror(errno));
+        }
+    }
+
+    return sock;
+}
index e11cb2a..3067323 100644 (file)
@@ -555,7 +555,7 @@ static const char *
 netdev_vport_get_tnl_iface(const struct netdev *netdev)
 {
     struct nlattr *a[ODP_TUNNEL_ATTR_MAX + 1];
-    uint32_t route;
+    ovs_be32 route;
     struct netdev_dev_vport *ndv;
     static char name[IFNAMSIZ];
 
index 771db5a..01d91db 100644 (file)
@@ -1549,6 +1549,15 @@ netdev_monitor_poll(struct netdev_monitor *monitor, char **devnamep)
     }
 }
 
+/* Clears all notifications from 'monitor'.  May be called instead of
+ * netdev_monitor_poll() by clients which don't care specifically which netdevs
+ * have changed.  */
+void
+netdev_monitor_flush(struct netdev_monitor *monitor)
+{
+    sset_clear(&monitor->changed_netdevs);
+}
+
 /* Registers with the poll loop to wake up from the next call to poll_block()
  * when netdev_monitor_poll(monitor) would indicate that a device has
  * changed. */
index 30bcf5e..81d74ae 100644 (file)
@@ -214,6 +214,7 @@ void netdev_monitor_destroy(struct netdev_monitor *);
 int netdev_monitor_add(struct netdev_monitor *, struct netdev *);
 void netdev_monitor_remove(struct netdev_monitor *, struct netdev *);
 int netdev_monitor_poll(struct netdev_monitor *, char **devnamep);
+void netdev_monitor_flush(struct netdev_monitor *);
 void netdev_monitor_poll_wait(const struct netdev_monitor *);
 
 #ifdef  __cplusplus
index 345f0d1..f5d62de 100644 (file)
@@ -677,7 +677,7 @@ nxm_put_eth(struct ofpbuf *b, uint32_t header,
 
 static void
 nxm_put_eth_dst(struct ofpbuf *b,
-                uint32_t wc, const uint8_t value[ETH_ADDR_LEN])
+                flow_wildcards_t wc, const uint8_t value[ETH_ADDR_LEN])
 {
     switch (wc & (FWW_DL_DST | FWW_ETH_MCAST)) {
     case FWW_DL_DST | FWW_ETH_MCAST:
index cbac1e4..89656cc 100644 (file)
@@ -123,7 +123,7 @@ ofp_print_packet_in(struct ds *string, const struct ofp_packet_in *op,
 
     data_len = len - offsetof(struct ofp_packet_in, data);
     ds_put_format(string, " data_len=%zu", data_len);
-    if (htonl(op->buffer_id) == UINT32_MAX) {
+    if (op->buffer_id == htonl(UINT32_MAX)) {
         ds_put_format(string, " (unbuffered)");
         if (ntohs(op->total_len) != data_len)
             ds_put_format(string, " (***total_len != data_len***)");
index 2e12eb5..4618567 100644 (file)
@@ -36,6 +36,8 @@
 
 VLOG_DEFINE_THIS_MODULE(ofp_util);
 
+static ovs_be32 normalize_wildcards(const struct ofp_match *);
+
 /* Rate limit for OpenFlow message parse errors.  These always indicate a bug
  * in the peer and so there's not much point in showing a lot of them. */
 static struct vlog_rate_limit bad_ofmsg_rl = VLOG_RATE_LIMIT_INIT(1, 5);
@@ -94,12 +96,11 @@ ofputil_netmask_to_wcbits(ovs_be32 netmask)
 
 /* WC_INVARIANTS is the invariant bits (as defined on WC_INVARIANT_LIST) all
  * OR'd together. */
-enum {
-    WC_INVARIANTS = 0
+static const flow_wildcards_t WC_INVARIANTS = 0
 #define WC_INVARIANT_BIT(NAME) | FWW_##NAME
     WC_INVARIANT_LIST
 #undef WC_INVARIANT_BIT
-};
+;
 
 /* Converts the ofp_match in 'match' into a cls_rule in 'rule', with the given
  * 'priority'. */
@@ -108,7 +109,7 @@ ofputil_cls_rule_from_match(const struct ofp_match *match,
                             unsigned int priority, struct cls_rule *rule)
 {
     struct flow_wildcards *wc = &rule->wc;
-    unsigned int ofpfw;
+    uint32_t ofpfw;
     ovs_be16 vid, pcp;
 
     /* Initialize rule->priority. */
@@ -117,7 +118,7 @@ ofputil_cls_rule_from_match(const struct ofp_match *match,
 
     /* Initialize most of rule->wc. */
     flow_wildcards_init_catchall(wc);
-    wc->wildcards = ofpfw & WC_INVARIANTS;
+    wc->wildcards = (OVS_FORCE flow_wildcards_t) ofpfw & WC_INVARIANTS;
 
     /* Wildcard fields that aren't defined by ofp_match or tun_id. */
     wc->wildcards |= (FWW_ARP_SHA | FWW_ARP_THA | FWW_ND_TARGET);
@@ -199,10 +200,10 @@ void
 ofputil_cls_rule_to_match(const struct cls_rule *rule, struct ofp_match *match)
 {
     const struct flow_wildcards *wc = &rule->wc;
-    unsigned int ofpfw;
+    uint32_t ofpfw;
 
     /* Figure out most OpenFlow wildcards. */
-    ofpfw = wc->wildcards & WC_INVARIANTS;
+    ofpfw = (OVS_FORCE uint32_t) (wc->wildcards & WC_INVARIANTS);
     ofpfw |= ofputil_netmask_to_wcbits(wc->nw_src_mask) << OFPFW_NW_SRC_SHIFT;
     ofpfw |= ofputil_netmask_to_wcbits(wc->nw_dst_mask) << OFPFW_NW_DST_SHIFT;
     if (wc->wildcards & FWW_NW_TOS) {
@@ -902,8 +903,9 @@ ofputil_decode_flow_mod(struct flow_mod *fm, const struct ofp_header *oh,
     ofputil_decode_msg_type(oh, &type);
     if (ofputil_msg_type_code(type) == OFPUTIL_OFPT_FLOW_MOD) {
         /* Standard OpenFlow flow_mod. */
-        struct ofp_match match, orig_match;
         const struct ofp_flow_mod *ofm;
+        uint16_t priority;
+        ovs_be32 wc;
         int error;
 
         /* Dissect the message. */
@@ -913,26 +915,37 @@ ofputil_decode_flow_mod(struct flow_mod *fm, const struct ofp_header *oh,
             return error;
         }
 
+        /* Set priority based on original wildcards.  Normally we'd allow
+         * ofputil_cls_rule_from_match() to do this for us, but
+         * normalize_wildcards() can put wildcards where the original flow
+         * didn't have them. */
+        priority = ntohs(ofm->priority);
+        if (!(ofm->match.wildcards & htonl(OFPFW_ALL))) {
+            priority = UINT16_MAX;
+        }
+
         /* Normalize ofm->match.  If normalization actually changes anything,
          * then log the differences. */
-        match = ofm->match;
-        match.pad1[0] = match.pad2[0] = 0;
-        orig_match = match;
-        normalize_match(&match);
-        if (memcmp(&match, &orig_match, sizeof orig_match)) {
+        wc = normalize_wildcards(&ofm->match);
+        if (wc == ofm->match.wildcards) {
+            ofputil_cls_rule_from_match(&ofm->match, priority, &fm->cr);
+        } else {
+            struct ofp_match match = ofm->match;
+            match.wildcards = wc;
+            ofputil_cls_rule_from_match(&match, priority, &fm->cr);
+
             if (!VLOG_DROP_INFO(&bad_ofmsg_rl)) {
-                char *old = ofp_match_to_literal_string(&orig_match);
-                char *new = ofp_match_to_literal_string(&match);
+                char *pre = ofp_match_to_string(&ofm->match, 1);
+                char *post = ofp_match_to_string(&match, 1);
                 VLOG_INFO("normalization changed ofp_match, details:");
-                VLOG_INFO(" pre: %s", old);
-                VLOG_INFO("post: %s", new);
-                free(old);
-                free(new);
+                VLOG_INFO(" pre: %s", pre);
+                VLOG_INFO("post: %s", post);
+                free(pre);
+                free(post);
             }
         }
 
         /* Translate the message. */
-        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);
@@ -2065,123 +2078,29 @@ actions_next(struct actions_iterator *iter)
     }
 }
 
-void
-normalize_match(struct ofp_match *m)
+static ovs_be32
+normalize_wildcards(const struct ofp_match *m)
 {
-    enum { OFPFW_NW = (OFPFW_NW_SRC_MASK | OFPFW_NW_DST_MASK | OFPFW_NW_PROTO
+    enum { OFPFW_NW = (OFPFW_NW_SRC_ALL | OFPFW_NW_DST_ALL | OFPFW_NW_PROTO
                        | OFPFW_NW_TOS) };
     enum { OFPFW_TP = OFPFW_TP_SRC | OFPFW_TP_DST };
-    uint32_t wc;
-
-    wc = ntohl(m->wildcards) & OFPFW_ALL;
-    if (wc & OFPFW_DL_TYPE) {
-        m->dl_type = 0;
+    ovs_be32 wc;
 
-        /* Can't sensibly match on network or transport headers if the
-         * data link type is unknown. */
-        wc |= OFPFW_NW | OFPFW_TP;
-        m->nw_src = m->nw_dst = m->nw_proto = m->nw_tos = 0;
-        m->tp_src = m->tp_dst = 0;
+    wc = m->wildcards;
+    if (wc & htonl(OFPFW_DL_TYPE)) {
+        wc |= htonl(OFPFW_NW | OFPFW_TP);
     } else if (m->dl_type == htons(ETH_TYPE_IP)) {
-        if (wc & OFPFW_NW_PROTO) {
-            m->nw_proto = 0;
-
-            /* Can't sensibly match on transport headers if the network
-             * protocol is unknown. */
-            wc |= OFPFW_TP;
-            m->tp_src = m->tp_dst = 0;
-        } else if (m->nw_proto == IPPROTO_TCP ||
-                   m->nw_proto == IPPROTO_UDP ||
-                   m->nw_proto == IPPROTO_ICMP) {
-            if (wc & OFPFW_TP_SRC) {
-                m->tp_src = 0;
-            }
-            if (wc & OFPFW_TP_DST) {
-                m->tp_dst = 0;
-            }
-        } else {
-            /* Transport layer fields will always be extracted as zeros, so we
-             * can do an exact-match on those values.  */
-            wc &= ~OFPFW_TP;
-            m->tp_src = m->tp_dst = 0;
-        }
-        if (wc & OFPFW_NW_SRC_MASK) {
-            m->nw_src &= ofputil_wcbits_to_netmask(wc >> OFPFW_NW_SRC_SHIFT);
-        }
-        if (wc & OFPFW_NW_DST_MASK) {
-            m->nw_dst &= ofputil_wcbits_to_netmask(wc >> OFPFW_NW_DST_SHIFT);
-        }
-        if (wc & OFPFW_NW_TOS) {
-            m->nw_tos = 0;
-        } else {
-            m->nw_tos &= IP_DSCP_MASK;
+        if (wc & htonl(OFPFW_NW_PROTO) || (m->nw_proto != IPPROTO_TCP &&
+                                           m->nw_proto != IPPROTO_UDP &&
+                                           m->nw_proto != IPPROTO_ICMP)) {
+            wc |= htonl(OFPFW_TP);
         }
     } else if (m->dl_type == htons(ETH_TYPE_ARP)) {
-        if (wc & OFPFW_NW_PROTO) {
-            m->nw_proto = 0;
-        }
-        if (wc & OFPFW_NW_SRC_MASK) {
-            m->nw_src &= ofputil_wcbits_to_netmask(wc >> OFPFW_NW_SRC_SHIFT);
-        }
-        if (wc & OFPFW_NW_DST_MASK) {
-            m->nw_dst &= ofputil_wcbits_to_netmask(wc >> OFPFW_NW_DST_SHIFT);
-        }
-        m->tp_src = m->tp_dst = m->nw_tos = 0;
-    } else if (m->dl_type == htons(ETH_TYPE_IPV6)) {
-        /* Don't normalize IPv6 traffic, since OpenFlow doesn't have a
-         * way to express it. */
+        wc |= htonl(OFPFW_TP);
     } else {
-        /* Network and transport layer fields will always be extracted as
-         * zeros, so we can do an exact-match on those values. */
-        wc &= ~(OFPFW_NW | OFPFW_TP);
-        m->nw_proto = m->nw_src = m->nw_dst = m->nw_tos = 0;
-        m->tp_src = m->tp_dst = 0;
+        wc |= htonl(OFPFW_NW | OFPFW_TP);
     }
-    if (wc & OFPFW_DL_SRC) {
-        memset(m->dl_src, 0, sizeof m->dl_src);
-    }
-    if (wc & OFPFW_DL_DST) {
-        memset(m->dl_dst, 0, sizeof m->dl_dst);
-    }
-    m->wildcards = htonl(wc);
-}
-
-/* Returns a string that describes 'match' in a very literal way, without
- * interpreting its contents except in a very basic fashion.  The returned
- * string is intended to be fixed-length, so that it is easy to see differences
- * between two such strings if one is put above another.  This is useful for
- * describing changes made by normalize_match().
- *
- * The caller must free the returned string (with free()). */
-char *
-ofp_match_to_literal_string(const struct ofp_match *match)
-{
-    return xasprintf("wildcards=%#10"PRIx32" "
-                     " in_port=%5"PRId16" "
-                     " dl_src="ETH_ADDR_FMT" "
-                     " dl_dst="ETH_ADDR_FMT" "
-                     " dl_vlan=%5"PRId16" "
-                     " dl_vlan_pcp=%3"PRId8" "
-                     " dl_type=%#6"PRIx16" "
-                     " nw_tos=%#4"PRIx8" "
-                     " nw_proto=%#4"PRIx16" "
-                     " nw_src=%#10"PRIx32" "
-                     " nw_dst=%#10"PRIx32" "
-                     " tp_src=%5"PRId16" "
-                     " tp_dst=%5"PRId16,
-                     ntohl(match->wildcards),
-                     ntohs(match->in_port),
-                     ETH_ADDR_ARGS(match->dl_src),
-                     ETH_ADDR_ARGS(match->dl_dst),
-                     ntohs(match->dl_vlan),
-                     match->dl_vlan_pcp,
-                     ntohs(match->dl_type),
-                     match->nw_tos,
-                     match->nw_proto,
-                     ntohl(match->nw_src),
-                     ntohl(match->nw_dst),
-                     ntohs(match->tp_src),
-                     ntohs(match->tp_dst));
+    return wc;
 }
 
 static uint32_t
index c87b04b..975d8d2 100644 (file)
@@ -102,8 +102,6 @@ int ofputil_netmask_to_wcbits(ovs_be32 netmask);
 void ofputil_cls_rule_from_match(const struct ofp_match *,
                                  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);
 
 /* dl_type translation between OpenFlow and 'struct flow' format. */
 ovs_be16 ofputil_dl_type_to_openflow(ovs_be16 flow_dl_type);
index f45c331..20065ad 100644 (file)
@@ -328,8 +328,8 @@ BUILD_ASSERT_DECL(UDP_HEADER_LEN == sizeof(struct udp_header));
 #define TCP_ACK 0x10
 #define TCP_URG 0x20
 
-#define TCP_FLAGS(tcp_ctl) (htons(tcp_ctl) & 0x003f)
-#define TCP_OFFSET(tcp_ctl) (htons(tcp_ctl) >> 12)
+#define TCP_FLAGS(tcp_ctl) (ntohs(tcp_ctl) & 0x003f)
+#define TCP_OFFSET(tcp_ctl) (ntohs(tcp_ctl) >> 12)
 
 #define TCP_HEADER_LEN 20
 struct tcp_header {
index e47cccc..c944477 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 <poll.h>
 #include <stdlib.h>
 #include <string.h>
-#include "backtrace.h"
 #include "coverage.h"
 #include "dynamic-string.h"
 #include "fatal-signal.h"
 #include "list.h"
+#include "socket-util.h"
 #include "timeval.h"
 #include "vlog.h"
 
+#undef poll_fd_wait
+#undef poll_timer_wait
+#undef poll_timer_wait_until
+#undef poll_immediate_wake
+
 VLOG_DEFINE_THIS_MODULE(poll_loop);
 
 COVERAGE_DEFINE(poll_fd_wait);
@@ -41,7 +46,7 @@ struct poll_waiter {
     struct list node;           /* Element in global waiters list. */
     int fd;                     /* File descriptor. */
     short int events;           /* Events to wait for (POLLIN, POLLOUT). */
-    struct backtrace *backtrace; /* Optionally, event that created waiter. */
+    const char *where;          /* Where the waiter was created. */
 
     /* Set only when poll_block() is called. */
     struct pollfd *pollfd;      /* Pointer to element of the pollfds array. */
@@ -57,10 +62,11 @@ static size_t n_waiters;
  * wait forever. */
 static int timeout = -1;
 
-/* Backtrace of 'timeout''s registration, if debugging is enabled. */
-static struct backtrace timeout_backtrace;
+/* Location where waiter created. */
+static const char *timeout_where;
 
-static struct poll_waiter *new_waiter(int fd, short int events);
+static struct poll_waiter *new_waiter(int fd, short int events,
+                                      const char *where);
 
 /* Registers 'fd' as waiting for the specified 'events' (which should be POLLIN
  * or POLLOUT or POLLIN | POLLOUT).  The following call to poll_block() will
@@ -68,23 +74,24 @@ static struct poll_waiter *new_waiter(int fd, short int events);
  *
  * The event registration is one-shot: only the following call to poll_block()
  * is affected.  The event will need to be re-registered after poll_block() is
- * called if it is to persist. */
+ * called if it is to persist.
+ *
+ * Ordinarily the 'where' argument is supplied automatically; see poll-loop.h
+ * for more information. */
 struct poll_waiter *
-poll_fd_wait(int fd, short int events)
+poll_fd_wait(int fd, short int events, const char *where)
 {
     COVERAGE_INC(poll_fd_wait);
-    return new_waiter(fd, events);
+    return new_waiter(fd, events, where);
 }
 
 /* The caller must ensure that 'msec' is not negative. */
 static void
-poll_timer_wait__(int msec)
+poll_timer_wait__(int msec, const char *where)
 {
     if (timeout < 0 || msec < timeout) {
         timeout = msec;
-        if (VLOG_IS_DBG_ENABLED()) {
-            backtrace_capture(&timeout_backtrace);
-        }
+        timeout_where = where;
     }
 }
 
@@ -94,13 +101,17 @@ poll_timer_wait__(int msec)
  *
  * The timer registration is one-shot: only the following call to poll_block()
  * is affected.  The timer will need to be re-registered after poll_block() is
- * called if it is to persist. */
+ * called if it is to persist.
+ *
+ * Ordinarily the 'where' argument is supplied automatically; see poll-loop.h
+ * for more information. */
 void
-poll_timer_wait(long long int msec)
+poll_timer_wait(long long int msec, const char *where)
 {
-    poll_timer_wait__(msec < 0 ? 0
-                      : msec > INT_MAX ? INT_MAX
-                      : msec);
+    poll_timer_wait__((msec < 0 ? 0
+                       : msec > INT_MAX ? INT_MAX
+                       : msec),
+                      where);
 }
 
 /* Causes the following call to poll_block() to wake up when the current time,
@@ -110,26 +121,33 @@ poll_timer_wait(long long int msec)
  *
  * The timer registration is one-shot: only the following call to poll_block()
  * is affected.  The timer will need to be re-registered after poll_block() is
- * called if it is to persist. */
+ * called if it is to persist.
+ *
+ * Ordinarily the 'where' argument is supplied automatically; see poll-loop.h
+ * for more information. */
 void
-poll_timer_wait_until(long long int msec)
+poll_timer_wait_until(long long int msec, const char *where)
 {
     long long int now = time_msec();
-    poll_timer_wait__(msec <= now ? 0
-                      : msec < now + INT_MAX ? msec - now
-                      : INT_MAX);
+    poll_timer_wait__((msec <= now ? 0
+                       : msec < now + INT_MAX ? msec - now
+                       : INT_MAX),
+                      where);
 }
 
 /* Causes the following call to poll_block() to wake up immediately, without
- * blocking. */
+ * blocking.
+ *
+ * Ordinarily the 'where' argument is supplied automatically; see poll-loop.h
+ * for more information. */
 void
-poll_immediate_wake(void)
+poll_immediate_wake(const char *where)
 {
-    poll_timer_wait(0);
+    poll_timer_wait(0, where);
 }
 
 static void PRINTF_FORMAT(2, 3)
-log_wakeup(const struct backtrace *backtrace, const char *format, ...)
+log_wakeup(const char *where, const char *format, ...)
 {
     struct ds ds;
     va_list args;
@@ -139,14 +157,10 @@ log_wakeup(const struct backtrace *backtrace, const char *format, ...)
     ds_put_format_valist(&ds, format, args);
     va_end(args);
 
-    if (backtrace) {
-        int i;
-
-        ds_put_char(&ds, ':');
-        for (i = 0; i < backtrace->n_frames; i++) {
-            ds_put_format(&ds, " 0x%"PRIxPTR, backtrace->frames[i]);
-        }
+    if (where) {
+        ds_put_format(&ds, " at %s", where);
     }
+
     VLOG_DBG("%s", ds_cstr(&ds));
     ds_destroy(&ds);
 }
@@ -190,24 +204,26 @@ poll_block(void)
         static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
         VLOG_ERR_RL(&rl, "poll: %s", strerror(-retval));
     } else if (!retval && VLOG_IS_DBG_ENABLED()) {
-        log_wakeup(&timeout_backtrace, "%d-ms timeout", timeout);
+        log_wakeup(timeout_where, "%d-ms timeout", timeout);
     }
 
     LIST_FOR_EACH_SAFE (pw, next, node, &waiters) {
         if (pw->pollfd->revents && VLOG_IS_DBG_ENABLED()) {
-            log_wakeup(pw->backtrace, "%s%s%s%s%s on fd %d",
+            char *description = describe_fd(pw->fd);
+            log_wakeup(pw->where, "%s%s%s%s%s on fd %d (%s)",
                        pw->pollfd->revents & POLLIN ? "[POLLIN]" : "",
                        pw->pollfd->revents & POLLOUT ? "[POLLOUT]" : "",
                        pw->pollfd->revents & POLLERR ? "[POLLERR]" : "",
                        pw->pollfd->revents & POLLHUP ? "[POLLHUP]" : "",
                        pw->pollfd->revents & POLLNVAL ? "[POLLNVAL]" : "",
-                       pw->fd);
+                       pw->fd, description);
+            free(description);
         }
         poll_cancel(pw);
     }
 
     timeout = -1;
-    timeout_backtrace.n_frames = 0;
+    timeout_where = NULL;
 
     /* Handle any pending signals before doing anything else. */
     fatal_signal_run();
@@ -224,7 +240,6 @@ poll_cancel(struct poll_waiter *pw)
 {
     if (pw) {
         list_remove(&pw->node);
-        free(pw->backtrace);
         free(pw);
         n_waiters--;
     }
@@ -232,16 +247,13 @@ poll_cancel(struct poll_waiter *pw)
 \f
 /* Creates and returns a new poll_waiter for 'fd' and 'events'. */
 static struct poll_waiter *
-new_waiter(int fd, short int events)
+new_waiter(int fd, short int events, const char *where)
 {
     struct poll_waiter *waiter = xzalloc(sizeof *waiter);
     assert(fd >= 0);
     waiter->fd = fd;
     waiter->events = events;
-    if (VLOG_IS_DBG_ENABLED()) {
-        waiter->backtrace = xmalloc(sizeof *waiter->backtrace);
-        backtrace_capture(waiter->backtrace);
-    }
+    waiter->where = where;
     list_push_back(&waiters, &waiter->node);
     n_waiters++;
     return waiter;
index 65a2ff0..da8f6e2 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.
@@ -28,6 +28,7 @@
 #define POLL_LOOP_H 1
 
 #include <poll.h>
+#include "util.h"
 
 #ifdef  __cplusplus
 extern "C" {
@@ -35,11 +36,28 @@ extern "C" {
 
 struct poll_waiter;
 
-/* Schedule events to wake up the following poll_block(). */
-struct poll_waiter *poll_fd_wait(int fd, short int events);
-void poll_timer_wait(long long int msec);
-void poll_timer_wait_until(long long int msec);
-void poll_immediate_wake(void);
+/* Schedule events to wake up the following poll_block().
+ *
+ * The poll_loop logs the 'where' argument to each function at "debug" level
+ * when an event causes a wakeup.  Ordinarily, it is automatically filled in
+ * with the location in the source of the call, and caller should therefore
+ * omit it.  But, if the function you are implementing is very generic, so that
+ * its location in the source would not be very helpful for debugging, you can
+ * avoid the macro expansion and pass a different argument, e.g.:
+ *      (poll_fd_wait)(fd, events, where);
+ * See timer_wait() for an example.
+ */
+struct poll_waiter *poll_fd_wait(int fd, short int events, const char *where);
+#define poll_fd_wait(fd, events) poll_fd_wait(fd, events, SOURCE_LOCATOR)
+
+void poll_timer_wait(long long int msec, const char *where);
+#define poll_timer_wait(msec) poll_timer_wait(msec, SOURCE_LOCATOR)
+
+void poll_timer_wait_until(long long int msec, const char *where);
+#define poll_timer_wait_until(msec) poll_timer_wait_until(msec, SOURCE_LOCATOR)
+
+void poll_immediate_wake(const char *where);
+#define poll_immediate_wake() poll_immediate_wake(SOURCE_LOCATOR)
 
 /* Wait until an event occurs. */
 void poll_block(void);
index 7d0f4ce..1b69b8f 100644 (file)
@@ -119,8 +119,8 @@ struct rconn {
      *
      * We don't cache the local port, because that changes from one connection
      * attempt to the next. */
-    uint32_t local_ip, remote_ip;
-    uint16_t remote_port;
+    ovs_be32 local_ip, remote_ip;
+    ovs_be16 remote_port;
 
     /* Messages sent or received are copied to the monitor connections. */
 #define MAX_MONITORS 8
index 6ed85ab..d15669a 100644 (file)
@@ -55,7 +55,7 @@ rtnetlink_create(int multicast_group, rtnetlink_parse_func *parse,
     struct rtnetlink *rtn;
 
     rtn                  = xzalloc(sizeof *rtn);
-    rtn->notify_sock     = 0;
+    rtn->notify_sock     = NULL;
     rtn->multicast_group = multicast_group;
     rtn->parse           = parse;
     rtn->change          = change;
index 0e34959..019f38f 100644 (file)
@@ -1,6 +1,8 @@
 /* Copyright (c) 2002-2009 InMon Corp. Licensed under the terms of the InMon sFlow licence: */
 /* http://www.inmon.com/technology/sflowlicense.txt */
 
+#ifndef __CHECKER__            /* Don't run sparse on anything in this file. */
+
 #include <assert.h>
 #include "sflow_api.h"
 
@@ -830,3 +832,5 @@ static void sflError(SFLReceiver *receiver, char *msg)
     sfl_agent_error(receiver->agent, "receiver", msg);
     resetSampleCollector(receiver);
 }
+
+#endif  /* !__CHECKER__ */
index 249b6f0..935e747 100644 (file)
@@ -19,6 +19,7 @@
 #include <arpa/inet.h>
 #include <errno.h>
 #include <fcntl.h>
+#include <net/if.h>
 #include <netdb.h>
 #include <poll.h>
 #include <stddef.h>
 #include <sys/stat.h>
 #include <sys/un.h>
 #include <unistd.h>
+#include "dynamic-string.h"
 #include "fatal-signal.h"
+#include "packets.h"
 #include "util.h"
 #include "vlog.h"
+#if AF_PACKET && __linux__
+#include <linux/if_packet.h>
+#endif
+#ifdef HAVE_NETLINK
+#include "netlink-protocol.h"
+#include "netlink-socket.h"
+#endif
 
 VLOG_DEFINE_THIS_MODULE(socket_util);
 
@@ -784,3 +794,148 @@ xpipe(int fds[2])
         VLOG_FATAL("failed to create pipe (%s)", strerror(errno));
     }
 }
+
+static int
+getsockopt_int(int fd, int level, int optname, int *valuep)
+{
+    socklen_t len = sizeof *valuep;
+
+    return (getsockopt(fd, level, optname, valuep, &len) ? errno
+            : len == sizeof *valuep ? 0
+            : EINVAL);
+}
+
+static void
+describe_sockaddr(struct ds *string, int fd,
+                  int (*getaddr)(int, struct sockaddr *, socklen_t *))
+{
+    struct sockaddr_storage ss;
+    socklen_t len = sizeof ss;
+
+    if (!getaddr(fd, (struct sockaddr *) &ss, &len)) {
+        if (ss.ss_family == AF_INET) {
+            struct sockaddr_in sin;
+
+            memcpy(&sin, &ss, sizeof sin);
+            ds_put_format(string, IP_FMT":%"PRIu16,
+                          IP_ARGS(&sin.sin_addr.s_addr), ntohs(sin.sin_port));
+        } else if (ss.ss_family == AF_UNIX) {
+            struct sockaddr_un sun;
+            const char *null;
+            size_t maxlen;
+
+            memcpy(&sun, &ss, sizeof sun);
+            maxlen = len - offsetof(struct sockaddr_un, sun_path);
+            null = memchr(sun.sun_path, '\0', maxlen);
+            ds_put_buffer(string, sun.sun_path,
+                          null ? null - sun.sun_path : maxlen);
+        }
+#ifdef HAVE_NETLINK
+        else if (ss.ss_family == AF_NETLINK) {
+            int protocol;
+
+/* SO_PROTOCOL was introduced in 2.6.32.  Support it regardless of the version
+ * of the Linux kernel headers in use at build time. */
+#ifndef SO_PROTOCOL
+#define SO_PROTOCOL 38
+#endif
+
+            if (!getsockopt_int(fd, SOL_SOCKET, SO_PROTOCOL, &protocol)) {
+                switch (protocol) {
+                case NETLINK_ROUTE:
+                    ds_put_cstr(string, "NETLINK_ROUTE");
+                    break;
+
+                case NETLINK_GENERIC:
+                    ds_put_cstr(string, "NETLINK_GENERIC");
+                    break;
+
+                default:
+                    ds_put_format(string, "AF_NETLINK family %d", protocol);
+                    break;
+                }
+            } else {
+                ds_put_cstr(string, "AF_NETLINK");
+            }
+        }
+#endif
+#if AF_PACKET && __linux__
+        else if (ss.ss_family == AF_PACKET) {
+            struct sockaddr_ll sll;
+
+            memcpy(&sll, &ss, sizeof sll);
+            ds_put_cstr(string, "AF_PACKET");
+            if (sll.sll_ifindex) {
+                char name[IFNAMSIZ];
+
+                if (if_indextoname(sll.sll_ifindex, name)) {
+                    ds_put_format(string, "(%s)", name);
+                } else {
+                    ds_put_format(string, "(ifindex=%d)", sll.sll_ifindex);
+                }
+            }
+            if (sll.sll_protocol) {
+                ds_put_format(string, "(protocol=0x%"PRIu16")",
+                              ntohs(sll.sll_protocol));
+            }
+        }
+#endif
+        else if (ss.ss_family == AF_UNSPEC) {
+            ds_put_cstr(string, "AF_UNSPEC");
+        } else {
+            ds_put_format(string, "AF_%d", (int) ss.ss_family);
+        }
+    }
+}
+
+
+#ifdef __linux__
+static void
+put_fd_filename(struct ds *string, int fd)
+{
+    char buf[1024];
+    char *linkname;
+    int n;
+
+    linkname = xasprintf("/proc/self/fd/%d", fd);
+    n = readlink(linkname, buf, sizeof buf);
+    if (n > 0) {
+        ds_put_char(string, ' ');
+        ds_put_buffer(string, buf, n);
+        if (n > sizeof buf) {
+            ds_put_cstr(string, "...");
+        }
+    }
+    free(linkname);
+}
+#endif
+
+/* Returns a malloc()'d string describing 'fd', for use in logging. */
+char *
+describe_fd(int fd)
+{
+    struct ds string;
+    struct stat s;
+
+    ds_init(&string);
+    if (fstat(fd, &s)) {
+        ds_put_format(&string, "fstat failed (%s)", strerror(errno));
+    } else if (S_ISSOCK(s.st_mode)) {
+        describe_sockaddr(&string, fd, getsockname);
+        ds_put_cstr(&string, "<->");
+        describe_sockaddr(&string, fd, getpeername);
+    } else {
+        ds_put_cstr(&string, (isatty(fd) ? "tty"
+                              : S_ISDIR(s.st_mode) ? "directory"
+                              : S_ISCHR(s.st_mode) ? "character device"
+                              : S_ISBLK(s.st_mode) ? "block device"
+                              : S_ISREG(s.st_mode) ? "file"
+                              : S_ISFIFO(s.st_mode) ? "FIFO"
+                              : S_ISLNK(s.st_mode) ? "symbolic link"
+                              : "unknown"));
+#ifdef __linux__
+        put_fd_filename(&string, fd);
+#endif
+    }
+    return ds_steal_cstr(&string);
+}
index 56a978b..03f4449 100644 (file)
@@ -51,4 +51,6 @@ int get_mtime(const char *file_name, struct timespec *mtime);
 
 void xpipe(int fds[2]);
 
+char *describe_fd(int fd);
+
 #endif /* socket-util.h */
index 977c5ba..02ce7f5 100644 (file)
@@ -919,7 +919,7 @@ pssl_accept(struct pstream *pstream, struct stream **new_streamp)
     int new_fd;
     int error;
 
-    new_fd = accept(pssl->fd, &sin, &sin_len);
+    new_fd = accept(pssl->fd, (struct sockaddr *) &sin, &sin_len);
     if (new_fd < 0) {
         error = errno;
         if (error != EAGAIN) {
index 29c3120..83b9ddb 100644 (file)
@@ -27,9 +27,9 @@ void stream_ssl_set_key_and_cert(const char *private_key_file,
                                  const char *certificate_file);
 
 #define STREAM_SSL_LONG_OPTIONS                     \
-        {"private-key", required_argument, 0, 'p'}, \
-        {"certificate", required_argument, 0, 'c'}, \
-        {"ca-cert",     required_argument, 0, 'C'}
+        {"private-key", required_argument, NULL, 'p'}, \
+        {"certificate", required_argument, NULL, 'c'}, \
+        {"ca-cert",     required_argument, NULL, 'C'}
 
 #define STREAM_SSL_OPTION_HANDLERS                      \
         case 'p':                                       \
index 4244fca..9d6ea97 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010 Nicira Networks.
+ * Copyright (c) 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.
@@ -60,6 +60,7 @@ struct stress_option {
 #if USE_LINKER_SECTIONS
 #define STRESS_OPTION(NAME, DESCRIPTION, RECOMMENDED, MIN, MAX, DEFAULT) \
         STRESS_OPTION__(NAME, DESCRIPTION, RECOMMENDED, MIN, MAX, DEFAULT); \
+        extern struct stress_option *stress_option_ptr_##NAME;          \
         struct stress_option *stress_option_ptr_##NAME                  \
             __attribute__((section("stress_options"))) = &stress_##NAME
 #else
@@ -76,6 +77,7 @@ void stress_init_command(void);
 /* Implementation details. */
 
 #define STRESS_OPTION__(NAME, DESCRIPTION, RECOMMENDED, MIN, MAX, DEFAULT) \
+        extern struct stress_option stress_##NAME;                      \
         struct stress_option stress_##NAME =                            \
         { #NAME, DESCRIPTION, RECOMMENDED, MIN, MAX, DEFAULT,           \
           DEFAULT ? DEFAULT : 0,                /* period */            \
index e35fefa..146d4df 100644 (file)
@@ -85,12 +85,12 @@ struct table_style {
     OPT_PRETTY,                                 \
     OPT_BARE
 
-#define TABLE_LONG_OPTIONS                                  \
-        {"format", required_argument, 0, 'f'},              \
-        {"data", required_argument, 0, 'd'},                \
-        {"no-headings", no_argument, 0, OPT_NO_HEADINGS},   \
-        {"pretty", no_argument, 0, OPT_PRETTY},             \
-        {"bare", no_argument, 0, OPT_BARE}
+#define TABLE_LONG_OPTIONS                                      \
+        {"format", required_argument, NULL, 'f'},               \
+        {"data", required_argument, NULL, 'd'},                 \
+        {"no-headings", no_argument, NULL, OPT_NO_HEADINGS},    \
+        {"pretty", no_argument, NULL, OPT_PRETTY},              \
+        {"bare", no_argument, NULL, OPT_BARE}
 
 #define TABLE_OPTION_HANDLERS(STYLE)                \
         case 'f':                                   \
index 1c3c0f4..84d20a4 100644 (file)
@@ -34,22 +34,9 @@ timer_msecs_until_expired(const struct timer *timer)
 
 /* Causes poll_block() to wake when 'timer' expires. */
 void
-timer_wait(const struct timer *timer)
+(timer_wait)(const struct timer *timer, const char *where)
 {
     if (timer->t < LLONG_MAX) {
-        poll_timer_wait_until(timer->t);
-    }
-}
-
-/* Returns the time at which 'timer' was set with 'duration'.  Infinite timers
- * were enabled at time LLONG_MAX.  Manually expired timers were enabled at
- * LLONG_MIN. */
-long long int
-timer_enabled_at(const struct timer *timer, long long int duration)
-{
-    switch (timer->t) {
-    case LLONG_MAX: return LLONG_MAX;
-    case LLONG_MIN: return LLONG_MIN;
-    default: return timer->t - duration;
+        (poll_timer_wait_until)(timer->t, where);
     }
 }
index 7302055..2197f93 100644 (file)
 #include <stdbool.h>
 
 #include "timeval.h"
+#include "util.h"
 
 struct timer {
     long long int t;
 };
 
 long long int timer_msecs_until_expired(const struct timer *);
-long long int timer_enabled_at(const struct timer *, long long int duration);
-void timer_wait(const struct timer *);
+void timer_wait(const struct timer *, const char *where);
+#define timer_wait(timer) timer_wait(timer, SOURCE_LOCATOR)
 
 /* Causes 'timer' to expire when 'duration' milliseconds have passed.
  *
index a44ee8b..f1aab23 100644 (file)
@@ -156,6 +156,7 @@ put_32aligned_u64(ovs_32aligned_u64 *x, uint64_t value)
        x->lo = value;
 }
 
+#ifndef __CHECKER__
 /* Returns the value of 'x'. */
 static inline ovs_be64
 get_32aligned_be64(const ovs_32aligned_be64 *x)
@@ -179,5 +180,11 @@ put_32aligned_be64(ovs_32aligned_be64 *x, ovs_be64 value)
     x->lo = value >> 32;
 #endif
 }
+#else  /* __CHECKER__ */
+/* Making sparse happy with these functions also makes them unreadable, so
+ * don't bother to show it their implementations. */
+ovs_be64 get_32aligned_be64(const ovs_32aligned_be64 *);
+void put_32aligned_be64(ovs_32aligned_be64 *, ovs_be64);
+#endif
 
 #endif /* unaligned.h */
index 9c2352f..2be7a70 100644 (file)
 #endif
 #endif
 
-#ifndef __cplusplus
+#ifdef __CHECKER__
+#define BUILD_ASSERT(EXPR) ((void) 0)
+#define BUILD_ASSERT_DECL(EXPR) extern int (*build_assert(void))[1]
+#elif !defined(__cplusplus)
 /* Build-time assertion building block. */
 #define BUILD_ASSERT__(EXPR) \
         sizeof(struct { unsigned int build_assert_failed : (EXPR) ? 1 : -1; })
@@ -77,6 +80,14 @@ extern const char *program_name;
 
 #define NOT_REACHED() abort()
 
+/* Expands to a string that looks like "<file>:<line>", e.g. "tmp.c:10".
+ *
+ * See http://c-faq.com/ansi/stringize.html for an explanation of STRINGIZE and
+ * STRINGIZE2. */
+#define SOURCE_LOCATOR __FILE__ ":" STRINGIZE(__LINE__)
+#define STRINGIZE(ARG) STRINGIZE2(ARG)
+#define STRINGIZE2(ARG) #ARG
+
 /* Given a pointer-typed lvalue OBJECT, expands to a pointer type that may be
  * assigned to OBJECT. */
 #ifdef __GNUC__
index bbc00ad..3f40c29 100644 (file)
@@ -92,6 +92,7 @@ struct vlog_module {
 #if USE_LINKER_SECTIONS
 #define VLOG_DEFINE_MODULE(MODULE)                                      \
         VLOG_DEFINE_MODULE__(MODULE)                                    \
+        extern struct vlog_module *vlog_module_ptr_##MODULE;            \
         struct vlog_module *vlog_module_ptr_##MODULE                    \
             __attribute__((section("vlog_modules"))) = &VLM_##MODULE
 #else
@@ -222,8 +223,8 @@ void vlog_rate_limit(const struct vlog_module *, enum vlog_level,
 /* Command line processing. */
 #define VLOG_OPTION_ENUMS OPT_LOG_FILE
 #define VLOG_LONG_OPTIONS                                   \
-        {"verbose",     optional_argument, 0, 'v'},         \
-        {"log-file",    optional_argument, 0, OPT_LOG_FILE}
+        {"verbose",     optional_argument, NULL, 'v'},         \
+        {"log-file",    optional_argument, NULL, OPT_LOG_FILE}
 #define VLOG_OPTION_HANDLERS                    \
         case 'v':                               \
             vlog_set_verbosity(optarg);         \
@@ -258,6 +259,7 @@ void vlog_usage(void);
     } while (0)
 
 #define VLOG_DEFINE_MODULE__(MODULE)                                    \
+        extern struct vlog_module VLM_##MODULE;                         \
         struct vlog_module VLM_##MODULE =                               \
         {                                                               \
             #MODULE,                                      /* name */    \
index e6d03a6..73db4bb 100644 (file)
@@ -152,6 +152,11 @@ AC_DEFUN([OVS_CHECK_LOGDIR],
      [LOGDIR='${localstatedir}/log/${PACKAGE}'])
    AC_SUBST([LOGDIR])])
 
+dnl Defines HAVE_BACKTRACE if backtrace() is declared in <execinfo.h>
+dnl and exists in libc.
+AC_DEFUN([OVS_CHECK_BACKTRACE],
+  [AC_CHECK_HEADER([execinfo.h], [AC_CHECK_FUNCS([backtrace])])])
+
 dnl Checks for __malloc_hook, etc., supported by glibc.
 AC_DEFUN([OVS_CHECK_MALLOC_HOOKS],
   [AC_CACHE_CHECK(
index c237ef2..381ff8e 100644 (file)
@@ -133,7 +133,7 @@ gen_netflow_rec(struct netflow *nf, struct netflow_flow *nf_flow,
     nf_rec = ofpbuf_put_zeros(&nf->packet, sizeof *nf_rec);
     nf_rec->src_addr = expired->flow.nw_src;
     nf_rec->dst_addr = expired->flow.nw_dst;
-    nf_rec->nexthop = htons(0);
+    nf_rec->nexthop = htonl(0);
     if (nf->add_id_to_iface) {
         uint16_t iface = (nf->engine_id & 0x7f) << 9;
         nf_rec->input = htons(iface | (expired->flow.in_port & 0x1ff));
index 26a0fbf..36e7213 100644 (file)
@@ -351,8 +351,7 @@ static void handle_upcall(struct ofproto_dpif *, struct dpif_upcall *);
 static int expire(struct ofproto_dpif *);
 
 /* Utilities. */
-static int send_packet(struct ofproto_dpif *,
-                       uint32_t odp_port, uint16_t vlan_tci,
+static int send_packet(struct ofproto_dpif *, uint32_t odp_port,
                        const struct ofpbuf *packet);
 
 /* Global variables. */
@@ -1391,7 +1390,7 @@ port_run(struct ofport_dpif *ofport)
                               ETH_TYPE_CFM, sizeof *ccm);
             cfm_compose_ccm(ofport->cfm, ccm);
             send_packet(ofproto_dpif_cast(ofport->up.ofproto),
-                        ofport->odp_port, 0, &packet);
+                        ofport->odp_port, &packet);
             ofpbuf_uninit(&packet);
         }
     }
@@ -1591,7 +1590,7 @@ handle_miss_upcall(struct ofproto_dpif *ofproto, struct dpif_upcall *upcall)
     /* Check with in-band control to see if this packet should be sent
      * to the local port regardless of the flow table. */
     if (connmgr_msg_in_hook(ofproto->up.connmgr, &flow, upcall->packet)) {
-        send_packet(ofproto, OFPP_LOCAL, 0, upcall->packet);
+        send_packet(ofproto, OFPP_LOCAL, upcall->packet);
     }
 
     facet = facet_lookup_valid(ofproto, &flow);
@@ -2617,23 +2616,16 @@ rule_modify_actions(struct rule *rule_,
     return error;
 }
 \f
-/* Sends 'packet' out of port 'odp_port' within 'ofproto'.  If 'vlan_tci' is
- * zero the packet will not have any 802.1Q hader; if it is nonzero, then the
- * packet will be sent with the VLAN TCI specified by 'vlan_tci & ~VLAN_CFI'.
- *
+/* Sends 'packet' out of port 'odp_port' within 'p'.
  * Returns 0 if successful, otherwise a positive errno value. */
 static int
-send_packet(struct ofproto_dpif *ofproto, uint32_t odp_port, uint16_t vlan_tci,
+send_packet(struct ofproto_dpif *ofproto, uint32_t odp_port,
             const struct ofpbuf *packet)
 {
     struct ofpbuf odp_actions;
     int error;
 
     ofpbuf_init(&odp_actions, 32);
-    if (vlan_tci != 0) {
-        nl_msg_put_u32(&odp_actions, ODP_ACTION_ATTR_SET_DL_TCI,
-                       ntohs(vlan_tci & ~VLAN_CFI));
-    }
     nl_msg_put_u32(&odp_actions, ODP_ACTION_ATTR_OUTPUT, odp_port);
     error = dpif_execute(ofproto->dpif, odp_actions.data, odp_actions.size,
                          packet);
index 5351b83..a3f4d81 100644 (file)
@@ -252,7 +252,7 @@ sflow_choose_agent_address(const char *agent_device, const char *control_ip,
     return false;
 
 success:
-    agent_addr->address.ip_v4.addr = in4.s_addr;
+    agent_addr->address.ip_v4.addr = (OVS_FORCE uint32_t) in4.s_addr;
     return true;
 }
 
index 46e7c1f..beab99c 100644 (file)
@@ -1455,7 +1455,7 @@ handle_set_config(struct ofconn *ofconn, const struct ofp_switch_config *osc)
  *
  * The log message mentions 'msg_type'. */
 static int
-reject_slave_controller(struct ofconn *ofconn, const const char *msg_type)
+reject_slave_controller(struct ofconn *ofconn, const char *msg_type)
 {
     if (ofconn_get_type(ofconn) == OFCONN_PRIMARY
         && ofconn_get_role(ofconn) == NX_ROLE_SLAVE) {
index 708cc60..1768582 100644 (file)
@@ -200,7 +200,7 @@ exit:
     return results;
 }
 
-struct ovsdb_error *
+static struct ovsdb_error *
 ovsdb_execute_commit(struct ovsdb_execution *x, struct ovsdb_parser *parser,
                      struct json *result OVS_UNUSED)
 {
@@ -270,7 +270,7 @@ parse_row(const struct json *json, const struct ovsdb_table *table,
     }
 }
 
-struct ovsdb_error *
+static struct ovsdb_error *
 ovsdb_execute_insert(struct ovsdb_execution *x, struct ovsdb_parser *parser,
                      struct json *result)
 {
@@ -341,7 +341,7 @@ ovsdb_execute_insert(struct ovsdb_execution *x, struct ovsdb_parser *parser,
     return error;
 }
 
-struct ovsdb_error *
+static struct ovsdb_error *
 ovsdb_execute_select(struct ovsdb_execution *x, struct ovsdb_parser *parser,
                      struct json *result)
 {
@@ -408,7 +408,7 @@ update_row_cb(const struct ovsdb_row *row, void *ur_)
     return true;
 }
 
-struct ovsdb_error *
+static struct ovsdb_error *
 ovsdb_execute_update(struct ovsdb_execution *x, struct ovsdb_parser *parser,
                      struct json *result)
 {
@@ -465,7 +465,7 @@ mutate_row_cb(const struct ovsdb_row *row, void *mr_)
     return true;
 }
 
-struct ovsdb_error *
+static struct ovsdb_error *
 ovsdb_execute_mutate(struct ovsdb_execution *x, struct ovsdb_parser *parser,
                      struct json *result)
 {
@@ -522,7 +522,7 @@ delete_row_cb(const struct ovsdb_row *row, void *dr_)
     return true;
 }
 
-struct ovsdb_error *
+static struct ovsdb_error *
 ovsdb_execute_delete(struct ovsdb_execution *x, struct ovsdb_parser *parser,
                      struct json *result)
 {
index fc9c604..379fc52 100644 (file)
@@ -1,4 +1,4 @@
-/* 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.
@@ -42,7 +42,7 @@ struct ovsdb_jsonrpc_remote;
 struct ovsdb_jsonrpc_session;
 
 /* Message rate-limiting. */
-struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
+static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
 
 /* Sessions. */
 static struct ovsdb_jsonrpc_session *ovsdb_jsonrpc_session_create(
index 6704307..f0926c0 100644 (file)
@@ -289,7 +289,7 @@ ovsdb_log_read(struct ovsdb_log *file, struct json **jsonp)
     file->prev_offset = file->offset;
     file->offset = data_offset + data_length;
     *jsonp = json;
-    return 0;
+    return NULL;
 
 error:
     file->read_error = ovsdb_error_clone(error);
@@ -372,7 +372,7 @@ ovsdb_log_write(struct ovsdb_log *file, struct json *json)
 
     file->offset += strlen(header) + length;
     free(json_string);
-    return 0;
+    return NULL;
 
 error:
     file->write_error = ovsdb_error_clone(error);
@@ -386,7 +386,7 @@ ovsdb_log_commit(struct ovsdb_log *file)
     if (fsync(fileno(file->stream))) {
         return ovsdb_io_error(errno, "%s: fsync failed", file->name);
     }
-    return 0;
+    return NULL;
 }
 
 /* Returns the current offset into the file backing 'log', in bytes.  This
index e8afdd6..800d3e1 100644 (file)
@@ -74,16 +74,16 @@ parse_options(int argc, char *argv[])
         TABLE_OPTION_ENUMS
     };
     static struct option long_options[] = {
-        {"verbose", optional_argument, 0, 'v'},
-        {"help", no_argument, 0, 'h'},
-        {"version", no_argument, 0, 'V'},
+        {"verbose", optional_argument, NULL, 'v'},
+        {"help", no_argument, NULL, 'h'},
+        {"version", no_argument, NULL, 'V'},
         DAEMON_LONG_OPTIONS,
 #ifdef HAVE_OPENSSL
-        {"bootstrap-ca-cert", required_argument, 0, OPT_BOOTSTRAP_CA_CERT},
+        {"bootstrap-ca-cert", required_argument, NULL, OPT_BOOTSTRAP_CA_CERT},
         STREAM_SSL_LONG_OPTIONS,
 #endif
         TABLE_LONG_OPTIONS,
-        {0, 0, 0, 0},
+        {NULL, 0, NULL, 0},
     };
     char *short_options = long_options_to_short_options(long_options);
 
index 14f0fbf..5477e86 100644 (file)
@@ -344,7 +344,7 @@ read_string_column(const struct ovsdb_row *row, const char *column_name,
     const union ovsdb_atom *atom;
 
     atom = read_column(row, column_name, OVSDB_TYPE_STRING);
-    *stringp = atom ? atom->string : 0;
+    *stringp = atom ? atom->string : NULL;
     return atom != NULL;
 }
 
@@ -659,19 +659,19 @@ parse_options(int argc, char *argv[], char **file_namep,
         DAEMON_OPTION_ENUMS
     };
     static struct option long_options[] = {
-        {"remote",      required_argument, 0, OPT_REMOTE},
-        {"unixctl",     required_argument, 0, OPT_UNIXCTL},
-        {"run",         required_argument, 0, OPT_RUN},
-        {"help",        no_argument, 0, 'h'},
-        {"version",     no_argument, 0, 'V'},
+        {"remote",      required_argument, NULL, OPT_REMOTE},
+        {"unixctl",     required_argument, NULL, OPT_UNIXCTL},
+        {"run",         required_argument, NULL, OPT_RUN},
+        {"help",        no_argument, NULL, 'h'},
+        {"version",     no_argument, NULL, 'V'},
         DAEMON_LONG_OPTIONS,
         VLOG_LONG_OPTIONS,
         LEAK_CHECKER_LONG_OPTIONS,
-        {"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'},
-        {0, 0, 0, 0},
+        {"bootstrap-ca-cert", required_argument, NULL, OPT_BOOTSTRAP_CA_CERT},
+        {"private-key", required_argument, NULL, 'p'},
+        {"certificate", required_argument, NULL, 'c'},
+        {"ca-cert",     required_argument, NULL, 'C'},
+        {NULL, 0, NULL, 0},
     };
     char *short_options = long_options_to_short_options(long_options);
 
index 2754909..07d2729 100644 (file)
@@ -60,11 +60,11 @@ static void
 parse_options(int argc, char *argv[])
 {
     static struct option long_options[] = {
-        {"more", no_argument, 0, 'm'},
-        {"verbose", optional_argument, 0, 'v'},
-        {"help", no_argument, 0, 'h'},
-        {"version", no_argument, 0, 'V'},
-        {0, 0, 0, 0},
+        {"more", no_argument, NULL, 'm'},
+        {"verbose", optional_argument, NULL, 'v'},
+        {"help", no_argument, NULL, 'h'},
+        {"version", no_argument, NULL, 'V'},
+        {NULL, 0, NULL, 0},
     };
     char *short_options = long_options_to_short_options(long_options);
 
index abe88e9..fb020c9 100644 (file)
@@ -253,7 +253,7 @@ ovsdb_schema_from_json(struct json *json, struct ovsdb_schema **schemap)
     }
 
     *schemap = schema;
-    return 0;
+    return NULL;
 }
 
 struct json *
index 2f69350..2ea73bf 100644 (file)
@@ -157,7 +157,7 @@ ovsdb_table_schema_from_json(const struct json *json, const char *name,
         add_column(ts, column);
     }
     *tsp = ts;
-    return 0;
+    return NULL;
 }
 
 /* Returns table schema 'ts' serialized into JSON.
index 40e54d5..79ecb02 100644 (file)
@@ -3,10 +3,10 @@ AT_BANNER([autopath link selection])
 AT_SETUP([autopath basic])
 AT_CHECK([ovs-ofctl parse-flow 'actions=autopath(1, NXM_NX_REG0[[]])'], [0],
   [OFPT_FLOW_MOD (xid=0x1): ADD actions=autopath(1,NXM_NX_REG0[[]])
-], [ignore])
+])
 AT_CHECK([ovs-ofctl parse-flow 'actions=autopath(2, NXM_NX_REG0[[2..30]])'], [0],
   [OFPT_FLOW_MOD (xid=0x1): ADD actions=autopath(2,NXM_NX_REG0[[2..30]])
-], [ignore])
+])
 AT_CLEANUP
 
 AT_SETUP([autopath action missing argument])
index 9a2549c..bc5a051 100644 (file)
@@ -6,7 +6,7 @@ AT_CAPTURE_FILE([pid])
 AT_CAPTURE_FILE([expected])
 # Start the daemon and wait for the pidfile to get created
 # and that its contents are the correct pid.
-AT_CHECK([$PYTHON $srcdir/test-daemon.py --pidfile-name=$PWD/pid& echo $! > expected], [0], [ignore], [ignore])
+AT_CHECK([$PYTHON $srcdir/test-daemon.py --pidfile-name=$PWD/pid& echo $! > expected], [0])
 OVS_WAIT_UNTIL([test -s pid], [kill `cat expected`])
 AT_CHECK(
   [pid=`cat pid` && expected=`cat expected` && test "$pid" = "$expected"],
@@ -25,7 +25,7 @@ AT_CAPTURE_FILE([parent])
 AT_CAPTURE_FILE([parentpid])
 AT_CAPTURE_FILE([newpid])
 # Start the daemon and wait for the pidfile to get created.
-AT_CHECK([$PYTHON $srcdir/test-daemon.py --pidfile-name=$PWD/pid --monitor& echo $! > parent], [0], [ignore], [ignore])
+AT_CHECK([$PYTHON $srcdir/test-daemon.py --pidfile-name=$PWD/pid --monitor& echo $! > parent], [0])
 OVS_WAIT_UNTIL([test -s pid], [kill `cat parent`])
 # Check that the pidfile names a running process,
 # and that the parent process of that process is our child process.
@@ -68,7 +68,7 @@ AT_CAPTURE_FILE([parent])
 AT_CAPTURE_FILE([parentpid])
 AT_CAPTURE_FILE([newpid])
 # Start the daemon and wait for the pidfile to get created.
-AT_CHECK([$PYTHON $srcdir/test-daemon.py --pidfile-name=$PWD/pid --monitor& echo $! > parent], [0], [ignore], [ignore])
+AT_CHECK([$PYTHON $srcdir/test-daemon.py --pidfile-name=$PWD/pid --monitor& echo $! > parent], [0])
 OVS_WAIT_UNTIL([test -s pid], [kill `cat parent`])
 # Check that the pidfile names a running process,
 # and that the parent process of that process is our child process.
@@ -110,7 +110,7 @@ AT_CAPTURE_FILE([pid])
 # Start the daemon and make sure that the pidfile exists immediately.
 # We don't wait for the pidfile to get created because the daemon is
 # supposed to do so before the parent exits.
-AT_CHECK([$PYTHON $srcdir/test-daemon.py --pidfile-name=$PWD/pid --detach], [0], [ignore], [ignore])
+AT_CHECK([$PYTHON $srcdir/test-daemon.py --pidfile-name=$PWD/pid --detach], [0])
 AT_CHECK([test -s pid])
 AT_CHECK([kill -0 `cat pid`])
 # Kill the daemon and make sure that the pidfile gets deleted.
@@ -133,7 +133,7 @@ AT_CAPTURE_FILE([init])
 # Start the daemon and make sure that the pidfile exists immediately.
 # We don't wait for the pidfile to get created because the daemon is
 # supposed to do so before the parent exits.
-AT_CHECK([$PYTHON $srcdir/test-daemon.py --pidfile-name=$PWD/daemon --detach --monitor], [0], [ignore], [ignore])
+AT_CHECK([$PYTHON $srcdir/test-daemon.py --pidfile-name=$PWD/daemon --detach --monitor], [0])
 AT_CHECK([test -s daemon])
 # Check that the pidfile names a running process,
 # and that the parent process of that process is a running process,
index a97b05c..f7154e8 100644 (file)
@@ -7,7 +7,7 @@ AT_CAPTURE_FILE([pid])
 AT_CAPTURE_FILE([expected])
 # Start the daemon and wait for the pidfile to get created
 # and that its contents are the correct pid.
-AT_CHECK([ovsdb-server --pidfile=$PWD/pid --remote=punix:socket --unixctl=$PWD/unixctl db& echo $! > expected], [0], [ignore], [ignore])
+AT_CHECK([ovsdb-server --pidfile=$PWD/pid --remote=punix:socket --unixctl=$PWD/unixctl db& echo $! > expected], [0])
 OVS_WAIT_UNTIL([test -s pid], [kill `cat expected`])
 AT_CHECK(
   [pid=`cat pid` && expected=`cat expected` && test "$pid" = "$expected"],
@@ -27,7 +27,7 @@ AT_CAPTURE_FILE([parent])
 AT_CAPTURE_FILE([parentpid])
 AT_CAPTURE_FILE([newpid])
 # Start the daemon and wait for the pidfile to get created.
-AT_CHECK([ovsdb-server --monitor --pidfile=$PWD/pid --remote=punix:socket --unixctl=$PWD/unixctl db& echo $! > parent], [0], [ignore], [ignore])
+AT_CHECK([ovsdb-server --monitor --pidfile=$PWD/pid --remote=punix:socket --unixctl=$PWD/unixctl db& echo $! > parent], [0])
 OVS_WAIT_UNTIL([test -s pid], [kill `cat parent`])
 # Check that the pidfile names a running process,
 # and that the parent process of that process is our child process.
@@ -70,7 +70,7 @@ OVSDB_INIT([db])
 # Start the daemon and make sure that the pidfile exists immediately.
 # We don't wait for the pidfile to get created because the daemon is
 # supposed to do so before the parent exits.
-AT_CHECK([ovsdb-server --detach --pidfile=$PWD/pid --remote=punix:socket --unixctl=$PWD/unixctl db], [0], [ignore], [ignore])
+AT_CHECK([ovsdb-server --detach --pidfile=$PWD/pid --remote=punix:socket --unixctl=$PWD/unixctl db], [0])
 AT_CHECK([test -s pid])
 AT_CHECK([kill -0 `cat pid`])
 # Kill the daemon and make sure that the pidfile gets deleted.
@@ -94,7 +94,7 @@ AT_CAPTURE_FILE([init])
 # Start the daemon and make sure that the pidfile exists immediately.
 # We don't wait for the pidfile to get created because the daemon is
 # supposed to do so before the parent exits.
-AT_CHECK([ovsdb-server --detach --pidfile=$PWD/daemon --monitor --remote=punix:socket --unixctl=$PWD/unixctl db], [0], [ignore], [ignore])
+AT_CHECK([ovsdb-server --detach --pidfile=$PWD/daemon --monitor --remote=punix:socket --unixctl=$PWD/unixctl db], [0])
 AT_CHECK([test -s daemon])
 # Check that the pidfile names a running process,
 # and that the parent process of that process is a running process,
@@ -107,7 +107,7 @@ CHECK([test `cat init` = 1])
 # Kill the daemon process, making it look like a segfault,
 # and wait for a new daemon process to get spawned.
 CHECK([cp daemon olddaemon])
-CHECK([kill -SEGV `cat daemon`], [0], [ignore], [ignore])
+CHECK([kill -SEGV `cat daemon`], [0])
 OVS_WAIT_WHILE([kill -0 `cat olddaemon`], [kill `cat olddaemon daemon`])
 OVS_WAIT_UNTIL([test -s daemon && test `cat daemon` != `cat olddaemon`],
   [kill `cat olddaemon daemon`])
index e8a98bb..cda34ab 100644 (file)
@@ -8,7 +8,7 @@ AT_CHECK([kill -0 `cat pid`])
 AT_CHECK(
   [[$PYTHON $srcdir/test-jsonrpc.py request unix:socket echo '[{"a": "b", "x": null}]']], [0],
   [[{"error":null,"id":0,"result":[{"a":"b","x":null}]}
-]], [ignore], [test ! -e pid || kill `cat pid`])
+]], [], [test ! -e pid || kill `cat pid`])
 AT_CHECK([kill `cat pid`])
 AT_CLEANUP
 
@@ -20,7 +20,7 @@ AT_CHECK([kill -0 `cat pid`])
 AT_CHECK(
   [[$PYTHON $srcdir/test-jsonrpc.py request unix:socket bad-request '[]']], [0],
   [[{"error":{"error":"unknown method"},"id":0,"result":null}
-]], [ignore], [test ! -e pid || kill `cat pid`])
+]], [], [test ! -e pid || kill `cat pid`])
 AT_CHECK([kill `cat pid`])
 AT_CLEANUP
 
@@ -32,7 +32,7 @@ AT_CHECK([test -s pid])
 AT_CHECK([cp pid pid2])
 AT_CHECK([kill -0 `cat pid2`])
 AT_CHECK([[$PYTHON $srcdir/test-jsonrpc.py notify unix:socket shutdown '[]']], [0], [], 
-  [ignore], [kill `cat pid2`])
+  [], [kill `cat pid2`])
 AT_CHECK(
   [pid=`cat pid2`
    # First try a quick sleep, so that the test completes very quickly
index 856fa46..b669a39 100644 (file)
@@ -7,7 +7,7 @@ AT_CHECK([kill -0 `cat pid`])
 AT_CHECK(
   [[test-jsonrpc request unix:socket echo '[{"a": "b", "x": null}]']], [0],
   [[{"error":null,"id":0,"result":[{"a":"b","x":null}]}
-]], [ignore], [test ! -e pid || kill `cat pid`])
+]], [], [test ! -e pid || kill `cat pid`])
 AT_CHECK([kill `cat pid`])
 AT_CLEANUP
 
@@ -18,7 +18,7 @@ AT_CHECK([kill -0 `cat pid`])
 AT_CHECK(
   [[test-jsonrpc request unix:socket bad-request '[]']], [0],
   [[{"error":{"error":"unknown method"},"id":0,"result":null}
-]], [ignore], [test ! -e pid || kill `cat pid`])
+]], [], [test ! -e pid || kill `cat pid`])
 AT_CHECK([kill `cat pid`])
 AT_CLEANUP
 
@@ -29,7 +29,7 @@ AT_CHECK([test -s pid])
 AT_CHECK([cp pid pid2])
 AT_CHECK([kill -0 `cat pid2`])
 AT_CHECK([[test-jsonrpc notify unix:socket shutdown '[]']], [0], [], 
-  [ignore], [kill `cat pid2`])
+  [], [kill `cat pid2`])
 AT_CHECK(
   [pid=`cat pid2`
    # First try a quick sleep, so that the test completes very quickly
index d199373..ec50e23 100644 (file)
@@ -7,19 +7,22 @@ AT_CHECK([test-flows <flows 3<pcap], [0], [checked 247 packets, 0 errors
 AT_CLEANUP
 
 AT_SETUP([test TCP/IP checksumming])
-AT_CHECK([test-csum], [0], [ignore])
+AT_CHECK([test-csum], [0], [....#....#....##................................#................................#
+])
 AT_CLEANUP
 
 AT_SETUP([test hash functions])
-AT_CHECK([test-hash], [0], [ignore])
+AT_CHECK([test-hash])
 AT_CLEANUP
 
 AT_SETUP([test hash map])
-AT_CHECK([test-hmap], [0], [ignore])
+AT_CHECK([test-hmap], [0], [.........
+])
 AT_CLEANUP
 
 AT_SETUP([test linked lists])
-AT_CHECK([test-list], [0], [ignore])
+AT_CHECK([test-list], [0], [..
+])
 AT_CLEANUP
 
 AT_SETUP([test packet library])
@@ -27,20 +30,22 @@ AT_CHECK([test-packets])
 AT_CLEANUP
 
 AT_SETUP([test SHA-1])
-AT_CHECK([test-sha1], [0], [ignore])
+AT_CHECK([test-sha1], [0], [.........
+])
 AT_CLEANUP
 
 AT_SETUP([test type properties])
-AT_CHECK([test-type-props], [0], [ignore])
+AT_CHECK([test-type-props])
 AT_CLEANUP
 
 AT_SETUP([test strtok_r bug fix])
-AT_CHECK([test-strtok_r], [0], [ignore])
+AT_CHECK([test-strtok_r], [0], [NULL NULL
+])
 AT_CLEANUP
 
 AT_SETUP([test byte order conversion])
 AT_KEYWORDS([byte order])
-AT_CHECK([test-byte-order], [0], [ignore])
+AT_CHECK([test-byte-order])
 AT_CLEANUP
 
 AT_SETUP([test random number generator])
index 923e00e..417ef48 100644 (file)
@@ -280,21 +280,25 @@ AT_CLEANUP
 # The flow is formatted with cls_rule_format() for the low-verbosity case.
 AT_SETUP([OFPT_FLOW_MOD - low verbosity])
 AT_KEYWORDS([ofp-print])
-AT_CHECK([ovs-ofctl ofp-print "\
+AT_CHECK([ovs-ofctl '-vPATTERN:console:%c|%p|%m' ofp-print "\
 01 0e 00 50 00 00 00 00 00 00 00 00 00 01 50 54 \
 00 00 00 06 50 54 00 00 00 05 ff ff 00 00 08 06 \
 00 02 00 00 c0 a8 00 02 c0 a8 00 01 00 00 00 00 \
 00 00 00 00 00 00 00 00 00 00 00 05 00 00 00 00 \
 00 00 01 0e 00 00 00 00 00 00 00 08 00 03 00 00 \
 " 2], [0], [dnl
-OFPT_FLOW_MOD (xid=0x0): ADD priority=65535,arp,in_port=1,vlan_tci=0x0000,dl_src=50:54:00:00:00:06,dl_dst=50:54:00:00:00:05,nw_src=192.168.0.2,nw_dst=192.168.0.1,opcode=2,nw_tos=0,tp_src=0,tp_dst=0 idle:5 buf:0x10e actions=output:3
+OFPT_FLOW_MOD (xid=0x0): ADD priority=65535,arp,in_port=1,vlan_tci=0x0000,dl_src=50:54:00:00:00:06,dl_dst=50:54:00:00:00:05,nw_src=192.168.0.2,nw_dst=192.168.0.1,opcode=2,nw_tos=0 idle:5 buf:0x10e actions=output:3
+], [dnl
+ofp_util|INFO|normalization changed ofp_match, details:
+ofp_util|INFO| pre: arp,in_port=1,dl_vlan=65535,dl_vlan_pcp=0,dl_src=50:54:00:00:00:06,dl_dst=50:54:00:00:00:05,nw_src=192.168.0.2,nw_dst=192.168.0.1,opcode=2,nw_tos=0,tp_src=0,tp_dst=0
+ofp_util|INFO|post: arp,in_port=1,dl_vlan=65535,dl_vlan_pcp=0,dl_src=50:54:00:00:00:06,dl_dst=50:54:00:00:00:05,nw_src=192.168.0.2,nw_dst=192.168.0.1,opcode=2,nw_tos=0
 ])
 AT_CLEANUP
 
-# The flow is formatted with ofp_match_to_string() for the low-verbosity case.
+# The flow is formatted with ofp_match_to_string() for the high-verbosity case.
 AT_SETUP([OFPT_FLOW_MOD - high verbosity])
 AT_KEYWORDS([ofp-print])
-AT_CHECK([ovs-ofctl ofp-print "\
+AT_CHECK([ovs-ofctl '-vPATTERN:console:%c|%p|%m' ofp-print "\
 01 0e 00 50 00 00 00 00 00 00 00 00 00 01 50 54 \
 00 00 00 06 50 54 00 00 00 05 ff ff 00 00 08 06 \
 00 02 00 00 c0 a8 00 02 c0 a8 00 01 00 00 00 00 \
@@ -302,6 +306,10 @@ AT_CHECK([ovs-ofctl ofp-print "\
 00 00 01 0e 00 00 00 00 00 00 00 08 00 03 00 00 \
 " 3], [0], [dnl
 OFPT_FLOW_MOD (xid=0x0): ADD arp,in_port=1,dl_vlan=65535,dl_vlan_pcp=0,dl_src=50:54:00:00:00:06,dl_dst=50:54:00:00:00:05,nw_src=192.168.0.2,nw_dst=192.168.0.1,opcode=2,nw_tos=0,tp_src=0,tp_dst=0 idle:5 pri:65535 buf:0x10e actions=output:3
+], [dnl
+ofp_util|INFO|normalization changed ofp_match, details:
+ofp_util|INFO| pre: arp,in_port=1,dl_vlan=65535,dl_vlan_pcp=0,dl_src=50:54:00:00:00:06,dl_dst=50:54:00:00:00:05,nw_src=192.168.0.2,nw_dst=192.168.0.1,opcode=2,nw_tos=0,tp_src=0,tp_dst=0
+ofp_util|INFO|post: arp,in_port=1,dl_vlan=65535,dl_vlan_pcp=0,dl_src=50:54:00:00:00:06,dl_dst=50:54:00:00:00:05,nw_src=192.168.0.2,nw_dst=192.168.0.1,opcode=2,nw_tos=0
 ])
 AT_CLEANUP
 
index d5ff2ad..3927550 100644 (file)
@@ -8,7 +8,13 @@ m4_define([OFPROTO_START],
    AT_CAPTURE_FILE([ovs-openflowd.log])
    AT_CHECK(
      [ovs-openflowd --detach --pidfile --enable-dummy --log-file --fail=closed dummy@br0 none --datapath-id=fedcba9876543210 $1],
-     [0], [ignore], [ignore])
+     [0], [], [stderr])
+   AT_CHECK([[sed < stderr '
+/vlog|INFO|opened log file/d
+/openflowd|INFO|Open vSwitch version/d
+/openflowd|INFO|OpenFlow protocol version/d
+/ofproto|INFO|using datapath ID/d
+/ofproto|INFO|datapath ID changed to fedcba9876543210/d']])
 ])
 
 m4_define([OFPROTO_STOP],
index 3a8f0b6..997cc30 100644 (file)
@@ -18,7 +18,7 @@ table=1,actions=drop
 tun_id=0x1234000056780000/0xffff0000ffff0000,actions=drop
 ]])
 AT_CHECK([ovs-ofctl parse-flows flows.txt
-], [0], [stdout], [stderr])
+], [0], [stdout])
 AT_CHECK([[sed 's/ (xid=0x[0-9a-fA-F]*)//' stdout]], [0], 
 [[OFPT_FLOW_MOD: ADD tcp,tp_src=123 actions=FLOOD
 OFPT_FLOW_MOD: ADD in_port=65534,dl_vlan=9,dl_src=00:0a:e4:25:6b:b0 actions=drop
@@ -36,17 +36,6 @@ NXT_FLOW_MOD_TABLE_ID: enable
 NXT_FLOW_MOD: ADD table_id:1 actions=drop
 NXT_FLOW_MOD: ADD table_id:255 tun_id=0x1234000056780000/0xffff0000ffff0000 actions=drop
 ]])
-AT_CHECK([sed 's/.*|//' stderr], [0], [dnl
-normalization changed ofp_match, details:
- pre: wildcards=  0x3820f8  in_port=65534  dl_src=00:0a:e4:25:6b:b0  dl_dst=00:00:00:00:00:00  dl_vlan=    9  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=  0x3ffff8  in_port=65534  dl_src=00:0a:e4:25:6b:b0  dl_dst=00:00:00:00:00:00  dl_vlan=    9  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
-])
 AT_CLEANUP
 
 AT_SETUP([ovs-ofctl -F nxm parse-flows])
index f7b6432..bd06110 100644 (file)
@@ -46,7 +46,7 @@ AT_CHECK(
 file: read: [1]
 ]], [ignore])
 AT_CHECK(
-  [test-ovsdb -vlockfile:console:emer log-io file create read], [1], 
+  [test-ovsdb log-io file create read], [1],
   [], [test-ovsdb: I/O error: create: file failed (File exists)
 ])
 AT_CHECK([test -f .file.~lock~])
index b603cf7..d7c0335 100644 (file)
@@ -50,7 +50,7 @@ AT_DATA([txnfile], [[ovsdb-client transact unix:socket \
    "table": "ordinals",
    "row": {"number": 0, "name": "zero"}}]'
 ]])
-AT_CHECK([ovsdb-server -vlockfile:ANY:EMER --remote=punix:socket --unixctl=$PWD/unixctl db --run="sh txnfile"], [0], [stdout], [])
+AT_CHECK([ovsdb-server --remote=punix:socket --unixctl=$PWD/unixctl db --run="sh txnfile"], [0], [stdout], [])
 cat stdout >> output
 dnl Add some crap to the database log and run another transaction, which should
 dnl ignore the crap and truncate it out of the log.
@@ -61,7 +61,7 @@ AT_DATA([txnfile], [[ovsdb-client transact unix:socket \
    "table": "ordinals",
    "row": {"number": 1, "name": "one"}}]'
 ]])
-AT_CHECK([ovsdb-server -vlockfile:ANY:EMER --remote=punix:socket --unixctl=$PWD/unixctl db --run="sh txnfile"], [0], [stdout], [stderr])
+AT_CHECK([ovsdb-server --remote=punix:socket --unixctl=$PWD/unixctl db --run="sh txnfile"], [0], [stdout], [stderr])
 AT_CHECK([grep 'syntax error: db: parse error.* in header line "xxx"' stderr],
   [0], [ignore])
 cat stdout >> output
@@ -75,7 +75,7 @@ AT_DATA([txnfile], [[ovsdb-client transact unix:socket \
    "where": [],
    "sort": ["number"]}]'
 ]])
-AT_CHECK([ovsdb-server -vlockfile:ANY:EMER --remote=punix:socket --unixctl=$PWD/unixctl db --run="sh txnfile"], [0], [stdout], [])
+AT_CHECK([ovsdb-server --remote=punix:socket --unixctl=$PWD/unixctl db --run="sh txnfile"], [0], [stdout], [])
 cat stdout >> output
 AT_CHECK([perl $srcdir/uuidfilt.pl output], [0],
   [[[{"uuid":["uuid","<0>"]}]
@@ -97,7 +97,7 @@ AT_DATA([txnfile], [[ovsdb-client transact unix:socket \
    "table": "ordinals",
    "row": {"number": 0, "name": "zero"}}]'
 ]])
-AT_CHECK([ovsdb-server -vlockfile:ANY:EMER --remote=punix:socket --unixctl=$PWD/unixctl db --run="sh txnfile"], [0], [stdout], [])
+AT_CHECK([ovsdb-server --remote=punix:socket --unixctl=$PWD/unixctl db --run="sh txnfile"], [0], [stdout], [])
 cat stdout >> output
 dnl Add some crap to the database log and run another transaction, which should
 dnl ignore the crap and truncate it out of the log.
@@ -109,7 +109,7 @@ AT_DATA([txnfile], [[ovsdb-client transact unix:socket \
    "table": "ordinals",
    "row": {"number": 1, "name": "one"}}]'
 ]])
-AT_CHECK([ovsdb-server -vlockfile:ANY:EMER --remote=punix:socket --unixctl=$PWD/unixctl db --run="sh txnfile"], [0], [stdout], [stderr])
+AT_CHECK([ovsdb-server --remote=punix:socket --unixctl=$PWD/unixctl db --run="sh txnfile"], [0], [stdout], [stderr])
 AT_CHECK([grep 'syntax "{"invalid":{}}": unknown table: No table named invalid.' stderr],
   [0], [ignore])
 cat stdout >> output
@@ -123,7 +123,7 @@ AT_DATA([txnfile], [[ovsdb-client transact unix:socket \
    "where": [],
    "sort": ["number"]}]'
 ]])
-AT_CHECK([ovsdb-server -vlockfile:ANY:EMER --remote=punix:socket --unixctl=$PWD/unixctl db --run="sh txnfile"], [0], [stdout], [])
+AT_CHECK([ovsdb-server --remote=punix:socket --unixctl=$PWD/unixctl db --run="sh txnfile"], [0], [stdout], [])
 cat stdout >> output
 AT_CHECK([perl $srcdir/uuidfilt.pl output], [0],
   [[[{"uuid":["uuid","<0>"]}]
index 1870754..1c5bf38 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010 Nicira Networks.
+ * Copyright (c) 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.
@@ -22,6 +22,7 @@
 int
 main(void)
 {
+#ifndef __CHECKER__
     /* I picked some random numbers. */
     const uint16_t s = 0xc9bd;
     const uint32_t l = 0xffe56ae8;
@@ -44,6 +45,9 @@ main(void)
     assert(ntohll(htonll(ll)) == ll);
     assert(CONSTANT_HTONLL(ntohll(ll)) == ll);
     assert(ntohll(CONSTANT_HTONLL(ll)));
+#else  /* __CHECKER__ */
+/* Making sparse happy with this code makes it unreadable, so don't bother. */
+#endif
 
     return 0;
 }
index af6655e..81f54b8 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.
@@ -40,7 +40,7 @@ static const struct test_case test_cases[] = {
     /* RFC 1071 section 3. */
     TEST_CASE("\x00\x01\xf2\x03"
               "\xf4\xf5\xf6\xf7",
-              (uint16_t) ~0xddf2),
+              0xffff - 0xddf2 /* ~0xddf2 */),
 
     /* http://www.sbprojects.com/projects/tcpip/theory/theory14.htm */
     TEST_CASE("\x45\x00\x00\x28"
@@ -99,7 +99,7 @@ test_rfc1624(void)
         "\x66\x64\xfc\x96\x63\x97\x64\xee\x12\x53\x1d\xa9\x2d\xa9\x55\x55";
 
     /* "...the one's complement sum of all other header octets is 0xCD7A." */
-    assert(ntohs(csum(data, sizeof data - 2)) == (uint16_t) ~0xcd7a);
+    assert(ntohs(csum(data, sizeof data - 2)) == 0xffff - 0xcd7a);
 
     /* "...the header checksum would be:
 
@@ -127,7 +127,8 @@ test_rfc1624(void)
               = ~(0x22D0 + ~0x5555 + 0x3285)
               = ~0xFFFF
               =  0x0000" */
-    assert(recalc_csum16(0xdd2f, 0x5555, 0x3285) == 0x0000);
+    assert(recalc_csum16(htons(0xdd2f), htons(0x5555), htons(0x3285))
+           == htons(0x0000));
 
     mark('#');
 }
@@ -139,8 +140,8 @@ main(void)
     int i;
 
     for (tc = test_cases; tc < &test_cases[ARRAY_SIZE(test_cases)]; tc++) {
-        const uint16_t *data16 = (const uint16_t *) tc->data;
-        const uint32_t *data32 = (const uint32_t *) tc->data;
+        const ovs_be16 *data16 = (OVS_FORCE const ovs_be16 *) tc->data;
+        const ovs_be32 *data32 = (OVS_FORCE const ovs_be32 *) tc->data;
         uint32_t partial;
 
         /* Test csum(). */
@@ -150,7 +151,7 @@ main(void)
         /* Test csum_add16(). */
         partial = 0;
         for (i = 0; i < tc->size / 2; i++) {
-            partial = csum_add16(partial, get_unaligned_u16(&data16[i]));
+            partial = csum_add16(partial, get_unaligned_be16(&data16[i]));
         }
         assert(ntohs(csum_finish(partial)) == tc->csum);
         mark('.');
@@ -158,7 +159,7 @@ main(void)
         /* Test csum_add32(). */
         partial = 0;
         for (i = 0; i < tc->size / 4; i++) {
-            partial = csum_add32(partial, get_unaligned_u32(&data32[i]));
+            partial = csum_add32(partial, get_unaligned_be32(&data32[i]));
         }
         assert(ntohs(csum_finish(partial)) == tc->csum);
         mark('.');
@@ -167,10 +168,10 @@ main(void)
         partial = 0;
         for (i = 0; i < tc->size / 4; i++) {
             if (i % 2) {
-                partial = csum_add32(partial, get_unaligned_u32(&data32[i]));
+                partial = csum_add32(partial, get_unaligned_be32(&data32[i]));
             } else {
-                uint16_t u0 = get_unaligned_u16(&data16[i * 2]);
-                uint16_t u1 = get_unaligned_u16(&data16[i * 2 + 1]);
+                ovs_be16 u0 = get_unaligned_be16(&data16[i * 2]);
+                ovs_be16 u1 = get_unaligned_be16(&data16[i * 2 + 1]);
                 partial = csum_add16(partial, u0);
                 partial = csum_add16(partial, u1);
             }
@@ -196,18 +197,18 @@ main(void)
 
     /* Test recalc_csum16(). */
     for (i = 0; i < 32; i++) {
-        uint16_t old_u16, new_u16;
-        uint16_t old_csum;
-        uint16_t data[16];
+        ovs_be16 old_u16, new_u16;
+        ovs_be16 old_csum;
+        ovs_be16 data[16];
         int j, index;
 
         for (j = 0; j < ARRAY_SIZE(data); j++) {
-            data[j] = random_uint32();
+            data[j] = (OVS_FORCE ovs_be16) random_uint32();
         }
         old_csum = csum(data, sizeof data);
         index = random_range(ARRAY_SIZE(data));
         old_u16 = data[index];
-        new_u16 = data[index] = random_uint32();
+        new_u16 = data[index] = (OVS_FORCE ovs_be16) random_uint32();
         assert(csum(data, sizeof data)
                == recalc_csum16(old_csum, old_u16, new_u16));
         mark('.');
@@ -216,18 +217,18 @@ main(void)
 
     /* Test recalc_csum32(). */
     for (i = 0; i < 32; i++) {
-        uint32_t old_u32, new_u32;
-        uint16_t old_csum;
-        uint32_t data[16];
+        ovs_be32 old_u32, new_u32;
+        ovs_be16 old_csum;
+        ovs_be32 data[16];
         int j, index;
 
         for (j = 0; j < ARRAY_SIZE(data); j++) {
-            data[j] = random_uint32();
+            data[j] = (OVS_FORCE ovs_be32) random_uint32();
         }
         old_csum = csum(data, sizeof data);
         index = random_range(ARRAY_SIZE(data));
         old_u32 = data[index];
-        new_u32 = data[index] = random_uint32();
+        new_u32 = data[index] = (OVS_FORCE ovs_be32) random_uint32();
         assert(csum(data, sizeof data)
                == recalc_csum32(old_csum, old_u32, new_u32));
         mark('.');
index 5d93850..d892ece 100644 (file)
@@ -57,12 +57,12 @@ parse_options(int argc, char *argv[])
         DAEMON_OPTION_ENUMS
     };
     static struct option long_options[] = {
-        {"verbose", optional_argument, 0, 'v'},
-        {"help", no_argument, 0, 'h'},
+        {"verbose", optional_argument, NULL, 'v'},
+        {"help", no_argument, NULL, 'h'},
         DAEMON_LONG_OPTIONS,
-        {"bootstrap-ca-cert", required_argument, 0, OPT_BOOTSTRAP_CA_CERT},
+        {"bootstrap-ca-cert", required_argument, NULL, OPT_BOOTSTRAP_CA_CERT},
         STREAM_SSL_LONG_OPTIONS,
-        {0, 0, 0, 0},
+        {NULL, 0, NULL, 0},
     };
     char *short_options = long_options_to_short_options(long_options);
 
index 0feb270..121b2ba 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.
@@ -231,7 +231,7 @@ static const struct test tests[] = {
     TEST(lock_timeout_runs_out),
     TEST(lock_multiple),
     TEST(help),
-    { 0, 0 }
+    { NULL, NULL }
 #undef TEST
 };
 
index 990bf6d..8fe1727 100644 (file)
@@ -68,10 +68,10 @@ static void
 parse_options(int argc, char *argv[])
 {
     static struct option long_options[] = {
-        {"timeout", required_argument, 0, 't'},
-        {"verbose", optional_argument, 0, 'v'},
-        {"help", no_argument, 0, 'h'},
-        {0, 0, 0, 0},
+        {"timeout", required_argument, NULL, 't'},
+        {"verbose", optional_argument, NULL, 'v'},
+        {"help", no_argument, NULL, 'h'},
+        {NULL, 0, NULL, 0},
     };
     char *short_options = long_options_to_short_options(long_options);
 
index 65751c8..c7aec4b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009 Nicira Networks.
+ * Copyright (c) 2009, 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.
@@ -127,9 +127,12 @@ test_big_vector(void)
         { 0x34, 0xAA, 0x97, 0x3C, 0xD4, 0xC4, 0xDA, 0xA4, 0xF6, 0x1E,
           0xEB, 0x2B, 0xDB, 0xAD, 0x27, 0x31, 0x65, 0x34, 0x01, 0x6F }
     };
+    size_t i;
 
     vec.data = xmalloc(SIZE);
-    memset(vec.data, 'a', SIZE);
+    for (i = 0; i < SIZE; i++) {
+        vec.data[i] = 'a';
+    }
     test_one(&vec);
     free(vec.data);
 }
index 9f8d898..b302630 100644 (file)
@@ -33,6 +33,6 @@ main(void)
     char *token1, *token2;
     token1 = strtok_r(string, ":", &save_ptr);
     token2 = strtok_r(NULL, ":", &save_ptr);
-    printf ("%s %s\n", token1, token2);
+    printf ("%s %s\n", token1 ? token1 : "NULL", token2 ? token2 : "NULL");
     return 0;
 }
index 12b69ca..2b14fa8 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.
@@ -203,7 +203,7 @@ test_read_hello(int argc OVS_UNUSED, char *argv[])
        if (retval == sizeof hello) {
            CHECK(hello.version, OFP_VERSION);
            CHECK(hello.type, OFPT_HELLO);
-           CHECK(hello.length, htons(sizeof hello));
+           CHECK(ntohs(hello.length), sizeof hello);
            break;
        } else {
            CHECK_ERRNO(retval, -EAGAIN);
@@ -269,7 +269,7 @@ test_send_hello(const char *type, const void *out, size_t out_size,
            if (retval == sizeof hello) {
                CHECK(hello.version, OFP_VERSION);
                CHECK(hello.type, OFPT_HELLO);
-               CHECK(hello.length, htons(sizeof hello));
+               CHECK(ntohs(hello.length), sizeof hello);
                read_hello = true;
            } else {
                CHECK_ERRNO(retval, -EAGAIN);
index 742603b..27fbe5e 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.
@@ -109,7 +109,7 @@ parse_command_line(int argc, char *argv[])
         {"execute", no_argument, NULL, 'e'},
         {"help", no_argument, NULL, 'h'},
         {"version", no_argument, NULL, 'V'},
-        {0, 0, 0, 0},
+        {NULL, 0, NULL, 0},
     };
     const char *target;
     int e_options;
index 89e6a56..f977974 100644 (file)
@@ -314,23 +314,23 @@ parse_options(int argc, char *argv[])
         DAEMON_OPTION_ENUMS
     };
     static struct option long_options[] = {
-        {"hub",         no_argument, 0, 'H'},
-        {"noflow",      no_argument, 0, 'n'},
-        {"normal",      no_argument, 0, 'N'},
-        {"wildcard",    no_argument, 0, 'w'},
-        {"max-idle",    required_argument, 0, OPT_MAX_IDLE},
-        {"mute",        no_argument, 0, OPT_MUTE},
-        {"queue",       required_argument, 0, 'q'},
-        {"port-queue",  required_argument, 0, 'Q'},
-        {"with-flows",  required_argument, 0, OPT_WITH_FLOWS},
-        {"unixctl",     required_argument, 0, OPT_UNIXCTL},
-        {"help",        no_argument, 0, 'h'},
-        {"version",     no_argument, 0, 'V'},
+        {"hub",         no_argument, NULL, 'H'},
+        {"noflow",      no_argument, NULL, 'n'},
+        {"normal",      no_argument, NULL, 'N'},
+        {"wildcard",    no_argument, NULL, 'w'},
+        {"max-idle",    required_argument, NULL, OPT_MAX_IDLE},
+        {"mute",        no_argument, NULL, OPT_MUTE},
+        {"queue",       required_argument, NULL, 'q'},
+        {"port-queue",  required_argument, NULL, 'Q'},
+        {"with-flows",  required_argument, NULL, OPT_WITH_FLOWS},
+        {"unixctl",     required_argument, NULL, OPT_UNIXCTL},
+        {"help",        no_argument, NULL, 'h'},
+        {"version",     no_argument, NULL, 'V'},
         DAEMON_LONG_OPTIONS,
         VLOG_LONG_OPTIONS,
         STREAM_SSL_LONG_OPTIONS,
-        {"peer-ca-cert", required_argument, 0, OPT_PEER_CA_CERT},
-        {0, 0, 0, 0},
+        {"peer-ca-cert", required_argument, NULL, OPT_PEER_CA_CERT},
+        {NULL, 0, NULL, 0},
     };
     char *short_options = long_options_to_short_options(long_options);
 
index 40048b4..c7350e5 100644 (file)
@@ -46,7 +46,7 @@
 VLOG_DEFINE_THIS_MODULE(dpctl);
 
 /* -s, --statistics: Print port statistics? */
-bool print_statistics;
+static bool print_statistics;
 
 static const struct command all_commands[];
 
@@ -71,12 +71,12 @@ 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'},
+        {"statistics", no_argument, NULL, 's'},
+        {"timeout", required_argument, NULL, 't'},
+        {"help", no_argument, NULL, 'h'},
+        {"version", no_argument, NULL, 'V'},
         VLOG_LONG_OPTIONS,
-        {0, 0, 0, 0},
+        {NULL, 0, NULL, 0},
     };
     char *short_options = long_options_to_short_options(long_options);
 
index 5fa11db..5f9c830 100644 (file)
@@ -85,15 +85,15 @@ parse_options(int argc, char *argv[])
         VLOG_OPTION_ENUMS
     };
     static struct option long_options[] = {
-        {"timeout", required_argument, 0, 't'},
-        {"strict", no_argument, 0, OPT_STRICT},
-        {"flow-format", required_argument, 0, 'F'},
-        {"more", no_argument, 0, 'm'},
-        {"help", no_argument, 0, 'h'},
-        {"version", no_argument, 0, 'V'},
+        {"timeout", required_argument, NULL, 't'},
+        {"strict", no_argument, NULL, OPT_STRICT},
+        {"flow-format", required_argument, NULL, 'F'},
+        {"more", no_argument, NULL, 'm'},
+        {"help", no_argument, NULL, 'h'},
+        {"version", no_argument, NULL, 'V'},
         VLOG_LONG_OPTIONS,
         STREAM_SSL_LONG_OPTIONS,
-        {0, 0, 0, 0},
+        {NULL, 0, NULL, 0},
     };
     char *short_options = long_options_to_short_options(long_options);
 
index 9a9dffe..4ca22e0 100644 (file)
@@ -241,37 +241,37 @@ parse_options(int argc, char *argv[], struct ofsettings *s)
         DAEMON_OPTION_ENUMS
     };
     static struct option long_options[] = {
-        {"datapath-id", required_argument, 0, OPT_DATAPATH_ID},
-        {"mfr-desc", required_argument, 0, OPT_MFR_DESC},
-        {"hw-desc", required_argument, 0, OPT_HW_DESC},
-        {"sw-desc", required_argument, 0, OPT_SW_DESC},
-        {"serial-desc", required_argument, 0, OPT_SERIAL_DESC},
-        {"dp-desc", required_argument, 0, OPT_DP_DESC},
-        {"config",      required_argument, 0, 'F'},
-        {"br-name",     required_argument, 0, OPT_BR_NAME},
-        {"fail",        required_argument, 0, OPT_FAIL_MODE},
-        {"inactivity-probe", required_argument, 0, OPT_INACTIVITY_PROBE},
-        {"max-idle",    required_argument, 0, OPT_MAX_IDLE},
-        {"max-backoff", required_argument, 0, OPT_MAX_BACKOFF},
-        {"listen",      required_argument, 0, 'l'},
-        {"snoop",      required_argument, 0, OPT_SNOOP},
-        {"rate-limit",  optional_argument, 0, OPT_RATE_LIMIT},
-        {"burst-limit", required_argument, 0, OPT_BURST_LIMIT},
-        {"out-of-band", no_argument, 0, OPT_OUT_OF_BAND},
-        {"in-band",     no_argument, 0, OPT_IN_BAND},
-        {"netflow",     required_argument, 0, OPT_NETFLOW},
-        {"ports",       required_argument, 0, OPT_PORTS},
-        {"unixctl",     required_argument, 0, OPT_UNIXCTL},
-        {"enable-dummy", no_argument, 0, OPT_ENABLE_DUMMY},
-        {"verbose",     optional_argument, 0, 'v'},
-        {"help",        no_argument, 0, 'h'},
-        {"version",     no_argument, 0, 'V'},
+        {"datapath-id", required_argument, NULL, OPT_DATAPATH_ID},
+        {"mfr-desc", required_argument, NULL, OPT_MFR_DESC},
+        {"hw-desc", required_argument, NULL, OPT_HW_DESC},
+        {"sw-desc", required_argument, NULL, OPT_SW_DESC},
+        {"serial-desc", required_argument, NULL, OPT_SERIAL_DESC},
+        {"dp-desc", required_argument, NULL, OPT_DP_DESC},
+        {"config",      required_argument, NULL, 'F'},
+        {"br-name",     required_argument, NULL, OPT_BR_NAME},
+        {"fail",        required_argument, NULL, OPT_FAIL_MODE},
+        {"inactivity-probe", required_argument, NULL, OPT_INACTIVITY_PROBE},
+        {"max-idle",    required_argument, NULL, OPT_MAX_IDLE},
+        {"max-backoff", required_argument, NULL, OPT_MAX_BACKOFF},
+        {"listen",      required_argument, NULL, 'l'},
+        {"snoop",      required_argument, NULL, OPT_SNOOP},
+        {"rate-limit",  optional_argument, NULL, OPT_RATE_LIMIT},
+        {"burst-limit", required_argument, NULL, OPT_BURST_LIMIT},
+        {"out-of-band", no_argument, NULL, OPT_OUT_OF_BAND},
+        {"in-band",     no_argument, NULL, OPT_IN_BAND},
+        {"netflow",     required_argument, NULL, OPT_NETFLOW},
+        {"ports",       required_argument, NULL, OPT_PORTS},
+        {"unixctl",     required_argument, NULL, OPT_UNIXCTL},
+        {"enable-dummy", no_argument, NULL, OPT_ENABLE_DUMMY},
+        {"verbose",     optional_argument, NULL, 'v'},
+        {"help",        no_argument, NULL, 'h'},
+        {"version",     no_argument, NULL, 'V'},
         DAEMON_LONG_OPTIONS,
         VLOG_LONG_OPTIONS,
         LEAK_CHECKER_LONG_OPTIONS,
         STREAM_SSL_LONG_OPTIONS,
-        {"bootstrap-ca-cert", required_argument, 0, OPT_BOOTSTRAP_CA_CERT},
-        {0, 0, 0, 0},
+        {"bootstrap-ca-cert", required_argument, NULL, OPT_BOOTSTRAP_CA_CERT},
+        {NULL, 0, NULL, 0},
     };
     char *short_options = long_options_to_short_options(long_options);
     struct ofproto_controller controller_opts;
index 54316dd..309d64e 100644 (file)
@@ -113,7 +113,7 @@ parse_options(int argc, char *argv[])
     static const struct option long_options[] = {
         {"help", no_argument, NULL, 'h'},
         {"version", no_argument, NULL, 'V'},
-        {0, 0, 0, 0},
+        {NULL, 0, NULL, 0},
     };
     char *short_options = long_options_to_short_options(long_options);
 
index 8516966..780d242 100644 (file)
@@ -207,19 +207,19 @@ parse_options(int argc, char *argv[])
         TABLE_OPTION_ENUMS
     };
     static struct option long_options[] = {
-        {"db", required_argument, 0, OPT_DB},
-        {"no-syslog", no_argument, 0, OPT_NO_SYSLOG},
-        {"no-wait", no_argument, 0, OPT_NO_WAIT},
-        {"dry-run", no_argument, 0, OPT_DRY_RUN},
-        {"oneline", no_argument, 0, OPT_ONELINE},
-        {"timeout", required_argument, 0, 't'},
-        {"help", no_argument, 0, 'h'},
-        {"version", no_argument, 0, 'V'},
+        {"db", required_argument, NULL, OPT_DB},
+        {"no-syslog", no_argument, NULL, OPT_NO_SYSLOG},
+        {"no-wait", no_argument, NULL, OPT_NO_WAIT},
+        {"dry-run", no_argument, NULL, OPT_DRY_RUN},
+        {"oneline", no_argument, NULL, OPT_ONELINE},
+        {"timeout", required_argument, NULL, 't'},
+        {"help", no_argument, NULL, 'h'},
+        {"version", no_argument, NULL, 'V'},
         VLOG_LONG_OPTIONS,
         TABLE_LONG_OPTIONS,
         STREAM_SSL_LONG_OPTIONS,
-        {"peer-ca-cert", required_argument, 0, OPT_PEER_CA_CERT},
-        {0, 0, 0, 0},
+        {"peer-ca-cert", required_argument, NULL, OPT_PEER_CA_CERT},
+        {NULL, 0, NULL, 0},
     };
     char *tmp, *short_options;
 
@@ -1111,7 +1111,7 @@ cmd_emer_reset(struct vsctl_context *ctx)
 static void
 cmd_add_br(struct vsctl_context *ctx)
 {
-    bool may_exist = shash_find(&ctx->options, "--may-exist") != 0;
+    bool may_exist = shash_find(&ctx->options, "--may-exist") != NULL;
     const char *br_name, *parent_name;
     struct vsctl_info info;
     int vlan;
@@ -1563,7 +1563,7 @@ add_port(struct vsctl_context *ctx,
 static void
 cmd_add_port(struct vsctl_context *ctx)
 {
-    bool may_exist = shash_find(&ctx->options, "--may-exist") != 0;
+    bool may_exist = shash_find(&ctx->options, "--may-exist") != NULL;
 
     add_port(ctx, ctx->argv[1], ctx->argv[2], may_exist, false,
              &ctx->argv[2], 1, &ctx->argv[3], ctx->argc - 3);
@@ -1572,7 +1572,7 @@ cmd_add_port(struct vsctl_context *ctx)
 static void
 cmd_add_bond(struct vsctl_context *ctx)
 {
-    bool may_exist = shash_find(&ctx->options, "--may-exist") != 0;
+    bool may_exist = shash_find(&ctx->options, "--may-exist") != NULL;
     bool fake_iface = shash_find(&ctx->options, "--fake-iface");
     int n_ifaces;
     int i;
index dd0d1b2..3faeee1 100644 (file)
@@ -1629,7 +1629,11 @@ bridge_create(const struct ovsrec_bridge *br_cfg)
     br->name = xstrdup(br_cfg->name);
     br->type = xstrdup(ofproto_normalize_type(br_cfg->datapath_type));
     br->cfg = br_cfg;
-    eth_addr_nicira_random(br->default_ea);
+
+    /* Derive the default Ethernet address from the bridge's UUID.  This should
+     * be unique and it will be stable between ovs-vswitchd runs.  */
+    memcpy(br->default_ea, &br_cfg->header_.uuid, ETH_ADDR_LEN);
+    eth_addr_mark_random(br->default_ea);
 
     hmap_init(&br->ports);
     hmap_init(&br->ifaces);
index 9d5cdfb..973b098 100644 (file)
@@ -1398,14 +1398,14 @@ parse_options(int argc, char *argv[])
         DAEMON_OPTION_ENUMS
     };
     static struct option long_options[] = {
-        {"help",             no_argument, 0, 'h'},
-        {"version",          no_argument, 0, 'V'},
-        {"prune-timeout",    required_argument, 0, OPT_PRUNE_TIMEOUT},
-        {"appctl-command",   required_argument, 0, OPT_APPCTL_COMMAND},
+        {"help",             no_argument, NULL, 'h'},
+        {"version",          no_argument, NULL, 'V'},
+        {"prune-timeout",    required_argument, NULL, OPT_PRUNE_TIMEOUT},
+        {"appctl-command",   required_argument, NULL, OPT_APPCTL_COMMAND},
         DAEMON_LONG_OPTIONS,
         VLOG_LONG_OPTIONS,
         LEAK_CHECKER_LONG_OPTIONS,
-        {0, 0, 0, 0},
+        {NULL, 0, NULL, 0},
     };
     char *short_options = long_options_to_short_options(long_options);
 
index 66b78f0..d591e95 100644 (file)
@@ -119,17 +119,17 @@ parse_options(int argc, char *argv[])
         DAEMON_OPTION_ENUMS
     };
     static struct option long_options[] = {
-        {"help",        no_argument, 0, 'h'},
-        {"version",     no_argument, 0, 'V'},
-        {"mlockall",    no_argument, 0, OPT_MLOCKALL},
+        {"help",        no_argument, NULL, 'h'},
+        {"version",     no_argument, NULL, 'V'},
+        {"mlockall",    no_argument, NULL, OPT_MLOCKALL},
         DAEMON_LONG_OPTIONS,
         VLOG_LONG_OPTIONS,
         LEAK_CHECKER_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},
-        {"enable-dummy", no_argument, 0, OPT_ENABLE_DUMMY},
-        {0, 0, 0, 0},
+        {"peer-ca-cert", required_argument, NULL, OPT_PEER_CA_CERT},
+        {"bootstrap-ca-cert", required_argument, NULL, OPT_BOOTSTRAP_CA_CERT},
+        {"enable-dummy", no_argument, NULL, OPT_ENABLE_DUMMY},
+        {NULL, 0, NULL, 0},
     };
     char *short_options = long_options_to_short_options(long_options);