@@ -24,6 +24,7 @@ Post-v2.16.0
IPv6/TCP.
* Add AVX512 optimized profiles to miniflow extract for VLAN/IPv6/UDP
and VLAN/IPv6/TCP.
+ * Add IPv4 profile based 5tuple hashing optimizations.
v2.16.0 - 16 Aug 2021
@@ -297,6 +297,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 hash_len;
};
/* Ensure dp_pkt_offs[4] is the correct size as in struct dp_packet. */
@@ -350,6 +354,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
@@ -369,6 +380,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 },
+ .hash_len = 72,
},
[PROFILE_ETH_IPV4_TCP] = {
@@ -383,6 +397,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 },
+ .hash_len = 80,
},
[PROFILE_ETH_VLAN_IPV4_UDP] = {
@@ -401,6 +418,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 },
+ .hash_len = 80,
},
[PROFILE_ETH_VLAN_IPV4_TCP] = {
@@ -419,6 +439,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 },
+ .hash_len = 88,
},
[PROFILE_ETH_IPV6_UDP] = {
@@ -530,6 +553,33 @@ mfex_ipv6_set_l2_pad_size(struct dp_packet *pkt,
dp_packet_set_l2_pad_size(pkt, payload_size_ipv6 - p_len);
}
+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,
@@ -664,6 +714,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->hash_len;
} break;
case PROFILE_ETH_VLAN_IPV4_UDP: {
@@ -674,6 +728,10 @@ mfex_avx512_process(struct dp_packet_batch *packets,
if (mfex_ipv4_set_l2_pad_size(packet, nh, size_from_ipv4)) {
continue;
}
+
+ mfex_5tuple_hash_ipv4(packet, pkt, &keys[i],
+ profile->hash_pkt_offs);
+ keys[i].len = profile->hash_len;
} break;
case PROFILE_ETH_IPV4_TCP: {
@@ -687,6 +745,10 @@ mfex_avx512_process(struct dp_packet_batch *packets,
if (mfex_ipv4_set_l2_pad_size(packet, nh, size_from_ipv4)) {
continue;
}
+
+ mfex_5tuple_hash_ipv4(packet, pkt, &keys[i],
+ profile->hash_pkt_offs);
+ keys[i].len = profile->hash_len;
} break;
case PROFILE_ETH_IPV4_UDP: {
@@ -697,6 +759,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->hash_len;
} break;
case PROFILE_ETH_IPV6_UDP: {