Merging multiple routes into a single multipath route
Hello. I am running a setup with 2 uplinks which both have dynamic addresses (via DHCP) and NAT and a Linux router. So I get 2 default routes via DHCP. I would like to use both uplinks via the linux multipath routing and I am searching for a way to "merge" both default routes that I get into one route with multiple next hops. Is there a way to accomplish that with bird? (or any other tool?) All of this is only relevant for IPv4. Greetings Jo
Hey Jo, that is a very interesting and repeating use-case that exists for ... as long as routing exists? While I am not sure how I'd solve it with bird, it is probably easy to solve it statically: - the next hop (default gateway) in these scenarios are often static - thus you can easily just create the static route with both gateways once (ip route add default nexthop ..) and be done with it Alternatively you could Linux VRF with your dhcp client, add the default routes into a separate table (let's say 101 for the first upstream, 102 for the second upstream) and then use bird to read the routes and write a new merge route. HTH, Nico Johannes Erwerle <jo+bird@swagspace.org> writes:
Hello.
I am running a setup with 2 uplinks which both have dynamic addresses (via DHCP) and NAT and a Linux router. So I get 2 default routes via DHCP.
I would like to use both uplinks via the linux multipath routing and I am searching for a way to "merge" both default routes that I get into one route with multiple next hops.
Is there a way to accomplish that with bird? (or any other tool?)
All of this is only relevant for IPv4.
Greetings Jo
-- Sustainable and modern Infrastructures by ungleich.ch
Hi, You can import them to bird, do some tricks to make multipath default route and export them back to the kernel. But it should take precedence over routes intalled by DHCP, so you have to alter them somehow - put them in other table, increase metric, etc. In bird you can for example take routes from one kernel table and put it into another with "merge paths" option. If it is the same kernel table, you can do something with them, to get routes not from the kernel protocol, so that they could be exported back. You can make some local bgp session from bird to itself or you can pipe this defaults to other tables where you will make static recursive default routes and export these recursive routes back to your table, from which they will be exported to the kernel. I only not sure that the trick with recursive routes will work directly, because you will have same prefix in the separate table and there may be conflict between original default route and a static default route. In that case you may need 2 separate tables and 2 recursive routes (and another 2 tables & routes for another default route). First, you export your default to the filrst table, there you make static recursive route for example 0.0.0.1/32 via 0.0.0.0, then you export 0.0.0.1/32 to the second table where you have static recursive route 0.0.0.0/0 via 0.0.0.1 and then you export this default route from the second table back to your original (usually master) table. On Tue, May 3, 2022 at 4:14 PM Johannes Erwerle <jo+bird@swagspace.org> wrote:
Hello.
I am running a setup with 2 uplinks which both have dynamic addresses (via DHCP) and NAT and a Linux router. So I get 2 default routes via DHCP.
I would like to use both uplinks via the linux multipath routing and I am searching for a way to "merge" both default routes that I get into one route with multiple next hops.
Is there a way to accomplish that with bird? (or any other tool?)
All of this is only relevant for IPv4.
Greetings Jo
On 03/05/2022 17.37, Alexander Zubkov wrote:
In bird you can for example take routes from one kernel table and put it into another with "merge paths" option. Ah, the merge path option is what I was looking for. Thank you very much for that.
I will do some experiments how to best work around the restrictions given by the kernel protocol. Greetings Jo
Well, some observations: You need to make sure that the dhcp client assigns the default routes with different metrics so they appear in the kernel routing table in the first place. Also it appears like bird imports only the first default route: # bird.conf filter test { print net, " interface: ", ifname; accept; } protocol kernel { ipv4 { import filter test; export none; }; learn; } root@host-1:/etc/bird# ip r default via 172.21.0.1 dev bond0.300 default via 172.21.101.1 dev eno1 metric 200 <... snip ...> root@host-1:/etc/bird# birdc show route all BIRD 2.0.7 ready. Table master4: 0.0.0.0/0 unicast [kernel1 21:54:15.332] (10) via 172.21.0.1 on bond0.300 Type: inherit univ Kernel.source: 3 Kernel.metric: 0 I assume this is an intended behavior, because a second route with a higher metric would usually not be used? Greetings Jo
If you able to set different metrics than probably you can set different tables on that dhcp routes? In that case it will be different kernel protocols in bird. You can also try to set different "tos" to your dhcp routes, Linux kernel treats different tos as different routes so dhcp clients would not conflict. Also ensure that when dhcp client deletes route, it deletes only its own route, i.e. additional attributes like metric/table/tos should be added to the delete statement too. On Tue, May 3, 2022 at 10:11 PM Johannes Erwerle <jo+bird@swagspace.org> wrote:
Well, some observations:
You need to make sure that the dhcp client assigns the default routes with different metrics so they appear in the kernel routing table in the first place.
Also it appears like bird imports only the first default route:
# bird.conf filter test { print net, " interface: ", ifname; accept; }
protocol kernel { ipv4 { import filter test; export none; }; learn; }
root@host-1:/etc/bird# ip r default via 172.21.0.1 dev bond0.300 default via 172.21.101.1 dev eno1 metric 200 <... snip ...>
root@host-1:/etc/bird# birdc show route all BIRD 2.0.7 ready. Table master4: 0.0.0.0/0 unicast [kernel1 21:54:15.332] (10) via 172.21.0.1 on bond0.300 Type: inherit univ Kernel.source: 3 Kernel.metric: 0
I assume this is an intended behavior, because a second route with a higher metric would usually not be used?
Greetings Jo
Hi Johannes, On Tue, May 03, 2022 at 04:07:08PM +0200, Johannes Erwerle wrote:
I would like to use both uplinks via the linux multipath routing and I am searching for a way to "merge" both default routes that I get into one route with multiple next hops.
Is there a way to accomplish that with bird? (or any other tool?)
Instead of letting the dhcp client install the routes and then trying to massage them into shape you could do this directly by configuring the dhcp client appropriately. The isc-dhcp client actually and very good support for scripting in dhclient-*-hooks.d that lets you override what the dhclient-script (which handles the OS specific stuff) does by default. I have been working on a dhcp script myself to allow for VRRP redundancy on a DHCP managed interface. You should be able to use the neutralize_ip_change hack I use to override iproute2 commands called by dhclient-script for your purposes too: neutralize_ip_change () { ip () neutered_ip "$@" } neutered_ip () { : do stuff and call real "ip" command; } This works because dhclient-script (a bash script) sources the hooks so we can mess with the shell environment to override the "ip" command with a shell function that matches on the args and does whatever we want. Script attached since I haven't published it anywhere yet. Note this is only lightly tested so far but I'd be happy to help you make this work for your use-case. --Daniel
participants (4)
-
Alexander Zubkov -
Daniel Gröber -
Johannes Erwerle -
Nico Schottelius