Is there any way to tell the kernel which policy routing table should receive the default route learned from an IPv6 router advertisement?

My home network has native IPv6 service from Spectrum and a tunnel from Hurricane Electric that I still need for other reasons. They won't do router redirection so I use policy routing to maintain separate routing tables for each set of source addresses.

My policy rule list first searches the 'main' routing table, which is limited to local destination prefixes that can be reached with either set of source addresses. I tell dhcpcd to tell the kernel to not put a default route into that table, so if there's no match routing falls through to the next rule.

That next rule invokes a HE-specific table for HE source addresses only. That table consists only of a default route pointing at HE.

And the last rule invokes a Spectrum-specific table only for Spectrum source addresses. It contains only a default route pointing at Spectrum.

It all works well enough with static scripts, but it seems inelegant to hardwire addresses all over my scripts. What if Spectrum changes its IPv6 router address?

I'd like to maintain the default route to Spectrum automatically, but the Linux kernel only gives me two choices: pick up Spectrum's router advertisement and put that into a default route in the 'main' table, or (if you set "accept_ra_def_rtr=0"), do nothing. dhcpcd won't tell you the IPv6 gateway address since DHCP6, unlike DHCP4, doesn't assign IPv6 gateways; that function is done by the kernel when it receives Router Advertisement messages.

I could let the kernel install Spectrum's default route in the "main" table, invoke that table only if the source address belongs to Spectrum, and then fall through to the table for HE. But then I'd have to replicate all my local routes in the HE table, and again that gets messy.

A simple and obvious answer occurred to me: let me tell the kernel WHICH routing table to use for default routes to the gateways learned from IPv6 router advertisements. There's even a special table named "default" which is automatically put on the end of the policy rule list. But I can't find any way to tell the kernel to do that. It's either the 'main' table or nothing. Again, I'd rather limit the 'main' table to local entries managed (in part) by dhcpcd (e.g. my delegated prefix from Spectrum).

Anybody else ran into this problem? Any workarounds?


1 Answer 1


Using this suppressor in ip rule:

suppress_prefixlength NUMBER
         reject routing decisions that have a prefix length of NUMBER or less.

You can use the main table, unmodified, in your first (lower priority value) rule, while ignoring its default route by using something like:

ip -6 rule add priority 32000 from all lookup main suppress_prefixlength 0

This rule will ignore any /0 prefix from the main routing table, ie, the "default" default route.

The main table can still be reused later with its default route (in the usual rule with priority 32766) if nothing else matched before (ie: if the rule for the HE source didn't match in an in-between rule).

  • Sure, just did. It wasn't the answer I was expecting (I still think there should be a way to select the table to receive RA default routes) but it does completely solve my actual problem.
    – Phil Karn
    Dec 27, 2018 at 11:44
  • @PhilKarn Digging a bit: ndisc_router_discovery() calls rt6_add_dflt_router() which uses either the hardcoded default, or l3mdev_fib_table(dev). This appears to be related to VRF devices. Maybe an other method would be to use vrf devices, but I don't know about it: kernel.org/doc/Documentation/networking/vrf.txt
    – A.B
    Dec 27, 2018 at 12:26

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .