Centos – IPv6 source address selection and routing in Linux


I'm in the process of setting an ipv6 on my test network.

I work with a /56 network and CentOS 6.2.

I have an interface with 2 IPv6 addresses on 2 different networks :

  • 2b0 1:abcd:4001:c00::30/56 connected to Internet (default gw 2b0 1 :abcd:4001:c00::1/56)
  • 2b0 2:abcd:4001:c00::30/56 only the local network.

So normally, if I ping an address to an unknown network, I use the first address IPv6 as source address and I go through the default gateway :

$ ping6 -v -c 1 -w 1 -I eth0 2620:0:ccc::2 
PING 2620:0:ccc::2(2620:0:ccc::2) from 2b02:abcd:4001:c00::30 eth0: 56 data bytes

--- 2620:0:ccc::2 ping statistics ---
2 packets transmitted, 0 received, 100% packet loss, time 1000ms

BUT no… However, if I mark the address as deprecated, it's Ok (IPv6 Source Address Selection on Linux).

$ ip addr change 2b02:abcd:4001:c00::30 dev eth0 preferred_lft 0

BUT, if i ping a host on the same local network, the first/wrong address source is used !

$ ping6 -v -c1 -w1 -I eth0 2b02:abcd:4001:c00::10
PING 2b02:abcd:4001:c00::10(2b02:abcd:4001:c00::10) from 2b01:abcd:4001:c00::30 eth0: 56 data bytes
64 bytes from 2b02:abcd:4001:c00::10: icmp_seq=1 ttl=64 time=2.17 ms

--- 2b02:abcd:4001:c00::10 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 2ms
rtt min/avg/max/mdev = 2.175/2.175/2.175/0.000 ms

Does someone can explain this behavior ?

Configuration :

$ cat /etc/sysconfig/network-scripts/ifcfg-eth0



Routing table :

$ route -n -A inet6
Table de routage IPv6 du noyau
Destination                                 Prochain Hop                            Indic Metric Ref    Utilis. Iface
2b01:abcd:4001:c00::/56                     ::                                      UA    256    5        0 eth0    
2b02:abcd:4001:c00::/56                     ::                                      U     256    0        0 eth0    
fe80::/64                                   ::                                      U     256    0        0 eth0    
::/0                                        2b01:abcd:4001:c00::1                   UG    1      605       0 eth0    
::/0                                        fe80::2237:6ff:fe46:e320                UGDA  1024   2        0 eth0    
::1/128                                     ::                                      U     0      0        1 lo      
2b01:abcd:4001:c00::30/128                  ::                                      U     0      0        1 lo      
2b02:abcd:4001:c00::30/128                  ::                                      U     0      0        1 lo      
fe80::1ec1:deff:feb8:a3fd/128               ::                                      U     0      53       1 lo      
ff02::1/128                                 ff02::1                                 UC    0      1        0 eth0    
ff00::/8                                    ::                                      U     256    0        0 eth0 

Best Answer

It seems to be following the rules correctly.

When you ping 2620:0:ccc::2, none of the rules apply:

  • Rule 1 (Prefer same address) not applicable
  • Rule 2 (Prefer appropriate scope) both candidate source addresses have the same scope
  • Rule 3 (Avoid deprecated addresses) neither candidate source address is deprecated
  • Rule 4 (Prefer home address) not applicable
  • Rule 5 (Outgoing interface) both candidate source addresses are assigned to the same interface
  • Rule 6 (Prefer matching label) you're probably not configured any labels
  • Rule 7 (Prefer public address) both addresses are public
  • Rule 8 (Use longest matching prefix) the common prefix is the same in both cases: it might be 2000::/4 or maybe longer, depending on what your actual IP addresses are.

So it picks arbitrarily.

In your next test, you set one of the addresses to be deprecated. So then, by Rule 3, it's always going to avoid that one.

One solution is to reconsider why your local-only prefix resembles your global prefix so much. Maybe your local-only prefix should be under fc00::/7 (ULA).

Another solution would be to make sure your local addresses are labelled differently, so that Rule 6 will be able to pick the right address. The downside of this solution is that you will have to manually modify the label table on all hosts in your local network. Anyway, something like this might work:

ip addrlabel add 2XX2:Y:4001:c00::30/56 label 42