kernel: does not learn routes with RTPROT_KERNEL (proto kernel in ip-route(8) output)

Сергей Попович popovich_sergei at mail.ru
Wed Aug 7 12:11:46 CEST 2013


 Hello.

Recently I spot following issue with BIRD:
  kernel syncer does not learn routes with RTPROT_KERNEL even with
    "learn" and "device routes" turned on.

Config is wery simple:

# Main routing table (master), mapped to ipt_main kernel table.
# ipt_main == 254 (see /etc/iproute2/rt_tables)
protocol kernel kernel254 {
        persist no;
        scan time 120;
        learn yes;
        device routes yes;
        kernel table ipt_main;
        import all;
        export all;
}

$ birdc 'show route'
BIRD 1.3.10 ready.

$ ip -4 route show table main
172.16.1.0/24 dev lo255  proto kernel  scope link  src 172.16.1.254

Can some one explain why this was done, and is there any way
other than patching BIRD (at least sysdep/linux/netlink.c does checking and ignoring
and sysdep/unix/krt.c makes its final verdict to ignore such route).

Background of problem or why this might be important (at least for me).
There is lot of text, and no need to read it, however it describes why learning
routes with RTPROT_KENREL might be important.
-----------------------------------------------------------------------------------------------

There is requirement to create separate Linux kernel RIB and install
rules to direct traffic to it (ip-rules(8)). This is an PBR (Policy-Based Routing)

BIRD has all necessary means to do that:
  protocols direct - to learn directly connected routes and
  pipe to import from main (master in BIRD) routing table some routes.

And everything works as expected, except that protocol direct "imports"
(better to say create may be?) routes based on interface ip address configuration.
Contrary to this, kernel installs such directly connected routes with some attributes:
like proto kernel, and very important as I discover src (krt_prefsrc attribute in BIRD).

Actually attribute perfsrc used in kernel to determine outgoning source for packets
that has no src addresses in it (application does not call bind(2), which is common for UDP).

Without prefsrc on route, kernel uses fallback mechanism to find source:
this is inet_select_addr() function, which is not ideal in functionality (in some cases
strange source address might be choosen), and all it does it looks outgoing interface itself for
primary address and other interfaces if interface has no such one).

Recent kernels (linux-2.6.39+) has implemented genid table to cache information from
inet_select_addr()
(commits 436c3b66ec98 "ipv4: Invalidate nexthop cache nh_saddr more correctly." and
 1fc050a13473 "ipv4: Cache source address in nexthop entries.")
lookups, but implementation has also wholes (for example if interface has zero ip address
on it and host on lan referenced by a route with interface as nexthop (so called ip unnumbered
in proven vendor terms) as only event to regenerate (and thus recall inet_select_addr())
genid is changing state of the interface (i.e. changing route pointing to device has no chance
to regenerate genid and packets might still go with source from previous call to inet_select_addr()).

Some distributions with longterm support still provides 2.6.32 kernels.

Having system with thousands interfaces and sending UDP for example over all of it
is wery expensive in CPU terms. Thus I decided to learn routes from kernel protocol
and then pass them trought pipe and install it in new kernel table for PBR.

--
SP5474-RIPE
Sergey Popovich
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://trubka.network.cz/pipermail/bird-users/attachments/20130807/357f3b17/attachment.html>


More information about the Bird-users mailing list