From patchwork Wed Mar 31 10:38:49 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jan Engelhardt X-Patchwork-Id: 49123 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 1AAB4B6F11 for ; Wed, 31 Mar 2010 21:39:10 +1100 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932809Ab0CaKjH (ORCPT ); Wed, 31 Mar 2010 06:39:07 -0400 Received: from borg.medozas.de ([188.40.89.202]:55971 "EHLO borg.medozas.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1757647Ab0CaKjB (ORCPT ); Wed, 31 Mar 2010 06:39:01 -0400 Received: by borg.medozas.de (Postfix, from userid 25121) id 1A5ADF0C26FED; Wed, 31 Mar 2010 12:39:00 +0200 (CEST) From: Jan Engelhardt To: kaber@trash.net Cc: netfilter-devel@vger.kernel.org, netdev@vger.kernel.org Subject: [PATCH 1/5] netfilter: ipv6: move POSTROUTING invocation before fragmentation Date: Wed, 31 Mar 2010 12:38:49 +0200 Message-Id: <1270031934-15940-2-git-send-email-jengelh@medozas.de> X-Mailer: git-send-email 1.7.0.2 In-Reply-To: <1270031934-15940-1-git-send-email-jengelh@medozas.de> References: <1270031934-15940-1-git-send-email-jengelh@medozas.de> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Patrick McHardy notes: "We used to invoke IPv4 POST_ROUTING after fragmentation as well just to defragment the packets in conntrack immediately afterwards, but that got changed during the netfilter-ipsec integration. Ideally IPv6 would behave like IPv4." This patch makes it so. Sending an oversized frame (e.g. `ping6 -s64000 -c1 ::1`) will now show up in POSTROUTING as a single skb rather than multiple ones. Signed-off-by: Jan Engelhardt --- net/ipv6/ip6_output.c | 49 +++++++++++++++++++++++-------------------------- 1 files changed, 23 insertions(+), 26 deletions(-) diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 4535b7a..f314ba4 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -82,22 +82,6 @@ int ip6_local_out(struct sk_buff *skb) } EXPORT_SYMBOL_GPL(ip6_local_out); -static int ip6_output_finish(struct sk_buff *skb) -{ - struct dst_entry *dst = skb_dst(skb); - - if (dst->hh) - return neigh_hh_output(dst->hh, skb); - else if (dst->neighbour) - return dst->neighbour->output(skb); - - IP6_INC_STATS_BH(dev_net(dst->dev), - ip6_dst_idev(dst), IPSTATS_MIB_OUTNOROUTES); - kfree_skb(skb); - return -EINVAL; - -} - /* dev_loopback_xmit for use with netfilter. */ static int ip6_dev_loopback_xmit(struct sk_buff *newskb) { @@ -111,8 +95,7 @@ static int ip6_dev_loopback_xmit(struct sk_buff *newskb) return 0; } - -static int ip6_output2(struct sk_buff *skb) +static int ip6_finish_output2(struct sk_buff *skb) { struct dst_entry *dst = skb_dst(skb); struct net_device *dev = dst->dev; @@ -150,8 +133,15 @@ static int ip6_output2(struct sk_buff *skb) skb->len); } - return NF_HOOK(NFPROTO_IPV6, NF_INET_POST_ROUTING, skb, NULL, skb->dev, - ip6_output_finish); + if (dst->hh) + return neigh_hh_output(dst->hh, skb); + else if (dst->neighbour) + return dst->neighbour->output(skb); + + IP6_INC_STATS_BH(dev_net(dst->dev), + ip6_dst_idev(dst), IPSTATS_MIB_OUTNOROUTES); + kfree_skb(skb); + return -EINVAL; } static inline int ip6_skb_dst_mtu(struct sk_buff *skb) @@ -162,21 +152,28 @@ static inline int ip6_skb_dst_mtu(struct sk_buff *skb) skb_dst(skb)->dev->mtu : dst_mtu(skb_dst(skb)); } +static int ip6_finish_output(struct sk_buff *skb) +{ + if ((skb->len > ip6_skb_dst_mtu(skb) && !skb_is_gso(skb)) || + dst_allfrag(skb_dst(skb))) + return ip6_fragment(skb, ip6_finish_output2); + else + return ip6_finish_output2(skb); +} + int ip6_output(struct sk_buff *skb) { + struct net_device *dev = skb_dst(skb)->dev; struct inet6_dev *idev = ip6_dst_idev(skb_dst(skb)); if (unlikely(idev->cnf.disable_ipv6)) { - IP6_INC_STATS(dev_net(skb_dst(skb)->dev), idev, + IP6_INC_STATS(dev_net(dev), idev, IPSTATS_MIB_OUTDISCARDS); kfree_skb(skb); return 0; } - if ((skb->len > ip6_skb_dst_mtu(skb) && !skb_is_gso(skb)) || - dst_allfrag(skb_dst(skb))) - return ip6_fragment(skb, ip6_output2); - else - return ip6_output2(skb); + return NF_HOOK(NFPROTO_IPV6, NF_INET_POST_ROUTING, skb, NULL, dev, + ip6_finish_output); } /*