On 19/04/2024 15:06, David Marchand wrote:
> The outer checksum offloading API in DPDK is ambiguous and was
> implemented by Intel folks in their drivers with the assumption that
> any outer offloading always goes with an inner offloading request.
> 
> With net/i40e and net/ice drivers, in the case of encapsulating a ARP
> packet in a vxlan tunnel (which results in requesting outer ip checksum
> with a tunnel context but no inner offloading request), a Tx failure is
> triggered, associated with a port MDD event.
> 2024-03-27T16:02:07.084Z|00018|dpdk|WARN|ice_interrupt_handler(): OICR:
>       MDD event
> 
> To avoid this situation, if no checksum or segmentation offloading is
> requested on the inner part of a packet, fallback to "normal" (non outer)
> offloading request.
> 
> Reported-at: https://github.com/openvswitch/ovs-issues/issues/321
> Fixes: 084c8087292c ("userspace: Support VXLAN and GENEVE TSO.")
> Fixes: f81d782c1906 ("netdev-native-tnl: Mark all vxlan/geneve packets as 
> tunneled.")
> Signed-off-by: David Marchand <david.march...@redhat.com>
> ---
> Changes since v2:
> - kept offloads disabled for net/i40e and net/ice as this patch does not
>   fix outer udp checksum (a DPDK fix is required),
> - updated commitlog with details to reproduce the issue,
> - adjusted indent,
> 
> Changes since v1:
> - reset inner marks before converting outer requests,
> - fixed some coding style,
> 
> ---
>  lib/netdev-dpdk.c | 71 +++++++++++++++++++++++++++--------------------
>  1 file changed, 41 insertions(+), 30 deletions(-)
> 
> diff --git a/lib/netdev-dpdk.c b/lib/netdev-dpdk.c
> index 2111f77681..7e109903c0 100644
> --- a/lib/netdev-dpdk.c
> +++ b/lib/netdev-dpdk.c
> @@ -2584,16 +2584,18 @@ netdev_dpdk_prep_hwol_packet(struct netdev_dpdk *dev, 
> struct rte_mbuf *mbuf)
>      struct dp_packet *pkt = CONTAINER_OF(mbuf, struct dp_packet, mbuf);
>      struct tcp_header *th;
>  
> -    const uint64_t all_requests = (RTE_MBUF_F_TX_IP_CKSUM |
> -                                   RTE_MBUF_F_TX_L4_MASK  |
> -                                   RTE_MBUF_F_TX_OUTER_IP_CKSUM  |
> -                                   RTE_MBUF_F_TX_OUTER_UDP_CKSUM |
> -                                   RTE_MBUF_F_TX_TCP_SEG);
> -    const uint64_t all_marks = (RTE_MBUF_F_TX_IPV4 |
> -                                RTE_MBUF_F_TX_IPV6 |
> -                                RTE_MBUF_F_TX_OUTER_IPV4 |
> -                                RTE_MBUF_F_TX_OUTER_IPV6 |
> -                                RTE_MBUF_F_TX_TUNNEL_MASK);
> +    const uint64_t all_inner_requests = (RTE_MBUF_F_TX_IP_CKSUM |
> +                                         RTE_MBUF_F_TX_L4_MASK |
> +                                         RTE_MBUF_F_TX_TCP_SEG);
> +    const uint64_t all_outer_requests = (RTE_MBUF_F_TX_OUTER_IP_CKSUM |
> +                                         RTE_MBUF_F_TX_OUTER_UDP_CKSUM);
> +    const uint64_t all_requests = all_inner_requests | all_outer_requests;
> +    const uint64_t all_inner_marks = (RTE_MBUF_F_TX_IPV4 |
> +                                      RTE_MBUF_F_TX_IPV6);
> +    const uint64_t all_outer_marks = (RTE_MBUF_F_TX_OUTER_IPV4 |
> +                                      RTE_MBUF_F_TX_OUTER_IPV6 |
> +                                      RTE_MBUF_F_TX_TUNNEL_MASK);
> +    const uint64_t all_marks = all_inner_marks | all_outer_marks;
>  
>      if (!(mbuf->ol_flags & all_requests)) {
>          /* No offloads requested, no marks should be set. */
> @@ -2614,34 +2616,43 @@ netdev_dpdk_prep_hwol_packet(struct netdev_dpdk *dev, 
> struct rte_mbuf *mbuf)
>       * l2 len and outer l3 len. Inner l2/l3/l4 len are calculated
>       * before. */
>      const uint64_t tunnel_type = mbuf->ol_flags & RTE_MBUF_F_TX_TUNNEL_MASK;
> -    if (tunnel_type == RTE_MBUF_F_TX_TUNNEL_GENEVE ||
> -        tunnel_type == RTE_MBUF_F_TX_TUNNEL_VXLAN) {
> -        mbuf->outer_l2_len = (char *) dp_packet_l3(pkt) -
> -                 (char *) dp_packet_eth(pkt);
> -        mbuf->outer_l3_len = (char *) dp_packet_l4(pkt) -
> -                 (char *) dp_packet_l3(pkt);
> -
> -        /* If neither inner checksums nor TSO is requested, inner marks
> -         * should not be set. */
> -        if (!(mbuf->ol_flags & (RTE_MBUF_F_TX_IP_CKSUM |
> -                                RTE_MBUF_F_TX_L4_MASK  |
> -                                RTE_MBUF_F_TX_TCP_SEG))) {
> -            mbuf->ol_flags &= ~(RTE_MBUF_F_TX_IPV4 |
> -                                RTE_MBUF_F_TX_IPV6);
> -        }
> -    } else if (OVS_UNLIKELY(tunnel_type)) {
> +    if (OVS_UNLIKELY(tunnel_type &&
> +                     tunnel_type != RTE_MBUF_F_TX_TUNNEL_GENEVE &&
> +                     tunnel_type != RTE_MBUF_F_TX_TUNNEL_VXLAN)) {
>          VLOG_WARN_RL(&rl, "%s: Unexpected tunnel type: %#"PRIx64,
>                       netdev_get_name(&dev->up), tunnel_type);
>          netdev_dpdk_mbuf_dump(netdev_get_name(&dev->up),
>                                "Packet with unexpected tunnel type", mbuf);
>          return false;
> +    }
> +
> +    if (tunnel_type && (mbuf->ol_flags & all_inner_requests)) {
> +        mbuf->outer_l2_len = (char *) dp_packet_l3(pkt) -
> +                             (char *) dp_packet_eth(pkt);
> +        mbuf->outer_l3_len = (char *) dp_packet_l4(pkt) -
> +                             (char *) dp_packet_l3(pkt);
>      } else {
> -        mbuf->l2_len = (char *) dp_packet_l3(pkt) -
> -               (char *) dp_packet_eth(pkt);
> -        mbuf->l3_len = (char *) dp_packet_l4(pkt) -
> -               (char *) dp_packet_l3(pkt);
> +        if (tunnel_type) {
> +            /* No inner offload is requested, fallback to non tunnel
> +             * checksum offloads. */
> +            mbuf->ol_flags &= ~all_inner_marks;
> +            if (mbuf->ol_flags & RTE_MBUF_F_TX_OUTER_IP_CKSUM) {
> +                mbuf->ol_flags |= RTE_MBUF_F_TX_IP_CKSUM;
> +                mbuf->ol_flags |= RTE_MBUF_F_TX_IPV4;
> +            }
> +            if (mbuf->ol_flags & RTE_MBUF_F_TX_OUTER_UDP_CKSUM) {
> +                mbuf->ol_flags |= RTE_MBUF_F_TX_UDP_CKSUM;
> +                mbuf->ol_flags |= mbuf->ol_flags & RTE_MBUF_F_TX_OUTER_IPV4
> +                                  ? RTE_MBUF_F_TX_IPV4 : RTE_MBUF_F_TX_IPV6;
> +            }
> +            mbuf->ol_flags &= ~(all_outer_requests | all_outer_marks);
> +        }
>          mbuf->outer_l2_len = 0;
>          mbuf->outer_l3_len = 0;
> +        mbuf->l2_len = (char *) dp_packet_l3(pkt) -
> +                       (char *) dp_packet_eth(pkt);
> +        mbuf->l3_len = (char *) dp_packet_l4(pkt) -
> +                       (char *) dp_packet_l3(pkt);
>      }
>      th = dp_packet_l4(pkt);
>  

Acked-by: Kevin Traynor <ktray...@redhat.com>

Just to note, I reviewed the series but did not test all the combinations.



_______________________________________________
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to