dpif-netdev: Fix race condition in pmd thread initialization.
[cascardo/ovs.git] / lib / flow.c
index b9ce331..a4c1215 100644 (file)
@@ -32,7 +32,7 @@
 #include "openvswitch/dynamic-string.h"
 #include "hash.h"
 #include "jhash.h"
-#include "match.h"
+#include "openvswitch/match.h"
 #include "dp-packet.h"
 #include "openflow/openflow.h"
 #include "packets.h"
@@ -524,7 +524,7 @@ miniflow_extract(struct dp_packet *packet, struct miniflow *dst)
         miniflow_push_uint32(mf, ct_mark, md->ct_mark);
         miniflow_pad_to_64(mf, ct_mark);
 
-        if (!ovs_u128_is_zero(&md->ct_label)) {
+        if (!ovs_u128_is_zero(md->ct_label)) {
             miniflow_push_words(mf, ct_label, &md->ct_label,
                                 sizeof md->ct_label / sizeof(uint64_t));
         }
@@ -895,7 +895,7 @@ flow_get_metadata(const struct flow *flow, struct match *flow_metadata)
     if (flow->ct_mark != 0) {
         match_set_ct_mark(flow_metadata, flow->ct_mark);
     }
-    if (!ovs_u128_is_zero(&flow->ct_label)) {
+    if (!ovs_u128_is_zero(flow->ct_label)) {
         match_set_ct_label(flow_metadata, flow->ct_label);
     }
 }
@@ -1206,7 +1206,7 @@ flow_format(struct ds *ds, const struct flow *flow)
     if (!flow->ct_mark) {
         WC_UNMASK_FIELD(wc, ct_mark);
     }
-    if (ovs_u128_is_zero(&flow->ct_label)) {
+    if (ovs_u128_is_zero(flow->ct_label)) {
         WC_UNMASK_FIELD(wc, ct_label);
     }
     for (int i = 0; i < FLOW_N_REGS; i++) {
@@ -1405,13 +1405,13 @@ flow_wc_map(const struct flow *flow, struct flowmap *map)
         FLOWMAP_SET(map, nw_frag);
         FLOWMAP_SET(map, nw_tos);
         FLOWMAP_SET(map, nw_ttl);
+        FLOWMAP_SET(map, tp_src);
+        FLOWMAP_SET(map, tp_dst);
 
         if (OVS_UNLIKELY(flow->nw_proto == IPPROTO_IGMP)) {
             FLOWMAP_SET(map, igmp_group_ip4);
         } else {
             FLOWMAP_SET(map, tcp_flags);
-            FLOWMAP_SET(map, tp_src);
-            FLOWMAP_SET(map, tp_dst);
         }
     } else if (flow->dl_type == htons(ETH_TYPE_IPV6)) {
         FLOWMAP_SET(map, ipv6_src);
@@ -1421,6 +1421,8 @@ flow_wc_map(const struct flow *flow, struct flowmap *map)
         FLOWMAP_SET(map, nw_frag);
         FLOWMAP_SET(map, nw_tos);
         FLOWMAP_SET(map, nw_ttl);
+        FLOWMAP_SET(map, tp_src);
+        FLOWMAP_SET(map, tp_dst);
 
         if (OVS_UNLIKELY(flow->nw_proto == IPPROTO_ICMPV6)) {
             FLOWMAP_SET(map, nd_target);
@@ -1428,8 +1430,6 @@ flow_wc_map(const struct flow *flow, struct flowmap *map)
             FLOWMAP_SET(map, arp_tha);
         } else {
             FLOWMAP_SET(map, tcp_flags);
-            FLOWMAP_SET(map, tp_src);
-            FLOWMAP_SET(map, tp_dst);
         }
     } else if (eth_type_mpls(flow->dl_type)) {
         FLOWMAP_SET(map, mpls_lse);
@@ -1584,14 +1584,13 @@ flow_wildcards_set_xreg_mask(struct flow_wildcards *wc, int idx, uint64_t mask)
 uint32_t
 miniflow_hash_5tuple(const struct miniflow *flow, uint32_t basis)
 {
+    BUILD_ASSERT_DECL(FLOW_WC_SEQ == 35);
     uint32_t hash = basis;
 
     if (flow) {
         ovs_be16 dl_type = MINIFLOW_GET_BE16(flow, dl_type);
+        uint8_t nw_proto;
 
-        hash = hash_add(hash, MINIFLOW_GET_U8(flow, nw_proto));
-
-        /* Separate loops for better optimization. */
         if (dl_type == htons(ETH_TYPE_IPV6)) {
             struct flowmap map = FLOWMAP_EMPTY_INITIALIZER;
             uint64_t value;
@@ -1602,15 +1601,27 @@ miniflow_hash_5tuple(const struct miniflow *flow, uint32_t basis)
             MINIFLOW_FOR_EACH_IN_FLOWMAP(value, flow, map) {
                 hash = hash_add64(hash, value);
             }
-        } else {
+        } else if (dl_type == htons(ETH_TYPE_IP)
+                   || dl_type == htons(ETH_TYPE_ARP)) {
             hash = hash_add(hash, MINIFLOW_GET_U32(flow, nw_src));
             hash = hash_add(hash, MINIFLOW_GET_U32(flow, nw_dst));
+        } else {
+            goto out;
         }
+
+        nw_proto = MINIFLOW_GET_U8(flow, nw_proto);
+        hash = hash_add(hash, nw_proto);
+        if (nw_proto != IPPROTO_TCP && nw_proto != IPPROTO_UDP
+            && nw_proto != IPPROTO_SCTP && nw_proto != IPPROTO_ICMP
+            && nw_proto != IPPROTO_ICMPV6) {
+            goto out;
+        }
+
         /* Add both ports at once. */
         hash = hash_add(hash, MINIFLOW_GET_U32(flow, tp_src));
-        hash = hash_finish(hash, 42); /* Arbitrary number. */
     }
-    return hash;
+out:
+    return hash_finish(hash, 42);
 }
 
 ASSERT_SEQUENTIAL_SAME_WORD(tp_src, tp_dst);
@@ -1620,10 +1631,10 @@ ASSERT_SEQUENTIAL(ipv6_src, ipv6_dst);
 uint32_t
 flow_hash_5tuple(const struct flow *flow, uint32_t basis)
 {
+    BUILD_ASSERT_DECL(FLOW_WC_SEQ == 35);
     uint32_t hash = basis;
 
     if (flow) {
-        hash = hash_add(hash, flow->nw_proto);
 
         if (flow->dl_type == htons(ETH_TYPE_IPV6)) {
             const uint64_t *flow_u64 = (const uint64_t *)flow;
@@ -1633,17 +1644,28 @@ flow_hash_5tuple(const struct flow *flow, uint32_t basis)
             for (;ofs < end; ofs++) {
                 hash = hash_add64(hash, flow_u64[ofs]);
             }
-        } else {
+        } else if (flow->dl_type == htons(ETH_TYPE_IP)
+                   || flow->dl_type == htons(ETH_TYPE_ARP)) {
             hash = hash_add(hash, (OVS_FORCE uint32_t) flow->nw_src);
             hash = hash_add(hash, (OVS_FORCE uint32_t) flow->nw_dst);
+        } else {
+            goto out;
         }
+
+        hash = hash_add(hash, flow->nw_proto);
+        if (flow->nw_proto != IPPROTO_TCP && flow->nw_proto != IPPROTO_UDP
+            && flow->nw_proto != IPPROTO_SCTP && flow->nw_proto != IPPROTO_ICMP
+            && flow->nw_proto != IPPROTO_ICMPV6) {
+            goto out;
+        }
+
         /* Add both ports at once. */
         hash = hash_add(hash,
                         ((const uint32_t *)flow)[offsetof(struct flow, tp_src)
                                                  / sizeof(uint32_t)]);
-        hash = hash_finish(hash, 42); /* Arbitrary number. */
     }
-    return hash;
+out:
+    return hash_finish(hash, 42); /* Arbitrary number. */
 }
 
 /* Hashes 'flow' based on its L2 through L4 protocol information. */