From: Justin Pettit <jpettit@nicira.com>
Date: Wed, 26 Jun 2013 23:37:16 +0000 (-0700)
Subject: flow: Only un-wildcard relevant IP headers.
X-Git-Tag: sliver-openvswitch-1.10.90-3~6^2~19
X-Git-Url: http://git.onelab.eu/?a=commitdiff_plain;h=6cdd514560e16a294d09aa9d6bf5c8c7ac31e442;p=sliver-openvswitch.git

flow: Only un-wildcard relevant IP headers.

When determining the fields to un-wildcard, we need to be careful
about only un-wildcarding fields that are relevant.  Also, we
didn't properly handle IPv6 addresses.

Signed-off-by: Justin Pettit <jpettit@nicira.com>
Acked-by: Ethan Jackson <ethan@nicira.com>
---

diff --git a/lib/bond.c b/lib/bond.c
index 198db0f2b..183c37be1 100644
--- a/lib/bond.c
+++ b/lib/bond.c
@@ -1397,12 +1397,12 @@ choose_output_slave(const struct bond *bond, const struct flow *flow,
             return NULL;
         }
         if (wc) {
-            flow_mask_hash_fields(wc, NX_HASH_FIELDS_SYMMETRIC_L4);
+            flow_mask_hash_fields(flow, wc, NX_HASH_FIELDS_SYMMETRIC_L4);
         }
         /* Fall Through. */
     case BM_SLB:
         if (wc) {
-            flow_mask_hash_fields(wc, NX_HASH_FIELDS_ETH_SRC);
+            flow_mask_hash_fields(flow, wc, NX_HASH_FIELDS_ETH_SRC);
         }
         e = lookup_bond_entry(bond, flow, vlan);
         if (!e->slave || !e->slave->enabled) {
diff --git a/lib/bundle.c b/lib/bundle.c
index d1834d0e9..78a297a78 100644
--- a/lib/bundle.c
+++ b/lib/bundle.c
@@ -60,7 +60,7 @@ execute_hrw(const struct ofpact_bundle *bundle,
     int best, i;
 
     if (bundle->n_slaves > 1) {
-        flow_mask_hash_fields(wc, bundle->fields);
+        flow_mask_hash_fields(flow, wc, bundle->fields);
     }
 
     flow_hash = flow_hash_fields(flow, bundle->fields, bundle->basis);
diff --git a/lib/flow.c b/lib/flow.c
index a42fea1e3..1a5084b60 100644
--- a/lib/flow.c
+++ b/lib/flow.c
@@ -781,7 +781,8 @@ flow_hash_symmetric_l4(const struct flow *flow, uint32_t basis)
 
 /* Masks the fields in 'wc' that are used by the flow hash 'fields'. */
 void
-flow_mask_hash_fields(struct flow_wildcards *wc, enum nx_hash_fields fields)
+flow_mask_hash_fields(const struct flow *flow, struct flow_wildcards *wc,
+                      enum nx_hash_fields fields)
 {
     switch (fields) {
     case NX_HASH_FIELDS_ETH_SRC:
@@ -791,11 +792,18 @@ flow_mask_hash_fields(struct flow_wildcards *wc, enum nx_hash_fields fields)
     case NX_HASH_FIELDS_SYMMETRIC_L4:
         memset(&wc->masks.dl_src, 0xff, sizeof wc->masks.dl_src);
         memset(&wc->masks.dl_dst, 0xff, sizeof wc->masks.dl_dst);
-        memset(&wc->masks.nw_proto, 0xff, sizeof wc->masks.nw_proto);
-        memset(&wc->masks.nw_src, 0xff, sizeof wc->masks.nw_src);
-        memset(&wc->masks.nw_dst, 0xff, sizeof wc->masks.nw_dst);
-        memset(&wc->masks.tp_src, 0xff, sizeof wc->masks.tp_src);
-        memset(&wc->masks.tp_dst, 0xff, sizeof wc->masks.tp_dst);
+        if (flow->dl_type == htons(ETH_TYPE_IP)) {
+            memset(&wc->masks.nw_src, 0xff, sizeof wc->masks.nw_src);
+            memset(&wc->masks.nw_dst, 0xff, sizeof wc->masks.nw_dst);
+        } else {
+            memset(&wc->masks.ipv6_src, 0xff, sizeof wc->masks.ipv6_src);
+            memset(&wc->masks.ipv6_dst, 0xff, sizeof wc->masks.ipv6_dst);
+        }
+        if (is_ip_any(flow)) {
+            memset(&wc->masks.nw_proto, 0xff, sizeof wc->masks.nw_proto);
+            memset(&wc->masks.tp_src, 0xff, sizeof wc->masks.tp_src);
+            memset(&wc->masks.tp_dst, 0xff, sizeof wc->masks.tp_dst);
+        }
         wc->masks.vlan_tci |= htons(VLAN_VID_MASK | VLAN_CFI);
         break;
 
diff --git a/lib/flow.h b/lib/flow.h
index 9a6e93781..7c3654b00 100644
--- a/lib/flow.h
+++ b/lib/flow.h
@@ -262,7 +262,8 @@ bool flow_wildcards_equal(const struct flow_wildcards *,
                           const struct flow_wildcards *);
 uint32_t flow_hash_symmetric_l4(const struct flow *flow, uint32_t basis);
 
-void flow_mask_hash_fields(struct flow_wildcards *, enum nx_hash_fields);
+void flow_mask_hash_fields(const struct flow *, struct flow_wildcards *,
+                           enum nx_hash_fields);
 uint32_t flow_hash_fields(const struct flow *, enum nx_hash_fields,
                           uint16_t basis);
 const char *flow_hash_fields_to_str(enum nx_hash_fields);
diff --git a/lib/multipath.c b/lib/multipath.c
index dbd570446..1be69646f 100644
--- a/lib/multipath.c
+++ b/lib/multipath.c
@@ -113,7 +113,7 @@ multipath_execute(const struct ofpact_multipath *mp, struct flow *flow,
     uint16_t link = multipath_algorithm(hash, mp->algorithm,
                                         mp->max_link + 1, mp->arg);
 
-    flow_mask_hash_fields(wc, mp->fields);
+    flow_mask_hash_fields(flow, wc, mp->fields);
     nxm_reg_load(&mp->dst, link, flow);
 }