| From foo@baz Wed May 28 21:03:54 PDT 2014 |
| From: Eric Dumazet <edumazet@google.com> |
| Date: Thu, 10 Apr 2014 21:23:36 -0700 |
| Subject: ipv6: Limit mtu to 65575 bytes |
| |
| From: Eric Dumazet <edumazet@google.com> |
| |
| [ Upstream commit 30f78d8ebf7f514801e71b88a10c948275168518 ] |
| |
| Francois reported that setting big mtu on loopback device could prevent |
| tcp sessions making progress. |
| |
| We do not support (yet ?) IPv6 Jumbograms and cook corrupted packets. |
| |
| We must limit the IPv6 MTU to (65535 + 40) bytes in theory. |
| |
| Tested: |
| |
| ifconfig lo mtu 70000 |
| netperf -H ::1 |
| |
| Before patch : Throughput : 0.05 Mbits |
| |
| After patch : Throughput : 35484 Mbits |
| |
| Reported-by: Francois WELLENREITER <f.wellenreiter@gmail.com> |
| Signed-off-by: Eric Dumazet <edumazet@google.com> |
| Acked-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org> |
| Acked-by: Hannes Frederic Sowa <hannes@stressinduktion.org> |
| Signed-off-by: David S. Miller <davem@davemloft.net> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| include/net/ip6_route.h | 5 +++++ |
| net/ipv6/route.c | 5 +++-- |
| 2 files changed, 8 insertions(+), 2 deletions(-) |
| |
| --- a/include/net/ip6_route.h |
| +++ b/include/net/ip6_route.h |
| @@ -32,6 +32,11 @@ struct route_info { |
| #define RT6_LOOKUP_F_SRCPREF_PUBLIC 0x00000010 |
| #define RT6_LOOKUP_F_SRCPREF_COA 0x00000020 |
| |
| +/* We do not (yet ?) support IPv6 jumbograms (RFC 2675) |
| + * Unlike IPv4, hdr->seg_len doesn't include the IPv6 header |
| + */ |
| +#define IP6_MAX_MTU (0xFFFF + sizeof(struct ipv6hdr)) |
| + |
| /* |
| * rt6_srcprefs2flags() and rt6_flags2srcprefs() translate |
| * between IPV6_ADDR_PREFERENCES socket option values |
| --- a/net/ipv6/route.c |
| +++ b/net/ipv6/route.c |
| @@ -1342,7 +1342,7 @@ static unsigned int ip6_mtu(const struct |
| unsigned int mtu = dst_metric_raw(dst, RTAX_MTU); |
| |
| if (mtu) |
| - return mtu; |
| + goto out; |
| |
| mtu = IPV6_MIN_MTU; |
| |
| @@ -1352,7 +1352,8 @@ static unsigned int ip6_mtu(const struct |
| mtu = idev->cnf.mtu6; |
| rcu_read_unlock(); |
| |
| - return mtu; |
| +out: |
| + return min_t(unsigned int, mtu, IP6_MAX_MTU); |
| } |
| |
| static struct dst_entry *icmp6_dst_gc_list; |