Skip to contentSkip to conversation

IPv6 problems (mtu is less than advmss?)

PATCH In review Jim Paris 2 participants 3 messages Jan 21, 2008 – Feb 1, 2008

Subsystems (3)
lore
Share & tools
lore

Jim Paris

author
#0 lore raw

Hi,

When the IPv6 default route is first autoconfigured, it seems the advertised MSS doesn't get set properly.

I have computer A connected to an external interface with IPv4 and tunneling IPv6 using 6to4. It runs radvd on an internal interface to provide connectivity to my LAN. radvd.conf contains:

  interface brint {
	AdvLinkMTU 1420;    # advertise tiny MTU due to tunnel
	AdvSendAdvert on;
	prefix 0:0:0:1::/64
	{ Base6to4Interface brext; };

};

Computer B is on the LAN and autoconfigures an IPv6 address. However, I have problems with some specific hosts [1]. They're probably doing broken ICMP/PMTU filtering or something, but I've tracked down some weirdness in the kernel:

computerA# /etc/init.d/radvd start

computerB# ifconfig eth0 down
computerB# ifconfig eth0 up
computerB# ip -6 route
2002:125f:205:1::/64 dev eth0 proto kernel metric 256 expires 2592312sec mtu 1420 advmss 1360 hoplimit 4294967295 fe80::/64 dev eth0 metric 256 expires 21334361sec mtu 1420 advmss 1360 hoplimit 4294967295
ff00::/8 dev eth0 metric 256 expires 21334361sec mtu 1420 advmss 1360 hoplimit 4294967295
default via fe80::230:48ff:fe8b:5df4 dev eth0 proto kernel metric 1024 expires 1788sec mtu 1420 advmss 1440 hoplimit 64

At this point, I see the network problems. Note how the advmss in the last line is not only larger than all the other lines, it's even bigger than the MTU. I won't be able to download [1] until I manually fix advmss, _or_ just restart radvd on the other computer:

computerA# /etc/init.d/radvd restart

computerB# ip -6 route
2002:125f:205:1::/64 dev eth0 proto kernel metric 256 expires 2592160sec mtu 1420 advmss 1360 hoplimit 4294967295 fe80::/64 dev eth0 metric 256 expires 21334355sec mtu 1420 advmss 1360 hoplimit 4294967295
ff00::/8 dev eth0 metric 256 expires 21334355sec mtu 1420 advmss 1360 hoplimit 4294967295
default via fe80::230:48ff:fe8b:5df4 dev eth0 proto kernel metric 1024 expires 1798sec mtu 1420 advmss 1360 hoplimit 64

Now the advmss is better and everything works fine. It seems that if it's being created for the first time, the advmss is not correctly set based on the MTU, but if there's already a route when it gets the RA, it reconfigures it correctly.

Computer A is 2.6.23.1 and computer B is 2.6.24-rc8, both x86_64.

Any suggestions or other debugging I can do?

-jim

[1] wget -6 http://releases.mozilla.org/pub/mozilla.org/addons/12/all-in-one_gestures-0.18.0-fx.xpi

author
#1 lore raw

PATCH 1/1 ipv6: update MSS even if MTU is unchanged

This is needed because in ndisc.c, we have:

  static void ndisc_router_discovery(struct sk_buff *skb)
  {
  // ...
  	if (ndopts.nd_opts_mtu) {
  // ...
  			if (rt)
  				rt->u.dst.metrics[RTAX_MTU-1] = mtu;

  			rt6_mtu_change(skb->dev, mtu);
  // ...
  }

Since the mtu is set directly here, rt6_mtu_change_route thinks that it is unchanged, and so it fails to update the MSS accordingly. This patch lets rt6_mtu_change_route still update MSS if old_mtu == new_mtu.

---
This fixes the problem I reported earlier where IPv6 autoconfiguration ends up with mtu < advmss on the default route.

I don't know if this is the best way to fix the problem, but it works for me. Other options: set rt->u.dst.metrics[RTAX_ADVMSS-1] directly in ndisc_router_discovery (but ipv6_advmss function isn't available); don't set MTU at all in ndisc_router_discovery and let rt6_mtu_change handle it; etc.

 net/ipv6/route.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)
net/ipv6/route.c +1 -1
index 6ecb5e6..0965fb3 100644
@@ -1912,7 +1912,7 @@ static int rt6_mtu_change_route(struct rt6_info *rt, void *p_arg)
 	 */
 	if (rt->rt6i_dev == arg->dev &&
 	    !dst_metric_locked(&rt->u.dst, RTAX_MTU) &&
-	    (dst_mtu(&rt->u.dst) > arg->mtu ||
+	    (dst_mtu(&rt->u.dst) >= arg->mtu ||
 	     (dst_mtu(&rt->u.dst) < arg->mtu &&
 	      dst_mtu(&rt->u.dst) == idev->cnf.mtu6))) {
 		rt->u.dst.metrics[RTAX_MTU-1] = arg->mtu;
Signature · 1 line
1.5.3.8
maintainer
#2 lore raw

Re: [PATCH] ipv6: update MSS even if MTU is unchanged

From: Jim Paris <[email protected]>
Date: Mon, 21 Jan 2008 17:02:48 -0500

Quoted 14 lines

This is needed because in ndisc.c, we have:

  static void ndisc_router_discovery(struct sk_buff *skb)
  {
  // ...
  	if (ndopts.nd_opts_mtu) {
  // ...
  			if (rt)
  				rt->u.dst.metrics[RTAX_MTU-1] = mtu;

  			rt6_mtu_change(skb->dev, mtu);
  // ...
  }
Quoted 5 lines

Since the mtu is set directly here, rt6_mtu_change_route thinks that it is unchanged, and so it fails to update the MSS accordingly. This patch lets rt6_mtu_change_route still update MSS if old_mtu == new_mtu.

This seems ok, patch applied, thanks.