diff mbox series

[ovs-dev,v5,1/2] dpif-netdev/mfex: Add ipv4 profile based hashing

Message ID 20220112161107.1463714-2-harry.van.haaren@intel.com
State Deferred
Headers show
Series MFEX Hashing Optimizations | expand

Checks

Context Check Description
ovsrobot/apply-robot success apply and check: success
ovsrobot/github-robot-_Build_and_Test success github build: passed

Commit Message

Van Haaren, Harry Jan. 12, 2022, 4:11 p.m. UTC
From: Kumar Amber <kumar.amber@intel.com>

This commit adds IPv4 profile specific hashing which
uses fixed offsets into the packet to improve hashing
performance.

Signed-off-by: Kumar Amber <kumar.amber@intel.com>
Signed-off-by: Harry van Haaren <harry.van.haaren@intel.com>
Co-authored-by: Harry van Haaren <harry.van.haaren@intel.com>

---

v5:
- Rename "hash_len" to "key_len" to describe its use better.
---
 NEWS                             |  2 +-
 lib/dpif-netdev-extract-avx512.c | 65 ++++++++++++++++++++++++++++++++
 2 files changed, 66 insertions(+), 1 deletion(-)
diff mbox series

Patch

diff --git a/NEWS b/NEWS
index afef81b40..e70c968a6 100644
--- a/NEWS
+++ b/NEWS
@@ -3,6 +3,7 @@  Post-v2.16.0
    - Userspace datapath:
      * Optimized flow lookups for datapath flows with simple match criteria.
        See 'Simple Match Lookup' in Documentation/topics/dpdk/bridge.rst.
+     * Add IPv4 profile based 5tuple hashing optimizations.
    - DPDK:
      * EAL argument --socket-mem is no longer configured by default upon
        start-up.  If dpdk-socket-mem and dpdk-alloc-mem are not specified,
@@ -38,7 +39,6 @@  Post-v2.16.0
        now dp_hash.  Previously this was limited to 64 buckets.  This change
        is mainly for the benefit of OVN load balancing configurations.
 
-
 v2.16.0 - 16 Aug 2021
 ---------------------
    - Removed support for 1024-bit Diffie-Hellman key exchange, which is now
diff --git a/lib/dpif-netdev-extract-avx512.c b/lib/dpif-netdev-extract-avx512.c
index d23349482..64b1c29cb 100644
--- a/lib/dpif-netdev-extract-avx512.c
+++ b/lib/dpif-netdev-extract-avx512.c
@@ -258,6 +258,10 @@  struct mfex_profile {
     uint64_t mf_bits[FLOWMAP_UNITS];
     uint16_t dp_pkt_offs[4];
     uint16_t dp_pkt_min_size;
+
+    /* Constant data offsets for Hashing. */
+    uint8_t hash_pkt_offs[6];
+    uint32_t key_len;
 };
 
 /* Ensure dp_pkt_offs[4] is the correct size as in struct dp_packet. */
@@ -307,6 +311,13 @@  enum MFEX_PROFILES {
     PROFILE_COUNT,
 };
 
