В письме от 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