Removing device-bound routes when interface is going down
Hi (again), I've encountered a problem which is (most likely) is caused by a bug in the Linux kernel, but significantly affects routing handling in bird (everything else like quagga is most likely also affected). When route is added manually/externally to the kernel, and bound to specific interface, like this: $ ip route add 10.1.1.0/24 dev eth0 ...it is correctly identified by bird (via async netlink message), but when the interface goes down, this route is not deleted, as there is no corresponding netlink message (tested on most recent kernel, 3.16.1, and also on older 3.11, this happens only on if-down event, manual deletion works fine). Since bird does not see the route removal, it is still kept in the routing table, thus, it is still announced via OSPF (in my particular case), however the kernel knows nothing about this. Obviously, it is possible to set up periodic scanning of kernel table with small interval, but even then, this removal will not be instant, and additionally, it introduces additional CPU usage - even if the table in question is small by itself, but there is another huge table, this scan will consume significant time, in my case - it takes 0.3s to dump main table (~10 entries), all due to huge BGP table (~500k entries), thus scanning every 10 seconds will consume 3% CPU (mostly for nothing, as this kind of changes are relatively seldom). Fixing this problem in the mainstream kernel (if this is indeed unintentional behavior) will clearly take ages, but it could be easily solved in bird itself - if interface is going down, all routes pointing to this device must be removed (not only direct and static routes - where it works perfectly). I feel that this workaround is quite easy to implement, but not sure where exactly to look, thus I'll be really grateful for right directions :) Thank you! -- With best regards, Alexander.
On 18 Aug 2014, at 18:32, Alexander Demenshin <aldem-bird.2014@nk7.net> wrote:
When route is added manually/externally to the kernel, and bound to specific interface, like this:
$ ip route add 10.1.1.0/24 dev eth0
...it is correctly identified by bird (via async netlink message), but when the interface goes down, this route is not deleted, as there is no corresponding netlink message (tested on most recent kernel, 3.16.1, and also on older 3.11, this happens only on if-down event, manual deletion works fine).
Would you expect such routes to be *deleted*? Let's say you had 100 carefully crafted device routes to an ethernet interface, and the switch at the other end of the cable rebooted. If the routes were deleted, you would lose them all.
Fixing this problem in the mainstream kernel (if this is indeed unintentional behavior) will clearly take ages, but it could be easily solved in bird itself - if interface is going down, all routes pointing to this device must be removed (not only direct and static routes - where it works perfectly).
That would seem the right thing to do. -- Alex Bligh
On 2014-08-18 19:39, Alex Bligh wrote:
Would you expect such routes to be *deleted*?
Perhaps I did use misleading term - "interface going down" in my description means "interface deleted", sorry for that. Of course, when interface is deleted, all routes must be deleted as well, and they are deleted but netlink does not see this. When *link* goes down, it should not affect anything (and it does not), though there is an option for that in bird ("check link"). -- With best regards, Alexander.
В письме от 18 августа 2014 19:32:10 пользователь Alexander Demenshin написал:
Hi (again),
I've encountered a problem which is (most likely) is caused by a bug in the Linux kernel, but significantly affects routing handling in bird (everything else like quagga is most likely also affected).
When route is added manually/externally to the kernel, and bound to specific interface, like this:
$ ip route add 10.1.1.0/24 dev eth0
...it is correctly identified by bird (via async netlink message), but when the interface goes down, this route is not deleted, as there is no corresponding netlink message (tested on most recent kernel, 3.16.1, and also on older 3.11, this happens only on if-down event, manual deletion works fine).
This is long standing "feature" of the Linux kernel. There are at least two times this problem hits netdev mailing list. One of which described here: http://www.spinics.net/lists/netdev/msg254133.html And the resolution from the DM about this situation and why this should not be solved within kernel: http://www.spinics.net/lists/netdev/msg254186.html Summary is that if you have ~500k routes in the BIRD and interface where nexthop of such routes changes its operstate kernel should sent notification about each of them (~500k). This causes near DoS level of netlink traffic from kernel to userspace. In most cases more than half of these messages are being not delivered/handled by userspace.
Since bird does not see the route removal, it is still kept in the routing table, thus, it is still announced via OSPF (in my particular case), however the kernel knows nothing about this.
Obviously, it is possible to set up periodic scanning of kernel table with small interval, but even then, this removal will not be instant, and additionally, it introduces additional CPU usage - even if the table in question is small by itself, but there is another huge table, this scan will consume significant time, in my case - it takes 0.3s to dump main table (~10 entries), all due to huge BGP table (~500k entries), thus scanning every 10 seconds will consume 3% CPU (mostly for nothing, as this kind of changes are relatively seldom).
You are right, this is really happens and there is nothing to do with this currently.
Fixing this problem in the mainstream kernel (if this is indeed unintentional behavior) will clearly take ages, but it could be easily solved in bird itself - if interface is going down, all routes pointing to this device must be removed (not only direct and static routes - where it works perfectly).
I feel that this workaround is quite easy to implement, but not sure where exactly to look, thus I'll be really grateful for right directions :)
Thank you!
-- SP5474-RIPE Sergey Popovich
On 2014-08-18 19:54, Sergey Popovich wrote:
Summary is that if you have ~500k routes in the BIRD and interface where nexthop of such routes changes its operstate kernel should sent notification about each of them (~500k).
I see... thank you - this didn't cross my mind :) But nevertheless, what about handling this in bird directly, by watching for "interface deleted" (not "operstate down"!) event and cleaning up [kernel linked] routes that use this device? Kernel deletes them anyway. /Al
On Mon, Aug 18, 2014 at 08:32:37PM +0200, Alexander Demenshin wrote:
On 2014-08-18 19:54, Sergey Popovich wrote:
Summary is that if you have ~500k routes in the BIRD and interface where nexthop of such routes changes its operstate kernel should sent notification about each of them (~500k).
I see... thank you - this didn't cross my mind :)
But nevertheless, what about handling this in bird directly, by watching for "interface deleted" (not "operstate down"!) event and cleaning up [kernel linked] routes that use this device? Kernel deletes them anyway.
That probably should be implemented. Thanks for the suggestion. -- Elen sila lumenn' omentielvo Ondrej 'Santiago' Zajicek (email: santiago@crfreenet.org) OpenPGP encrypted e-mails preferred (KeyID 0x11DEADC3, wwwkeys.pgp.net) "To err is human -- to blame it on a computer is even more so."
On 2014-08-19 00:35, Ondrej Zajicek wrote:
But nevertheless, what about handling this in bird directly, by watching for "interface deleted" (not "operstate down"!) event and cleaning up [kernel linked] routes that use this device? Kernel deletes them anyway.
That probably should be implemented. Thanks for the suggestion.
Well, it seems that even for operstate "down" (not "link down") all device related routes are deleted by the kernel, thus handling should be similar. /Al
participants (4)
-
Alex Bligh -
Alexander Demenshin -
Ondrej Zajicek -
Sergey Popovich