For a series of IP fragments, only the first packet includes the transport
header (TCP/UDP/SCTP) and the src/dst ports. By including these port
numbers in the hash, it may happen that a first fragment hashes to a
different value than subsequent packets, causing different packets from
the same flow to follow different paths. This in turn may result in
out-of-order delivery or failed reassembly. This patch excludes port
numbers from the hash calculation in case of IP fragmentation.

Signed-off-by: Jeroen van Bemmel <[email protected]>
---
diff --git a/lib/flow.c b/lib/flow.c
index f39b57f5b..0ff20a87a 100644
--- a/lib/flow.c
+++ b/lib/flow.c
@@ -2370,8 +2370,10 @@ flow_hash_symmetric_l3l4(const struct flow *flow, 
uint32_t basis,
     }
     hash = hash_add(hash, flow->nw_proto);
-    if (flow->nw_proto == IPPROTO_TCP || flow->nw_proto == IPPROTO_SCTP ||
-         (inc_udp_ports && flow->nw_proto == IPPROTO_UDP)) {
+    if ((flow->nw_proto == IPPROTO_TCP || flow->nw_proto == IPPROTO_SCTP ||
+        (inc_udp_ports && flow->nw_proto == IPPROTO_UDP))
+        /* For first fragments, don't include ports in hash */
+        && !(flow->nw_frag & FLOW_NW_FRAG_MASK) ) {
         hash = hash_add(hash,
                         (OVS_FORCE uint16_t) (flow->tp_src ^ flow->tp_dst));
     }
@@ -2486,7 +2488,8 @@ flow_mask_hash_fields(const struct flow *flow, struct 
flow_wildcards *wc,
         break;
     case NX_HASH_FIELDS_SYMMETRIC_L3L4_UDP:
-        if (is_ip_any(flow) && flow->nw_proto == IPPROTO_UDP) {
+        if (is_ip_any(flow) && flow->nw_proto == IPPROTO_UDP
+            && !(flow->nw_frag & FLOW_NW_FRAG_MASK) ) {
             memset(&wc->masks.tp_src, 0xff, sizeof wc->masks.tp_src);
             memset(&wc->masks.tp_dst, 0xff, sizeof wc->masks.tp_dst);
         }
@@ -2503,7 +2506,8 @@ flow_mask_hash_fields(const struct flow *flow, struct 
flow_wildcards *wc,
         }
         memset(&wc->masks.nw_proto, 0xff, sizeof wc->masks.nw_proto);
-        if (flow->nw_proto == IPPROTO_TCP || flow->nw_proto == IPPROTO_SCTP) {
+        if ((flow->nw_proto == IPPROTO_TCP || flow->nw_proto == IPPROTO_SCTP)
+             && OVS_LIKELY(!(flow->nw_frag & FLOW_NW_FRAG_MASK))) {
             memset(&wc->masks.tp_src, 0xff, sizeof wc->masks.tp_src);
             memset(&wc->masks.tp_dst, 0xff, sizeof wc->masks.tp_dst);
         }
_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to