@@ -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
@@ -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;