IPv6 host route is deleted after PMTU expires
- by SAPikachu
I am experimenting my new IPv6 tunnel setup between my local Ubuntu box and a scratch Linode. I set up some docker containers, configured 6in4 tunnel server and IPv6 forwarding on the Linode:
# uname -a
Linux argo 3.15.4-x86_64-linode45 #1 SMP Mon Jul 7 08:42:36 EDT 2014 x86_64 x86_64 x86_64 GNU/Linux
# ip addr
.. snipped ..
48: sit-sapikachu: <POINTOPOINT,NOARP,UP,LOWER_UP> mtu 1472 qdisc noqueue state UNKNOWN group default
link/sit 106.185.41.115 peer 1.2.3.4
inet6 fd00::1/64 scope global
valid_lft forever preferred_lft forever
inet6 fe80::6ab9:2973/64 scope link
valid_lft forever preferred_lft forever
13: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 56:84:7a:fe:97:99 brd ff:ff:ff:ff:ff:ff
inet 172.17.42.1/16 scope global docker0
valid_lft forever preferred_lft forever
inet6 fc00::1/64 scope global
valid_lft forever preferred_lft forever
inet6 fe80::5484:7aff:fefe:9799/64 scope link
valid_lft forever preferred_lft forever
// Docker containers are bridged to docker0
On my local box, I configured a 6in4 tunnel interface to connect to the Linode box, and added a host route to one of the docker container:
# uname -a
Linux sapikachu-netbox 3.13.0-24-generic #47-Ubuntu SMP Fri May 2 23:30:00 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux
# ip addr
.. snipped ..
16: sit-argo: <POINTOPOINT,NOARP,UP,LOWER_UP> mtu 1480 qdisc noqueue state UNKNOWN group default
link/sit 0.0.0.0 peer 106.185.41.115
inet6 fd00::2/64 scope global
valid_lft forever preferred_lft forever
inet6 fe80::a97:302/64 scope link
valid_lft forever preferred_lft forever
inet6 fe80::ac19:1/64 scope link
valid_lft forever preferred_lft forever
inet6 fe80::c0a8:1f0/64 scope link
valid_lft forever preferred_lft forever
inet6 fe80::c0a8:1fa/64 scope link
valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether *** brd ff:ff:ff:ff:ff:ff
.. snipped ..
inet6 fd00:0:1::1/64 scope global
valid_lft forever preferred_lft forever
inet6 fe80::2e0:6fff:fe0e:365e/64 scope link
valid_lft forever preferred_lft forever
# ip route replace fc00::1875:8606:d8c1:8a9d via fd00::1 # Add route to docker container
# ip -6 route
.. snipped unrelated routes
fc00::1875:8606:d8c1:8a9d via fd00::1 dev sit-argo metric 1024 expires 590sec mtu 1472
fd00::/64 dev sit-argo proto kernel metric 256
fd00:0:1::/64 dev eth0 proto kernel metric 256
fe80::/64 dev sit-argo proto kernel metric 256
(Note that tunnel MTU on my local box is different from the server, this is intentional for testing)
After adding the host route to the docker container (fc00::1875:8606:d8c1:8a9d), I can ping the container without problem until the route expires. After that I couldn't get reply any more. If I run ip -6 route in a few seconds after expiration, expiration time of the host route will be a negative number:
fc00::1875:8606:d8c1:8a9d via fd00::1 dev sit-argo metric 1024 expires -1sec
And output of ip route get fc00::1875:8606:d8c1:8a9d shows that it is routed to my default IPv6 gateway (which fails to route it correctly of course, since the address is not globally routable).
After some time, the host route disappears without a trace.
This problem won't happen if I do either one of the following things:
Set MTU of tunnel on my local box to be the same as the server (1472). The route won't have expiration time in both ip -6 route and ip route get in this case.
Instead of adding a host route, add a route with network mask (even /127 works). In this case ip -6 route shows the route without expiration time, ip route get shows expiration time but it will be correctly refreshed after expiration.
Although this problem can be easily resolved, I am curious to know why this happens. Is there error in my configuration, or is this a kernel bug?