1

I'm trying to configure IPv6 for one of my linux machines, but there are things going on that I don't understand yet. There is one tricky thing: The machine shall have a static address setup, but it shall also do SLAAC. The machine needs to operate in two different environments: In the first environment, there is a router which supports SLAAC, but the static gateway is not there. In the second environment, SLAAC will not work at all, but the static gateway is there instead. Maybe that sounds somewhat scary (does it?), but a very similar setup worked fine for IPv4 only so far. I really want to stick with it; my question is not so much about very different alternative approaches.

In the first environment, I can only reach some IPv6 hosts (I don't know yet how it would behave in the second environment).

I use systemd-networkd for networking, and this is my network interface config (with some values anonymized):

 [Match] Name=e* [Network] Address=2a00:.../64 DNS=... # IPv4 works fine, but to have it more complete: Address=185.1.2.3/29 Address=185.1.2.4/29 DHCP=ipv4 [Route] Gateway=2a00:...:1 Metric=2000 [Route] Gateway=185.1.2.5 Metric=2000 

This is the output of ip addr for that interface (in the first environment), again anonymized:

 2: enp5s0: mtu 1500 qdisc fq_codel state UP group default qlen 1000 link/ether aa:bb:cc:dd:ee:ff brd ff:ff:ff:ff:ff:ff altname enxfoo inet 185.1.2.3/29 brd 185.1.2.5 scope global enp5s0 valid_lft forever preferred_lft forever inet 192.168.50.209/24 metric 1024 brd 192.168.50.255 scope global dynamic enp5s0 valid_lft 83782sec preferred_lft 83782sec inet 185.1.2.4/29 brd 185.1.2.5 scope global secondary enp5s0 valid_lft forever preferred_lft forever inet6 2001:.../64 scope global dynamic mngtmpaddr noprefixroute valid_lft 594sec preferred_lft 594sec inet6 2a00:.../64 scope global valid_lft forever preferred_lft forever inet6 fe80:.../64 scope link proto kernel_ll valid_lft forever preferred_lft forever 

The routing table looks like that:

 2001:.../64 dev enp5s0 proto ra metric 1024 expires 595sec pref medium 2a00:.../64 dev enp5s0 proto kernel metric 256 pref medium fe80::/64 dev enp5s0 proto kernel metric 256 pref medium default nhid 2343432122 via fe80:... dev enp5s0 proto ra metric 1024 expires 595sec pref medium default via 2a00:...:1 dev enp5s0 proto static metric 2000 pref medium 
 $ ip nexthop show id 2343432122 via fe80:... dev enp5s0 scope link proto ra 

So far so good. I have a course understanding about all that, but I'm not an expert. To me it looks like we have the static setup there, but SLAAC also worked, and the dynamic route has a better metric, so it was good enough for me to give it a try. However, I can only reach some hosts. This one works:

 $ ping6 2604:1380:4641:c500::1 PING 2604:1380:4641:c500::1 (2604:1380:4641:c500::1) 56 data bytes 64 bytes from 2604:1380:4641:c500::1: icmp_seq=1 ttl=54 time=126 ms 64 bytes from 2604:1380:4641:c500::1: icmp_seq=2 ttl=54 time=127 ms 

And this one does not:

 $ ping6 2a00:1450:4001:830::2003 PING 2a00:1450:4001:830::2003 (2a00:1450:4001:830::2003) 56 data bytes 

I tried some more, and it feels like it depends on the beginning of the destination address. Then I checked what the routing decisions are for those two cases:

 $ ip -6 route get 2604:1380:4641:c500::1 2604:1380:4641:c500::1 from :: via fe80::... dev enp5s0 proto ra src 2001:... metric 1024 pref medium $ ip -6 route get 2a00:1450:4001:830::2003 2a00:1450:4001:830::2003 from :: via fe80::... dev enp5s0 proto ra src 2a00:... metric 1024 pref medium 

So, for the working case, it decided to use the address it got via SLAAC as the source address. Great. For the non-working case, it decided to use the static address. That can't work. The packets will never find their way back. But why does it do that? I see that my static address starts with "2a00", as the destination address does. But is that the reason? How exactly are the rules there? I don't really understand that yet and wasn't able to find valuable answers on the web yet either. Is there a simple way to fix that?

1 Answer 1

0

One of the main rules for IPv6 Source Address Selection is "longest common prefix". Each of the candidate source addresses is compared against the destination to determine how many identical bits they have (counting from the left, just like with CIDR prefixes) and the address with the longest common prefix is the one chosen as the source address.

The important bit is that only the destination address – not the gateway address – is compared against the candidate sources. (Though with IPv6 SLAAC there's also supposed to be a rule to prefer sources which are within a prefix advertised by that particular gateway but I don't recall if Linux implements it. I think it doesn't.)

Try adding the PreferredSource= parameter to your routes (aka src in iproute2). It works the same in IPv4 and IPv6 and can be used to hint at a preferred source IP address whenever that route gets used.

2
  • Thanks a lot, that's a good explanation (that means the problems was there for IPv4 as well then?!). Since I'd need to set the preferred source on the dynamically created route, I don't see a quick way to fix that, though. Am I right? Commented Mar 10 at 1:43
  • I don't recall how Linux handles IPv4 source address selection (whether it uses the IPv6 algorithm or something else). Try other SLAAC clients, e.g. dhcpcd or systemd-networkd, to see if they behave any better than the kernel's built-in SLAAC client. One common way of handling multi-homed hosts is to have each interface's default route in a separate routing table (plus a way to copy all the 'scope link' routes from the default table…) – I think at least networkd can be configured to put the SLAAC routes in a non-default table, but there's not really any good way to handle it overall. Commented Mar 10 at 5:18

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.