From patchwork Fri Jan 29 23:44:24 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiri Bohac X-Patchwork-Id: 575885 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id E2A6214056B for ; Sat, 30 Jan 2016 10:44:37 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932606AbcA2Xo3 (ORCPT ); Fri, 29 Jan 2016 18:44:29 -0500 Received: from mx2.suse.de ([195.135.220.15]:33737 "EHLO mx2.suse.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932583AbcA2Xo1 (ORCPT ); Fri, 29 Jan 2016 18:44:27 -0500 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay1.suse.de (charybdis-ext.suse.de [195.135.220.254]) by mx2.suse.de (Postfix) with ESMTP id 49D38ABB4; Fri, 29 Jan 2016 23:44:25 +0000 (UTC) Date: Sat, 30 Jan 2016 00:44:24 +0100 From: Jiri Bohac To: Steffen Klassert , Herbert Xu , "David S. Miller" Cc: netdev@vger.kernel.org Subject: xfrm: UFO + ESP = double fragmentation Message-ID: <20160129234424.GC7907@midget.suse.cz> MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.5.21 (2010-09-15) Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Hi, I'm seeing wrong fragmentation on locally generated UDPv6 packets going out over ESP (transport mode): UFO is turned on on the outgoing interface and MTU is 1500. When 8 kB is written to a UDP socket, udpv6_sendmsg() calls ip_append_data() which generates a single 8 kB GSO skb. Through ip6_send_skb() it reaches xfrm_output(). Since skb_is_gso(skb) is nonzero, xfrm_output_gso() is called. It immediatelly segments the skb via skb_gso_segment() and then calls xfrm_output2() on each individual segment. This is wrong. RFC4303 says: 3.3.4. Fragmentation If necessary, fragmentation is performed after ESP processing within an IPsec implementation. Thus, transport mode ESP is applied only to whole IP datagrams (not to IP fragments). Instead, xfrm_output_gso() applies the transform to each segment. Since both the fragmentation header _and_ the ESP headers now don't fit in the MTU and the ESP-encapsulated segments are fragmented for a second time in ip6_finish_output(). The outcome is: - the original 8k UDP packet is split into 6 ESP fragments - the first 5 ESP fragments are 1508 bytes each, thus fragmented again into two fragments The destination host replies with ICMP parameter problem. How is this supposed to work? This hack fixes this specific case: Is there a situation when xfrm_output_gso() does the right thing? Thanks, --- a/net/xfrm/xfrm_output.c +++ b/net/xfrm/xfrm_output.c @@ -198,7 +198,7 @@ int xfrm_output(struct sock *sk, struct sk_buff *skb) int err; if (skb_is_gso(skb)) - return xfrm_output_gso(net, sk, skb); + return xfrm_output2(net, sk, skb); if (skb->ip_summed == CHECKSUM_PARTIAL) { err = skb_checksum_help(skb);