summaryrefslogtreecommitdiff
path: root/include/net/ipv6_frag.h
diff options
context:
space:
mode:
authorPeter Oskolkov <posk@google.com>2019-01-22 10:02:51 -0800
committerDavid S. Miller <davem@davemloft.net>2019-01-25 21:37:11 -0800
commitd4289fcc9b16b89619ee1c54f829e05e56de8b9a (patch)
treec49e51dc6fb2121bdfb57e250f7962f1dae1b43a /include/net/ipv6_frag.h
parentc23f35d19db3b36ffb9e04b08f1d91565d15f84f (diff)
downloadlwn-d4289fcc9b16b89619ee1c54f829e05e56de8b9a.tar.gz
lwn-d4289fcc9b16b89619ee1c54f829e05e56de8b9a.zip
net: IP6 defrag: use rbtrees for IPv6 defrag
Currently, IPv6 defragmentation code drops non-last fragments that are smaller than 1280 bytes: see commit 0ed4229b08c1 ("ipv6: defrag: drop non-last frags smaller than min mtu") This behavior is not specified in IPv6 RFCs and appears to break compatibility with some IPv6 implemenations, as reported here: https://www.spinics.net/lists/netdev/msg543846.html This patch re-uses common IP defragmentation queueing and reassembly code in IPv6, removing the 1280 byte restriction. Signed-off-by: Peter Oskolkov <posk@google.com> Reported-by: Tom Herbert <tom@herbertland.com> Cc: Eric Dumazet <edumazet@google.com> Cc: Florian Westphal <fw@strlen.de> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'include/net/ipv6_frag.h')
-rw-r--r--include/net/ipv6_frag.h11
1 files changed, 9 insertions, 2 deletions
diff --git a/include/net/ipv6_frag.h b/include/net/ipv6_frag.h
index 6ced1e6899b6..28aa9b30aece 100644
--- a/include/net/ipv6_frag.h
+++ b/include/net/ipv6_frag.h
@@ -82,8 +82,15 @@ ip6frag_expire_frag_queue(struct net *net, struct frag_queue *fq)
__IP6_INC_STATS(net, __in6_dev_get(dev), IPSTATS_MIB_REASMTIMEOUT);
/* Don't send error if the first segment did not arrive. */
- head = fq->q.fragments;
- if (!(fq->q.flags & INET_FRAG_FIRST_IN) || !head)
+ if (!(fq->q.flags & INET_FRAG_FIRST_IN))
+ goto out;
+
+ /* sk_buff::dev and sk_buff::rbnode are unionized. So we
+ * pull the head out of the tree in order to be able to
+ * deal with head->dev.
+ */
+ head = inet_frag_pull_head(&fq->q);
+ if (!head)
goto out;
head->dev = dev;