libnl icon indicating copy to clipboard operation
libnl copied to clipboard

route: properly handle multiple kernel prefix routes with same dst

Open KanjiMonster opened this issue 9 months ago • 0 comments

When configuring IP(v6) addresses on interfaces, the kernel will install appropriate prefix routes (except when using noprefixroute).

When configuring addresses from the same subnet on multiple interfaces, the kernel will happily configure multiple prefix routes. Most prominent example are per interface IPv6 link local fe80::/64 routes.

Currently libnl treats these routes as identical, and thus will only keep the newest one of the routes in the cache (as each additional one is treated as an update to the previous route).

Therefore we need to extend route_id_attrs_get() to properly treat these routes as different:

  • For IPv4, these routes will have a preferred source set.
  • For IPv6, these routes will have a single nexthop pointing to the interface (OIF).

Also, only kernel may create these routes, attempts from userspace will be rejected when trying to add a second route for the same prefix.

ip route output:

$ ip r show table all
...
10.0.0.0/24 dev tun0 proto kernel scope link src 10.0.0.1
10.0.0.0/24 dev enp0s31f6 proto kernel scope link src 10.0.0.2
...
broadcast 10.0.0.255 dev tun0 table local proto kernel scope link src 10.0.0.1
broadcast 10.0.0.255 dev enp0s31f6 table local proto kernel scope link src 10.0.0.2
...
fe80::/64 dev tun0 proto kernel metric 256 pref medium
fe80::/64 dev enp0s31f6 proto kernel metric 1024 pref medium
...
multicast ff00::/8 dev enp0s31f6 table local proto kernel metric 256 pref medium
multicast ff00::/8 dev tun0 table local proto kernel metric 256 pref medium

$ ip r show table all | wc -l
37

Before:

$ ./src/nl-route-list
...
inet 10.0.0.0/24 table main type unicast via dev tun0
...
inet 10.0.0.255 table local type broadcast via dev tun0
...
inet6 fe80::/64 table main type unicast via dev tun0
inet6 fe80::/64 table main type unicast via dev enp0s31f6
...
inet6 ff00::/8 table local type multicast via dev enp0s31f6

$ ./src/nl-route-list | grep -v cache | wc -l
34

After:

$ ./src/nl-route-list
...
inet 10.0.0.0/24 table main type unicast via dev tun0
inet 10.0.0.0/24 table main type unicast via dev enp0s31f6
...
inet6 fe80::/64 table main type unicast via dev tun0
inet6 fe80::/64 table main type unicast via dev enp0s31f6
...
inet6 ff00::/8 table local type multicast via dev enp0s31f6
inet6 ff00::/8 table local type multicast via dev tun0

$ ./src/nl-route-list | grep -v cache | wc -l
37

(ip route doesn't show cache routes)

KanjiMonster avatar May 14 '24 11:05 KanjiMonster