+/* Packet offsets for 5 tuple Hash function. */
+#define HASH_IPV4 \
+    26, 30, 23, 34, 0, 0
+
+#define HASH_DT1Q_IPV4 \
+    30, 34, 27, 38, 0, 0
+
 /* Static const instances of profiles. These are compile-time constants,
  * and are specialized into individual miniflow-extract functions.
  * NOTE: Order of the fields is significant, any change in the order must be
@@ -326,6 +337,9 @@  static const struct mfex_profile mfex_profiles[PROFILE_COUNT] =
             0, UINT16_MAX, 14, 34,
         },
         .dp_pkt_min_size = 42,
+
+        .hash_pkt_offs = { HASH_IPV4 },
+        .key_len = 72,
     },
 
     [PROFILE_ETH_IPV4_TCP] = {
@@ -348,6 +362,9 @@  static const struct mfex_profile mfex_profiles[PROFILE_COUNT] =
             0, UINT16_MAX, 14, 34,
         },
         .dp_pkt_min_size = 54,
+
+        .hash_pkt_offs = { HASH_IPV4 },
+        .key_len = 80,
     },
 
     [PROFILE_ETH_VLAN_IPV4_UDP] = {
@@ -366,6 +383,9 @@  static const struct mfex_profile mfex_profiles[PROFILE_COUNT] =
             14, UINT16_MAX, 18, 38,
         },
         .dp_pkt_min_size = 46,
+
+        .hash_pkt_offs = { HASH_DT1Q_IPV4 },
+        .key_len = 80,
     },
 
     [PROFILE_ETH_VLAN_IPV4_TCP] = {
@@ -390,10 +410,40 @@  static const struct mfex_profile mfex_profiles[PROFILE_COUNT] =
             14, UINT16_MAX, 18, 38,
         },
         .dp_pkt_min_size = 46,
+
+        .hash_pkt_offs = { HASH_DT1Q_IPV4 },
+        .key_len = 88,
     },
 };
 
 
+static inline void
+mfex_5tuple_hash_ipv4(struct dp_packet *packet, const uint8_t *pkt,
+                      struct netdev_flow_key *key,
+                      const uint8_t *pkt_offsets)
+{
+    if (!dp_packet_rss_valid(packet)) {
+        uint32_t hash = 0;
+        void *ipv4_src = (void *) &pkt[pkt_offsets[0]];
+        void *ipv4_dst = (void *) &pkt[pkt_offsets[1]];
+        void *ports_l4 = (void *) &pkt[pkt_offsets[3]];
+
+        /* IPv4 Src and Dst. */
+        hash = hash_add(hash, *(uint32_t *) ipv4_src);
+        hash = hash_add(hash, *(uint32_t *) ipv4_dst);
+        /* IPv4 proto. */
+        hash = hash_add(hash, pkt[pkt_offsets[2]]);
+        /* L4 ports. */
+        hash = hash_add(hash, *(uint32_t *) ports_l4);
+        hash = hash_finish(hash, 42);
+
+        dp_packet_set_rss_hash(packet, hash);
+        key->hash = hash;
+    } else {
+        key->hash = dp_packet_get_rss_hash(packet);
+    }
+}
+
 /* Protocol specific helper functions, for calculating offsets/lenghts. */
 static int32_t
 mfex_ipv4_set_l2_pad_size(struct dp_packet *pkt, struct ip_header *nh,
@@ -551,6 +601,10 @@  mfex_avx512_process(struct dp_packet_batch *packets,
                 /* Process TCP flags, and store to blocks. */
                 const struct tcp_header *tcp = (void *)&pkt[38];
                 mfex_handle_tcp_flags(tcp, &blocks[7]);
+
+                mfex_5tuple_hash_ipv4(packet, pkt, &keys[i],
+                                      profile->hash_pkt_offs);
+                keys[i].len = profile->key_len;
             } break;
 
         case PROFILE_ETH_VLAN_IPV4_UDP: {
@@ -562,6 +616,10 @@  mfex_avx512_process(struct dp_packet_batch *packets,
                                               UDP_HEADER_LEN)) {
                     continue;
                 }
+
+                mfex_5tuple_hash_ipv4(packet, pkt, &keys[i],
+                                      profile->hash_pkt_offs);
+                keys[i].len = profile->key_len;
             } break;
 
         case PROFILE_ETH_IPV4_TCP: {
@@ -576,6 +634,10 @@  mfex_avx512_process(struct dp_packet_batch *packets,
                                               TCP_HEADER_LEN)) {
                     continue;
                 }
+
+                mfex_5tuple_hash_ipv4(packet, pkt, &keys[i],
+                                      profile->hash_pkt_offs);
+                keys[i].len = profile->key_len;
             } break;
 
         case PROFILE_ETH_IPV4_UDP: {
@@ -587,6 +649,9 @@  mfex_avx512_process(struct dp_packet_batch *packets,
                     continue;
                 }
 
+                mfex_5tuple_hash_ipv4(packet, pkt, &keys[i],
+                                      profile->hash_pkt_offs);
+                keys[i].len = profile->key_len;
             } break;
         default:
             break;