A typical NVGRE encapsulated packet starts with the ETH/IP/GRE protocols. Miniflow extract will parse just the ETH and IP headers. The GRE header will be processed later as part of the pop action. Add support for parsing the ETH/IP headers in this scenario.
Signed-off-by: Cian Ferriter <[email protected]> --- lib/dp-packet.h | 58 +++++++++++++++++++++++-------- lib/dpif-netdev-extract-avx512.c | 43 +++++++++++++++++++++-- lib/dpif-netdev-private-extract.c | 10 ++++++ lib/dpif-netdev-private-extract.h | 5 +++ 4 files changed, 100 insertions(+), 16 deletions(-) diff --git a/lib/dp-packet.h b/lib/dp-packet.h index 55eeaab2c..230bbec27 100644 --- a/lib/dp-packet.h +++ b/lib/dp-packet.h @@ -1089,8 +1089,28 @@ dp_packet_l4_checksum_bad(const struct dp_packet *p) DP_PACKET_OL_RX_L4_CKSUM_BAD; } +static inline uint32_t ALWAYS_INLINE +dp_packet_calc_hash_ipv4(const uint8_t *pkt, const uint16_t l3_ofs, + uint32_t hash) +{ + const void *ipv4_src = &pkt[l3_ofs + offsetof(struct ip_header, ip_src)]; + const void *ipv4_dst = &pkt[l3_ofs + offsetof(struct ip_header, ip_dst)]; + uint32_t ip_src, ip_dst; + + memcpy(&ip_src, ipv4_src, sizeof ip_src); + memcpy(&ip_dst, ipv4_dst, sizeof ip_dst); + + /* IPv4 Src and Dst. */ + hash = hash_add(hash, ip_src); + hash = hash_add(hash, ip_dst); + /* IPv4 proto. */ + hash = hash_add(hash, pkt[l3_ofs + offsetof(struct ip_header, ip_proto)]); + + return hash; +} + static inline void ALWAYS_INLINE -dp_packet_update_rss_hash_ipv4_tcp_udp(struct dp_packet *packet) +dp_packet_update_rss_hash_ipv4(struct dp_packet *packet) { if (dp_packet_rss_valid(packet)) { return; @@ -1098,26 +1118,36 @@ dp_packet_update_rss_hash_ipv4_tcp_udp(struct dp_packet *packet) const uint8_t *pkt = dp_packet_data(packet); const uint16_t l3_ofs = packet->l3_ofs; - const void *ipv4_src = &pkt[l3_ofs + offsetof(struct ip_header, ip_src)]; - const void *ipv4_dst = &pkt[l3_ofs + offsetof(struct ip_header, ip_dst)]; + uint32_t hash = 0; + + /* IPv4 Src, Dst and proto. */ + hash = dp_packet_calc_hash_ipv4(pkt, l3_ofs, hash); + + hash = hash_finish(hash, 42); + dp_packet_set_rss_hash(packet, hash); +} + +static inline void ALWAYS_INLINE +dp_packet_update_rss_hash_ipv4_tcp_udp(struct dp_packet *packet) +{ + if (dp_packet_rss_valid(packet)) { + return; + } + + const uint8_t *pkt = dp_packet_data(packet); const void *l4_ports = &pkt[packet->l4_ofs]; - uint32_t ip_src, ip_dst, ports; + const uint16_t l3_ofs = packet->l3_ofs; uint32_t hash = 0; + uint32_t ports; - memcpy(&ip_src, ipv4_src, sizeof ip_src); - memcpy(&ip_dst, ipv4_dst, sizeof ip_dst); - memcpy(&ports, l4_ports, sizeof ports); + /* IPv4 Src, Dst and proto. */ + hash = dp_packet_calc_hash_ipv4(pkt, l3_ofs, hash); - /* IPv4 Src and Dst. */ - hash = hash_add(hash, ip_src); - hash = hash_add(hash, ip_dst); - /* IPv4 proto. */ - hash = hash_add(hash, - pkt[l3_ofs + offsetof(struct ip_header, ip_proto)]); /* L4 ports. */ + memcpy(&ports, l4_ports, sizeof ports); hash = hash_add(hash, ports); - hash = hash_finish(hash, 42); + hash = hash_finish(hash, 42); dp_packet_set_rss_hash(packet, hash); } diff --git a/lib/dpif-netdev-extract-avx512.c b/lib/dpif-netdev-extract-avx512.c index 4afbed97e..968845f2d 100644 --- a/lib/dpif-netdev-extract-avx512.c +++ b/lib/dpif-netdev-extract-avx512.c @@ -194,6 +194,7 @@ _mm512_maskz_permutexvar_epi8_selector(__mmask64 k_shuf, __m512i v_shuf, #define PATTERN_IPV4_MASK PATTERN_IPV4_GEN(0xFF, 0xBF, 0xFF, 0xFF) #define PATTERN_IPV4_UDP PATTERN_IPV4_GEN(0x45, 0, 0, 0x11) #define PATTERN_IPV4_TCP PATTERN_IPV4_GEN(0x45, 0, 0, 0x06) +#define PATTERN_IPV4_NVGRE PATTERN_IPV4_GEN(0x45, 0, 0, 0x2f) #define PATTERN_TCP_GEN(data_offset) \ 0, 0, 0, 0, /* sport, dport */ \ @@ -218,6 +219,12 @@ _mm512_maskz_permutexvar_epi8_selector(__mmask64 k_shuf, __m512i v_shuf, NU, NU, NU, NU, NU, NU, NU, NU, 34, 35, 36, 37, NU, NU, NU, NU, /* TCP */ \ NU, NU, NU, NU, NU, NU, NU, NU, NU, NU, NU, NU, NU, NU, NU, NU, /* Unused. */ +#define PATTERN_IPV4_NVGRE_SHUFFLE \ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, NU, NU, /* Ether */ \ + 26, 27, 28, 29, 30, 31, 32, 33, NU, NU, NU, NU, 20, 15, 22, 23, /* IPv4 */ \ + NU, NU, NU, NU, NU, NU, NU, NU, NU, NU, NU, NU, NU, NU, NU, NU, /* Unused */\ + NU, NU, NU, NU, NU, NU, NU, NU, NU, NU, NU, NU, NU, NU, NU, NU, /* Unused */ + #define PATTERN_DT1Q_IPV4_UDP_SHUFFLE \ /* Ether (2 blocks): Note that *VLAN* type is written here. */ \ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 16, 17, 0, 0, \ @@ -286,6 +293,9 @@ _mm512_maskz_permutexvar_epi8_selector(__mmask64 k_shuf, __m512i v_shuf, #define KMASK_DT1Q_IPV6 0xFF0FULL #define KMASK_IPV6_NOHDR 0x00FFULL +#define PATTERN_IPV4_KMASK \ + (KMASK_ETHER | (KMASK_IPV4 << 16)) + #define PATTERN_IPV4_UDP_KMASK \ (KMASK_ETHER | (KMASK_IPV4 << 16) | (KMASK_UDP << 32)) @@ -332,6 +342,7 @@ _mm512_maskz_permutexvar_epi8_selector(__mmask64 k_shuf, __m512i v_shuf, #define PKT_OFFSET_VLAN_IPV6_L4 (PKT_OFFSET_VLAN_L3 + IPV6_HEADER_LEN) #define PKT_OFFSET_IPV6_L4 (PKT_OFFSET_L3 + IPV6_HEADER_LEN) +#define PKT_MIN_ETH_IPV4 (ETH_HEADER_LEN + IP_HEADER_LEN) #define PKT_MIN_ETH_IPV4_UDP (PKT_OFFSET_IPV4_L4 + UDP_HEADER_LEN) #define PKT_MIN_ETH_VLAN_IPV4_UDP (PKT_OFFSET_VLAN_IPV4_L4 + UDP_HEADER_LEN) #define PKT_MIN_ETH_IPV4_TCP (PKT_OFFSET_IPV4_L4 + TCP_HEADER_LEN) @@ -352,8 +363,8 @@ _mm512_maskz_permutexvar_epi8_selector(__mmask64 k_shuf, __m512i v_shuf, | MF_BIT(dl_dst) | MF_BIT(dl_src)| MF_BIT(dl_type)) #define MF_ETH_VLAN (MF_ETH | MF_BIT(vlans)) -#define MF_IPV4_UDP (MF_BIT(nw_src) | MF_BIT(ipv6_label) | MF_BIT(tp_src) | \ - MF_BIT(tp_dst)) +#define MF_IPV4 (MF_BIT(nw_src) | MF_BIT(ipv6_label)) +#define MF_IPV4_UDP (MF_IPV4 | MF_BIT(tp_src) | MF_BIT(tp_dst)) #define MF_IPV4_TCP (MF_IPV4_UDP | MF_BIT(tcp_flags) | MF_BIT(arp_tha.ea[2])) #define MF_IPV6_UDP (MF_BIT(ipv6_label) | MF_WORD(ipv6_src, 2) | \ @@ -449,6 +460,7 @@ enum MFEX_PROFILES { PROFILE_ETH_IPV6_TCP, PROFILE_ETH_VLAN_IPV6_TCP, PROFILE_ETH_VLAN_IPV6_UDP, + PROFILE_ETH_IPV4_NVGRE, PROFILE_COUNT, }; @@ -608,6 +620,21 @@ static const struct mfex_profile mfex_profiles[PROFILE_COUNT] = }, .dp_pkt_min_size = PKT_MIN_ETH_VLAN_IPV6_UDP, }, + + [PROFILE_ETH_IPV4_NVGRE] = { + .probe_mask.u8_data = { PATTERN_ETHERTYPE_MASK PATTERN_IPV4_MASK }, + .probe_data.u8_data = { PATTERN_ETHERTYPE_IPV4 PATTERN_IPV4_NVGRE}, + + .store_shuf.u8_data = { PATTERN_IPV4_NVGRE_SHUFFLE }, + .strip_mask.u8_data = { PATTERN_STRIP_IPV4_MASK }, + .store_kmsk = PATTERN_IPV4_KMASK, + + .mf_bits = { MF_ETH, MF_IPV4}, + .dp_pkt_offs = { + 0, UINT16_MAX, PKT_OFFSET_L3, PKT_OFFSET_IPV4_L4, + }, + .dp_pkt_min_size = PKT_MIN_ETH_IPV4, + }, }; /* IPv6 header helper function to fix TC, flow label and next header. */ @@ -959,6 +986,17 @@ mfex_avx512_process(struct dp_packet_batch *packets, mfex_handle_ipv6_l4((void *)&pkt[58], &blocks[10]); dp_packet_update_rss_hash_ipv6_tcp_udp(packet); } break; + + case PROFILE_ETH_IPV4_NVGRE: { + /* Handle dynamic l2_pad_size. */ + uint32_t size_from_ipv4 = size - sizeof(struct eth_header); + struct ip_header *nh = (void *)&pkt[sizeof(struct eth_header)]; + if (mfex_ipv4_set_l2_pad_size(packet, nh, size_from_ipv4, 0)) { + continue; + } + dp_packet_update_rss_hash_ipv4(packet); + } break; + default: break; }; @@ -1013,6 +1051,7 @@ DECLARE_MFEX_FUNC(ipv6_udp, PROFILE_ETH_IPV6_UDP) DECLARE_MFEX_FUNC(ipv6_tcp, PROFILE_ETH_IPV6_TCP) DECLARE_MFEX_FUNC(dot1q_ipv6_tcp, PROFILE_ETH_VLAN_IPV6_TCP) DECLARE_MFEX_FUNC(dot1q_ipv6_udp, PROFILE_ETH_VLAN_IPV6_UDP) +DECLARE_MFEX_FUNC(ip_nvgre, PROFILE_ETH_IPV4_NVGRE) #endif /* __CHECKER__ */ #endif /* __x86_64__ */ diff --git a/lib/dpif-netdev-private-extract.c b/lib/dpif-netdev-private-extract.c index 1a9b35420..ded08fd3e 100644 --- a/lib/dpif-netdev-private-extract.c +++ b/lib/dpif-netdev-private-extract.c @@ -184,6 +184,16 @@ static struct dpif_miniflow_extract_impl mfex_impls[] = { .extract_func = mfex_avx512_dot1q_ipv6_udp, .name = "avx512_dot1q_ipv6_udp", }, +#if HAVE_AVX512VBMI + [MFEX_IMPL_VBMI_IPv4_NVGRE] = { + .probe = mfex_avx512_vbmi_probe, + .extract_func = mfex_avx512_vbmi_ip_nvgre, + .name = "avx512_vbmi_ipv4_nvgre", }, +#endif + [MFEX_IMPL_IPv4_NVGRE] = { + .probe = mfex_avx512_probe, + .extract_func = mfex_avx512_ip_nvgre, + .name = "avx512_ipv4_nvgre", }, #endif }; diff --git a/lib/dpif-netdev-private-extract.h b/lib/dpif-netdev-private-extract.h index 8a7f9b01a..48549beaa 100644 --- a/lib/dpif-netdev-private-extract.h +++ b/lib/dpif-netdev-private-extract.h @@ -117,6 +117,10 @@ enum dpif_miniflow_extract_impl_idx { MFEX_IMPL_VBMI_DOT1Q_IPv6_UDP, #endif MFEX_IMPL_DOT1Q_IPv6_UDP, +#if HAVE_AVX512VBMI + MFEX_IMPL_VBMI_IPv4_NVGRE, +#endif + MFEX_IMPL_IPv4_NVGRE, #endif MFEX_IMPL_MAX }; @@ -230,6 +234,7 @@ DECLARE_AVX512_MFEX_PROTOTYPE(ipv6_udp); DECLARE_AVX512_MFEX_PROTOTYPE(ipv6_tcp); DECLARE_AVX512_MFEX_PROTOTYPE(dot1q_ipv6_tcp); DECLARE_AVX512_MFEX_PROTOTYPE(dot1q_ipv6_udp); +DECLARE_AVX512_MFEX_PROTOTYPE(ip_nvgre); #endif /* __x86_64__ */ -- 2.25.1 _______________________________________________ dev mailing list [email protected] https://mail.openvswitch.org/mailman/listinfo/ovs-dev
