From patchwork Fri Apr 10 22:16:28 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Florian Westphal X-Patchwork-Id: 460251 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 37EA814016A for ; Sat, 11 Apr 2015 08:17:03 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932701AbbDJWQz (ORCPT ); Fri, 10 Apr 2015 18:16:55 -0400 Received: from Chamillionaire.breakpoint.cc ([80.244.247.6]:59136 "EHLO Chamillionaire.breakpoint.cc" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932277AbbDJWQx (ORCPT ); Fri, 10 Apr 2015 18:16:53 -0400 Received: from fw by Chamillionaire.breakpoint.cc with local (Exim 4.80) (envelope-from ) id 1YghEJ-0000ad-Sv; Sat, 11 Apr 2015 00:16:52 +0200 From: Florian Westphal To: Cc: kaber@trash.net, Florian Westphal Subject: [PATCH -next 2/3] ipv6: don't increase size when refragmenting forwarded skbs Date: Sat, 11 Apr 2015 00:16:28 +0200 Message-Id: <1428704189-31247-3-git-send-email-fw@strlen.de> X-Mailer: git-send-email 2.0.5 In-Reply-To: <1428704189-31247-1-git-send-email-fw@strlen.de> References: <1428704189-31247-1-git-send-email-fw@strlen.de> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org since commit 6aafeef03b9d ("netfilter: push reasm skb through instead of original frag skbs") we will end up sometimes re-fragmenting skbs that we've reassembled. In this case, we must not use the device mtu, we might increase the fragment size, possibly breaking connectivity as later router might send packet-too-big errors even if sender never sent fragments exceeding the reported mtu: mtu 1500 - 1500:1400 - 1400:1280 - 1280 A R1 R2 B - A sends to B, fragment size 1500 - R1 sends pkttoobig error for 1400 - A sends to B, fragment size 1400 - R2 sends pkttoobig error for 1280 - A sends to B, fragment size 1280 - R2 sends pkttoobig error for 1280 again because it sees fragments of size 1400. This doesn't occur in practice because we currently use routing information to fetch the mtu. Acked-by: Hannes Frederic Sowa Signed-off-by: Florian Westphal --- net/ipv6/ip6_output.c | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 7fde1f2..604c99d 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -564,18 +564,17 @@ int ip6_fragment(struct sock *sk, struct sk_buff *skb, /* We must not fragment if the socket is set to force MTU discovery * or if the skb it not generated by a local socket. */ - if (unlikely(!skb->ignore_df && skb->len > mtu) || - (IP6CB(skb)->frag_max_size && - IP6CB(skb)->frag_max_size > mtu)) { - if (skb->sk && dst_allfrag(skb_dst(skb))) - sk_nocaps_add(skb->sk, NETIF_F_GSO_MASK); + if (unlikely(!skb->ignore_df && skb->len > mtu)) + goto fail_toobig; - skb->dev = skb_dst(skb)->dev; - icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu); - IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)), - IPSTATS_MIB_FRAGFAILS); - kfree_skb(skb); - return -EMSGSIZE; + if (IP6CB(skb)->frag_max_size) { + if (IP6CB(skb)->frag_max_size > mtu) + goto fail_toobig; + + /* don't send larger fragments than what we received */ + mtu = IP6CB(skb)->frag_max_size; + if (mtu < IPV6_MIN_MTU) + mtu = IPV6_MIN_MTU; } if (np && np->frag_size < mtu) { @@ -815,6 +814,14 @@ slow_path: consume_skb(skb); return err; +fail_toobig: + if (skb->sk && dst_allfrag(skb_dst(skb))) + sk_nocaps_add(skb->sk, NETIF_F_GSO_MASK); + + skb->dev = skb_dst(skb)->dev; + icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu); + err = -EMSGSIZE; + fail: IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)), IPSTATS_MIB_FRAGFAILS);