On 18 April 2017 at 02:09, Steffen Klassert <steffen.klass...@secunet.com> wrote: > On Thu, Apr 13, 2017 at 07:45:08PM -0700, Ansis Atteka wrote: >> On 11 April 2017 at 00:07, Steffen Klassert <steffen.klass...@secunet.com> >> wrote: >> > >> > What's wrong with the checksum provided by the GSO layer and >> > why we have to do this unconditionally here? >> > >> >> I believe with "GSO layer" you meant the skb_gso_segment() function >> invocation from xfrm_output_gso()? >> >> If so, then the problem with that is that the list of the skb's returned by >> that function could be in CHECKSUM_PARTIAL state if skb came from a UDP >> tunnel such as Geneve: > > This should not happen. We don't announce checksum capabilities, > so the GSO layer should generate the full checksum. > > __skb_udp_tunnel_segment() and udp4_ufo_fragment() add the > NETIF_F_HW_CSUM flag to features. This is certainly wrong > if the packet undergoes an IPsec transformation. > > I don't have a testcase for this, so not sure if this is > your problem. Could you try the (untested) patch below?
I am still seeing the same ESP packet corruption issue with the patch you attached. However, after taking pointers from your patch I came up with this one that may solve this problem once and for all (note, that I was seeing this bug only with ixgbe NIC that supports tx csum offloads). I hope it does not break any other IPsec tests that you have. diff --git a/net/ipv4/udp_offload.c b/net/ipv4/udp_offload.c index b2be1d9..7812501 100644 --- a/net/ipv4/udp_offload.c +++ b/net/ipv4/udp_offload.c @@ -29,6 +29,7 @@ static struct sk_buff *__skb_udp_tunnel_segment(struct sk_buff *skb, u16 mac_len = skb->mac_len; int udp_offset, outer_hlen; __wsum partial; + bool need_ipsec; if (unlikely(!pskb_may_pull(skb, tnl_hlen))) goto out; @@ -62,8 +63,10 @@ static struct sk_buff *__skb_udp_tunnel_segment(struct sk_buff *skb, ufo = !!(skb_shinfo(skb)->gso_type & SKB_GSO_UDP); + need_ipsec = skb_dst(skb) && dst_xfrm(skb_dst(skb)); /* Try to offload checksum if possible */ offload_csum = !!(need_csum && + !need_ipsec && (skb->dev->features & (is_ipv6 ? (NETIF_F_HW_CSUM | NETIF_F_IPV6_CSUM) : (NETIF_F_HW_CSUM | NETIF_F_IP_CSUM))));