"gw" attribute assignment in filter invalidates routes learned via BGP, static, and possibly others?

Sergey Popovich popovich_sergei at mail.ru
Fri Sep 27 12:43:25 CEST 2013


В письме от 13 августа 2013 16:25:14 Вы написали:
> On Tue, Aug 13, 2013 at 01:57:48PM +0300, Sergey Popovich wrote:
> > Hello!
> > 
> > Another issue I spot last time:
> >   assigning value in protocol export filter
> >   invalidates route and prevents its from being
> >   installed in KRT.
> 
> Yes, this is a known issue. Works just for setting gw on the same iface.
> 

> The attached patch should do that (essentially just lookup iface,
> fix it and force the route to RTD_ROUTER in case of setting 'gw').
> Is this OK for you?
> 

There are new circumstances comes with this patch (currently
in upstream git tree):
  deletion IP address from interface, in which subnet "gw" attribute
  was set, does not change route reachability status.

BIRD configuration. I use simple static protocol, but other protocols
are affected as well when "gw" attribute changed in filters.

BIRD is running on Linux 3.2.x stable tree.
------------------------------------------------------
# Configure logging                                                                                                                         
log stderr all;                                                                                                                             
log syslog all;                                                                                                                             
                                                                                                                                            
router id 172.16.1.1;                                                                                                                       
                                                                                                                                            
protocol device devices {                                                                                                                   
        scan time 120;                                                                                                                      
}                                                                                                                                           
                                                                                                                                            
table rt_10;                                                                                                                                
                                                                                                                                            
protocol static static10 {                                                                                                                  
        table rt_10;

        debug all;

        # This route represents protocol specific.
        #
        # For simplicity we use "blackhole" route without
        # neighbor attached to it.
        #
        route 192.168.0.0/16 blackhole;

        # This route have attached neighbor via neigh_find2()
        # with %NEF_STICKY to track its nexthop changes,
        # and thus neigh_notify() callback in static protocol
        # takes care on  nexthop state changes.
        #
        route 10.0.0.0/8 via 192.0.2.5;

        import filter {
                # Overwrite "gw" attribute on
                # "blackhole" route
                if dest = RTD_BLACKHOLE then
                        gw = 192.0.2.5;
                accept;
        };
        export none;
}

protocol kernel kernel10 {
        table rt_10;

        debug all;

        persist no;
        scan time 120;
        learn no;
        device routes no;
        kernel table 10;
        import none;
        export all;
}

System network stack configuration
----------------------------------------------

# ip -4 addr show dev lo255
6: lo255: <BROADCAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN 
    inet 192.0.2.1/24 scope global lo255

# ip -4 route show table 10

Starting bird, complied with -DGLOBAL_DEBUG and "-d" option
-------------------------------------------------------------------------------

# bird -d
...

After bird starts, everything works as expected
------------------------------------------------------------

# birdc 'show route table rt_10 all'
BIRD 1.3.11 ready.
10.0.0.0/8         via 192.0.2.5 on lo255 [static10 12:49] * (200)
        Type: static unicast univ
192.168.0.0/16     via 192.0.2.5 on lo255 [static10 12:49] * (200)
        Type: static unicast univ

# ip -4 route show table 10
10.0.0.0/8 via 192.0.2.5 dev lo255  proto bird 
192.168.0.0/16 via 192.0.2.5 dev lo255  proto bird

Now, delete IP address 192.0.2.1/24 from "lo255" interface
---------------------------------------------------------------------------

# ip -4 addr del 192.0.2.1/24 dev lo255                                                                          

# ip -4 route show table 10                                                                          
192.168.0.0/16 via 192.0.2.5 dev lo255  proto bird                                                                                          

# birdc 'show route table rt_10 all'                                                                 
BIRD 1.3.11 ready.                                                                                                                          
192.168.0.0/16     via 192.0.2.5 on lo255 [static10 12:49] * (200)                                                                          
        Type: static unicast univ

And debugging output from bird
-----------------------------------------

