TIL - ignore_routes_with_linkdown

TIL, Today I Learned, is more of a "I just figured this out: here are my notes, you may find them useful too" rather than a full blog post

Usually, a high level network managers such as NetworkManager or Connman, removes routes for unaccessible ("linkdown" or "unplugged") links states.

In some cases, these links are not managed eiter by a network manager but are managed in other ways or in somehow misconfigured, then you can end up with a default route still hangs around even if the link is down.

It doesn't sound too bad, if it weren't for the fact that it is still active and if its metric value is lower than some other default route, it will be the chosen route.

Consider the following routes:

# ip route
default via 10.42.0.1 dev rndis proto static metric 100 linkdown
default via 192.168.30.1 dev br0 proto static metric 425
10.42.0.0/24 dev rndis proto kernel scope link src 10.42.0.20 metric 100 linkdown
192.168.30.0/23 dev br0 proto static scope link metric 425
192.168.30.0/23 dev br0 proto kernel scope link src 192.168.30.97 metric 425

Even if the rndis interface has the "linkdown" flag, Linux will use it as default route regardless (lowest metric value) for any FIB (Forward Information Base) lookup.

/media/ignore_routes_with_linkdown.png

The kernel provide a feature to ignore routes that use links with the down state; ignore_routes_with_linkdown.

This is a rather old feature [1] introduced in v4.2 and documented [3] as follows:

ignore_routes_with_linkdown - BOOLEAN
        Ignore routes whose link is down when performing a FIB lookup.

When set, the route will not only be set as linkdown but dead linkdown to indicate that the route is currently ignored during a FIB lookup.

The flag could be set with some granuality, both for IPv4/IPv6, all interfaces or just on a single interface. For example:

$sysctl -a | grep ignore_routes_with_link
net.ipv4.conf.all.ignore_routes_with_linkdown = 0
net.ipv4.conf.default.ignore_routes_with_linkdown = 0
net.ipv4.conf.docker0.ignore_routes_with_linkdown = 0
net.ipv4.conf.enp0s13f0u2u4.ignore_routes_with_linkdown = 0
net.ipv4.conf.enp0s31f6.ignore_routes_with_linkdown = 0
net.ipv4.conf.eth0.ignore_routes_with_linkdown = 0
net.ipv4.conf.lo.ignore_routes_with_linkdown = 0
net.ipv4.conf.tun0.ignore_routes_with_linkdown = 0
net.ipv4.conf.wlp0s20f3.ignore_routes_with_linkdown = 0
net.ipv6.conf.all.ignore_routes_with_linkdown = 0
net.ipv6.conf.default.ignore_routes_with_linkdown = 0
net.ipv6.conf.docker0.ignore_routes_with_linkdown = 0
net.ipv6.conf.enp0s13f0u2u4.ignore_routes_with_linkdown = 0
net.ipv6.conf.enp0s31f6.ignore_routes_with_linkdown = 0
net.ipv6.conf.eth0.ignore_routes_with_linkdown = 0
net.ipv6.conf.lo.ignore_routes_with_linkdown = 0
net.ipv6.conf.tun0.ignore_routes_with_linkdown = 0
net.ipv6.conf.wlp0s20f3.ignore_routes_with_linkdown = 0

Set the flag

The flag could be set in a few different ways:

  • Via sysctl [4] on command line:

    sudo sysctl -w net.ipv4.conf.all.ignore_routes_with_linkdown=1
    
  • Via sysctl configuration file:

    echo "net.ipv4.conf.all.ignore_routes_with_linkdown = 1" | sudo tee /etc/sysctl.conf
    sudo /sbin/sysctl -p
    
  • Via procfs:

    echo 1 | sudo tee /proc/sys/net/ipv4/conf/all/ignore_routes_with_linkdown