In this blog post I want to explain when and why it is important to set route priorities. Let’s consider the following scenario: you have a Linux host that has more than one network interface, both are routable and both are up and running. How do you determine which interface or route is used when trying to reach another host?
In other words the routing table looks like this:
netbeez.net$ route -n Kernel IP routing table Destination Gateway Genmask Flags Metric Ref Use Iface 0.0.0.0 192.168.1.254 0.0.0.0 UG 0 0 0 wlan0 0.0.0.0 172.31.0.1 0.0.0.0 UG 202 0 0 eth0 172.31.0.0 0.0.0.0 255.255.255.0 U 202 0 0 eth0 192.168.1.0 0.0.0.0 255.255.255.0 U 0 0 0 wlan0
As you can see, we have a WiFi wlan0 and a wired eth0 interface.
Obviously, route specificity is the first deciding factor, then comes administrative distance, followed by “Metric,” in this order. In this example, if we try to access google.com both interfaces have the same route specificity and administrative distance. The metric is the deciding factor, and wlan0 with the lower value would be prioritized.
To remember this relationship think about network packets as electric current flow and metric as resistance: the lower the interface resistance the higher the priority on that interface. This is the function of route priorities: let’s learn how to set them!
Configuration
The question is how can you manipulate the metric to suit your needs. A typical use case is having a host with a WiFi and a cellular interface, and prioritize the WiFi one when both are connected.
The utility that can do this is called ifmetric. It can be installed as follows:
apt-get install ifmetric
It’s very simple to use and does one (and only one) thing, which is to set the metric value on an interface, shown as follows:
ifmetric <interface name> [metric value]
In the example above, wlan0 has higher priority than eth0. If you want to reverse that, you can do the following:
netbeez.net$ ifmetric wlan0 203 netbeez.net$ route -n Kernel IP routing table Destination Gateway Genmask Flags Metric Ref Use Iface 0.0.0.0 172.31.0.1 0.0.0.0 UG 202 0 0 eth0 0.0.0.0 192.168.1.254 0.0.0.0 UG 203 0 0 wlan0 172.31.0.0 0.0.0.0 255.255.255.0 U 202 0 0 eth0 192.168.1.0 0.0.0.0 255.255.255.0 U 203 0 0 wlan0
Note that now that eth0 has higher priority is listed first in the “route -n” output.
These changes are not permanent and will be reset once the host reboots. To make them permanent you have to add the metric value into its interface configuration file. For example, if you are using dhclient and /etc/network/interfaces, or /etc/network/interfaces.d/<interface name>, the metric value would look like this:
netbeez.net$ cat /etc/network/interfaces.d/eth0 auto eth0 allow-hotplug eth0 iface eth0 inet dhcp metric 1
If you are using dhcpcd then you need the following configuration in /etc/dhcpcd.conf:
interface eth0 metric 0
When the metric is the same for both interfaces, the one listed first in the output of “route -n” is the one that has the higher priority:
netbeez.net$ route -n Kernel IP routing table Destination Gateway Genmask Flags Metric Ref Use Iface 0.0.0.0 192.168.1.254 0.0.0.0 UG 0 0 0 wlan0 0.0.0.0 172.31.0.1 0.0.0.0 UG 0 0 0 eth0 172.31.0.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0 192.168.1.0 0.0.0.0 255.255.255.0 U 0 0 0 wlan0
Keep in mind that the metric also depends on the dhcp client that handles the interfaces. For example, if you are using dhcpcd as a DHCP client, according to its configuration, the metrics are configured as follows:
Metrics are used to prefer an interface over another one, lowest wins. dhcpcd will supply a default metric of 200 + if_nametoindex(3). An extra 100 will be added for wireless interfaces.
I haven’t been able to find any documentation about dhclient’s approach to assigning the metric value.