diff mbox

[ovs-dev,2/2] conntrack: Hash entire NAT data structure in nat_range_hash().

Message ID 20170607163703.3638-2-blp@ovn.org
State Superseded
Headers show

Commit Message

Ben Pfaff June 7, 2017, 4:37 p.m. UTC
From: Darrell Ball <dlu998@gmail.com>

Part of the hash input for nat_range_hash() was accidentally
omitted, so this fixes the problem.  Also, add a missing call to
hash_finish().

Fixes: 286de2729955 ("dpdk: Userspace Datapath: Introduce NAT Support.")
Signed-off-by: Darrell Ball <dlu998@gmail.com>
Signed-off-by: Ben Pfaff <blp@ovn.org>
---
 lib/conntrack-private.h |  4 ++++
 lib/conntrack.c         | 47 ++++++++++++++++++++++++++---------------------
 2 files changed, 30 insertions(+), 21 deletions(-)
diff mbox

Patch

diff --git a/lib/conntrack-private.h b/lib/conntrack-private.h
index bfa88f0fe7e2..55084d3ea64e 100644
--- a/lib/conntrack-private.h
+++ b/lib/conntrack-private.h
@@ -42,6 +42,10 @@  struct ct_endpoint {
     };
 };
 
+/* Verify that there is no padding in struct ct_endpoint, to facilitate
+ * hashing in ct_endpoint_hash_add(). */
+BUILD_ASSERT_DECL(sizeof(struct ct_endpoint) == sizeof(struct ct_addr) + 4);
+
 /* Changes to this structure need to be reflected in conn_key_hash() */
 struct conn_key {
     struct ct_endpoint src;
diff --git a/lib/conntrack.c b/lib/conntrack.c
index 44a6bc4e3ccf..55029c82e7a6 100644
--- a/lib/conntrack.c
+++ b/lib/conntrack.c
@@ -1613,36 +1613,41 @@  nat_ipv6_addr_increment(struct in6_addr *ipv6_aligned, uint32_t increment)
 }
 
 static uint32_t
-nat_range_hash(const struct conn *conn, uint32_t basis)
+ct_addr_hash_add(uint32_t hash, const struct ct_addr *addr)
 {
-    uint32_t hash = basis;
-    int i;
-    uint16_t port;
+    BUILD_ASSERT_DECL(sizeof *addr % 4 == 0);
+    return hash_add_bytes32(hash, (const uint32_t *) addr, sizeof *addr);
+}
 
-    for (i = 0;
-         i < sizeof(conn->nat_info->min_addr) / sizeof(uint32_t);
-         i++) {
-        hash = hash_add(hash, ((uint32_t *) &conn->nat_info->min_addr)[i]);
-        hash = hash_add(hash, ((uint32_t *) &conn->nat_info->max_addr)[i]);
-    }
+static uint32_t
+ct_endpoint_hash_add(uint32_t hash, const struct ct_endpoint *ep)
+{
+    BUILD_ASSERT_DECL(sizeof *ep % 4 == 0);
+    return hash_add_bytes32(hash, (const uint32_t *) ep, sizeof *ep);
+}
 
-    memcpy(&port, &conn->nat_info->min_port, sizeof port);
-    hash = hash_add(hash, port);
+static uint32_t
+nat_range_hash(const struct conn *conn, uint32_t basis)
+{
+    uint32_t hash = basis;
 
-    for (i = 0; i < sizeof(conn->key.src.addr) / sizeof(uint32_t); i++) {
-        hash = hash_add(hash, ((uint32_t *) &conn->key.src)[i]);
-        hash = hash_add(hash, ((uint32_t *) &conn->key.dst)[i]);
-    }
+    hash = ct_addr_hash_add(hash, &conn->nat_info->min_addr);
+    hash = ct_addr_hash_add(hash, &conn->nat_info->max_addr);
+    hash = hash_add(hash,
+                    (conn->nat_info->max_port << 16)
+                    | conn->nat_info->min_port);
 
-    memcpy(&port, &conn->key.src.port, sizeof port);
-    hash = hash_add(hash, port);
-    memcpy(&port, &conn->key.dst.port, sizeof port);
-    hash = hash_add(hash, port);
+    hash = ct_endpoint_hash_add(hash, &conn->key.src);
+    hash = ct_endpoint_hash_add(hash, &conn->key.dst);
 
     hash = hash_add(hash, (OVS_FORCE uint32_t) conn->key.dl_type);
     hash = hash_add(hash, conn->key.nw_proto);
     hash = hash_add(hash, conn->key.zone);
-    return hash;
+
+    /* The purpose of the second parameter is to distinguish hashes of data of
+     * different length; our data always has the same length so there is no
+     * value in counting. */
+    return hash_finish(hash, 0);
 }
 
 static bool