> For packets which don't already have a hash calculated,
> miniflow_hash_5tuple() calculates the hash of a packet
> using the previously built miniflow.
>
> This commit adds IPv4 profile specific hashing which
> uses fixed offsets into the packet to improve hashing
> performance.
>
> Signed-off-by: Kumar Amber <[email protected]>
> Signed-off-by: Harry van Haaren <[email protected]>
> Co-authored-by: Harry van Haaren <[email protected]>
> Acked-by: Cian Ferriter <[email protected]>
Thanks for the patch Amber.
@Ilya, I know your busy with the stable releases this week, but does this
revision address you previous concerns?
Thanks
Ian
> ---
> v9:
> - Use memcpy in place of typecast to fix memory alingment.
> v8:
> - Fix comments from cian.
> v4:
> - Use pre-defined hash length values.
> v3:
> - Fix check-patch sign-offs.
> ---
> ---
> NEWS | 2 +
> lib/dpif-netdev-extract-avx512.c | 72 ++++++++++++++++++++++++++++++++
> 2 files changed, 74 insertions(+)
>
> diff --git a/NEWS b/NEWS
> index 8fa57836a..db58be457 100644
> --- a/NEWS
> +++ b/NEWS
> @@ -3,6 +3,8 @@ Post-v2.17.0
> - OVSDB:
> * 'relay' service model now supports transaction history, i.e. honors
> the
> 'last-txn-id' field in 'monitor_cond_since' requests from clients.
> + - Userspace datapath:
> + * Add IPv4 profile based 5tuple hashing optimizations.
>
>
> v2.17.0 - 17 Feb 2022
> diff --git a/lib/dpif-netdev-extract-avx512.c
> b/lib/dpif-netdev-extract-avx512.c
> index c1c1fefb6..1e0d4e31a 100644
> --- a/lib/dpif-netdev-extract-avx512.c
> +++ b/lib/dpif-netdev-extract-avx512.c
> @@ -278,6 +278,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[4];
> + uint32_t hash_len;
> };
>
> /* Ensure dp_pkt_offs[4] is the correct size as in struct dp_packet. */
> @@ -327,6 +331,13 @@ enum MFEX_PROFILES {
> PROFILE_COUNT,
> };
>
> +/* Packet offsets for 5 tuple hash function. */
> +#define HASH_IPV4 \
> + 26, 30, 23, 34
> +
> +#define HASH_DT1Q_IPV4 \
> + 30, 34, 27, 38
> +
> /* 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
> @@ -347,6 +358,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] = {
> @@ -370,6 +384,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] = {
> @@ -389,6 +406,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] = {
> @@ -414,6 +434,9 @@ static const struct mfex_profile
> mfex_profiles[PROFILE_COUNT] =
> 14, UINT16_MAX, 18, 38,
> },
> .dp_pkt_min_size = 58,
> +
> + .hash_pkt_offs = { HASH_DT1Q_IPV4 },
> + .hash_len = 88,
> },
> };
>
> @@ -467,6 +490,40 @@ mfex_handle_tcp_flags(const struct tcp_header *tcp,
> uint64_t *block)
> *block = ctl_u64 << 32;
> }
>
> +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;
> + uint32_t ip_src = 0;
> + uint32_t ip_dst = 0;
> + uint32_t ports = 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]];
> +
> + memcpy(&ip_src, ipv4_src, sizeof(uint32_t));
> + memcpy(&ip_dst, ipv4_dst, sizeof(uint32_t));
> + memcpy(&ports, ports_l4, sizeof(uint32_t));
> +
> + /* IPv4 Src and Dst. */
> + hash = hash_add(hash, ip_src);
> + hash = hash_add(hash, ip_dst);
> + /* IPv4 proto. */
> + hash = hash_add(hash, pkt[pkt_offsets[2]]);
> + /* L4 ports. */
> + hash = hash_add(hash, ports);
> + hash = hash_finish(hash, 42);
> +
> + dp_packet_set_rss_hash(packet, hash);
> + key->hash = hash;
> + } else {
> + key->hash = dp_packet_get_rss_hash(packet);
> + }
> +}
> +
> /* Generic loop to process any mfex profile. This code is specialized into
> * multiple actual MFEX implementation functions. Its marked ALWAYS_INLINE
> * to ensure the compiler specializes each instance. The code is marked "hot"
> @@ -577,6 +634,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: {
> @@ -588,6 +649,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->hash_len;
> } break;
>
> case PROFILE_ETH_IPV4_TCP: {
> @@ -602,6 +667,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->hash_len;
> } break;
>
> case PROFILE_ETH_IPV4_UDP: {
> @@ -613,6 +682,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;
> default:
> break;
> --
> 2.25.1
_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev