David Woodhouse <dw...@infradead.org> wrote: > On Wed, 2015-09-16 at 01:48 +0200, Florian Westphal wrote: > > > > What I don't understand is why you see this with fragmented ipv6 > > packets only (and not with all ipv6 forwarded skbs). > > > > Something like this copy-pastry from ip_finish_output2 should fix it: > > That works; thanks. > > Tested-by: David Woodhouse <david.woodho...@intel.com> > > A little extra debugging output shows that the offending fragments were > arriving here with skb_headroom(skb)==10. Which is reasonable, being > the Solos ADSL card's header of 8 bytes followed by 2 bytes of PPP > frame type. > > The non-fragmented packets, on the other hand, are arriving with a > headroom of 42 bytes. Could something else already have reallocated > them before they get that far?
Yep. I missed if (skb_cow(skb, dst->dev->hard_header_len)) { call in ip6_forward(). Problem is of course that we only expand headroom of the skb and not of the fragment(s) stored in that skbs frag list. So we have several options for a fix. - expand headroom in ip6_finish_output2, like we do for ipv4 - expand headroom in ip6_fragment - defer to slowpath if frags don't have enough headroom. The latter is the smallest patch and would not add test for locally generated, non-fragmented skbs. (not even compile tested) David, could you test this? I'd do an official patch submission then. diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -586,6 +586,7 @@ int ip6_fragment(struct sock *sk, struct sk_buff *skb, frag_id = ipv6_select_ident(net, &ipv6_hdr(skb)->daddr, &ipv6_hdr(skb)->saddr); + hroom = LL_RESERVED_SPACE(rt->dst.dev); if (skb_has_frag_list(skb)) { int first_len = skb_pagelen(skb); struct sk_buff *frag2; @@ -599,7 +600,7 @@ int ip6_fragment(struct sock *sk, struct sk_buff *skb, /* Correct geometry. */ if (frag->len > mtu || ((frag->len & 7) && frag->next) || - skb_headroom(frag) < hlen) + skb_headroom(frag) < (hlen + hroom)) goto slow_path_clean; /* Partially cloned skb? */ @@ -724,7 +725,6 @@ slow_path: */ *prevhdr = NEXTHDR_FRAGMENT; - hroom = LL_RESERVED_SPACE(rt->dst.dev); troom = rt->dst.dev->needed_tailroom; /* -- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html