KRT: Received async address notification (21)
KIF: IF6(lo255): removed IPA 192.0.2.1, flg 0, net 192.0.2.0/24, brd 
192.0.2.255, opp 0.0.0.0
Flushing neighbor 192.0.2.5 on lo255
Static: neighbor notify for 192.0.2.5: iface 0000000000000000
Removing static route 10.0.0.0/8
27-09-2013 12:50:10 <TRACE> static10 > removed [sole] 10.0.0.0/8 via 192.0.2.5 
on lo255
27-09-2013 12:50:10 <TRACE> kernel10 < removed 10.0.0.0/8 via 192.0.2.5 on 
lo255
nl_send_route(10.0.0.0/8,new=0)
IFA change notification (2) for lo255:192.0.2.1
KRT: Received async route notification (25)
KRT: Got 192.0.2.0/24, type=1, oif=6, table=254, prid=2, proto=(none)
KRT: Ignoring route - unknown table 254
KRT: Received async route notification (25)
KRT: Got 192.0.2.255/32, type=3, oif=6, table=255, prid=2, proto=(none)
KRT: Ignoring route - unknown table 255
KRT: Received async route notification (25)
KRT: Got 192.0.2.0/32, type=3, oif=6, table=255, prid=2, proto=(none)
KRT: Ignoring route - unknown table 255
KRT: Received async route notification (25)
KRT: Got 192.0.2.1/32, type=2, oif=6, table=255, prid=2, proto=(none)
KRT: Ignoring route - unknown table 255
KRT: Received async route notification (25)
KRT: Got 10.0.0.0/8, type=1, oif=6, table=10, prid=12, proto=kernel10
KRT: Ignoring route - echo

----------------------------------------------------------------------------------------

There is problem with route to 192.168.0.0/16: after deleting its nexthop
192.0.2.5, route reachability information changes - nexthop no more available,
but route is still valid and installed in KRT.

First this is an issue with 3.2.x linux kernel which does not flush its FIB on 
nexthop change (fixed in recent kernels, at least with 3.10).

Second, BIRD does not renews its information about route when nexthop
reachability changes for routes with "gw" attribute changed.

This happens due to ignored neighbor status change notification in
static_neigh_notify() callback at proto/static/static.c, for route 
192.168.0.0/16, created with "dest" RTD_BLACKHOE and thus
does not depending on any external information on determining route 
reachability. 

Contrary to this, route 10.0.0.0/8 have attached neighbor to its 
nexthop with %NEF_STICKY flag via neigh_find(), to track state changes,
so when neighbor 192.0.2.5 state changes static protocol receives
notification from neigh_up()/neigh_down() at nest/neighbor.c via
neigh_notify()  (static_neigh_notify()) callback.

So when neighbor 192.0.2.5 state changes, static_neigh_notify() receives
pointer to neighbor structure with list of static routes, that depend
on neighbor at n->data field. However n->data contains only one route - 
10.0.0.0/8, as 192.168.0.0/16 created by static protocol as blackhole.

Also n->data  might be empty, if route 10.0.0.0/8 nexthop set something
other than 192.0.2.5, and notification received for neighbor 192.0.2.5, set
in filter code with "gw" address.

This is only one case, which describes core problem:
  how to handle notifications for routes with changed "gw" attribute?

===========================================
So I need some advice from BIRD developers on how to address this issue
correctly!
===========================================

Currently I have only basic idea on how to do this:

1. Create possibly sticky neighbor for "gw" attribute, in filter code with
neigh_find(..., NFA_STICKY), and really change gw attribute (and friends, as 
done currently in patch) in rta if n->scope > SCOPE_HOST (neighbor currently 
exists). Overwise do not touch rta->gw.

1. Each protocol must have neigh_notify() callback defined, when state change
for neighbor received, we should find route by prefix, and propagate it to the 
table as this done when new route comes or route changes some of its 
attributes (nexthop again for example?). Route should pass "import" filter 
before entering table in this way.

2. In import filter, where "gw" attribute present we check neighbor
reachability with n->scope > SCOPE_HOST and do real rta->gw attribute
update.

-- 
SP5474-RIPE
Sergey Popovich



More information about the Bird-users mailing list